Will you start to change the OVMF platform to use the core PciHostBridge next week? I am still not quite sure it's the only gap:)
Regards, Ray >-----Original Message----- >From: Laszlo Ersek [mailto:[email protected]] >Sent: Friday, February 26, 2016 8:34 PM >To: Ni, Ruiyu <[email protected]>; [email protected] >Subject: Re: [PATCH v3] MdeModulePkg/PciHostBridge: Don't assume resources are >fully NonExistent > >On 02/26/16 13:15, Ni, Ruiyu wrote: >> Thanks for the quick patch. >> >> Reviewed-by: Ruiyu Ni <[email protected]> > >Thanks a lot! > >Committed & pushed as 6474f1f156eefa6886e594039f4d562e374ba344. > >Laszlo > >> >> >>> -----Original Message----- >>> From: Laszlo Ersek [mailto:[email protected]] >>> Sent: Friday, February 26, 2016 7:16 PM >>> To: [email protected] >>> Cc: Ni, Ruiyu <[email protected]> >>> Subject: [PATCH v3] MdeModulePkg/PciHostBridge: Don't assume resources are >>> fully NonExistent >>> >>> From: Ruiyu Ni <[email protected]> >>> >>> The patch removes the assumption that the resources claimed by root >>> bridges should not exist. Because resources might have been added: >>> 1. by platform modules either in PEI through resource HOB, or in DXE, >>> before the PCI host bridge driver runs. >>> 2. Resources claimed by different root bridges may overlap so that >>> resource adding operation for latter root bridges may fail if >>> we assume the resource should not exist. >>> >>> In real world, this patch is to fit OVMF platform needs because >>> different root bridges in OVMF platform shares the same resources. >>> >>> Contributed-under: TianoCore Contribution Agreement 1.0 >>> Signed-off-by: Ruiyu Ni <[email protected]> >>> [[email protected]: intersection-based implementation] >>> Contributed-under: TianoCore Contribution Agreement 1.0 >>> Signed-off-by: Laszlo Ersek <[email protected]> >>> Cc: Ruiyu Ni <[email protected]> >>> --- >>> >>> Notes: >>> v3: >>> - replace "completely missing" with "fully NonExistent" in the subject >>> [Ray] >>> >>> - sorting is only necessary for gap checking, but there are no gaps -- >>> drop both gap checking and sorting [Ray] >>> >>> - comment in the code that (IntersectionBase >= IntersectionEnd) means >>> "no overlap" [Ray] >>> >>> - log errors when incompatible descriptors are encountered >>> >>> - log an error when GetIoSpaceMap() / GetMemorySpaceMap() fails >>> >>> - remove useless ASSERT()s on the descriptors returned by >>> GetIoSpaceDescriptor() and GetMemorySpaceDescriptor() [Ray] >>> >>> - eliminate the Remaining, DescriptorLeft and Step variables, >>> simplifying the verification loops [Ray] >>> >>> - the verification loops should assert on CheckStatus, not Status >>> >>> MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c | 305 >>> +++++++++++++++++++- >>> 1 file changed, 294 insertions(+), 11 deletions(-) >>> >>> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c >>> b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c >>> index edf042cc2547..ef0c4f2a5e7b 100644 >>> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c >>> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c >>> @@ -29,6 +29,290 @@ GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 >>> *mPciResourceTypeStr[] = { >>> }; >>> >>> /** >>> + Ensure the compatibility of an IO space descriptor with the IO aperture. >>> + >>> + The IO space descriptor can come from the GCD IO space map, or it can >>> + represent a gap between two neighboring IO space descriptors. In the >>> latter >>> + case, the GcdIoType field is expected to be EfiGcdIoTypeNonExistent. >>> + >>> + If the IO space descriptor already has type EfiGcdIoTypeIo, then no >>> action is >>> + taken -- it is by definition compatible with the aperture. >>> + >>> + Otherwise, the intersection of the IO space descriptor is calculated >>> with the >>> + aperture. If the intersection is the empty set (no overlap), no action is >>> + taken; the IO space descriptor is compatible with the aperture. >>> + >>> + Otherwise, the type of the descriptor is investigated again. If the type >>> is >>> + EfiGcdIoTypeNonExistent (representing a gap, or a genuine descriptor with >>> + such a type), then an attempt is made to add the intersection as IO >>> space to >>> + the GCD IO space map. This ensures continuity for the aperture, and the >>> + descriptor is deemed compatible with the aperture. >>> + >>> + Otherwise, the IO space descriptor is incompatible with the IO aperture. >>> + >>> + @param[in] Base Base address of the aperture. >>> + @param[in] Length Length of the aperture. >>> + @param[in] Descriptor The descriptor to ensure compatibility with the >>> + aperture for. >>> + >>> + @retval EFI_SUCCESS The descriptor is compatible. The GCD IO >>> space >>> + map may have been updated, for continuity >>> + within the aperture. >>> + @retval EFI_INVALID_PARAMETER The descriptor is incompatible. >>> + @return Error codes from gDS->AddIoSpace(). >>> +**/ >>> +EFI_STATUS >>> +IntersectIoDescriptor ( >>> + IN UINT64 Base, >>> + IN UINT64 Length, >>> + IN CONST EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor >>> + ) >>> +{ >>> + UINT64 IntersectionBase; >>> + UINT64 IntersectionEnd; >>> + EFI_STATUS Status; >>> + >>> + if (Descriptor->GcdIoType == EfiGcdIoTypeIo) { >>> + return EFI_SUCCESS; >>> + } >>> + >>> + IntersectionBase = MAX (Base, Descriptor->BaseAddress); >>> + IntersectionEnd = MIN (Base + Length, >>> + Descriptor->BaseAddress + Descriptor->Length); >>> + if (IntersectionBase >= IntersectionEnd) { >>> + // >>> + // The descriptor and the aperture don't overlap. >>> + // >>> + return EFI_SUCCESS; >>> + } >>> + >>> + if (Descriptor->GcdIoType == EfiGcdIoTypeNonExistent) { >>> + Status = gDS->AddIoSpace (EfiGcdIoTypeIo, IntersectionBase, >>> + IntersectionEnd - IntersectionBase); >>> + >>> + DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, >>> + "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__, >>> + IntersectionBase, IntersectionEnd, Status)); >>> + return Status; >>> + } >>> + >>> + DEBUG ((EFI_D_ERROR, "%a: %a: desc [%Lx, %Lx) type %u conflicts with " >>> + "aperture [%Lx, %Lx)\n", gEfiCallerBaseName, __FUNCTION__, >>> + Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length, >>> + (UINT32)Descriptor->GcdIoType, Base, Base + Length)); >>> + return EFI_INVALID_PARAMETER; >>> +} >>> + >>> +/** >>> + Add IO space to GCD. >>> + The routine checks the GCD database and only adds those which are >>> + not added in the specified range to GCD. >>> + >>> + @param Base Base address of the IO space. >>> + @param Length Length of the IO space. >>> + >>> + @retval EFI_SUCCES The IO space was added successfully. >>> +**/ >>> +EFI_STATUS >>> +AddIoSpace ( >>> + IN UINT64 Base, >>> + IN UINT64 Length >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINTN Index; >>> + UINTN NumberOfDescriptors; >>> + EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap; >>> + >>> + Status = gDS->GetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((EFI_D_ERROR, "%a: %a: GetIoSpaceMap(): %r\n", >>> + gEfiCallerBaseName, __FUNCTION__, Status)); >>> + return Status; >>> + } >>> + >>> + for (Index = 0; Index < NumberOfDescriptors; Index++) { >>> + Status = IntersectIoDescriptor (Base, Length, &IoSpaceMap[Index]); >>> + if (EFI_ERROR (Status)) { >>> + goto FreeIoSpaceMap; >>> + } >>> + } >>> + >>> + DEBUG_CODE ( >>> + // >>> + // Make sure there are adjacent descriptors covering [Base, Base + >>> Length). >>> + // It is possible that they have not been merged; merging can be >>> prevented >>> + // by allocation. >>> + // >>> + UINT64 CheckBase; >>> + EFI_STATUS CheckStatus; >>> + EFI_GCD_IO_SPACE_DESCRIPTOR Descriptor; >>> + >>> + for (CheckBase = Base; >>> + CheckBase < Base + Length; >>> + CheckBase = Descriptor.BaseAddress + Descriptor.Length) { >>> + CheckStatus = gDS->GetIoSpaceDescriptor (CheckBase, &Descriptor); >>> + ASSERT_EFI_ERROR (CheckStatus); >>> + ASSERT (Descriptor.GcdIoType == EfiGcdIoTypeIo); >>> + } >>> + ); >>> + >>> +FreeIoSpaceMap: >>> + FreePool (IoSpaceMap); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> + Ensure the compatibility of a memory space descriptor with the MMIO >>> aperture. >>> + >>> + The memory space descriptor can come from the GCD memory space map, or >>> it can >>> + represent a gap between two neighboring memory space descriptors. In the >>> + latter case, the GcdMemoryType field is expected to be >>> + EfiGcdMemoryTypeNonExistent. >>> + >>> + If the memory space descriptor already has type >>> + EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of >>> the >>> + required capabilities, then no action is taken -- it is by definition >>> + compatible with the aperture. >>> + >>> + Otherwise, the intersection of the memory space descriptor is calculated >>> with >>> + the aperture. If the intersection is the empty set (no overlap), no >>> action is >>> + taken; the memory space descriptor is compatible with the aperture. >>> + >>> + Otherwise, the type of the descriptor is investigated again. If the type >>> is >>> + EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor >>> with >>> + such a type), then an attempt is made to add the intersection as MMIO >>> space >>> + to the GCD memory space map, with the specified capabilities. This >>> ensures >>> + continuity for the aperture, and the descriptor is deemed compatible >>> with the >>> + aperture. >>> + >>> + Otherwise, the memory space descriptor is incompatible with the MMIO >>> + aperture. >>> + >>> + @param[in] Base Base address of the aperture. >>> + @param[in] Length Length of the aperture. >>> + @param[in] Capabilities Capabilities required by the aperture. >>> + @param[in] Descriptor The descriptor to ensure compatibility with the >>> + aperture for. >>> + >>> + @retval EFI_SUCCESS The descriptor is compatible. The GCD >>> memory >>> + space map may have been updated, for >>> + continuity within the aperture. >>> + @retval EFI_INVALID_PARAMETER The descriptor is incompatible. >>> + @return Error codes from gDS->AddMemorySpace(). >>> +**/ >>> +EFI_STATUS >>> +IntersectMemoryDescriptor ( >>> + IN UINT64 Base, >>> + IN UINT64 Length, >>> + IN UINT64 Capabilities, >>> + IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor >>> + ) >>> +{ >>> + UINT64 IntersectionBase; >>> + UINT64 IntersectionEnd; >>> + EFI_STATUS Status; >>> + >>> + if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo && >>> + (Descriptor->Capabilities & Capabilities) == Capabilities) { >>> + return EFI_SUCCESS; >>> + } >>> + >>> + IntersectionBase = MAX (Base, Descriptor->BaseAddress); >>> + IntersectionEnd = MIN (Base + Length, >>> + Descriptor->BaseAddress + Descriptor->Length); >>> + if (IntersectionBase >= IntersectionEnd) { >>> + // >>> + // The descriptor and the aperture don't overlap. >>> + // >>> + return EFI_SUCCESS; >>> + } >>> + >>> + if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) { >>> + Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo, >>> + IntersectionBase, IntersectionEnd - IntersectionBase, >>> + Capabilities); >>> + >>> + DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, >>> + "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__, >>> + IntersectionBase, IntersectionEnd, Status)); >>> + return Status; >>> + } >>> + >>> + DEBUG ((EFI_D_ERROR, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts " >>> + "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName, __FUNCTION__, >>> + Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length, >>> + (UINT32)Descriptor->GcdMemoryType, Descriptor->Capabilities, >>> + Base, Base + Length, Capabilities)); >>> + return EFI_INVALID_PARAMETER; >>> +} >>> + >>> +/** >>> + Add MMIO space to GCD. >>> + The routine checks the GCD database and only adds those which are >>> + not added in the specified range to GCD. >>> + >>> + @param Base Base address of the MMIO space. >>> + @param Length Length of the MMIO space. >>> + @param Capabilities Capabilities of the MMIO space. >>> + >>> + @retval EFI_SUCCES The MMIO space was added successfully. >>> +**/ >>> +EFI_STATUS >>> +AddMemoryMappedIoSpace ( >>> + IN UINT64 Base, >>> + IN UINT64 Length, >>> + IN UINT64 Capabilities >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINTN Index; >>> + UINTN NumberOfDescriptors; >>> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; >>> + >>> + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((EFI_D_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n", >>> + gEfiCallerBaseName, __FUNCTION__, Status)); >>> + return Status; >>> + } >>> + >>> + for (Index = 0; Index < NumberOfDescriptors; Index++) { >>> + Status = IntersectMemoryDescriptor (Base, Length, Capabilities, >>> + &MemorySpaceMap[Index]); >>> + if (EFI_ERROR (Status)) { >>> + goto FreeMemorySpaceMap; >>> + } >>> + } >>> + >>> + DEBUG_CODE ( >>> + // >>> + // Make sure there are adjacent descriptors covering [Base, Base + >>> Length). >>> + // It is possible that they have not been merged; merging can be >>> prevented >>> + // by allocation and different capabilities. >>> + // >>> + UINT64 CheckBase; >>> + EFI_STATUS CheckStatus; >>> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; >>> + >>> + for (CheckBase = Base; >>> + CheckBase < Base + Length; >>> + CheckBase = Descriptor.BaseAddress + Descriptor.Length) { >>> + CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor); >>> + ASSERT_EFI_ERROR (CheckStatus); >>> + ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo); >>> + ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities); >>> + } >>> + ); >>> + >>> +FreeMemorySpaceMap: >>> + FreePool (MemorySpaceMap); >>> + >>> + return Status; >>> +} >>> + >>> +/** >>> >>> Entry point of this driver. >>> >>> @@ -89,6 +373,7 @@ InitializePciHostBridge ( >>> &gEfiPciHostBridgeResourceAllocationProtocolGuid, >>> &HostBridge->ResAlloc, >>> NULL >>> ); >>> + ASSERT_EFI_ERROR (Status); >>> if (EFI_ERROR (Status)) { >>> FreePool (HostBridge); >>> PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount); >>> @@ -109,11 +394,10 @@ InitializePciHostBridge ( >>> } >>> >>> if (RootBridges[Index].Io.Limit > RootBridges[Index].Io.Base) { >>> - Status = gDS->AddIoSpace ( >>> - EfiGcdIoTypeIo, >>> - RootBridges[Index].Io.Base, >>> - RootBridges[Index].Io.Limit - >>> RootBridges[Index].Io.Base + 1 >>> - ); >>> + Status = AddIoSpace ( >>> + RootBridges[Index].Io.Base, >>> + RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base >>> + 1 >>> + ); >>> ASSERT_EFI_ERROR (Status); >>> } >>> >>> @@ -130,12 +414,11 @@ InitializePciHostBridge ( >>> >>> for (MemApertureIndex = 0; MemApertureIndex < sizeof (MemApertures) / >>> sizeof (MemApertures[0]); >>> MemApertureIndex++) { >>> if (MemApertures[MemApertureIndex]->Limit > >>> MemApertures[MemApertureIndex]->Base) { >>> - Status = gDS->AddMemorySpace ( >>> - EfiGcdMemoryTypeMemoryMappedIo, >>> - MemApertures[MemApertureIndex]->Base, >>> - MemApertures[MemApertureIndex]->Limit - >>> MemApertures[MemApertureIndex]->Base + >1, >>> - EFI_MEMORY_UC >>> - ); >>> + Status = AddMemoryMappedIoSpace ( >>> + MemApertures[MemApertureIndex]->Base, >>> + MemApertures[MemApertureIndex]->Limit - >>> MemApertures[MemApertureIndex]->Base + 1, >>> + EFI_MEMORY_UC >>> + ); >>> ASSERT_EFI_ERROR (Status); >>> Status = gDS->SetMemorySpaceAttributes ( >>> MemApertures[MemApertureIndex]->Base, >>> -- >>> 1.8.3.1 >> _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

