From: Guo Heyi <heyi.guo@linaro.org>
To: "Ni, Ruiyu" <ruiyu.ni@Intel.com>
Cc: Guo Heyi <heyi.guo@linaro.org>,
edk2-devel@lists.01.org,
Ard Biesheuvel <ard.biesheuvel@linaro.org>,
Star Zeng <star.zeng@intel.com>, Eric Dong <eric.dong@intel.com>,
Laszlo Ersek <lersek@redhat.com>,
Michael D Kinney <michael.d.kinney@intel.com>
Subject: Re: [PATCH v5 4/6] MdeModulePkg/PciHostBridgeDxe: Add support for address translation
Date: Wed, 7 Mar 2018 14:01:43 +0800 [thread overview]
Message-ID: <20180307060143.GB91936@SZX1000114654> (raw)
In-Reply-To: <71a21699-a1b3-155a-e743-ee5e6288ce20@Intel.com>
Thanks. Please let me know if any further changes are needed.
Regards,
Heyi
On Wed, Mar 07, 2018 at 12:30:59PM +0800, Ni, Ruiyu wrote:
> On 3/6/2018 10:44 AM, Guo Heyi wrote:
> >Hi Ray,
> >
> >Any comments for v5?
>
> Heyi,
> Some backward compatibility concerns were received from internal production
> teams. Current change will cause silent failure on old platforms because
> TranslationOffset might be random if uninitialized.
> I will solve the concern and then send out updates to you, hopefully by end
> of next week.
>
> >
> >Regards,
> >
> >Heyi
> >
> >On Thu, Mar 01, 2018 at 02:57:22PM +0800, Heyi Guo wrote:
> >>PCI address translation is necessary for some non-x86 platforms. On
> >>such platforms, address value (denoted as "device address" or "address
> >>in PCI view") set to PCI BAR registers in configuration space might be
> >>different from the address which is used by CPU to access the
> >>registers in memory BAR or IO BAR spaces (denoted as "host address" or
> >>"address in CPU view"). The difference between the two addresses is
> >>called "Address Translation Offset" or simply "translation", and can
> >>be represented by "Address Translation Offset" in ACPI QWORD Address
> >>Space Descriptor (Offset 0x1E). However UEFI and ACPI differs on the
> >>definitions of QWORD Address Space Descriptor, and we will follow UEFI
> >>definition on UEFI protocols, such as PCI root bridge IO protocol and
> >>PCI IO protocol. In UEFI 2.7, "Address Translation Offset" is "Offset
> >>to apply to the Starting address to convert it to a PCI address". This
> >>means:
> >>
> >>1. Translation = device address - host address.
> >>
> >>2. PciRootBridgeIo->Configuration should return CPU view address, as
> >>well as PciIo->GetBarAttributes.
> >>
> >>Summary of addresses used in protocol interfaces and internal
> >>implementations:
> >>
> >>1. *Only* the following protocol interfaces assume Address is Device
> >> Address:
> >>(1). PciHostBridgeResourceAllocation.GetProposedResources()
> >> Otherwise PCI bus driver cannot set correct address into PCI
> >> BARs.
> >>(2). PciRootBridgeIo.Mem.Read() and PciRootBridgeIo.Mem.Write()
> >>(3). PciRootBridgeIo.CopyMem()
> >>UEFI and PI spec have clear statements for all other protocol
> >>interfaces about the address type.
> >>
> >>2. Library interfaces and internal implementation:
> >>(1). Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >> It is easy to check whether the address is below 4G or above 4G.
> >>(2). Addresses in PCI_ROOT_BRIDGE_INSTANCE.ResAllocNode are host
> >> address, for they are allocated from GCD.
> >>(3). Address passed to PciHostBridgeResourceConflict is host address,
> >> for it comes from PCI_ROOT_BRIDGE_INSTANCE.ResAllocNode.
> >>
> >>RESTRICTION: to simplify the situation, we require the alignment of
> >>Translation must be larger than any BAR alignment in the same root
> >>bridge, so that resource allocation alignment can be applied to both
> >>device address and host address.
> >>
> >>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>
> >>---
> >>
> >>Notes:
> >> v5:
> >> - Add check for the alignment of Translation against the BAR alignment
> >> [Ray]
> >> - Keep coding style of comments consistent with the context [Ray]
> >> - Comment change for Base in PCI_RES_NODE [Ray]
> >> - Add macros of TO_HOST_ADDRESS and TO_DEVICE_ADDRESS for address type
> >> conversion (After that we can also simply the comments about the
> >> calculation [Ray]
> >> - Add check for bus translation offset in CreateRootBridge(), making
> >> sure it is zero, and unify code logic for all types of resource
> >> after that [Ray]
> >> - Use GetTranslationByResourceType() to simplify the code in
> >> RootBridgeIoConfiguration() (also fix a bug in previous patch
> >> version of missing a break after case TypePMem64) [Ray]
> >> - Commit message refinement [Ray]
> >> v4:
> >> - Add ASSERT (FALSE) to default branch in GetTranslationByResourceType
> >> [Laszlo]
> >> - Fix bug when passing BaseAddress to gDS->AllocateIoSpace and
> >> gDS->AllocateMemorySpace [Laszlo]
> >> - Add comment for applying alignment to both device address and host
> >> address, and add NOTE for the alignment requirement of Translation,
> >> as well as in commit message [Laszlo][Ray]
> >> - Improve indention for the code in CreateRootBridge [Laszlo]
> >> - Improve comment for Translation in PCI_ROOT_BRIDGE_APERTURE
> >> definition [Laszlo]
> >> - Ignore translation of bus in CreateRootBridge
> >> v4:
> >> - Add ASSERT (FALSE) to default branch in GetTranslationByResourceType
> >> [Laszlo]
> >> - Fix bug when passing BaseAddress to gDS->AllocateIoSpace and
> >> gDS->AllocateMemorySpace [Laszlo]
> >> - Add comment for applying alignment to both device address and host
> >> address, and add NOTE for the alignment requirement of Translation,
> >> as well as in commit message [Laszlo][Ray]
> >> - Improve indention for the code in CreateRootBridge [Laszlo]
> >> - Improve comment for Translation in PCI_ROOT_BRIDGE_APERTURE
> >> definition [Laszlo]
> >> - Ignore translation of bus in CreateRootBridge
> >>
> >> MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h | 21 ++++
> >> MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostResource.h | 3 +
> >> MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c | 129 +++++++++++++++++---
> >> MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 118 ++++++++++++++++--
> >> 4 files changed, 245 insertions(+), 26 deletions(-)
> >>
> >>diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
> >>index 9a8ca21f4819..c2791ea5c2a4 100644
> >>--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
> >>+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
> >>@@ -38,6 +38,13 @@ typedef struct {
> >> #define PCI_HOST_BRIDGE_FROM_THIS(a) CR (a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
> >> //
> >>+// Macros to translate device address to host address and vice versa. According
> >>+// to UEFI 2.7, device address = host address + translation offset.
> >>+//
> >>+#define TO_HOST_ADDRESS(DeviceAddress,TranslationOffset) ((DeviceAddress) - (TranslationOffset))
> >>+#define TO_DEVICE_ADDRESS(HostAddress,TranslationOffset) ((HostAddress) + (TranslationOffset))
> >>+
> >>+//
> >> // Driver Entry Point
> >> //
> >> /**
> >>@@ -247,6 +254,20 @@ ResourceConflict (
> >> IN PCI_HOST_BRIDGE_INSTANCE *HostBridge
> >> );
> >>+/**
> >>+ This routine gets translation offset from a root bridge instance by resource type.
> >>+
> >>+ @param RootBridge The Root Bridge Instance for the resources.
> >>+ @param ResourceType The Resource Type of the translation offset.
> >>+
> >>+ @retval The Translation Offset of the specified resource.
> >>+**/
> >>+UINT64
> >>+GetTranslationByResourceType (
> >>+ IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge,
> >>+ IN PCI_RESOURCE_TYPE ResourceType
> >>+ );
> >>+
> >> extern EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
> >> extern EFI_CPU_IO2_PROTOCOL *mCpuIo;
> >> #endif
> >>diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostResource.h b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostResource.h
> >>index 8612c0c3251b..a6c3739db368 100644
> >>--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostResource.h
> >>+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostResource.h
> >>@@ -38,6 +38,9 @@ typedef enum {
> >> typedef struct {
> >> PCI_RESOURCE_TYPE Type;
> >>+ //
> >>+ // Base is a host address
> >>+ //
> >> UINT64 Base;
> >> UINT64 Length;
> >> UINT64 Alignment;
> >>diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> >>index 1494848c3e8c..42ded2855c71 100644
> >>--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> >>+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
> >>@@ -33,6 +33,39 @@ EFI_EVENT mIoMmuEvent;
> >> VOID *mIoMmuRegistration;
> >> /**
> >>+ This routine gets translation offset from a root bridge instance by resource type.
> >>+
> >>+ @param RootBridge The Root Bridge Instance for the resources.
> >>+ @param ResourceType The Resource Type of the translation offset.
> >>+
> >>+ @retval The Translation Offset of the specified resource.
> >>+**/
> >>+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;
> >>+ case TypeBus:
> >>+ return RootBridge->Bus.Translation;
> >>+ default:
> >>+ ASSERT (FALSE);
> >>+ return 0;
> >>+ }
> >>+}
> >>+
> >>+/**
> >> 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
> >>@@ -366,6 +399,7 @@ InitializePciHostBridge (
> >> UINTN MemApertureIndex;
> >> BOOLEAN ResourceAssigned;
> >> LIST_ENTRY *Link;
> >>+ UINT64 HostAddress;
> >> RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
> >> if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
> >>@@ -411,8 +445,15 @@ InitializePciHostBridge (
> >> }
> >> if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
> >>+ //
> >>+ // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >>+ // For GCD resource manipulation, we need to use host address.
> >>+ //
> >>+ HostAddress = TO_HOST_ADDRESS (RootBridges[Index].Io.Base,
> >>+ RootBridges[Index].Io.Translation);
> >>+
> >> Status = AddIoSpace (
> >>- RootBridges[Index].Io.Base,
> >>+ HostAddress,
> >> RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
> >> );
> >> ASSERT_EFI_ERROR (Status);
> >>@@ -422,7 +463,7 @@ InitializePciHostBridge (
> >> EfiGcdIoTypeIo,
> >> 0,
> >> RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
> >>- &RootBridges[Index].Io.Base,
> >>+ &HostAddress,
> >> gImageHandle,
> >> NULL
> >> );
> >>@@ -443,14 +484,20 @@ InitializePciHostBridge (
> >> for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {
> >> if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {
> >>+ //
> >>+ // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >>+ // For GCD resource manipulation, we need to use host address.
> >>+ //
> >>+ HostAddress = TO_HOST_ADDRESS (MemApertures[MemApertureIndex]->Base,
> >>+ MemApertures[MemApertureIndex]->Translation);
> >> Status = AddMemoryMappedIoSpace (
> >>- MemApertures[MemApertureIndex]->Base,
> >>+ HostAddress,
> >> MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
> >> EFI_MEMORY_UC
> >> );
> >> ASSERT_EFI_ERROR (Status);
> >> Status = gDS->SetMemorySpaceAttributes (
> >>- MemApertures[MemApertureIndex]->Base,
> >>+ HostAddress,
> >> MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
> >> EFI_MEMORY_UC
> >> );
> >>@@ -463,7 +510,7 @@ InitializePciHostBridge (
> >> EfiGcdMemoryTypeMemoryMappedIo,
> >> 0,
> >> MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
> >>- &MemApertures[MemApertureIndex]->Base,
> >>+ &HostAddress,
> >> gImageHandle,
> >> NULL
> >> );
> >>@@ -654,6 +701,11 @@ AllocateResource (
> >> if (BaseAddress < Limit) {
> >> //
> >> // Have to make sure Aligment is handled since we are doing direct address allocation
> >>+ // Strictly speaking, alignment requirement should be applied to device
> >>+ // address instead of host address which is used in GCD manipulation below,
> >>+ // but as we restrict the alignment of Translation to be larger than any BAR
> >>+ // alignment in the root bridge, we can simplify the situation and consider
> >>+ // the same alignment requirement is also applied to host address.
> >> //
> >> BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));
> >>@@ -721,6 +773,7 @@ NotifyPhase (
> >> PCI_RESOURCE_TYPE Index2;
> >> BOOLEAN ResNodeHandled[TypeMax];
> >> UINT64 MaxAlignment;
> >>+ UINT64 Translation;
> >> HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
> >>@@ -822,14 +875,43 @@ NotifyPhase (
> >> BitsOfAlignment = LowBitSet64 (Alignment + 1);
> >> BaseAddress = MAX_UINT64;
> >>+ //
> >>+ // RESTRICTION: To simplify the situation, we require the alignment of
> >>+ // Translation must be larger than any BAR alignment in the same root
> >>+ // bridge, so that resource allocation alignment can be applied to
> >>+ // both device address and host address.
> >>+ //
> >>+ Translation = GetTranslationByResourceType (RootBridge, Index);
> >>+ if ((Translation & Alignment) != 0) {
> >>+ DEBUG ((DEBUG_ERROR, "[%a:%d] Translation %lx is not aligned to %lx!\n",
> >>+ __FUNCTION__, __LINE__, Translation, Alignment
> >>+ ));
> >>+ ASSERT (FALSE);
> >>+ //
> >>+ // This may be caused by too large alignment or too small
> >>+ // Translation; pick the 1st possibility and return out of resource,
> >>+ // which can also go thru the same process for out of resource
> >>+ // outside the loop.
> >>+ //
> >>+ ReturnStatus = EFI_OUT_OF_RESOURCES;
> >>+ continue;
> >>+ }
> >>+
> >> switch (Index) {
> >> case TypeIo:
> >>+ //
> >>+ // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
> >>+ // For AllocateResource is manipulating GCD resource, we need to use
> >>+ // host address here.
> >>+ //
> >> BaseAddress = AllocateResource (
> >> FALSE,
> >> RootBridge->ResAllocNode[Index].Length,
> >> MIN (15, BitsOfAlignment),
> >>- ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
> >>- RootBridge->Io.Limit
> >>+ TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
> >>+ RootBridge->Io.Translation),
> >>+ TO_HOST_ADDRESS (RootBridge->Io.Limit,
> >>+ RootBridge->Io.Translation)
> >> );
> >> break;
> >>@@ -838,8 +920,10 @@ NotifyPhase (
> >> TRUE,
> >> RootBridge->ResAllocNode[Index].Length,
> >> MIN (63, BitsOfAlignment),
> >>- ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
> >>- RootBridge->MemAbove4G.Limit
> >>+ TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
> >>+ RootBridge->MemAbove4G.Translation),
> >>+ TO_HOST_ADDRESS (RootBridge->MemAbove4G.Limit,
> >>+ RootBridge->MemAbove4G.Translation)
> >> );
> >> if (BaseAddress != MAX_UINT64) {
> >> break;
> >>@@ -853,8 +937,10 @@ NotifyPhase (
> >> TRUE,
> >> RootBridge->ResAllocNode[Index].Length,
> >> MIN (31, BitsOfAlignment),
> >>- ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
> >>- RootBridge->Mem.Limit
> >>+ TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
> >>+ RootBridge->Mem.Translation),
> >>+ TO_HOST_ADDRESS (RootBridge->Mem.Limit,
> >>+ RootBridge->Mem.Translation)
> >> );
> >> break;
> >>@@ -863,8 +949,10 @@ NotifyPhase (
> >> TRUE,
> >> RootBridge->ResAllocNode[Index].Length,
> >> MIN (63, BitsOfAlignment),
> >>- ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
> >>- RootBridge->PMemAbove4G.Limit
> >>+ TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
> >>+ RootBridge->PMemAbove4G.Translation),
> >>+ TO_HOST_ADDRESS (RootBridge->PMemAbove4G.Limit,
> >>+ RootBridge->PMemAbove4G.Translation)
> >> );
> >> if (BaseAddress != MAX_UINT64) {
> >> break;
> >>@@ -877,8 +965,10 @@ NotifyPhase (
> >> TRUE,
> >> RootBridge->ResAllocNode[Index].Length,
> >> MIN (31, BitsOfAlignment),
> >>- ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
> >>- RootBridge->PMem.Limit
> >>+ TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
> >>+ RootBridge->PMem.Translation),
> >>+ TO_HOST_ADDRESS (RootBridge->PMem.Limit,
> >>+ RootBridge->PMem.Translation)
> >> );
> >> break;
> >>@@ -1421,7 +1511,14 @@ 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;
> >>+ //
> >>+ // AddrRangeMin in Resource Descriptor here should be device address
> >>+ // instead of host address, or else PCI bus driver cannot set correct
> >>+ // address into PCI BAR registers.
> >>+ // Base in ResAllocNode is a host address, so conversion is needed.
> >>+ //
> >>+ Descriptor->AddrRangeMin = TO_DEVICE_ADDRESS (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 dc06c16dc038..5dd9d257d46d 100644
> >>--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> >>+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
> >>@@ -86,12 +86,35 @@ 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""
> >> ));
> >>+ //
> >>+ // Translation for bus is not supported.
> >>+ //
> >> 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));
> >>+ ASSERT (Bridge->Bus.Translation == 0);
> >>+ if (Bridge->Bus.Translation != 0) {
> >>+ return NULL;
> >>+ }
> >>+
> >>+ 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
> >>@@ -206,7 +229,12 @@ CreateRootBridge (
> >> }
> >> RootBridge->ResAllocNode[Index].Type = Index;
> >> if (Bridge->ResourceAssigned && (Aperture->Limit >= Aperture->Base)) {
> >>- RootBridge->ResAllocNode[Index].Base = Aperture->Base;
> >>+ //
> >>+ // Base in ResAllocNode is a host address, while Base in Aperture is a
> >>+ // device address.
> >>+ //
> >>+ RootBridge->ResAllocNode[Index].Base = TO_HOST_ADDRESS (Aperture->Base,
> >>+ Aperture->Translation);
> >> RootBridge->ResAllocNode[Index].Length = Aperture->Limit - Aperture->Base + 1;
> >> RootBridge->ResAllocNode[Index].Status = ResAllocated;
> >> } else {
> >>@@ -403,6 +431,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 +708,25 @@ 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;
> >>+ }
> >>+
> >>+ // Address passed to CpuIo->Mem.Read needs to be a host address instead of
> >>+ // device address.
> >>+ return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
> >>+ TO_HOST_ADDRESS (Address, Translation), Count, Buffer);
> >> }
> >> /**
> >>@@ -705,13 +767,25 @@ 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;
> >>+ }
> >>+
> >>+ // Address passed to CpuIo->Mem.Write needs to be a host address instead of
> >>+ // device address.
> >>+ return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
> >>+ TO_HOST_ADDRESS (Address, Translation), Count, Buffer);
> >> }
> >> /**
> >>@@ -746,6 +820,8 @@ RootBridgeIoIoRead (
> >> )
> >> {
> >> EFI_STATUS Status;
> >>+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
> >>+
> >> Status = RootBridgeIoCheckParameter (
> >> This, IoOperation, Width,
> >> Address, Count, Buffer
> >>@@ -753,7 +829,13 @@ 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);
> >>+
> >>+ // Address passed to CpuIo->Io.Read needs to be a host address instead of
> >>+ // device address.
> >>+ return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
> >>+ TO_HOST_ADDRESS (Address, RootBridge->Io.Translation), Count, Buffer);
> >> }
> >> /**
> >>@@ -788,6 +870,8 @@ RootBridgeIoIoWrite (
> >> )
> >> {
> >> EFI_STATUS Status;
> >>+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
> >>+
> >> Status = RootBridgeIoCheckParameter (
> >> This, IoOperation, Width,
> >> Address, Count, Buffer
> >>@@ -795,7 +879,13 @@ 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);
> >>+
> >>+ // Address passed to CpuIo->Io.Write needs to be a host address instead of
> >>+ // device address.
> >>+ return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
> >>+ TO_HOST_ADDRESS (Address, RootBridge->Io.Translation), Count, Buffer);
> >> }
> >> /**
> >>@@ -1615,9 +1705,17 @@ 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 (host address), and ResAllocNode->Base is already a CPU
> >>+ // view address (host address).
> >> Descriptor->AddrRangeMin = ResAllocNode->Base;
> >> Descriptor->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
> >> Descriptor->AddrLen = ResAllocNode->Length;
> >>+ Descriptor->AddrTranslationOffset = GetTranslationByResourceType (
> >>+ RootBridge,
> >>+ ResAllocNode->Type
> >>+ );
> >>+
> >> switch (ResAllocNode->Type) {
> >> case TypeIo:
> >>--
> >>2.7.4
> >>
>
>
> --
> Thanks,
> Ray
next prev parent reply other threads:[~2018-03-07 5:55 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-01 6:57 [PATCH v5 0/6] Add translation support to generic PciHostBridge Heyi Guo
2018-03-01 6:57 ` [PATCH v5 1/6] CorebootPayloadPkg/PciHostBridgeLib: Init PCI aperture to 0 Heyi Guo
2018-03-14 11:24 ` Ard Biesheuvel
2018-03-01 6:57 ` [PATCH v5 2/6] OvmfPkg/PciHostBridgeLib: " Heyi Guo
2018-03-01 10:17 ` Laszlo Ersek
2018-03-01 10:48 ` Guo Heyi
2018-03-02 10:19 ` Laszlo Ersek
2018-03-05 8:23 ` Guo Heyi
2018-03-01 10:20 ` Laszlo Ersek
2018-03-01 10:25 ` Guo Heyi
2018-03-01 12:03 ` Ni, Ruiyu
2018-03-02 10:08 ` Laszlo Ersek
2018-03-01 6:57 ` [PATCH v5 3/6] MdeModulePkg/PciHostBridgeLib.h: add address Translation Heyi Guo
2018-03-01 6:57 ` [PATCH v5 4/6] MdeModulePkg/PciHostBridgeDxe: Add support for address translation Heyi Guo
2018-03-06 2:44 ` Guo Heyi
2018-03-07 4:30 ` Ni, Ruiyu
2018-03-07 6:01 ` Guo Heyi [this message]
2018-03-14 7:57 ` Ni, Ruiyu
2018-03-14 11:25 ` Ard Biesheuvel
2018-03-15 2:57 ` Guo Heyi
2018-03-15 3:25 ` Ni, Ruiyu
2018-03-12 17:18 ` Ard Biesheuvel
2018-03-13 3:00 ` Ni, Ruiyu
2018-03-13 7:31 ` Guo Heyi
2018-03-13 8:04 ` Ard Biesheuvel
2018-03-01 6:57 ` [PATCH v5 5/6] MdeModulePkg/PciBus: convert host address to device address Heyi Guo
2018-03-01 6:57 ` [PATCH v5 6/6] MdeModulePkg/PciBus: return CPU address for GetBarAttributes Heyi Guo
2018-03-01 8:28 ` [PATCH v5 0/6] Add translation support to generic PciHostBridge Ard Biesheuvel
2018-03-15 1:07 ` Ni, Ruiyu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180307060143.GB91936@SZX1000114654 \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox