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]] -=-=-=-=-=-=-=-=-=-=-=-
