The ARM FDT PCI producer path does not preserve the platform
PcdPciDisableBusEnumeration value. After parsing the PCI host node
from the device tree, it always sets that PCD to FALSE. This is
reasonable when firmware must discover and assign PCI resources
itself.

However, there are setups where the hypervisor (e.g. QEMU with
pre-enumeration) has already performed PCI bus enumeration and BAR
programming and expects firmware to preserve that configuration.
Always forcing the PCD to FALSE on this path removes that option,
so EDK2 will re-enumerate the bus regardless of hypervisor intent.

If the FDT PCI node contains "pci-enum-done", set
PcdPciDisableBusEnumeration to TRUE so EDK2 can treat the topology
as pre-configured. When absent, set it to FALSE and retain the
previous behavior (full firmware enumeration).

Also, mark the root bridges with ResourceAssigned based on the
PCD in FdtPciHostBridgeLib so the PCI bus driver does not
re-enumerate the bus.

Signed-off-by: Tushar Dave <[email protected]>
---
This patch accompanies the QEMU RFC series "hw/arm/virt, hw/pci:
PCI pre-enumeration and fixed BAR allocation" posted to qemu-devel:
https://lore.kernel.org/qemu-devel/[email protected]/

 .../FdtPciHostBridgeLib/FdtPciHostBridgeLib.c |  8 ++++-
 .../FdtPciHostBridgeLib.inf                   |  1 +
 .../FdtPciPcdProducerLib.c                    | 30 ++++++++++++++++++-
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c 
b/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
index 9af8c21a21..d84d15617d 100644
--- a/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
+++ b/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
@@ -444,7 +444,7 @@ PciHostBridgeGetRootBridges (
   PMemAbove4G.Base  = MAX_UINT64;

   PMemAbove4G.Limit = 0;

 

-  return PciHostBridgeUtilityGetRootBridges (

+  PCI_ROOT_BRIDGE  *Bridges = PciHostBridgeUtilityGetRootBridges (

            Count,

            Attributes,

            AllocationAttributes,

@@ -458,6 +458,12 @@ PciHostBridgeGetRootBridges (
            &PMem,

            &PMemAbove4G

            );

+  if (Bridges != NULL) {

+    for (UINTN Index = 0; Index < *Count; Index++) {

+      Bridges[Index].ResourceAssigned = PcdGetBool 
(PcdPciDisableBusEnumeration);

+    }

+  }

+  return Bridges;

 }

 

 /**

diff --git a/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf 
b/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
index 26b38b5966..636871866a 100644
--- a/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
+++ b/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
@@ -41,6 +41,7 @@
 [Pcd]

   gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation

   gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress

+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration

 

 [Depex]

   gFdtClientProtocolGuid

diff --git a/OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.c 
b/OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.c
index a3b09e547f..f5e30d8852 100644
--- a/OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.c
+++ b/OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.c
@@ -96,6 +96,9 @@ FdtPciPcdProducerLibConstructor (
   RETURN_STATUS        RetStatus;

   UINT64               IoTranslation;

   RETURN_STATUS        PcdStatus;

+  CONST VOID           *PropertyPtr;

+  UINT32               TempLen;

+  BOOLEAN              DisableBusEnumeration;

 

   PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);

   if (PciExpressBaseAddress != MAX_UINT64) {

@@ -135,7 +138,32 @@ FdtPciPcdProducerLibConstructor (
     if (!EFI_ERROR (Status) && (RegSize == 2 * sizeof (UINT64))) {

       PciExpressBaseAddress = SwapBytes64 (*Reg);

 

-      PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);

+      //

+      // If the FDT node has "pci-enum-done", the host (e.g. QEMU) has already

+      // run PCI enumeration and BAR allocation; allow 
PcdPciDisableBusEnumeration

+      // to remain as set by the platform. Otherwise force it to FALSE so EDK2

+      // performs full PCI enumeration.

+      //

+      PropertyPtr = NULL;

+      TempLen     = 0;

+      Status      = FdtClient->GetNodeProperty (

+                      FdtClient,

+                      Node,

+                      "pci-enum-done",

+                      &PropertyPtr,

+                      &TempLen

+                      );

+

+      DisableBusEnumeration = FALSE;

+      if (!EFI_ERROR (Status) && (TempLen > 0)) {

+        DisableBusEnumeration = TRUE;

+        DEBUG ((

+          DEBUG_INFO,

+          "  Found pci-enum-done property, disabling full PCI bus 
enumeration\n"

+          ));

+      }

+

+      PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, 
DisableBusEnumeration);

       ASSERT_RETURN_ERROR (PcdStatus);

 

       IoTranslation = 0;

-- 
2.34.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#121924): https://edk2.groups.io/g/devel/message/121924
Mute This Topic: https://groups.io/mt/119221711/21656
Group Owner: [email protected]
Unsubscribe: https://edk2.groups.io/g/devel/unsub [[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to