public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [RFC v2 0/2] Add translation support to generic PCIHostBridge
@ 2018-02-22  6:54 Heyi Guo
  2018-02-22  6:54 ` [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation Heyi Guo
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Heyi Guo @ 2018-02-22  6:54 UTC (permalink / raw)
  To: edk2-devel
  Cc: Heyi Guo, Ruiyu Ni, Ard Biesheuvel, Star Zeng, Eric Dong,
	Laszlo Ersek, Michael D Kinney

v2:
Changs are made according to the discussion on the mailing list, including:

1. PciRootBridgeIo->Configuration should return CPU view address, as well as
PciIo->GetBarAttributes, and Translation Offset should be equal to PCI view
address - CPU view address.

2. Add translation offset to PCI_ROOT_BRIDGE_APERTURE structure definition.

3. PciHostBridge driver internally used Base Address is still based on PCI view
address, and translation offset = CPU view - PCI view, which follows the
definition in ACPI, and not the same as that in UEFI spec.

This is still RFC version, so we have not gone thru all the code in EDK2 for
applying the change of PciSegmentLib definition.

Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>


Heyi Guo (2):
  MdeModulePkg/PciHostBridgeDxe: Add support for address translation
  MdeModulePkg/PciBus: return CPU address for GetBarAttributes

 MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c             |   9 +-
 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c       |  57 ++++++++----
 .../Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c     | 101 ++++++++++++++++++---
 MdeModulePkg/Include/Library/PciHostBridgeLib.h    |   1 +
 4 files changed, 138 insertions(+), 30 deletions(-)

-- 
2.7.4



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation
  2018-02-22  6:54 [RFC v2 0/2] Add translation support to generic PCIHostBridge Heyi Guo
@ 2018-02-22  6:54 ` Heyi Guo
  2018-02-22  8:55   ` Ni, Ruiyu
                     ` (2 more replies)
  2018-02-22  6:54 ` [RFC v2 2/2] MdeModulePkg/PciBus: return CPU address for GetBarAttributes Heyi Guo
  2018-02-22 10:06 ` [RFC v2 0/2] Add translation support to generic PCIHostBridge Laszlo Ersek
  2 siblings, 3 replies; 10+ messages in thread
From: Heyi Guo @ 2018-02-22  6:54 UTC (permalink / raw)
  To: edk2-devel
  Cc: Heyi Guo, Ruiyu Ni, Ard Biesheuvel, Star Zeng, Eric Dong,
	Laszlo Ersek, Michael D Kinney

This is the draft patch for the discussion posted in edk2-devel
mailing list:
https://lists.01.org/pipermail/edk2-devel/2017-December/019289.html

As discussed in the mailing list, we'd like to add support for PCI
address translation which is necessary for some non-x86 platforms. I
also want to minimize the changes to the generic host bridge driver
and platform PciHostBridgeLib implemetations, so additional two
interfaces are added to expose translation information of the
platform. To be generic, I add translation for each type of IO or
memory resources.

The patch is still a RFC, so I only passed the build for qemu64 and
the function has not been tested yet.

Please let me know your comments about it.

Thanks.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Heyi Guo <heyi.guo@linaro.org>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
---
 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c       |  57 ++++++++----
 .../Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c     | 101 ++++++++++++++++++---
 MdeModulePkg/Include/Library/PciHostBridgeLib.h    |   1 +
 3 files changed, 131 insertions(+), 28 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
index 1494848..fa22d8d 100644
--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
@@ -32,6 +32,29 @@ EDKII_IOMMU_PROTOCOL        *mIoMmuProtocol;
 EFI_EVENT                   mIoMmuEvent;
 VOID                        *mIoMmuRegistration;
 
+STATIC
+UINT64
+GetTranslationByResourceType (
+  IN  PCI_ROOT_BRIDGE_INSTANCE     *RootBridge,
+  IN  PCI_RESOURCE_TYPE            ResourceType
+  )
+{
+  switch (ResourceType) {
+    case TypeIo:
+      return RootBridge->Io.Translation;
+    case TypeMem32:
+      return RootBridge->Mem.Translation;
+    case TypePMem32:
+      return RootBridge->PMem.Translation;
+    case TypeMem64:
+      return RootBridge->MemAbove4G.Translation;
+    case TypePMem64:
+      return RootBridge->PMemAbove4G.Translation;
+    default:
+      return 0;
+  }
+}
+
 /**
   Ensure the compatibility of an IO space descriptor with the IO aperture.
 
@@ -412,7 +435,7 @@ InitializePciHostBridge (
 
     if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
       Status = AddIoSpace (
-                 RootBridges[Index].Io.Base,
+                 RootBridges[Index].Io.Base + RootBridges[Index].Io.Translation,
                  RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
                  );
       ASSERT_EFI_ERROR (Status);
@@ -422,7 +445,7 @@ InitializePciHostBridge (
                         EfiGcdIoTypeIo,
                         0,
                         RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
-                        &RootBridges[Index].Io.Base,
+                        &RootBridges[Index].Io.Base + RootBridges[Index].Io.Translation,
                         gImageHandle,
                         NULL
                         );
@@ -444,13 +467,13 @@ InitializePciHostBridge (
     for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {
       if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {
         Status = AddMemoryMappedIoSpace (
-                   MemApertures[MemApertureIndex]->Base,
+                   MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
                    MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
                    EFI_MEMORY_UC
                    );
         ASSERT_EFI_ERROR (Status);
         Status = gDS->SetMemorySpaceAttributes (
-                        MemApertures[MemApertureIndex]->Base,
+                        MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
                         MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
                         EFI_MEMORY_UC
                         );
@@ -463,7 +486,7 @@ InitializePciHostBridge (
                           EfiGcdMemoryTypeMemoryMappedIo,
                           0,
                           MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
-                          &MemApertures[MemApertureIndex]->Base,
+                          &MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
                           gImageHandle,
                           NULL
                           );
@@ -828,8 +851,8 @@ NotifyPhase (
                             FALSE,
                             RootBridge->ResAllocNode[Index].Length,
                             MIN (15, BitsOfAlignment),
-                            ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
-                            RootBridge->Io.Limit
+                            ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1) + RootBridge->Io.Translation,
+                            RootBridge->Io.Limit + RootBridge->Io.Translation
                             );
             break;
 
@@ -838,8 +861,8 @@ NotifyPhase (
                             TRUE,
                             RootBridge->ResAllocNode[Index].Length,
                             MIN (63, BitsOfAlignment),
-                            ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
-                            RootBridge->MemAbove4G.Limit
+                            ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1) + RootBridge->MemAbove4G.Translation,
+                            RootBridge->MemAbove4G.Limit + RootBridge->MemAbove4G.Translation
                             );
             if (BaseAddress != MAX_UINT64) {
               break;
@@ -853,8 +876,8 @@ NotifyPhase (
                             TRUE,
                             RootBridge->ResAllocNode[Index].Length,
                             MIN (31, BitsOfAlignment),
-                            ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
-                            RootBridge->Mem.Limit
+                            ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1) + RootBridge->Mem.Translation,
+                            RootBridge->Mem.Limit + RootBridge->Mem.Translation
                             );
             break;
 
@@ -863,8 +886,8 @@ NotifyPhase (
                             TRUE,
                             RootBridge->ResAllocNode[Index].Length,
                             MIN (63, BitsOfAlignment),
-                            ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
-                            RootBridge->PMemAbove4G.Limit
+                            ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1) + RootBridge->PMemAbove4G.Translation,
+                            RootBridge->PMemAbove4G.Limit + RootBridge->PMemAbove4G.Translation
                             );
             if (BaseAddress != MAX_UINT64) {
               break;
@@ -877,8 +900,8 @@ NotifyPhase (
                             TRUE,
                             RootBridge->ResAllocNode[Index].Length,
                             MIN (31, BitsOfAlignment),
-                            ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
-                            RootBridge->PMem.Limit
+                            ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1) + RootBridge->PMem.Translation,
+                            RootBridge->PMem.Limit + RootBridge->PMem.Translation
                             );
             break;
 
@@ -1152,6 +1175,7 @@ StartBusEnumeration (
       Descriptor->AddrSpaceGranularity  = 0;
       Descriptor->AddrRangeMin          = RootBridge->Bus.Base;
       Descriptor->AddrRangeMax          = 0;
+      // Ignore translation offset for bus
       Descriptor->AddrTranslationOffset = 0;
       Descriptor->AddrLen               = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;
 
@@ -1421,7 +1445,8 @@ GetProposedResources (
           Descriptor->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
           Descriptor->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;
           Descriptor->GenFlag               = 0;
-          Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base;
+          Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base -
+              GetTranslationByResourceType (RootBridge, Index);
           Descriptor->AddrRangeMax          = 0;
           Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;
           Descriptor->AddrLen               = RootBridge->ResAllocNode[Index].Length;
diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
index dc06c16..bd3394a 100644
--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -86,12 +86,23 @@ CreateRootBridge (
           (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",
           (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""
           ));
+  // We don't see any scenario for bus translation, so translation for bus is just ignored.
   DEBUG ((EFI_D_INFO, "           Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit));
-  DEBUG ((EFI_D_INFO, "            Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit));
-  DEBUG ((EFI_D_INFO, "           Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit));
-  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 ((DEBUG_INFO, "            Io: %lx - %lx translation=%lx\n",
+          Bridge->Io.Base, Bridge->Io.Limit, Bridge->Io.Translation
+          ));
+  DEBUG ((DEBUG_INFO, "           Mem: %lx - %lx translation=%lx\n",
+          Bridge->Mem.Base, Bridge->Mem.Limit, Bridge->Mem.Translation
+          ));
+  DEBUG ((DEBUG_INFO, "    MemAbove4G: %lx - %lx translation=%lx\n",
+          Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit, Bridge->MemAbove4G.Translation
+          ));
+  DEBUG ((DEBUG_INFO, "          PMem: %lx - %lx translation=%lx\n",
+          Bridge->PMem.Base, Bridge->PMem.Limit, Bridge->PMem.Translation
+          ));
+  DEBUG ((DEBUG_INFO, "   PMemAbove4G: %lx - %lx translation=%lx\n",
+          Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit, Bridge->PMemAbove4G.Translation
+          ));
 
   //
   // Make sure Mem and MemAbove4G apertures are valid
@@ -403,6 +414,28 @@ RootBridgeIoCheckParameter (
   return EFI_SUCCESS;
 }
 
+EFI_STATUS
+RootBridgeIoGetMemTranslationByAddress (
+  IN PCI_ROOT_BRIDGE_INSTANCE               *RootBridge,
+  IN UINT64                                 Address,
+  IN OUT UINT64                             *Translation
+  )
+{
+  if (Address >= RootBridge->Mem.Base && Address <= RootBridge->Mem.Limit) {
+    *Translation = RootBridge->Mem.Translation;
+  } else if (Address >= RootBridge->PMem.Base && Address <= RootBridge->PMem.Limit) {
+    *Translation = RootBridge->PMem.Translation;
+  } else if (Address >= RootBridge->MemAbove4G.Base && Address <= RootBridge->MemAbove4G.Limit) {
+    *Translation = RootBridge->MemAbove4G.Translation;
+  } else if (Address >= RootBridge->PMemAbove4G.Base && Address <= RootBridge->PMemAbove4G.Limit) {
+    *Translation = RootBridge->PMemAbove4G.Translation;
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
 /**
   Polls an address in memory mapped I/O space until an exit condition is met,
   or a timeout occurs.
@@ -658,13 +691,22 @@ RootBridgeIoMemRead (
   )
 {
   EFI_STATUS                             Status;
+  PCI_ROOT_BRIDGE_INSTANCE               *RootBridge;
+  UINT64                                 Translation;
 
   Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
                                        Count, Buffer);
   if (EFI_ERROR (Status)) {
     return Status;
   }
-  return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+  Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + Translation, Count, Buffer);
 }
 
 /**
@@ -705,13 +747,22 @@ RootBridgeIoMemWrite (
   )
 {
   EFI_STATUS                             Status;
+  PCI_ROOT_BRIDGE_INSTANCE               *RootBridge;
+  UINT64                                 Translation;
 
   Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
                                        Count, Buffer);
   if (EFI_ERROR (Status)) {
     return Status;
   }
-  return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+  Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + Translation, Count, Buffer);
 }
 
 /**
@@ -746,6 +797,8 @@ RootBridgeIoIoRead (
   )
 {
   EFI_STATUS                                    Status;
+  PCI_ROOT_BRIDGE_INSTANCE                      *RootBridge;
+
   Status = RootBridgeIoCheckParameter (
              This, IoOperation, Width,
              Address, Count, Buffer
@@ -753,7 +806,10 @@ RootBridgeIoIoRead (
   if (EFI_ERROR (Status)) {
     return Status;
   }
-  return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + RootBridge->Io.Translation, Count, Buffer);
 }
 
 /**
@@ -788,6 +844,8 @@ RootBridgeIoIoWrite (
   )
 {
   EFI_STATUS                                    Status;
+  PCI_ROOT_BRIDGE_INSTANCE                      *RootBridge;
+
   Status = RootBridgeIoCheckParameter (
              This, IoOperation, Width,
              Address, Count, Buffer
@@ -795,7 +853,10 @@ RootBridgeIoIoWrite (
   if (EFI_ERROR (Status)) {
     return Status;
   }
-  return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
+
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
+
+  return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + RootBridge->Io.Translation, Count, Buffer);
 }
 
 /**
@@ -1615,25 +1676,41 @@ RootBridgeIoConfiguration (
 
     Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
     Descriptor->Len  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+    // According to UEFI 2.7, RootBridgeIo::Configuration should return address
+    // range in CPU view, and TranslationOffset = PCI view - CPU view.
     Descriptor->AddrRangeMin  = ResAllocNode->Base;
     Descriptor->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
     Descriptor->AddrLen       = ResAllocNode->Length;
     switch (ResAllocNode->Type) {
 
     case TypeIo:
-      Descriptor->ResType       = ACPI_ADDRESS_SPACE_TYPE_IO;
+      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_IO;
+      // According to UEFI 2.7, translation = PCI address - CPU address,
+      // so we change the sign here to make it consistent with UEFI spec.
+      // The other translations will be treated as the same.
+      Descriptor->AddrTranslationOffset = -RootBridge->Io.Translation;
       break;
 
     case TypePMem32:
-      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
+      Descriptor->SpecificFlag          = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
+      Descriptor->AddrTranslationOffset = -RootBridge->PMem.Translation;
+      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      Descriptor->AddrSpaceGranularity  = 32;
+      break;
+
     case TypeMem32:
+      Descriptor->AddrTranslationOffset = -RootBridge->Mem.Translation;
       Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
       Descriptor->AddrSpaceGranularity  = 32;
       break;
 
     case TypePMem64:
-      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
+      Descriptor->SpecificFlag          = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
+      Descriptor->AddrTranslationOffset = -RootBridge->PMemAbove4G.Translation;
+      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      Descriptor->AddrSpaceGranularity  = 64;
     case TypeMem64:
+      Descriptor->AddrTranslationOffset = -RootBridge->MemAbove4G.Translation;
       Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
       Descriptor->AddrSpaceGranularity  = 64;
       break;
diff --git a/MdeModulePkg/Include/Library/PciHostBridgeLib.h b/MdeModulePkg/Include/Library/PciHostBridgeLib.h
index d42e9ec..b9e8c0f 100644
--- a/MdeModulePkg/Include/Library/PciHostBridgeLib.h
+++ b/MdeModulePkg/Include/Library/PciHostBridgeLib.h
@@ -22,6 +22,7 @@
 typedef struct {
   UINT64 Base;
   UINT64 Limit;
+  UINT64 Translation;
 } PCI_ROOT_BRIDGE_APERTURE;
 
 typedef struct {
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC v2 2/2] MdeModulePkg/PciBus: return CPU address for GetBarAttributes
  2018-02-22  6:54 [RFC v2 0/2] Add translation support to generic PCIHostBridge Heyi Guo
  2018-02-22  6:54 ` [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation Heyi Guo
@ 2018-02-22  6:54 ` Heyi Guo
  2018-02-22 10:41   ` Laszlo Ersek
  2018-02-22 10:06 ` [RFC v2 0/2] Add translation support to generic PCIHostBridge Laszlo Ersek
  2 siblings, 1 reply; 10+ messages in thread
From: Heyi Guo @ 2018-02-22  6:54 UTC (permalink / raw)
  To: edk2-devel
  Cc: Heyi Guo, Ruiyu Ni, Ard Biesheuvel, Star Zeng, Eric Dong,
	Laszlo Ersek, Michael D Kinney

PciIo::GetBarAttributes should return CPU view address according to
UEFI spec 2.7, so we change the implementation to follow the spec.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Heyi Guo <heyi.guo@linaro.org>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
index 190f4b0..0aafcba 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
@@ -1814,8 +1814,8 @@ GetMmioAddressTranslationOffset (
 
   while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
     if ((Configuration->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
-        (Configuration->AddrRangeMin <= AddrRangeMin) &&
-        (Configuration->AddrRangeMin + Configuration->AddrLen >= AddrRangeMin + AddrLen)
+        (Configuration->AddrRangeMin + Configuration->AddrTranslationOffset <= AddrRangeMin) &&
+        (Configuration->AddrRangeMin + Configuration->AddrLen + Configuration->AddrTranslationOffset >= AddrRangeMin + AddrLen)
         ) {
       return Configuration->AddrTranslationOffset;
     }
@@ -1968,6 +1968,11 @@ PciIoGetBarAttributes (
         return EFI_UNSUPPORTED;
       }
     }
+
+    // According to UEFI spec 2.7, we need return CPU view address for PciIo::GetBarAttributes,
+    // and PCI view = CPU view + translation
+    Descriptor->AddrRangeMin -= Descriptor->AddrTranslationOffset;
+    Descriptor->AddrRangeMax -= Descriptor->AddrTranslationOffset;
   }
 
   return EFI_SUCCESS;
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation
  2018-02-22  6:54 ` [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation Heyi Guo
@ 2018-02-22  8:55   ` Ni, Ruiyu
  2018-02-22  8:56   ` Ni, Ruiyu
  2018-02-22  9:43   ` Laszlo Ersek
  2 siblings, 0 replies; 10+ messages in thread
From: Ni, Ruiyu @ 2018-02-22  8:55 UTC (permalink / raw)
  To: Heyi Guo, edk2-devel
  Cc: Ard Biesheuvel, Star Zeng, Eric Dong, Laszlo Ersek,
	Michael D Kinney

On 2/22/2018 2:54 PM, Heyi Guo wrote:
> This is the draft patch for the discussion posted in edk2-devel
> mailing list:
> https://lists.01.org/pipermail/edk2-devel/2017-December/019289.html
> 
> As discussed in the mailing list, we'd like to add support for PCI
> address translation which is necessary for some non-x86 platforms. I
> also want to minimize the changes to the generic host bridge driver
> and platform PciHostBridgeLib implemetations, so additional two
> interfaces are added to expose translation information of the
> platform. To be generic, I add translation for each type of IO or
> memory resources.
> 
> The patch is still a RFC, so I only passed the build for qemu64 and
> the function has not been tested yet.
> 
> Please let me know your comments about it.
> 
> Thanks.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Heyi Guo <heyi.guo@linaro.org>
> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>   .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c       |  57 ++++++++----
>   .../Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c     | 101 ++++++++++++++++++---
>   MdeModulePkg/Include/Library/PciHostBridgeLib.h    |   1 +
>   3 files changed, 131 insertions(+), 28 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> index 1494848..fa22d8d 100644
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> @@ -32,6 +32,29 @@ EDKII_IOMMU_PROTOCOL        *mIoMmuProtocol;
>   EFI_EVENT                   mIoMmuEvent;
>   VOID                        *mIoMmuRegistration;
>   
> +STATIC
> +UINT64
> +GetTranslationByResourceType (
> +  IN  PCI_ROOT_BRIDGE_INSTANCE     *RootBridge,
> +  IN  PCI_RESOURCE_TYPE            ResourceType
> +  )
> +{
> +  switch (ResourceType) {
> +    case TypeIo:
> +      return RootBridge->Io.Translation;
> +    case TypeMem32:
> +      return RootBridge->Mem.Translation;
> +    case TypePMem32:
> +      return RootBridge->PMem.Translation;
> +    case TypeMem64:
> +      return RootBridge->MemAbove4G.Translation;
> +    case TypePMem64:
> +      return RootBridge->PMemAbove4G.Translation;
> +    default:
> +      return 0;
> +  }
> +}
> +
>   /**
>     Ensure the compatibility of an IO space descriptor with the IO aperture.
>   
> @@ -412,7 +435,7 @@ InitializePciHostBridge (
>   
>       if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
>         Status = AddIoSpace (
> -                 RootBridges[Index].Io.Base,
> +                 RootBridges[Index].Io.Base + RootBridges[Index].Io.Translation,
>                    RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
>                    );
>         ASSERT_EFI_ERROR (Status);
> @@ -422,7 +445,7 @@ InitializePciHostBridge (
>                           EfiGcdIoTypeIo,
>                           0,
>                           RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
> -                        &RootBridges[Index].Io.Base,
> +                        &RootBridges[Index].Io.Base + RootBridges[Index].Io.Translation,
>                           gImageHandle,
>                           NULL
>                           );
> @@ -444,13 +467,13 @@ InitializePciHostBridge (
>       for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {
>         if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {
>           Status = AddMemoryMappedIoSpace (
> -                   MemApertures[MemApertureIndex]->Base,
> +                   MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
>                      MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
>                      EFI_MEMORY_UC
>                      );
>           ASSERT_EFI_ERROR (Status);
>           Status = gDS->SetMemorySpaceAttributes (
> -                        MemApertures[MemApertureIndex]->Base,
> +                        MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
>                           MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
>                           EFI_MEMORY_UC
>                           );
> @@ -463,7 +486,7 @@ InitializePciHostBridge (
>                             EfiGcdMemoryTypeMemoryMappedIo,
>                             0,
>                             MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
> -                          &MemApertures[MemApertureIndex]->Base,
> +                          &MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
>                             gImageHandle,
>                             NULL
>                             );
> @@ -828,8 +851,8 @@ NotifyPhase (
>                               FALSE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (15, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
> -                            RootBridge->Io.Limit
> +                            ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1) + RootBridge->Io.Translation,
> +                            RootBridge->Io.Limit + RootBridge->Io.Translation
>                               );
>               break;
>   
> @@ -838,8 +861,8 @@ NotifyPhase (
>                               TRUE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (63, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
> -                            RootBridge->MemAbove4G.Limit
> +                            ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1) + RootBridge->MemAbove4G.Translation,
> +                            RootBridge->MemAbove4G.Limit + RootBridge->MemAbove4G.Translation
>                               );
>               if (BaseAddress != MAX_UINT64) {
>                 break;
> @@ -853,8 +876,8 @@ NotifyPhase (
>                               TRUE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (31, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
> -                            RootBridge->Mem.Limit
> +                            ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1) + RootBridge->Mem.Translation,
> +                            RootBridge->Mem.Limit + RootBridge->Mem.Translation
>                               );
>               break;
>   
> @@ -863,8 +886,8 @@ NotifyPhase (
>                               TRUE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (63, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
> -                            RootBridge->PMemAbove4G.Limit
> +                            ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1) + RootBridge->PMemAbove4G.Translation,
> +                            RootBridge->PMemAbove4G.Limit + RootBridge->PMemAbove4G.Translation
>                               );
>               if (BaseAddress != MAX_UINT64) {
>                 break;
> @@ -877,8 +900,8 @@ NotifyPhase (
>                               TRUE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (31, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
> -                            RootBridge->PMem.Limit
> +                            ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1) + RootBridge->PMem.Translation,
> +                            RootBridge->PMem.Limit + RootBridge->PMem.Translation
>                               );
>               break;
>   
> @@ -1152,6 +1175,7 @@ StartBusEnumeration (
>         Descriptor->AddrSpaceGranularity  = 0;
>         Descriptor->AddrRangeMin          = RootBridge->Bus.Base;
>         Descriptor->AddrRangeMax          = 0;
> +      // Ignore translation offset for bus
>         Descriptor->AddrTranslationOffset = 0;
>         Descriptor->AddrLen               = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;
>   
> @@ -1421,7 +1445,8 @@ GetProposedResources (
>             Descriptor->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
>             Descriptor->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;
>             Descriptor->GenFlag               = 0;
> -          Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base;
> +          Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base -
> +              GetTranslationByResourceType (RootBridge, Index);
>             Descriptor->AddrRangeMax          = 0;
>             Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;
>             Descriptor->AddrLen               = RootBridge->ResAllocNode[Index].Length;
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> index dc06c16..bd3394a 100644
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> @@ -86,12 +86,23 @@ CreateRootBridge (
>             (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",
>             (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""
>             ));
> +  // We don't see any scenario for bus translation, so translation for bus is just ignored.
>     DEBUG ((EFI_D_INFO, "           Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit));
> -  DEBUG ((EFI_D_INFO, "            Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit));
> -  DEBUG ((EFI_D_INFO, "           Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit));
> -  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 ((DEBUG_INFO, "            Io: %lx - %lx translation=%lx\n",
> +          Bridge->Io.Base, Bridge->Io.Limit, Bridge->Io.Translation
> +          ));
> +  DEBUG ((DEBUG_INFO, "           Mem: %lx - %lx translation=%lx\n",
> +          Bridge->Mem.Base, Bridge->Mem.Limit, Bridge->Mem.Translation
> +          ));
> +  DEBUG ((DEBUG_INFO, "    MemAbove4G: %lx - %lx translation=%lx\n",
> +          Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit, Bridge->MemAbove4G.Translation
> +          ));
> +  DEBUG ((DEBUG_INFO, "          PMem: %lx - %lx translation=%lx\n",
> +          Bridge->PMem.Base, Bridge->PMem.Limit, Bridge->PMem.Translation
> +          ));
> +  DEBUG ((DEBUG_INFO, "   PMemAbove4G: %lx - %lx translation=%lx\n",
> +          Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit, Bridge->PMemAbove4G.Translation
> +          ));
>   
>     //
>     // Make sure Mem and MemAbove4G apertures are valid
> @@ -403,6 +414,28 @@ RootBridgeIoCheckParameter (
>     return EFI_SUCCESS;
>   }
>   
> +EFI_STATUS
> +RootBridgeIoGetMemTranslationByAddress (
> +  IN PCI_ROOT_BRIDGE_INSTANCE               *RootBridge,
> +  IN UINT64                                 Address,
> +  IN OUT UINT64                             *Translation
> +  )
> +{
> +  if (Address >= RootBridge->Mem.Base && Address <= RootBridge->Mem.Limit) {
> +    *Translation = RootBridge->Mem.Translation;
> +  } else if (Address >= RootBridge->PMem.Base && Address <= RootBridge->PMem.Limit) {
> +    *Translation = RootBridge->PMem.Translation;
> +  } else if (Address >= RootBridge->MemAbove4G.Base && Address <= RootBridge->MemAbove4G.Limit) {
> +    *Translation = RootBridge->MemAbove4G.Translation;
> +  } else if (Address >= RootBridge->PMemAbove4G.Base && Address <= RootBridge->PMemAbove4G.Limit) {
> +    *Translation = RootBridge->PMemAbove4G.Translation;
> +  } else {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
>   /**
>     Polls an address in memory mapped I/O space until an exit condition is met,
>     or a timeout occurs.
> @@ -658,13 +691,22 @@ RootBridgeIoMemRead (
>     )
>   {
>     EFI_STATUS                             Status;
> +  PCI_ROOT_BRIDGE_INSTANCE               *RootBridge;
> +  UINT64                                 Translation;
>   
>     Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
>                                          Count, Buffer);
>     if (EFI_ERROR (Status)) {
>       return Status;
>     }
> -  return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
> +
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
> +  Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + Translation, Count, Buffer);
>   }
>   
>   /**
> @@ -705,13 +747,22 @@ RootBridgeIoMemWrite (
>     )
>   {
>     EFI_STATUS                             Status;
> +  PCI_ROOT_BRIDGE_INSTANCE               *RootBridge;
> +  UINT64                                 Translation;
>   
>     Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
>                                          Count, Buffer);
>     if (EFI_ERROR (Status)) {
>       return Status;
>     }
> -  return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
> +
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
> +  Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + Translation, Count, Buffer);
>   }
>   
>   /**
> @@ -746,6 +797,8 @@ RootBridgeIoIoRead (
>     )
>   {
>     EFI_STATUS                                    Status;
> +  PCI_ROOT_BRIDGE_INSTANCE                      *RootBridge;
> +
>     Status = RootBridgeIoCheckParameter (
>                This, IoOperation, Width,
>                Address, Count, Buffer
> @@ -753,7 +806,10 @@ RootBridgeIoIoRead (
>     if (EFI_ERROR (Status)) {
>       return Status;
>     }
> -  return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
> +
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
> +
> +  return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + RootBridge->Io.Translation, Count, Buffer);
>   }
>   
>   /**
> @@ -788,6 +844,8 @@ RootBridgeIoIoWrite (
>     )
>   {
>     EFI_STATUS                                    Status;
> +  PCI_ROOT_BRIDGE_INSTANCE                      *RootBridge;
> +
>     Status = RootBridgeIoCheckParameter (
>                This, IoOperation, Width,
>                Address, Count, Buffer
> @@ -795,7 +853,10 @@ RootBridgeIoIoWrite (
>     if (EFI_ERROR (Status)) {
>       return Status;
>     }
> -  return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
> +
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
> +
> +  return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + RootBridge->Io.Translation, Count, Buffer);
>   }
>   
>   /**
> @@ -1615,25 +1676,41 @@ RootBridgeIoConfiguration (
>   
>       Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
>       Descriptor->Len  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
> +    // According to UEFI 2.7, RootBridgeIo::Configuration should return address
> +    // range in CPU view, and TranslationOffset = PCI view - CPU view.
>       Descriptor->AddrRangeMin  = ResAllocNode->Base;
>       Descriptor->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
>       Descriptor->AddrLen       = ResAllocNode->Length;
>       switch (ResAllocNode->Type) {
>   
>       case TypeIo:
> -      Descriptor->ResType       = ACPI_ADDRESS_SPACE_TYPE_IO;
> +      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_IO;
> +      // According to UEFI 2.7, translation = PCI address - CPU address,
> +      // so we change the sign here to make it consistent with UEFI spec.
> +      // The other translations will be treated as the same.
> +      Descriptor->AddrTranslationOffset = -RootBridge->Io.Translation;
>         break;
>   
>       case TypePMem32:
> -      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
> +      Descriptor->SpecificFlag          = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
> +      Descriptor->AddrTranslationOffset = -RootBridge->PMem.Translation;
> +      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
> +      Descriptor->AddrSpaceGranularity  = 32;
> +      break;
> +
>       case TypeMem32:
> +      Descriptor->AddrTranslationOffset = -RootBridge->Mem.Translation;
>         Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
>         Descriptor->AddrSpaceGranularity  = 32;
>         break;
>   
>       case TypePMem64:
> -      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
> +      Descriptor->SpecificFlag          = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
> +      Descriptor->AddrTranslationOffset = -RootBridge->PMemAbove4G.Translation;
> +      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
> +      Descriptor->AddrSpaceGranularity  = 64;
>       case TypeMem64:
> +      Descriptor->AddrTranslationOffset = -RootBridge->MemAbove4G.Translation;
>         Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
>         Descriptor->AddrSpaceGranularity  = 64;
>         break;
> diff --git a/MdeModulePkg/Include/Library/PciHostBridgeLib.h b/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> index d42e9ec..b9e8c0f 100644
> --- a/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> +++ b/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> @@ -22,6 +22,7 @@
>   typedef struct {
>     UINT64 Base;
>     UINT64 Limit;
> +  UINT64 Translation;
>   } PCI_ROOT_BRIDGE_APERTURE;
>   
>   typedef struct {
> 
Heyi,
The address stored in GCD database should only be in CPU-view.
I think you might improperly add the CPU-view address range to GCD.
Thanks,
Ray

-- 
Thanks,
Ray


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation
  2018-02-22  6:54 ` [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation Heyi Guo
  2018-02-22  8:55   ` Ni, Ruiyu
@ 2018-02-22  8:56   ` Ni, Ruiyu
  2018-02-22  9:43   ` Laszlo Ersek
  2 siblings, 0 replies; 10+ messages in thread
From: Ni, Ruiyu @ 2018-02-22  8:56 UTC (permalink / raw)
  To: Heyi Guo, edk2-devel
  Cc: Ard Biesheuvel, Star Zeng, Eric Dong, Laszlo Ersek,
	Michael D Kinney

On 2/22/2018 2:54 PM, Heyi Guo wrote:
> This is the draft patch for the discussion posted in edk2-devel
> mailing list:
> https://lists.01.org/pipermail/edk2-devel/2017-December/019289.html
> 
> As discussed in the mailing list, we'd like to add support for PCI
> address translation which is necessary for some non-x86 platforms. I
> also want to minimize the changes to the generic host bridge driver
> and platform PciHostBridgeLib implemetations, so additional two
> interfaces are added to expose translation information of the
> platform. To be generic, I add translation for each type of IO or
> memory resources.
> 
> The patch is still a RFC, so I only passed the build for qemu64 and
> the function has not been tested yet.
> 
> Please let me know your comments about it.
> 
> Thanks.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Heyi Guo <heyi.guo@linaro.org>
> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>   .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c       |  57 ++++++++----
>   .../Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c     | 101 ++++++++++++++++++---
>   MdeModulePkg/Include/Library/PciHostBridgeLib.h    |   1 +
>   3 files changed, 131 insertions(+), 28 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> index 1494848..fa22d8d 100644
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> @@ -32,6 +32,29 @@ EDKII_IOMMU_PROTOCOL        *mIoMmuProtocol;
>   EFI_EVENT                   mIoMmuEvent;
>   VOID                        *mIoMmuRegistration;
>   
> +STATIC
> +UINT64
> +GetTranslationByResourceType (
> +  IN  PCI_ROOT_BRIDGE_INSTANCE     *RootBridge,
> +  IN  PCI_RESOURCE_TYPE            ResourceType
> +  )
> +{
> +  switch (ResourceType) {
> +    case TypeIo:
> +      return RootBridge->Io.Translation;
> +    case TypeMem32:
> +      return RootBridge->Mem.Translation;
> +    case TypePMem32:
> +      return RootBridge->PMem.Translation;
> +    case TypeMem64:
> +      return RootBridge->MemAbove4G.Translation;
> +    case TypePMem64:
> +      return RootBridge->PMemAbove4G.Translation;
> +    default:
> +      return 0;
> +  }
> +}
> +
>   /**
>     Ensure the compatibility of an IO space descriptor with the IO aperture.
>   
> @@ -412,7 +435,7 @@ InitializePciHostBridge (
>   
>       if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
>         Status = AddIoSpace (
> -                 RootBridges[Index].Io.Base,
> +                 RootBridges[Index].Io.Base + RootBridges[Index].Io.Translation,
>                    RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
>                    );
>         ASSERT_EFI_ERROR (Status);
> @@ -422,7 +445,7 @@ InitializePciHostBridge (
>                           EfiGcdIoTypeIo,
>                           0,
>                           RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
> -                        &RootBridges[Index].Io.Base,
> +                        &RootBridges[Index].Io.Base + RootBridges[Index].Io.Translation,
>                           gImageHandle,
>                           NULL
>                           );
> @@ -444,13 +467,13 @@ InitializePciHostBridge (
>       for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {
>         if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {
>           Status = AddMemoryMappedIoSpace (
> -                   MemApertures[MemApertureIndex]->Base,
> +                   MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
>                      MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
>                      EFI_MEMORY_UC
>                      );
>           ASSERT_EFI_ERROR (Status);
>           Status = gDS->SetMemorySpaceAttributes (
> -                        MemApertures[MemApertureIndex]->Base,
> +                        MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
>                           MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
>                           EFI_MEMORY_UC
>                           );
> @@ -463,7 +486,7 @@ InitializePciHostBridge (
>                             EfiGcdMemoryTypeMemoryMappedIo,
>                             0,
>                             MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
> -                          &MemApertures[MemApertureIndex]->Base,
> +                          &MemApertures[MemApertureIndex]->Base + MemApertures[MemApertureIndex]->Translation,
>                             gImageHandle,
>                             NULL
>                             );
> @@ -828,8 +851,8 @@ NotifyPhase (
>                               FALSE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (15, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
> -                            RootBridge->Io.Limit
> +                            ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1) + RootBridge->Io.Translation,
> +                            RootBridge->Io.Limit + RootBridge->Io.Translation
>                               );
>               break;
>   
> @@ -838,8 +861,8 @@ NotifyPhase (
>                               TRUE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (63, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
> -                            RootBridge->MemAbove4G.Limit
> +                            ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1) + RootBridge->MemAbove4G.Translation,
> +                            RootBridge->MemAbove4G.Limit + RootBridge->MemAbove4G.Translation
>                               );
>               if (BaseAddress != MAX_UINT64) {
>                 break;
> @@ -853,8 +876,8 @@ NotifyPhase (
>                               TRUE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (31, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
> -                            RootBridge->Mem.Limit
> +                            ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1) + RootBridge->Mem.Translation,
> +                            RootBridge->Mem.Limit + RootBridge->Mem.Translation
>                               );
>               break;
>   
> @@ -863,8 +886,8 @@ NotifyPhase (
>                               TRUE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (63, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
> -                            RootBridge->PMemAbove4G.Limit
> +                            ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1) + RootBridge->PMemAbove4G.Translation,
> +                            RootBridge->PMemAbove4G.Limit + RootBridge->PMemAbove4G.Translation
>                               );
>               if (BaseAddress != MAX_UINT64) {
>                 break;
> @@ -877,8 +900,8 @@ NotifyPhase (
>                               TRUE,
>                               RootBridge->ResAllocNode[Index].Length,
>                               MIN (31, BitsOfAlignment),
> -                            ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
> -                            RootBridge->PMem.Limit
> +                            ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1) + RootBridge->PMem.Translation,
> +                            RootBridge->PMem.Limit + RootBridge->PMem.Translation
>                               );
>               break;
>   
> @@ -1152,6 +1175,7 @@ StartBusEnumeration (
>         Descriptor->AddrSpaceGranularity  = 0;
>         Descriptor->AddrRangeMin          = RootBridge->Bus.Base;
>         Descriptor->AddrRangeMax          = 0;
> +      // Ignore translation offset for bus
>         Descriptor->AddrTranslationOffset = 0;
>         Descriptor->AddrLen               = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;
>   
> @@ -1421,7 +1445,8 @@ GetProposedResources (
>             Descriptor->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
>             Descriptor->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;
>             Descriptor->GenFlag               = 0;
> -          Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base;
> +          Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base -
> +              GetTranslationByResourceType (RootBridge, Index);
>             Descriptor->AddrRangeMax          = 0;
>             Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;
>             Descriptor->AddrLen               = RootBridge->ResAllocNode[Index].Length;
> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> index dc06c16..bd3394a 100644
> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> @@ -86,12 +86,23 @@ CreateRootBridge (
>             (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",
>             (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""
>             ));
> +  // We don't see any scenario for bus translation, so translation for bus is just ignored.
>     DEBUG ((EFI_D_INFO, "           Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit));
> -  DEBUG ((EFI_D_INFO, "            Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit));
> -  DEBUG ((EFI_D_INFO, "           Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit));
> -  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 ((DEBUG_INFO, "            Io: %lx - %lx translation=%lx\n",
> +          Bridge->Io.Base, Bridge->Io.Limit, Bridge->Io.Translation
> +          ));
> +  DEBUG ((DEBUG_INFO, "           Mem: %lx - %lx translation=%lx\n",
> +          Bridge->Mem.Base, Bridge->Mem.Limit, Bridge->Mem.Translation
> +          ));
> +  DEBUG ((DEBUG_INFO, "    MemAbove4G: %lx - %lx translation=%lx\n",
> +          Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit, Bridge->MemAbove4G.Translation
> +          ));
> +  DEBUG ((DEBUG_INFO, "          PMem: %lx - %lx translation=%lx\n",
> +          Bridge->PMem.Base, Bridge->PMem.Limit, Bridge->PMem.Translation
> +          ));
> +  DEBUG ((DEBUG_INFO, "   PMemAbove4G: %lx - %lx translation=%lx\n",
> +          Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit, Bridge->PMemAbove4G.Translation
> +          ));
>   
>     //
>     // Make sure Mem and MemAbove4G apertures are valid
> @@ -403,6 +414,28 @@ RootBridgeIoCheckParameter (
>     return EFI_SUCCESS;
>   }
>   
> +EFI_STATUS
> +RootBridgeIoGetMemTranslationByAddress (
> +  IN PCI_ROOT_BRIDGE_INSTANCE               *RootBridge,
> +  IN UINT64                                 Address,
> +  IN OUT UINT64                             *Translation
> +  )
> +{
> +  if (Address >= RootBridge->Mem.Base && Address <= RootBridge->Mem.Limit) {
> +    *Translation = RootBridge->Mem.Translation;
> +  } else if (Address >= RootBridge->PMem.Base && Address <= RootBridge->PMem.Limit) {
> +    *Translation = RootBridge->PMem.Translation;
> +  } else if (Address >= RootBridge->MemAbove4G.Base && Address <= RootBridge->MemAbove4G.Limit) {
> +    *Translation = RootBridge->MemAbove4G.Translation;
> +  } else if (Address >= RootBridge->PMemAbove4G.Base && Address <= RootBridge->PMemAbove4G.Limit) {
> +    *Translation = RootBridge->PMemAbove4G.Translation;
> +  } else {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
>   /**
>     Polls an address in memory mapped I/O space until an exit condition is met,
>     or a timeout occurs.
> @@ -658,13 +691,22 @@ RootBridgeIoMemRead (
>     )
>   {
>     EFI_STATUS                             Status;
> +  PCI_ROOT_BRIDGE_INSTANCE               *RootBridge;
> +  UINT64                                 Translation;
>   
>     Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
>                                          Count, Buffer);
>     if (EFI_ERROR (Status)) {
>       return Status;
>     }
> -  return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
> +
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
> +  Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + Translation, Count, Buffer);
>   }
>   
>   /**
> @@ -705,13 +747,22 @@ RootBridgeIoMemWrite (
>     )
>   {
>     EFI_STATUS                             Status;
> +  PCI_ROOT_BRIDGE_INSTANCE               *RootBridge;
> +  UINT64                                 Translation;
>   
>     Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
>                                          Count, Buffer);
>     if (EFI_ERROR (Status)) {
>       return Status;
>     }
> -  return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
> +
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
> +  Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + Translation, Count, Buffer);
>   }
>   
>   /**
> @@ -746,6 +797,8 @@ RootBridgeIoIoRead (
>     )
>   {
>     EFI_STATUS                                    Status;
> +  PCI_ROOT_BRIDGE_INSTANCE                      *RootBridge;
> +
>     Status = RootBridgeIoCheckParameter (
>                This, IoOperation, Width,
>                Address, Count, Buffer
> @@ -753,7 +806,10 @@ RootBridgeIoIoRead (
>     if (EFI_ERROR (Status)) {
>       return Status;
>     }
> -  return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
> +
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
> +
> +  return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + RootBridge->Io.Translation, Count, Buffer);
>   }
>   
>   /**
> @@ -788,6 +844,8 @@ RootBridgeIoIoWrite (
>     )
>   {
>     EFI_STATUS                                    Status;
> +  PCI_ROOT_BRIDGE_INSTANCE                      *RootBridge;
> +
>     Status = RootBridgeIoCheckParameter (
>                This, IoOperation, Width,
>                Address, Count, Buffer
> @@ -795,7 +853,10 @@ RootBridgeIoIoWrite (
>     if (EFI_ERROR (Status)) {
>       return Status;
>     }
> -  return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);
> +
> +  RootBridge = ROOT_BRIDGE_FROM_THIS (This);
> +
> +  return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + RootBridge->Io.Translation, Count, Buffer);
>   }
>   
>   /**
> @@ -1615,25 +1676,41 @@ RootBridgeIoConfiguration (
>   
>       Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
>       Descriptor->Len  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
> +    // According to UEFI 2.7, RootBridgeIo::Configuration should return address
> +    // range in CPU view, and TranslationOffset = PCI view - CPU view.
>       Descriptor->AddrRangeMin  = ResAllocNode->Base;
>       Descriptor->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
>       Descriptor->AddrLen       = ResAllocNode->Length;
>       switch (ResAllocNode->Type) {
>   
>       case TypeIo:
> -      Descriptor->ResType       = ACPI_ADDRESS_SPACE_TYPE_IO;
> +      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_IO;
> +      // According to UEFI 2.7, translation = PCI address - CPU address,
> +      // so we change the sign here to make it consistent with UEFI spec.
> +      // The other translations will be treated as the same.
> +      Descriptor->AddrTranslationOffset = -RootBridge->Io.Translation;
>         break;
>   
>       case TypePMem32:
> -      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
> +      Descriptor->SpecificFlag          = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
> +      Descriptor->AddrTranslationOffset = -RootBridge->PMem.Translation;
> +      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
> +      Descriptor->AddrSpaceGranularity  = 32;
> +      break;
> +
>       case TypeMem32:
> +      Descriptor->AddrTranslationOffset = -RootBridge->Mem.Translation;
>         Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
>         Descriptor->AddrSpaceGranularity  = 32;
>         break;
>   
>       case TypePMem64:
> -      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
> +      Descriptor->SpecificFlag          = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
> +      Descriptor->AddrTranslationOffset = -RootBridge->PMemAbove4G.Translation;
> +      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
> +      Descriptor->AddrSpaceGranularity  = 64;
>       case TypeMem64:
> +      Descriptor->AddrTranslationOffset = -RootBridge->MemAbove4G.Translation;
>         Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
>         Descriptor->AddrSpaceGranularity  = 64;
>         break;
> diff --git a/MdeModulePkg/Include/Library/PciHostBridgeLib.h b/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> index d42e9ec..b9e8c0f 100644
> --- a/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> +++ b/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> @@ -22,6 +22,7 @@
>   typedef struct {
>     UINT64 Base;
>     UINT64 Limit;
> +  UINT64 Translation;
>   } PCI_ROOT_BRIDGE_APERTURE;
>   
>   typedef struct {
> 
And I think you'd better to add comments in code to clarify whether it's
a PCI-view address or CPU-view address.

-- 
Thanks,
Ray


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation
  2018-02-22  6:54 ` [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation Heyi Guo
  2018-02-22  8:55   ` Ni, Ruiyu
  2018-02-22  8:56   ` Ni, Ruiyu
@ 2018-02-22  9:43   ` Laszlo Ersek
  2 siblings, 0 replies; 10+ messages in thread
From: Laszlo Ersek @ 2018-02-22  9:43 UTC (permalink / raw)
  To: Heyi Guo, edk2-devel
  Cc: Ruiyu Ni, Ard Biesheuvel, Star Zeng, Eric Dong, Michael D Kinney

Hello Heyi,

On 02/22/18 07:54, Heyi Guo wrote:
> This is the draft patch for the discussion posted in edk2-devel
> mailing list:
> https://lists.01.org/pipermail/edk2-devel/2017-December/019289.html
> 
> As discussed in the mailing list, we'd like to add support for PCI
> address translation which is necessary for some non-x86 platforms. I
> also want to minimize the changes to the generic host bridge driver
> and platform PciHostBridgeLib implemetations, so additional two
> interfaces are added to expose translation information of the
> platform. To be generic, I add translation for each type of IO or
> memory resources.
> 
> The patch is still a RFC, so I only passed the build for qemu64 and
> the function has not been tested yet.
> 
> Please let me know your comments about it.
> 
> Thanks.

I have two requests here:

(1) In the commit message -- and, as requested by Ray, near the
PCI_ROOT_BRIDGE_APERTURE typedef too --, please document the *exact*
mathematical formula that defines how the translation is supposed to work:

  DeviceAddress = HostAddress + AddressTranslationOffset

versus

  HostAddress = DeviceAddress + AddressTranslationOffset

We've have a whole lot of discussion around that, both on this list and
on the PIWG and/or USWG lists, and it's still unclear to me.

The last discussion I recall (that I was involved in) starts here:

  [edk2] [PATCH] MdeModulePkg/PciBusDxe: GetBarAttributes() returns Host
                 address
  https://lists.01.org/pipermail/edk2-devel/2017-September/014425.html

Due to our (apparently!) collective confusion in that thread, Ray
decided back then not to change the code at all.

So, have we cleared up the confusion? Do we have an agreement on what
formula to use? Is the formula consistent with the UEFI spec?

Reviewing the (more recent, December 2017) thread that you link in the
commit message (which I apparently didn't participate in, apologies), I
find the following message from Ray:

https://lists.01.org/pipermail/edk2-devel/2017-December/019335.html

> And further more, there was a discussion in the mailing list
> regarding how to utilize the Offset. There was 2 points
> about the meaning of Offset and we cannot agree with each
> other. Spec is not quite clear.
> 1. Offset = Host - Device
> 2. Offset = Device - Host

Based on your followup to that,
<https://lists.01.org/pipermail/edk2-devel/2017-December/019341.html>,
it looks like you picked #1, or in other words,

  HostAddress = DeviceAddress + AddressTranslationOffset

To quote Ray again from the September 2017 thread, 'Your understanding
to "apply to" is "add", my understanding is "minus"'.

So, if we go with this approach, please quote the
EFI_PCI_IO_PROTOCOL.GetBarAttributes() language from the UEFI 2.7 spec
in the code, and explicitly define "apply" as *subtract*:

    "Translation Offset. Offset to apply to the Starting
    address of a BAR to convert it to a PCI address"

    with "apply" defined as "subtract"; in other words

    DeviceAddress = HostAddress - AddressTranslationOffset

> diff --git a/MdeModulePkg/Include/Library/PciHostBridgeLib.h b/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> index d42e9ec..b9e8c0f 100644
> --- a/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> +++ b/MdeModulePkg/Include/Library/PciHostBridgeLib.h
> @@ -22,6 +22,7 @@
>  typedef struct {
>    UINT64 Base;
>    UINT64 Limit;
> +  UINT64 Translation;
>  } PCI_ROOT_BRIDGE_APERTURE;
>  
>  typedef struct {
> 

(2) My second request is that you please audit all uses of
PCI_ROOT_BRIDGE_APERTURE and PCI_ROOT_BRIDGE in the edk2 tree. For example:

(2a) "ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c" is
fine, it needs no updates. It uses

STATIC PCI_ROOT_BRIDGE mRootBridge;

so the new Translation field will be zero, in all the aperture fields. OK.

(2b) However, under "OvmfPkg/Library/PciHostBridgeLib", several updates
are needed. This library instance behaves differently on Xen vs. QEMU,
and both branches need fixes.

The InitRootBridge() function needs no change, because it calls
ZeroMem(), in order to "Be safe if other fields are added to
PCI_ROOT_BRIDGE later". OK.

There's also a global variable called "mNonExistAperture" where the
Translation field will be initialized to zero, implicitly. So that's OK too.

However, both the QEMU and the Xen code use *local variables* of type
PCI_ROOT_BRIDGE_APERTURE:

- in PciHostBridgeGetRootBridges(): Io, Mem, MemAbove4G
- in ScanForRootBridges(): Io, Mem, MemAbove4G, PMem, PMemAbove4G

The Translation field in all of these local structs would be
indeterminate, and then that would be copied into the PCI_ROOT_BRIDGE
object(s) exposed by PciHostBridgeGetRootBridges().

So, please zero out all of these local structs (with ZeroMem()) in their
respective functions, before they are populated member-wise. (Note that
in ScanForRootBridges(), the zeroing should occur at the top of the loop
body, replacing the manual zeroing of the .Limit fields.)

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC v2 0/2] Add translation support to generic PCIHostBridge
  2018-02-22  6:54 [RFC v2 0/2] Add translation support to generic PCIHostBridge Heyi Guo
  2018-02-22  6:54 ` [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation Heyi Guo
  2018-02-22  6:54 ` [RFC v2 2/2] MdeModulePkg/PciBus: return CPU address for GetBarAttributes Heyi Guo
@ 2018-02-22 10:06 ` Laszlo Ersek
  2018-02-22 10:32   ` Guo Heyi
  2 siblings, 1 reply; 10+ messages in thread
From: Laszlo Ersek @ 2018-02-22 10:06 UTC (permalink / raw)
  To: Heyi Guo, edk2-devel
  Cc: Ruiyu Ni, Ard Biesheuvel, Star Zeng, Eric Dong, Michael D Kinney

On 02/22/18 07:54, Heyi Guo wrote:
> v2:
> Changs are made according to the discussion on the mailing list, including:
> 
> 1. PciRootBridgeIo->Configuration should return CPU view address, as well as
> PciIo->GetBarAttributes, and Translation Offset should be equal to PCI view
> address - CPU view address.

> 3. PciHostBridge driver internally used Base Address is still based on PCI view
> address, and translation offset = CPU view - PCI view, which follows the
> definition in ACPI, and not the same as that in UEFI spec.

I find these opposite interpretations incredibly confusing. My review
for v2 1/2, point (1) namely, is likely wrong because of this.

This information absolutely needs to go into the commit message of patch
#1, and also into the code as comments.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC v2 0/2] Add translation support to generic PCIHostBridge
  2018-02-22 10:06 ` [RFC v2 0/2] Add translation support to generic PCIHostBridge Laszlo Ersek
@ 2018-02-22 10:32   ` Guo Heyi
  0 siblings, 0 replies; 10+ messages in thread
From: Guo Heyi @ 2018-02-22 10:32 UTC (permalink / raw)
  To: Laszlo Ersek, Ruiyu Ni
  Cc: Heyi Guo, edk2-devel, Ruiyu Ni, Ard Biesheuvel, Star Zeng,
	Eric Dong, Michael D Kinney

Thanks Ray and Laszlo; I think I'd better refine comments and commit message
first, or it is rather confusing for review.

I'll send v3 ASAP.

Regards,
Gary

On Thu, Feb 22, 2018 at 11:06:13AM +0100, Laszlo Ersek wrote:
> On 02/22/18 07:54, Heyi Guo wrote:
> > v2:
> > Changs are made according to the discussion on the mailing list, including:
> > 
> > 1. PciRootBridgeIo->Configuration should return CPU view address, as well as
> > PciIo->GetBarAttributes, and Translation Offset should be equal to PCI view
> > address - CPU view address.
> 
> > 3. PciHostBridge driver internally used Base Address is still based on PCI view
> > address, and translation offset = CPU view - PCI view, which follows the
> > definition in ACPI, and not the same as that in UEFI spec.
> 
> I find these opposite interpretations incredibly confusing. My review
> for v2 1/2, point (1) namely, is likely wrong because of this.
> 
> This information absolutely needs to go into the commit message of patch
> #1, and also into the code as comments.
> 
> Thanks
> Laszlo


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC v2 2/2] MdeModulePkg/PciBus: return CPU address for GetBarAttributes
  2018-02-22  6:54 ` [RFC v2 2/2] MdeModulePkg/PciBus: return CPU address for GetBarAttributes Heyi Guo
@ 2018-02-22 10:41   ` Laszlo Ersek
  2018-02-23  1:10     ` Guo Heyi
  0 siblings, 1 reply; 10+ messages in thread
From: Laszlo Ersek @ 2018-02-22 10:41 UTC (permalink / raw)
  To: Heyi Guo, edk2-devel
  Cc: Ruiyu Ni, Ard Biesheuvel, Star Zeng, Eric Dong, Michael D Kinney

On 02/22/18 07:54, Heyi Guo wrote:
> PciIo::GetBarAttributes should return CPU view address according to
> UEFI spec 2.7, so we change the implementation to follow the spec.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Heyi Guo <heyi.guo@linaro.org>
> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> 
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
> index 190f4b0..0aafcba 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
> @@ -1814,8 +1814,8 @@ GetMmioAddressTranslationOffset (
>  
>    while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
>      if ((Configuration->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
> -        (Configuration->AddrRangeMin <= AddrRangeMin) &&
> -        (Configuration->AddrRangeMin + Configuration->AddrLen >= AddrRangeMin + AddrLen)
> +        (Configuration->AddrRangeMin + Configuration->AddrTranslationOffset <= AddrRangeMin) &&
> +        (Configuration->AddrRangeMin + Configuration->AddrLen + Configuration->AddrTranslationOffset >= AddrRangeMin + AddrLen)
>          ) {
>        return Configuration->AddrTranslationOffset;
>      }
> @@ -1968,6 +1968,11 @@ PciIoGetBarAttributes (
>          return EFI_UNSUPPORTED;
>        }
>      }
> +
> +    // According to UEFI spec 2.7, we need return CPU view address for PciIo::GetBarAttributes,
> +    // and PCI view = CPU view + translation
> +    Descriptor->AddrRangeMin -= Descriptor->AddrTranslationOffset;
> +    Descriptor->AddrRangeMax -= Descriptor->AddrTranslationOffset;
>    }
>  
>    return EFI_SUCCESS;
> 

According to your blurb -- which should be instead part of the commit
message of patch #1, as discussed before --, we have the following
interpretations:

* internal: host = device + ATO
* external: device = host + ATO

The GetMmioAddressTranslationOffset() change looks correct, because
(according to your blurb) RootBridgeIo->Configuration() returns a host
(CPU) view. Adding the ATO we get the device view, and then we can do
the comparison against the BAR values read from the device. OK.

In PciIoGetBarAttributes(), Descriptor->AddrRangeMin is first set from
PciIoDevice, so it's a device view. I think the subtraction is correct;
the caller will re-add the ATO if it wants to return to the device view.

In PciIoGetBarAttributes(), I think the AddrRangeMax manipulation is
incorrect (possibly due to a preexistent bug in PciBusDxe). Namely,
Descriptor->AddrRangeMax is first set to the Alignment of the BAR, from
PciIoDevice, not the end address of the BAR. In order to output the
value required by the UEFI spec, we have to calculate the end address
using AddrLen. Is that right?

... To repeat myself, I find it extremely hard to reason about this
feature while using different internal and external ATO interpretations.
Can we pick one formula and stick with it everywhere? (I don't insist,
but without it, I don't think I can sensibly review future iterations of
this set.)

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC v2 2/2] MdeModulePkg/PciBus: return CPU address for GetBarAttributes
  2018-02-22 10:41   ` Laszlo Ersek
@ 2018-02-23  1:10     ` Guo Heyi
  0 siblings, 0 replies; 10+ messages in thread
From: Guo Heyi @ 2018-02-23  1:10 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Heyi Guo, edk2-devel, Ruiyu Ni, Ard Biesheuvel, Star Zeng,
	Eric Dong, Michael D Kinney

On Thu, Feb 22, 2018 at 11:41:50AM +0100, Laszlo Ersek wrote:
> On 02/22/18 07:54, Heyi Guo wrote:
> > PciIo::GetBarAttributes should return CPU view address according to
> > UEFI spec 2.7, so we change the implementation to follow the spec.
> > 
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Heyi Guo <heyi.guo@linaro.org>
> > Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > 
> > ---
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 9 +++++++--
> >  1 file changed, 7 insertions(+), 2 deletions(-)
> > 
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
> > index 190f4b0..0aafcba 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
> > @@ -1814,8 +1814,8 @@ GetMmioAddressTranslationOffset (
> >  
> >    while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> >      if ((Configuration->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
> > -        (Configuration->AddrRangeMin <= AddrRangeMin) &&
> > -        (Configuration->AddrRangeMin + Configuration->AddrLen >= AddrRangeMin + AddrLen)
> > +        (Configuration->AddrRangeMin + Configuration->AddrTranslationOffset <= AddrRangeMin) &&
> > +        (Configuration->AddrRangeMin + Configuration->AddrLen + Configuration->AddrTranslationOffset >= AddrRangeMin + AddrLen)
> >          ) {
> >        return Configuration->AddrTranslationOffset;
> >      }
> > @@ -1968,6 +1968,11 @@ PciIoGetBarAttributes (
> >          return EFI_UNSUPPORTED;
> >        }
> >      }
> > +
> > +    // According to UEFI spec 2.7, we need return CPU view address for PciIo::GetBarAttributes,
> > +    // and PCI view = CPU view + translation
> > +    Descriptor->AddrRangeMin -= Descriptor->AddrTranslationOffset;
> > +    Descriptor->AddrRangeMax -= Descriptor->AddrTranslationOffset;
> >    }
> >  
> >    return EFI_SUCCESS;
> > 
> 
> According to your blurb -- which should be instead part of the commit
> message of patch #1, as discussed before --, we have the following
> interpretations:
> 
> * internal: host = device + ATO
> * external: device = host + ATO
> 
> The GetMmioAddressTranslationOffset() change looks correct, because
> (according to your blurb) RootBridgeIo->Configuration() returns a host
> (CPU) view. Adding the ATO we get the device view, and then we can do
> the comparison against the BAR values read from the device. OK.
> 
> In PciIoGetBarAttributes(), Descriptor->AddrRangeMin is first set from
> PciIoDevice, so it's a device view. I think the subtraction is correct;
> the caller will re-add the ATO if it wants to return to the device view.
> 
> In PciIoGetBarAttributes(), I think the AddrRangeMax manipulation is
> incorrect (possibly due to a preexistent bug in PciBusDxe). Namely,
> Descriptor->AddrRangeMax is first set to the Alignment of the BAR, from
> PciIoDevice, not the end address of the BAR. In order to output the
> value required by the UEFI spec, we have to calculate the end address
> using AddrLen. Is that right?

Will double check what it really is.

> 
> ... To repeat myself, I find it extremely hard to reason about this
> feature while using different internal and external ATO interpretations.
> Can we pick one formula and stick with it everywhere? (I don't insist,
> but without it, I don't think I can sensibly review future iterations of
> this set.)

I made the patch according to the conclusion here:
https://lists.01.org/pipermail/edk2-devel/2018-February/020960.html
if I understood that correctly :)

However, if it turns out so confusing in the code, especially to someone who
didn't participate in the discussions, I agree it may worth keeping all the
definitions consistent in EDK2 code, while being different from what in ACPI ASL
code.

Thanks,

Gary (Heyi Guo)

> 
> Thanks
> Laszlo


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-02-23  1:04 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-22  6:54 [RFC v2 0/2] Add translation support to generic PCIHostBridge Heyi Guo
2018-02-22  6:54 ` [RFC v2 1/2] MdeModulePkg/PciHostBridgeDxe: Add support for address translation Heyi Guo
2018-02-22  8:55   ` Ni, Ruiyu
2018-02-22  8:56   ` Ni, Ruiyu
2018-02-22  9:43   ` Laszlo Ersek
2018-02-22  6:54 ` [RFC v2 2/2] MdeModulePkg/PciBus: return CPU address for GetBarAttributes Heyi Guo
2018-02-22 10:41   ` Laszlo Ersek
2018-02-23  1:10     ` Guo Heyi
2018-02-22 10:06 ` [RFC v2 0/2] Add translation support to generic PCIHostBridge Laszlo Ersek
2018-02-22 10:32   ` Guo Heyi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox