From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 60E4321A18AA9 for ; Mon, 17 Apr 2017 20:31:48 -0700 (PDT) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Apr 2017 20:31:47 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.37,217,1488873600"; d="scan'208,217";a="90668714" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by fmsmga005.fm.intel.com with ESMTP; 17 Apr 2017 20:31:47 -0700 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 17 Apr 2017 20:31:46 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.246]) by SHSMSX104.ccr.corp.intel.com ([10.239.4.70]) with mapi id 14.03.0319.002; Tue, 18 Apr 2017 11:31:45 +0800 From: "Yao, Jiewen" To: "Duran, Leo" , "edk2-devel@lists.01.org" CC: "Ni, Ruiyu" , "Singh, Brijesh" , Ard Biesheuvel Thread-Topic: [RFC] [PATCH V3 2/3] MdeModulePkg/PciHostBridge: Add IOMMU support. Thread-Index: AQHSt7F9gBdPoH97ykupv6e04IoN1aHKaXyQ Date: Tue, 18 Apr 2017 03:31:44 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503A92D8B6@shsmsx102.ccr.corp.intel.com> References: <1491289579-15888-1-git-send-email-jiewen.yao@intel.com> <1491289579-15888-3-git-send-email-jiewen.yao@intel.com> In-Reply-To: Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 10.0.102.7 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 X-Content-Filtered-By: Mailman/MimeDel 2.1.22 Subject: Re: [RFC] [PATCH V3 2/3] MdeModulePkg/PciHostBridge: Add IOMMU support. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Apr 2017 03:31:48 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Thanks Leo. Answer below: From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Dura= n, Leo Sent: Tuesday, April 18, 2017 3:33 AM To: Yao, Jiewen ; edk2-devel@lists.01.org Cc: Ni, Ruiyu ; Singh, Brijesh ;= Ard Biesheuvel Subject: Re: [edk2] [RFC] [PATCH V3 2/3] MdeModulePkg/PciHostBridge: Add IO= MMU support. Hi Yao, Just a couple of quick comments: 1) gIoMmuProtocol is declared (global) by PciHostBridge.c, but it is not in= itialized to NULL. [Jiewen] Our PECOFF loader zero it. I do not believe it will bring any real= impact. But I agree with you that we can explicit assign to NULL to avoid confusing= . 2) Would it be OK to do a one-time LocateProtocol() of gIoMmuProtocol in I= nitializePciHostBridge()? BTW, besides the global declaration, gIoMmuProtocol is currently not used = by PciHostBridge.c [Jiewen] It is hard, because of dependency. We are not able to guarantee IOMMU driver runs before PciHostBridge. We cannot add dependency for PciHostBridge, because IOMMU is an optional fe= ature. Leo > -----Original Message----- > From: Jiewen Yao [mailto:jiewen.yao@intel.com] > Sent: Tuesday, April 04, 2017 2:06 AM > To: edk2-devel@lists.01.org > Cc: Ruiyu Ni >; Duran, Leo = >; > Singh, Brijesh >; Ard= Biesheuvel > > > Subject: [RFC] [PATCH V3 2/3] MdeModulePkg/PciHostBridge: Add IOMMU > support. > > The responsibility of PciHostBridge is to allocate IOMMU page aligned > memory for Map and AllocateBuffer, because PciHostBridge driver already > handles Map() request to allocate another buffer for DMA read/write. > > If the max address requirement can not be satisfied, PciHostBridge may al= so > allocate any IOMMU page aligned memory and use IOMMU Remapping > feature to map to lower address to satisfy device requirement. > > PciHostBridge does not set IOMMU attribute because it does not know > which device request the DMA. This work is done by PciBus driver. > > Cc: Ruiyu Ni > > Cc: Leo Duran > > Cc: Brijesh Singh > > Cc: Ard Biesheuvel > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Jiewen Yao > > --- > MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c | 3 + > MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf | 1 + > MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h | 8 + > MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 350 > ++++++++++++++++++-- > 4 files changed, 326 insertions(+), 36 deletions(-) > > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c > index 9005dee..35233a7 100644 > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c > @@ -28,6 +28,9 @@ GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 > *mPciResourceTypeStr[] =3D { > L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus" > }; > > +EDKII_IOMMU_PROTOCOL *gIoMmuProtocol; > +UINTN mIoMmuPageSize =3D 1; > + > /** > Ensure the compatibility of an IO space descriptor with the IO apertur= e. > > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf > index d8b0439..2d3c8c9 100644 > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf > @@ -49,6 +49,7 @@ > gEfiDevicePathProtocolGuid ## BY_START > gEfiPciRootBridgeIoProtocolGuid ## BY_START > gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START > + gEdkiiIoMmuProtocolGuid ## CONSUMES > > [Depex] > gEfiCpuIo2ProtocolGuid AND > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h > index 13185b4..77c3490 100644 > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h > @@ -27,6 +27,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY > KIND, EITHER EXPRESS OR IMPLIED. > #include > #include > #include > +#include > #include > #include > #include > @@ -50,8 +51,11 @@ typedef struct { > EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation; > UINTN NumberOfBytes; > UINTN NumberOfPages; > + UINTN MappedNumberOfBytes; > + UINTN MappedNumberOfPages; > EFI_PHYSICAL_ADDRESS HostAddress; > EFI_PHYSICAL_ADDRESS MappedHostAddress; > + BOOLEAN RemapNonExisting; > } MAP_INFO; > #define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, > MAP_INFO_SIGNATURE) > > @@ -575,4 +579,8 @@ RootBridgeIoConfiguration ( > > extern EFI_METRONOME_ARCH_PROTOCOL *mMetronome; > extern EFI_CPU_IO2_PROTOCOL *mCpuIo; > + > +extern EDKII_IOMMU_PROTOCOL *gIoMmuProtocol; > +extern UINTN mIoMmuPageSize; > + > #endif > diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c > b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c > index 8af131b..2a17eb1 100644 > --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c > +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c > @@ -1022,6 +1022,121 @@ RootBridgeIoPciWrite ( } > > /** > + Allocates one or more 4KB pages of a certain memory type at a specifie= d > alignment. > + > + Allocates the number of 4KB pages specified by Pages of a certain > + memory type with an alignment specified by Alignment. The allocated > buffer is returned. If Pages is 0, then NULL is returned. > + If there is not enough memory at the specified alignment remaining to > + satisfy the request, then NULL is returned. > + If Alignment is not a power of two and Alignment is not zero, then > ASSERT(). > + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). > + > + @param Type The type of allocation to perform. > + @param MemoryType The type of memory to allocate. > + @param Pages The number of 4 KB pages to allocate. > + @param Alignment The requested alignment of the allocatio= n. > Must be a power of two. > + If Alignment is zero, then byte alignmen= t is used. > + @param Address Pointer to a physical address. > + > + @return Memory Allocation Status. > + > +**/ > +EFI_STATUS > +InternalAllocateAlignedPagesWithAllocateType ( > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN Pages, > + IN UINTN Alignment, > + IN OUT EFI_PHYSICAL_ADDRESS *Address > + ) > +{ > + EFI_STATUS Status; > + EFI_PHYSICAL_ADDRESS Memory; > + UINTN AlignedMemory; > + UINTN AlignmentMask; > + UINTN UnalignedPages; > + UINTN RealPages; > + > + // > + // Alignment must be a power of two or zero. > + // > + ASSERT ((Alignment & (Alignment - 1)) =3D=3D 0); > + > + if (Pages =3D=3D 0) { > + return EFI_INVALID_PARAMETER; > + } > + if (Alignment > EFI_PAGE_SIZE) { > + // > + // Calculate the total number of pages since alignment is larger tha= n page > size. > + // > + AlignmentMask =3D Alignment - 1; > + RealPages =3D Pages + EFI_SIZE_TO_PAGES (Alignment); > + // > + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not > overflow. > + // > + ASSERT (RealPages > Pages); > + > + Memory =3D *Address; > + Status =3D gBS->AllocatePages (Type, MemoryType, RealPages, > &Memory); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + AlignedMemory =3D ((UINTN) Memory + AlignmentMask) & > ~AlignmentMask; > + UnalignedPages =3D EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) > Memory); > + if (UnalignedPages > 0) { > + // > + // Free first unaligned page(s). > + // > + Status =3D gBS->FreePages (Memory, UnalignedPages); > + ASSERT_EFI_ERROR (Status); > + } > + Memory =3D (EFI_PHYSICAL_ADDRESS) (AlignedMemory + > EFI_PAGES_TO_SIZE (Pages)); > + UnalignedPages =3D RealPages - Pages - UnalignedPages; > + if (UnalignedPages > 0) { > + // > + // Free last unaligned page(s). > + // > + Status =3D gBS->FreePages (Memory, UnalignedPages); > + ASSERT_EFI_ERROR (Status); > + } > + } else { > + // > + // Do not over-allocate pages in this case. > + // > + Memory =3D *Address; > + Status =3D gBS->AllocatePages (Type, MemoryType, Pages, &Memory); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + AlignedMemory =3D (UINTN) Memory; > + } > + *Address =3D AlignedMemory; > + return EFI_SUCCESS; > +} > + > +/** > + Return if a value is aligned. > + > + @param Value the value to be checked > + @param Alignment the alignment to be checked with. > + > + @retval TRUE The value is aligned > + @retval FALSE The value is not aligned. > +**/ > +BOOLEAN > +InternalIsAlgined ( > + IN UINTN Value, > + IN UINTN Alignment > + ) > +{ > + if (Value =3D=3D ALIGN_VALUE(Value, Alignment)) { > + return TRUE; > + } else { > + return FALSE; > + } > +} > + > +/** > Provides the PCI controller-specific address needed to access > system memory for DMA. > > @@ -1057,6 +1172,9 @@ RootBridgeIoMap ( > PCI_ROOT_BRIDGE_INSTANCE *RootBridge; > EFI_PHYSICAL_ADDRESS PhysicalAddress; > MAP_INFO *MapInfo; > + EFI_PHYSICAL_ADDRESS MaxAddress; > + BOOLEAN NeedMap; > + BOOLEAN NeedAllocateNonExist= ing; > > if (HostAddress =3D=3D NULL || NumberOfBytes =3D=3D NULL || DeviceAddr= ess =3D=3D > NULL || > Mapping =3D=3D NULL) { > @@ -1072,13 +1190,41 @@ RootBridgeIoMap ( > > RootBridge =3D ROOT_BRIDGE_FROM_THIS (This); > > + if (gIoMmuProtocol =3D=3D NULL) { > + gBS->LocateProtocol ( > + &gEdkiiIoMmuProtocolGuid, > + NULL, > + (VOID **) &gIoMmuProtocol > + ); > + if (gIoMmuProtocol !=3D NULL) { > + gIoMmuProtocol->GetPageSize (gIoMmuProtocol, &mIoMmuPageSize); > + ASSERT ((mIoMmuPageSize & (mIoMmuPageSize - 1)) =3D=3D 0); > + } > + } > + > PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; > + > + MaxAddress =3D (EFI_PHYSICAL_ADDRESS)-1; NeedMap =3D FALSE; > + NeedAllocateNonExisting =3D FALSE; > + > if ((!RootBridge->DmaAbove4G || > (Operation !=3D EfiPciOperationBusMasterRead64 && > Operation !=3D EfiPciOperationBusMasterWrite64 && > Operation !=3D EfiPciOperationBusMasterCommonBuffer64)) && > ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) { > + NeedMap =3D TRUE; > + MaxAddress =3D SIZE_4GB - 1; > + } > > + if (gIoMmuProtocol !=3D NULL) { > + if ((!InternalIsAlgined (*NumberOfBytes, mIoMmuPageSize)) || > + (!InternalIsAlgined ((UINTN)HostAddress, mIoMmuPageSize))) { > + NeedMap =3D TRUE; > + } > + } > + > + if (NeedMap) { > // > // If the root bridge or the device cannot handle performing DMA abo= ve > // 4GB but any part of the DMA transfer being mapped is above 4GB, t= hen > @@ -1090,9 +1236,17 @@ RootBridgeIoMap ( > // > // Common Buffer operations can not be remapped. If the common > buffer > // if above 4GB, then it is not possible to generate a mapping, so= return > - // an error. > + // an error if there is no IOMMU. > // > - return EFI_UNSUPPORTED; > + if (gIoMmuProtocol =3D=3D NULL) { > + return EFI_UNSUPPORTED; > + } else { > + // > + // We can try to allocate non-existing memory for below 4GiB add= ress > + // and use IOMMU to remap it. > + // > + NeedAllocateNonExisting =3D TRUE; > + } > } > > // > @@ -1113,21 +1267,81 @@ RootBridgeIoMap ( > MapInfo->NumberOfBytes =3D *NumberOfBytes; > MapInfo->NumberOfPages =3D EFI_SIZE_TO_PAGES (MapInfo- > >NumberOfBytes); > MapInfo->HostAddress =3D PhysicalAddress; > - MapInfo->MappedHostAddress =3D SIZE_4GB - 1; > + MapInfo->MappedHostAddress =3D MaxAddress; > + MapInfo->MappedNumberOfBytes =3D ALIGN_VALUE (MapInfo- > >NumberOfBytes, mIoMmuPageSize); > + MapInfo->MappedNumberOfPages =3D EFI_SIZE_TO_PAGES (MapInfo- > >MappedNumberOfBytes); > + MapInfo->RemapNonExisting =3D FALSE; > > - // > - // Allocate a buffer below 4GB to map the transfer to. > - // > - Status =3D gBS->AllocatePages ( > - AllocateMaxAddress, > - EfiBootServicesData, > - MapInfo->NumberOfPages, > - &MapInfo->MappedHostAddress > - ); > - if (EFI_ERROR (Status)) { > - FreePool (MapInfo); > - *NumberOfBytes =3D 0; > - return Status; > + if (!((Operation =3D=3D EfiPciOperationBusMasterCommonBuffer) || > + (Operation =3D=3D EfiPciOperationBusMasterCommonBuffer64))) { > + // > + // Allocate a buffer below 4GB to map the transfer to. > + // > + Status =3D InternalAllocateAlignedPagesWithAllocateType ( > + AllocateMaxAddress, > + EfiBootServicesData, > + MapInfo->MappedNumberOfPages, > + mIoMmuPageSize, > + &MapInfo->MappedHostAddress > + ); > + if (EFI_ERROR (Status)) { > + if (gIoMmuProtocol =3D=3D NULL) { > + FreePool (MapInfo); > + *NumberOfBytes =3D 0; > + return Status; > + } > + // > + // We can try to allocate non-existing memory for below 4GiB add= ress > + // and use IOMMU to remap it. > + // > + NeedAllocateNonExisting =3D TRUE; > + } > + } > + > + if (NeedAllocateNonExisting) { > + if ((!InternalIsAlgined (*NumberOfBytes, mIoMmuPageSize)) || > + (!InternalIsAlgined ((UINTN)HostAddress, mIoMmuPageSize))) { > + // > + // If original memory is not IOMMU aligned, we cannot remap it. > + // > + FreePool (MapInfo); > + *NumberOfBytes =3D 0; > + return EFI_UNSUPPORTED; > + } > + // > + // If the code runs to here, it means: > + // 1) We need remap a common buffer to below 4G non-existing > memory. > + // 2) We need rempa a read/write buffer to below 4G non-existing > memory. > + // > + MapInfo->MappedHostAddress =3D MaxAddress; > + Status =3D gDS->AllocateMemorySpace ( > + EfiGcdAllocateMaxAddressSearchTopDown, > + EfiGcdMemoryTypeNonExistent, > + mIoMmuPageSize, > + MapInfo->MappedNumberOfBytes, > + &MapInfo->MappedHostAddress, > + gImageHandle, > + RootBridge->Handle > + ); > + if (EFI_ERROR(Status)) { > + FreePool (MapInfo); > + *NumberOfBytes =3D 0; > + return Status; > + } > + Status =3D gIoMmuProtocol->SetRemapAddress ( > + gIoMmuProtocol, > + NULL, > + MapInfo->MappedHostAddress, > + (VOID *)(UINTN)MapInfo->HostAddress, > + MapInfo->MappedNumberOfBytes > + ); > + if (EFI_ERROR(Status)) { > + gDS->FreeMemorySpace (MapInfo->MappedHostAddress, MapInfo- > >MappedNumberOfBytes); > + FreePool (MapInfo); > + *NumberOfBytes =3D 0; > + return Status; > + } > + MapInfo->RemapNonExisting =3D TRUE; > } > > // > @@ -1135,19 +1349,26 @@ RootBridgeIoMap ( > // then copy the contents of the real buffer into the mapped buffer > // so the Bus Master can read the contents of the real buffer. > // > - if (Operation =3D=3D EfiPciOperationBusMasterRead || > - Operation =3D=3D EfiPciOperationBusMasterRead64) { > - CopyMem ( > - (VOID *) (UINTN) MapInfo->MappedHostAddress, > - (VOID *) (UINTN) MapInfo->HostAddress, > - MapInfo->NumberOfBytes > - ); > + // This action can be skipped if there is IOMMU, because PciBus does > + // the action after setting IOMMU attributes. > + // > + if (gIoMmuProtocol =3D=3D NULL) { > + if (Operation =3D=3D EfiPciOperationBusMasterRead || > + Operation =3D=3D EfiPciOperationBusMasterRead64) { > + CopyMem ( > + (VOID *) (UINTN) MapInfo->MappedHostAddress, > + (VOID *) (UINTN) MapInfo->HostAddress, > + MapInfo->NumberOfBytes > + ); > + } > } > > InsertTailList (&RootBridge->Maps, &MapInfo->Link); > > // > // The DeviceAddress is the address of the maped buffer below 4GB > + // NOTE: It can be a valid system memory address. > + // Or a non-existing memory but mapped by IOMMU. > // > *DeviceAddress =3D MapInfo->MappedHostAddress; > // > @@ -1228,19 +1449,42 @@ RootBridgeIoUnmap ( > // then copy the contents of the mapped buffer into the real buffer > // so the processor can read the contents of the real buffer. > // > - if (MapInfo->Operation =3D=3D EfiPciOperationBusMasterWrite || > - MapInfo->Operation =3D=3D EfiPciOperationBusMasterWrite64) { > - CopyMem ( > - (VOID *) (UINTN) MapInfo->HostAddress, > - (VOID *) (UINTN) MapInfo->MappedHostAddress, > - MapInfo->NumberOfBytes > - ); > + // This action can be skipped if there is IOMMU, because PciBus does > + // the action. > + // > + if (gIoMmuProtocol =3D=3D NULL) { > + if (MapInfo->Operation =3D=3D EfiPciOperationBusMasterWrite || > + MapInfo->Operation =3D=3D EfiPciOperationBusMasterWrite64) { > + CopyMem ( > + (VOID *) (UINTN) MapInfo->HostAddress, > + (VOID *) (UINTN) MapInfo->MappedHostAddress, > + MapInfo->NumberOfBytes > + ); > + } > + } > + > + if (gIoMmuProtocol !=3D NULL) { > + // > + // Free GCD non existing memory. > + // > + if (MapInfo->RemapNonExisting) { > + gIoMmuProtocol->SetRemapAddress ( > + gIoMmuProtocol, > + NULL, > + MapInfo->MappedHostAddress, > + (VOID *)(UINTN)MapInfo->MappedHostAddress, > + MapInfo->MappedNumberOfBytes > + ); > + gDS->FreeMemorySpace (MapInfo->MappedHostAddress, MapInfo- > >MappedNumberOfBytes); > + FreePool (Mapping); > + return EFI_SUCCESS; > + } > } > > // > // Free the mapped buffer and the MAP_INFO structure. > // > - gBS->FreePages (MapInfo->MappedHostAddress, MapInfo- > >NumberOfPages); > + gBS->FreePages (MapInfo->MappedHostAddress, > + MapInfo->MappedNumberOfPages); > FreePool (Mapping); > return EFI_SUCCESS; > } > @@ -1285,7 +1529,7 @@ RootBridgeIoAllocateBuffer ( > EFI_STATUS Status; > EFI_PHYSICAL_ADDRESS PhysicalAddress; > PCI_ROOT_BRIDGE_INSTANCE *RootBridge; > - EFI_ALLOCATE_TYPE AllocateType; > + UINTN Size; > > // > // Validate Attributes > @@ -1312,25 +1556,52 @@ RootBridgeIoAllocateBuffer ( > > RootBridge =3D ROOT_BRIDGE_FROM_THIS (This); > > - AllocateType =3D AllocateAnyPages; > + PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (-1); > if (!RootBridge->DmaAbove4G || > (Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) =3D=3D 0) { > // > // Limit allocations to memory below 4GB > // > - AllocateType =3D AllocateMaxAddress; > PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1); > } > - Status =3D gBS->AllocatePages ( > - AllocateType, > + if (gIoMmuProtocol !=3D NULL) { > + Size =3D EFI_PAGES_TO_SIZE(Pages); > + Size =3D ALIGN_VALUE(EFI_PAGES_TO_SIZE(Pages), mIoMmuPageSize); > + Pages =3D EFI_SIZE_TO_PAGES (Size); > + } > + Status =3D InternalAllocateAlignedPagesWithAllocateType ( > + AllocateMaxAddress, > MemoryType, > Pages, > + mIoMmuPageSize, > &PhysicalAddress > ); > if (!EFI_ERROR (Status)) { > *HostAddress =3D (VOID *) (UINTN) PhysicalAddress; > + return EFI_SUCCESS; > } > > + if (gIoMmuProtocol !=3D NULL) { > + // > + // Try to allocate AnyAddress here. > + // > + // We can try to allocate non-existing memory for below 4GiB address > + // and use IOMMU to remap it later. > + // > + PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (-1); > + Status =3D InternalAllocateAlignedPagesWithAllocateType ( > + AllocateMaxAddress, > + MemoryType, > + Pages, > + mIoMmuPageSize, > + &PhysicalAddress > + ); > + if (EFI_ERROR(Status)) { > + return Status; > + } > + *HostAddress =3D (VOID *) (UINTN) PhysicalAddress; > + return EFI_SUCCESS; > + } > return Status; > } > > @@ -1356,6 +1627,13 @@ RootBridgeIoFreeBuffer ( > OUT VOID *HostAddress > ) > { > + UINTN Size; > + > + if (gIoMmuProtocol !=3D NULL) { > + Size =3D EFI_PAGES_TO_SIZE(Pages); > + Size =3D ALIGN_VALUE(EFI_PAGES_TO_SIZE(Pages), mIoMmuPageSize); > + Pages =3D EFI_SIZE_TO_PAGES (Size); > + } > return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, > Pages); } > > -- > 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel