Basically I don't agree to add a CFG space range field. See embedded reply in below.
Regards, Ray >-----Original Message----- >From: Laszlo Ersek [mailto:ler...@redhat.com] >Sent: Saturday, February 27, 2016 8:23 AM >To: edk2-devel-01 <edk2-de...@ml01.01.org> >Cc: Ni, Ruiyu <ruiyu...@intel.com>; Justen, Jordan L ><jordan.l.jus...@intel.com>; Marcel Apfelbaum <mar...@redhat.com> >Subject: [PATCH 01/17] MdeModulePkg: PciHostBridgeDxe: don't assume extended >config space > >The "PcAtChipsetPkg/PciHostBridgeDxe" driver hard-codes the [0x00..0xFF] >range as valid config space offsets, in the RootBridgeIoCheckParameter() >function -- see the MAX_PCI_REG_ADDRESS macro. This driver uses IO ports >0xCF8 / 0xCFC to access PCI config space. > >The (soon to be removed) "OvmfPkg/PciHostBridgeDxe" does the same. > >The "ArmVirtPkg/PciHostBridgeDxe" uses PCI Express (ECAM) instead, and >hard-codes the [0x00..0xFFF] range as valid config space offsets. > >The "MdeModulePkg/Bus/Pci/PciHostBridgeDxe" driver hard-codes the >[0x00..0xFFF] range as valid config space offsets, without actually >knowing if the platform uses PCI Express (ECAM) or plain PCI (0xCF8 / >0xCFC). For this generalized driver, the config access method is >ultimately decided by the platform's PciSegmentLib instance. > >Quoting the "MdePkg/Include/Library/PciSegmentLib.h" library class file: > > These functions perform PCI configuration cycles using the default PCI > configuration access method. This may use I/O ports 0xCF8 and 0xCFC to > perform PCI configuration accesses, or it may use MMIO registers > relative to the PcdPciExpressBaseAddress, or it may use some alternate > access method. [...] > >Clearly the configuration access method determines the boundaries of the >config space as well, for each individual PCI function. However, the >PciSegmentLib class provides no API for PciHostBridgeDxe to query these >boundaries! > >In order to remedy this, add another PCI_ROOT_BRIDGE_APERTURE field to the >root bridge structures in both PciHostBridgeDxe and the PciHostBridgeLib >class. This way platforms can control the PCI config space boundaries for >the purposes of PciHostBridgeDxe, in accordance with their config access >methods. > >This bug causes the following symptoms with OVMF and QEMU: > >QEMU's i440fx machine type is a PCI (0xCF8 / 0xCFC) machine. It supports >physical device assignment. When assigning a physical EVGA GTX750 GPU to >the guest, the PCI bus driver correctly determines that the GPU is a PCIe >device, and tries to locate its extended capabilities (specifically, ARI), >starting at config space offset 0x100. > >When OVMF is built with "OvmfPkg/PciHostBridgeDxe", this config access is >caught and rejected by RootBridgeIoCheckParameter(), due to the limit >being 0xFF. (And the PCI bus driver gracefully recovers from this >rejection.) Does the platform expect the graceful recovery? I may treat it as a silent failure:) Some additional devices cannot come up due to this recovery/failure but platform developer without deep debugging cannot know the root cause, if ARI is disabled. > >However, "MdeModulePkg/Bus/Pci/PciHostBridgeDxe" lets the address through, >because its variant of the same function hard-codes 0xFFF as the config >space limit. > >Then RootBridgeIoPciAccess() sends the (invalid) address down the >following chain of libraries: > > BasePciSegmentLibPci [class: PciSegmentLib] > BasePciLibCf8 [class: PciLib] > BasePciCf8Lib [class: PciCf8Lib] > >Finally, ASSERT_INVALID_PCI_ADDRESS() in PciCf8Read32() realizes that >offset 0x100 is invalid for the 0xCF8 / 0xCFC config access method, and >the firmware halts. The silent failure is bad. So the assertion is a good to tell platform developer to choose the correct PciSegment library instance. > >Fix this by informing the generalized PciHostBridgeDxe driver about the >platform's config space boundaries, so that the driver can recognize and >reject out-of-bounds accesses in time. > >Cc: Ruiyu Ni <ruiyu...@intel.com> >Cc: Jordan Justen <jordan.l.jus...@intel.com> >Cc: Marcel Apfelbaum <mar...@redhat.com> >Contributed-under: TianoCore Contribution Agreement 1.0 >Signed-off-by: Laszlo Ersek <ler...@redhat.com> >--- > MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h | 1 + > MdeModulePkg/Include/Library/PciHostBridgeLib.h | 1 + > MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 6 ++++-- > 3 files changed, 6 insertions(+), 2 deletions(-) > >diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h >b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h >index b1e83f1c9089..2dfc8963f8e9 100644 >--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h >+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h >@@ -71,6 +71,7 @@ typedef struct { > PCI_ROOT_BRIDGE_APERTURE PMem; > PCI_ROOT_BRIDGE_APERTURE MemAbove4G; > PCI_ROOT_BRIDGE_APERTURE PMemAbove4G; >+ PCI_ROOT_BRIDGE_APERTURE Pci; > BOOLEAN DmaAbove4G; > VOID *ConfigBuffer; > EFI_DEVICE_PATH_PROTOCOL *DevicePath; >diff --git a/MdeModulePkg/Include/Library/PciHostBridgeLib.h >b/MdeModulePkg/Include/Library/PciHostBridgeLib.h >index b1dba0f754d7..a9e9ca308c7c 100644 >--- a/MdeModulePkg/Include/Library/PciHostBridgeLib.h >+++ b/MdeModulePkg/Include/Library/PciHostBridgeLib.h >@@ -44,6 +44,7 @@ typedef struct { > PCI_ROOT_BRIDGE_APERTURE MemAbove4G; ///< MMIO aperture above 4GB > which can be used by the >root bridge. > PCI_ROOT_BRIDGE_APERTURE PMem; ///< Prefetchable MMIO > aperture below 4GB which can be >used by the root bridge. > PCI_ROOT_BRIDGE_APERTURE PMemAbove4G; ///< Prefetchable MMIO > aperture above 4GB which can be >used by the root bridge. >+ PCI_ROOT_BRIDGE_APERTURE Pci; ///< PCI config space range >that is valid for the devices behind >the root bridge. > EFI_DEVICE_PATH_PROTOCOL *DevicePath; ///< Device path. > } PCI_ROOT_BRIDGE; > >diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c >b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c >index 332860eb3819..6b7bd74290a7 100644 >--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c >+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c >@@ -90,6 +90,7 @@ CreateRootBridge ( > DEBUG ((EFI_D_INFO, " MemAbove4G: %lx - %lx\n", Bridge->MemAbove4G.Base, > Bridge->MemAbove4G.Limit)); > DEBUG ((EFI_D_INFO, " PMem: %lx - %lx\n", Bridge->PMem.Base, > Bridge->PMem.Limit)); > DEBUG ((EFI_D_INFO, " PMemAbove4G: %lx - %lx\n", Bridge->PMemAbove4G.Base, > Bridge->PMemAbove4G.Limit)); >+ DEBUG ((EFI_D_INFO, " Pci: %lx - %lx\n", Bridge->Pci.Base, >Bridge->Pci.Limit)); > > // > // Make sure Mem and MemAbove4G apertures are valid >@@ -168,6 +169,7 @@ CreateRootBridge ( > CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE)); > CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE)); > CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof > (PCI_ROOT_BRIDGE_APERTURE)); >+ CopyMem (&RootBridge->Pci, &Bridge->Pci, sizeof (PCI_ROOT_BRIDGE_APERTURE)); > > > for (Index = TypeIo; Index < TypeMax; Index++) { >@@ -350,8 +352,8 @@ RootBridgeIoCheckParameter ( > } else { > Address = PciRbAddr->Register; > } >- Base = 0; >- Limit = 0xFFF; >+ Base = RootBridge->Pci.Base; >+ Limit = RootBridge->Pci.Limit; > } > > if (Address < Base) { >-- >1.8.3.1 > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel