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

Reply via email to