Read the "hardware-info" item from fw-cfg to extract specifications
of PCI host bridges and analyze the 64-bit apertures of them to
find out if 64-bit PCI size needs to be increased in order to
allocate enough address space to fit all the host bridges in a
valid region.

Using the static Hardware Info Lib API, read the fw-cfg file of
hardware information to extract, one by one, all the host
bridges. Find the last 64-bit MMIO address of each host bridge,
using the HardwareInfoPciHostBridgeLib API, and compare it to an
accumulate value to discover the highest address used, which
corresponds to the highest value that must be covered by the
64-bit PCI MMIO window.

Given that platforms with multiple host bridges may provide the PCI
apertures' addresses, the PCD token used to initialize the available
address space (PcdPciMmio64Size) must include those addresses for
the allocation process to be able to place resources in the
intended regions. Since the Pcd entry defining the 64-bit PCI MMIO
size is dynamic and initialized with a platform-dependent value,
it is updated to a higher value if that is required for all
high memory PCI host bridge apertures to fit in the valid address
space.

As an example, if the PcdPciMmio64Size is initialized to 0x800000000
and the runtime calculated base address produces the value 0x800000000,
the last 64-bit MMIO address a PCI host bridge may use would be
0xFFFFFFFFF. If one of the host-specified bridges defines a high
memory window 0x1000000000 - 0x17FFFFFFFF (inclusive) it would be
outside of the valid range defined by the Base address + PcdPciMmio64Size.
Therefore, parsing the HardwwareInfo resource allows to notice the higher
requirement and increase the size to 0x1000000000 so that the MMIO
address space solicited by the host can be met and the range effectively
extended to 0x17FFFFFFFF.

Cc: Alexander Graf <g...@amazon.de>
Cc: Gerd Hoffmann <kra...@redhat.com>

Signed-off-by: Nicolas Ojeda Leon <ncol...@amazon.com>
---
 OvmfPkg/PlatformPei/MemDetect.c     | 110 ++++++++++++++++++++++++++++
 OvmfPkg/PlatformPei/PlatformPei.inf |   1 +
 2 files changed, 111 insertions(+)

diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
index 1bcb5a08bc..b0bdd435cb 100644
--- a/OvmfPkg/PlatformPei/MemDetect.c
+++ b/OvmfPkg/PlatformPei/MemDetect.c
@@ -36,6 +36,7 @@ Module Name:
 #include <Library/MtrrLib.h>
 #include <Library/QemuFwCfgLib.h>
 #include <Library/QemuFwCfgSimpleParserLib.h>
+#include <Library/QemuFwCfgHardwareInfoLib.h>
 
 #include "Platform.h"
 #include "Cmos.h"
@@ -369,6 +370,110 @@ GetSystemMemorySizeAbove4gb (
   return LShiftU64 (Size, 16);
 }
 
+/**
+  Iterate over the PCI host bridges resources information optionally provided
+  in fw-cfg.
+
+  Find the highest address used by the PCI bridges in 64-bit MMIO space to
+  calculate and modify the PCI aperture size accordingly (PciMmio64Size)
+
+  @param[in] PciMmio64Base    Base address (start) of the 64-bit PCI MMIO
+                              address space.
+
+  @param[inout] PciMmio64Size Size of the PCI 64-bit MMIO aperture provided
+                              as input and modified (output) if the resources
+                              indicated by fw_cfg require a larger address
+                              space.
+
+  @retval EFI_SUCCESS         The fw_cfg host-bridges-info was found and
+                              processed.
+
+  @retval EFI_PROTOCOL_ERROR  The host bridges information file was found,
+                              but its size wasn't a whole multiple of
+                              sizeof(HOST_BRIDGE_INFO). No entry was processed.
+
+  @retval EFI_NOT_FOUND       fw-cfg file with host bridges information was not
+                              found. Does not constitute an errro since the 
file
+                              is optional and used in special cases.
+
+  @retval EFI_UNSUPPORTED     fw-cfg is unavailable
+
+**/
+STATIC
+EFI_STATUS
+ScanPci64BitApertureSize (
+  IN UINT64      PciMmio64Base,
+  IN OUT UINT64  *PciMmio64Size
+  )
+{
+  EFI_STATUS            Status;
+  HOST_BRIDGE_INFO      HostBridge;
+  FIRMWARE_CONFIG_ITEM  FwCfgItem;
+  UINTN                 FwCfgSize;
+  UINTN                 FwCfgReadIndex;
+  UINTN                 ReadDataSize;
+  UINT64                PciEnd;
+  UINT64                PcdPciEnd;
+  UINT64                Above4GMmioEnd;
+
+  PciEnd         = 0;
+  Above4GMmioEnd = 0;
+  PcdPciEnd      = PciMmio64Base + *PciMmio64Size - 1;
+
+  Status = QemuFwCfgFindFile ("etc/hardware-info", &FwCfgItem, &FwCfgSize);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  QemuFwCfgSelectItem (FwCfgItem);
+
+  FwCfgReadIndex = 0;
+  while (FwCfgReadIndex < FwCfgSize) {
+    Status = QemuFwCfgReadNextHardwareInfoByType (
+               HardwareInfoTypeHostBridge,
+               sizeof (HostBridge),
+               FwCfgSize,
+               &HostBridge,
+               &ReadDataSize,
+               &FwCfgReadIndex
+               );
+
+    if (Status != EFI_SUCCESS) {
+      //
+      // No more data available to read in the file, break
+      // loop and finish process
+      //
+      break;
+    }
+
+    Status = HardwareInfoPciHostBridgeLastMmioAddress (
+               &HostBridge,
+               ReadDataSize,
+               TRUE,
+               &Above4GMmioEnd
+               );
+
+    if (Status != EFI_SUCCESS) {
+      //
+      // Error parsing MMIO apertures and extracting last MMIO
+      // address, bail out and propagate error
+      //
+      return Status;
+    }
+
+    if (Above4GMmioEnd > PciEnd) {
+      PciEnd = Above4GMmioEnd;
+    }
+  }
+
+  if (PciEnd > PcdPciEnd) {
+    *PciMmio64Size = PciEnd - PciMmio64Base + 1;
+    *PciMmio64Size = ALIGN_VALUE (*PciMmio64Size, (UINT64)SIZE_1GB);
+  }
+
+  return EFI_SUCCESS;
+}
+
 /**
   Return the highest address that DXE could possibly use, plus one.
 **/
@@ -515,6 +620,11 @@ GetFirstNonAddress (
   //
   Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));
 
+  //
+  // Extend Pci64Size if fw_cfg Host bridges specification requires it
+  //
+  ScanPci64BitApertureSize (Pci64Base, &Pci64Size);
+
   if (mBootMode != BOOT_ON_S3_RESUME) {
     //
     // The core PciHostBridgeDxe driver will automatically add this range to
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf 
b/OvmfPkg/PlatformPei/PlatformPei.inf
index 8ef404168c..413b92b855 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -64,6 +64,7 @@
   MemEncryptSevLib
   PcdLib
   VmgExitLib
+  QemuFwCfgHardwareInfoLib
 
 [Pcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
-- 
2.17.1




Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879





-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#85874): https://edk2.groups.io/g/devel/message/85874
Mute This Topic: https://groups.io/mt/88565405/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to