From nobody Thu May 2 16:32:29 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1490434136417385.03418077286256; Sat, 25 Mar 2017 02:28:56 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 1076E21DFA7B4; Sat, 25 Mar 2017 02:28:55 -0700 (PDT) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (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 CE58A21DFA7B0 for ; Sat, 25 Mar 2017 02:28:51 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga104.jf.intel.com with ESMTP; 25 Mar 2017 02:28:51 -0700 Received: from jyao1-mobl.ccr.corp.intel.com ([10.254.213.212]) by orsmga003.jf.intel.com with ESMTP; 25 Mar 2017 02:28:50 -0700 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,219,1486454400"; d="scan'208";a="948072134" From: Jiewen Yao To: edk2-devel@lists.01.org Date: Sat, 25 Mar 2017 17:28:40 +0800 Message-Id: <1490434122-16200-2-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1490434122-16200-1-git-send-email-jiewen.yao@intel.com> References: <1490434122-16200-1-git-send-email-jiewen.yao@intel.com> Subject: [edk2] [PATCH 1/3] MdeModulePkg/Include: Add IOMMU protocol definition. 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: , Cc: Ruiyu Ni , Brijesh Singh , Leo Duran MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This protocol is to abstract IOMMU access. Cc: Ruiyu Ni Cc: Leo Duran Cc: Brijesh Singh Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao --- MdeModulePkg/Include/Protocol/IoMmu.h | 132 ++++++++++++++++++++ MdeModulePkg/MdeModulePkg.dec | 3 + 2 files changed, 135 insertions(+) diff --git a/MdeModulePkg/Include/Protocol/IoMmu.h b/MdeModulePkg/Include/P= rotocol/IoMmu.h new file mode 100644 index 0000000..55b9c78 --- /dev/null +++ b/MdeModulePkg/Include/Protocol/IoMmu.h @@ -0,0 +1,132 @@ +/** @file + EFI IOMMU Protocol. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made availabl= e under +the terms and conditions of the BSD License that accompanies this distribu= tion. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + + +#ifndef __IOMMU_H__ +#define __IOMMU_H__ + +// +// IOMMU Protocol GUID value +// +#define EDKII_IOMMU_PROTOCOL_GUID \ + { \ + 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed, 0xe6, 0xe1, 0xce, 0x51, 0x= 7c, 0x1e } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EDKII_IOMMU_PROTOCOL EDKII_IOMMU_PROTOCOL; + +// +// Revision The revision to which the IOMMU interface adheres. +// All future revisions must be backwards compatible. +// If a future version is not back wards compatible it is not the= same GUID. +// +#define EDKII_IOMMU_PROTOCOL_REVISION 0x00010000 + +// +// IOMMU attribute. +// These types can be "ORed" together as needed. +// Any undefined bits are reserved and must be zero. +// +#define EDKII_IOMMU_ATTRIBUTE_READ 0x1 +#define EDKII_IOMMU_ATTRIBUTE_WRITE 0x2 + +/** + Set IOMMU attribute for a system memory. + + If the IOMMU protocol exists, the system memory cannot be used + for DMA by default. + + When a device requests a DMA access for a system memory, + the device driver need use SetAttribute() to update the IOMMU + attribute to request DMA access (read and/or write). + + The DeviceHandle is used to identify which device it is. + The IOMMU implementation need translate the device path to an IOMMU devi= ce ID, + and set IOMMU hardware register accordingly. + 1) DeviceHandle can be a standard PCI device. + The memory for BusMasterRead need set EDKII_IOMMU_ATTRIBUTE_READ. + The memory for BusMasterWrite need set EDKII_IOMMU_ATTRIBUTE_WRITE. + The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ATTRIBUTE_R= EAD|EDKII_IOMMU_ATTRIBUTE_WRITE. + After the memory is used, the memory need set 0 to keep it being prot= ected. + 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc). + The memory for DMA access need set EDKII_IOMMU_ATTRIBUTE_READ and/or = EDKII_IOMMU_ATTRIBUTE_WRITE. + + @param This The protocol instance pointer. + @param DeviceHandle The device who initiates the DMA access reques= t. + @param BaseAddress The base of system memory address to be used a= s the DMA memory. + @param Length The length of system memory address to be used= as the DMA memory. + @param IoMmuAttribute The IOMMU attribute. + + @retval EFI_SUCCESS The IoMmuAttribute is set for the memory = range specified by BaseAddress and Length. + @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle. + @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne= d. + @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned. + @retval EFI_INVALID_PARAMETER Length is 0. + @retval EFI_INVALID_PARAMETER IoMmuAttribute specified an illegal combi= nation of attributes. + @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU. + @retval EFI_UNSUPPORTED The bit mask of IoMmuAttribute is not sup= ported by the IOMMU. + @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran= ge specified by BaseAddress and Length. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available = to modify the IOMMU attribute. + @retval EFI_DEVICE_ERROR The IOMMU device reported an error while = attempting the operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_IOMMU_SET_ATTRIBUTE)( + IN EDKII_IOMMU_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN UINT64 BaseAddress, + IN UINT64 Length, + IN UINT64 IoMmuAttribute + ); + +/** + Get IOMMU page size. + + This is the minimal supported page size for a IOMMU. + For example, if an IOMMU supports 4KiB, 2MiB and 1GiB, + 4KiB should be returned. + + @param This Protocol instance pointer. + @param PageSize The minimal supported page size for a IOMMU. + + @retval EFI_SUCCESS The page size is returned. + @retval EFI_INVALID_PARAMETER PageSize is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_IOMMU_GET_PAGE_SIZE)( + IN EDKII_IOMMU_PROTOCOL *This, + OUT UINTN *PageSize + ); + +/// +/// IOMMU Protocol structure. +/// +struct _EDKII_IOMMU_PROTOCOL { + UINT64 Revision; + EDKII_IOMMU_GET_PAGE_SIZE GetPageSize; + EDKII_IOMMU_SET_ATTRIBUTE SetAttribute; +}; + +/// +/// IOMMU Protocol GUID variable. +/// +extern EFI_GUID gEdkiiIoMmuProtocolGuid; + +#endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 356b3e1..db596b6 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -540,6 +540,9 @@ ## Include/Protocol/NonDiscoverableDevice.h gEdkiiNonDiscoverableDeviceProtocolGuid =3D { 0x0d51905b, 0xb77e, 0x452a= , {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } } =20 + ## Include/Protocol/IoMmu.h + gEdkiiIoMmuProtocolGuid =3D { 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed, = 0xe6, 0xe1, 0xce, 0x51, 0x7c, 0x1e } } + # # [Error.gEfiMdeModulePkgTokenSpaceGuid] # 0x80000001 | Invalid value provided. --=20 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel From nobody Thu May 2 16:32:29 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1490434138318297.44068916392894; Sat, 25 Mar 2017 02:28:58 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 4239F21DFA916; Sat, 25 Mar 2017 02:28:55 -0700 (PDT) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (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 31BC321DFA7B4 for ; Sat, 25 Mar 2017 02:28:53 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga104.jf.intel.com with ESMTP; 25 Mar 2017 02:28:53 -0700 Received: from jyao1-mobl.ccr.corp.intel.com ([10.254.213.212]) by orsmga003.jf.intel.com with ESMTP; 25 Mar 2017 02:28:51 -0700 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,219,1486454400"; d="scan'208";a="948072138" From: Jiewen Yao To: edk2-devel@lists.01.org Date: Sat, 25 Mar 2017 17:28:41 +0800 Message-Id: <1490434122-16200-3-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1490434122-16200-1-git-send-email-jiewen.yao@intel.com> References: <1490434122-16200-1-git-send-email-jiewen.yao@intel.com> Subject: [edk2] [RFC] [PATCH 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: , Cc: Ruiyu Ni , Brijesh Singh , Leo Duran MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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. 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 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 | 7 + MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 172 +++++++++= ++++++++++- 4 files changed, 178 insertions(+), 5 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeMod= ulePkg/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" }; =20 +EDKII_IOMMU_PROTOCOL *gIoMmuProtocol; +UINTN mIoMmuPageSize =3D 1; + /** Ensure the compatibility of an IO space descriptor with the IO aperture. =20 diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf b/M= deModulePkg/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 =20 [Depex] gEfiCpuIo2ProtocolGuid AND diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h b/MdeMod= ulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h index 13185b4..4d21d10 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,6 +51,8 @@ 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; } MAP_INFO; @@ -575,4 +578,8 @@ RootBridgeIoConfiguration ( =20 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/MdeM= odulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c index 8af131b..47ea697 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c @@ -1022,6 +1022,121 @@ RootBridgeIoPciWrite ( } =20 /** + Allocates one or more 4KB pages of a certain memory type at a specified = 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 sa= tisfy the request, then + NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + 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 allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = 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 than = 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 ov= erflow. + // + ASSERT (RealPages > Pages); + + Memory =3D *Address; + Status =3D gBS->AllocatePages (Type, MemoryType, RealPages, &M= emory); + 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_T= O_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 ALIGN_VALUE(Value, Alignment)) { + return FALSE; + } else { + return FALSE; + } +} + +/** Provides the PCI controller-specific address needed to access system memory for DMA. =20 @@ -1057,6 +1172,8 @@ RootBridgeIoMap ( PCI_ROOT_BRIDGE_INSTANCE *RootBridge; EFI_PHYSICAL_ADDRESS PhysicalAddress; MAP_INFO *MapInfo; + BOOLEAN NeedMap; + EFI_PHYSICAL_ADDRESS MaxAddress; =20 if (HostAddress =3D=3D NULL || NumberOfBytes =3D=3D NULL || DeviceAddres= s =3D=3D NULL || Mapping =3D=3D NULL) { @@ -1072,12 +1189,40 @@ RootBridgeIoMap ( =20 RootBridge =3D ROOT_BRIDGE_FROM_THIS (This); =20 + 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; + + NeedMap =3D FALSE; + MaxAddress =3D (UINT64)-1; + 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) { =20 // // If the root bridge or the device cannot handle performing DMA above @@ -1113,15 +1258,18 @@ RootBridgeIoMap ( MapInfo->NumberOfBytes =3D *NumberOfBytes; MapInfo->NumberOfPages =3D EFI_SIZE_TO_PAGES (MapInfo->NumberOfByt= es); 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->MappedNum= berOfBytes); =20 // // Allocate a buffer below 4GB to map the transfer to. // - Status =3D gBS->AllocatePages ( + Status =3D InternalAllocateAlignedPagesWithAllocateType ( AllocateMaxAddress, EfiBootServicesData, - MapInfo->NumberOfPages, + MapInfo->MappedNumberOfPages, + mIoMmuPageSize, &MapInfo->MappedHostAddress ); if (EFI_ERROR (Status)) { @@ -1240,7 +1388,7 @@ RootBridgeIoUnmap ( // // 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; } @@ -1286,6 +1434,7 @@ RootBridgeIoAllocateBuffer ( EFI_PHYSICAL_ADDRESS PhysicalAddress; PCI_ROOT_BRIDGE_INSTANCE *RootBridge; EFI_ALLOCATE_TYPE AllocateType; + UINTN Size; =20 // // Validate Attributes @@ -1321,10 +1470,16 @@ RootBridgeIoAllocateBuffer ( AllocateType =3D AllocateMaxAddress; PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1); } - Status =3D gBS->AllocatePages ( + 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 ( AllocateType, MemoryType, Pages, + mIoMmuPageSize, &PhysicalAddress ); if (!EFI_ERROR (Status)) { @@ -1356,6 +1511,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= ); } =20 --=20 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel From nobody Thu May 2 16:32:29 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1490434140883338.79532368933087; Sat, 25 Mar 2017 02:29:00 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 7B1E021DFA7B8; Sat, 25 Mar 2017 02:28:57 -0700 (PDT) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (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 841F221DFA7B1 for ; Sat, 25 Mar 2017 02:28:54 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga104.jf.intel.com with ESMTP; 25 Mar 2017 02:28:54 -0700 Received: from jyao1-mobl.ccr.corp.intel.com ([10.254.213.212]) by orsmga003.jf.intel.com with ESMTP; 25 Mar 2017 02:28:53 -0700 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,219,1486454400"; d="scan'208";a="948072143" From: Jiewen Yao To: edk2-devel@lists.01.org Date: Sat, 25 Mar 2017 17:28:42 +0800 Message-Id: <1490434122-16200-4-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1490434122-16200-1-git-send-email-jiewen.yao@intel.com> References: <1490434122-16200-1-git-send-email-jiewen.yao@intel.com> Subject: [edk2] [RFC] [PATCH 3/3] MdeModulePkg/PciBus: 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: , Cc: Ruiyu Ni , Brijesh Singh , Leo Duran MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The responsibility of PciBus driver is to set IOMMU attribute, because only PciBus knows which device submits DMA access request. PciBus driver assumes that PciHostBridge driver can allocate IOMMU page aligned memory, if IOMMU protocol exists. Cc: Ruiyu Ni Cc: Leo Duran Cc: Brijesh Singh Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c | 12 +++ MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 10 ++ MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 100 ++++++++++++++++++++ 4 files changed, 123 insertions(+) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.c index f3be47a..c9ee4de 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c @@ -42,6 +42,8 @@ UINT64 gAllZero = =3D 0; =20 EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol; +EDKII_IOMMU_PROTOCOL *gIoMmuProtocol; +UINTN mIoMmuPageSize =3D 1; =20 =20 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlug= Request =3D { @@ -256,6 +258,16 @@ PciBusDriverBindingStart ( } =20 gBS->LocateProtocol ( + &gEdkiiIoMmuProtocolGuid, + NULL, + (VOID **) &gIoMmuProtocol + ); + if (gIoMmuProtocol !=3D NULL) { + gIoMmuProtocol->GetPageSize (gIoMmuProtocol, &mIoMmuPageSize); + ASSERT ((mIoMmuPageSize & (mIoMmuPageSize - 1)) =3D=3D 0); + } + + gBS->LocateProtocol ( &gEfiIncompatiblePciDeviceSupportProtocolGuid, NULL, (VOID **) &gIncompatiblePciDeviceSupport diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 39ba8b9..6f96696 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -32,6 +32,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. #include #include #include +#include =20 #include #include @@ -304,6 +305,13 @@ struct _PCI_IO_DEVICE { CR (a, PCI_IO_DEVICE, LoadFile2, PCI_IO_DEVICE_SIGNATURE) =20 =20 +#define PCI_IO_MAP_INFO_SIGNATURE SIGNATURE_32 ('p', 'm', 'a', 'p') +typedef struct { + UINT32 Signature; + UINTN NumberOfBytes; + EFI_PHYSICAL_ADDRESS DeviceAddress; + VOID *PciRootBridgeIoMapping; +} PCI_IO_MAP_INFO; =20 // // Global Variables @@ -319,6 +327,8 @@ extern UINT64 gAl= lOne; extern UINT64 gAllZero; extern EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; extern EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol; +extern EDKII_IOMMU_PROTOCOL *gIoMmuProtocol; +extern UINTN mIoMmuPageSize; extern BOOLEAN mReserveIsaAliases; extern BOOLEAN mReserveVgaAliases; =20 diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bu= s/Pci/PciBusDxe/PciBusDxe.inf index a3ab11f..5da094f 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf @@ -95,6 +95,7 @@ gEfiPciRootBridgeIoProtocolGuid ## TO_START gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_CONSUMES gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES + gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES =20 [FeaturePcd] gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## CON= SUMES diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c b/MdeModulePkg/Bus/Pci/= PciBusDxe/PciIo.c index f72598d..01786c1 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c @@ -967,6 +967,8 @@ PciIoMap ( { EFI_STATUS Status; PCI_IO_DEVICE *PciIoDevice; + PCI_IO_MAP_INFO *PciIoMapInfo; + UINT64 IoMmuAttribute; =20 PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); =20 @@ -999,6 +1001,46 @@ PciIoMap ( ); } =20 + if (gIoMmuProtocol !=3D NULL) { + if (!EFI_ERROR(Status)) { + PciIoMapInfo =3D AllocatePool (sizeof(*PciIoMapInfo)); + if (PciIoMapInfo =3D=3D NULL) { + PciIoDevice->PciRootBridgeIo->Unmap (PciIoDevice->PciRootBridgeIo,= *Mapping); + return EFI_OUT_OF_RESOURCES; + } + + PciIoMapInfo->Signature =3D PCI_IO_MAP_INFO_SIGNATURE; + PciIoMapInfo->NumberOfBytes =3D *NumberOfBytes; + PciIoMapInfo->DeviceAddress =3D *DeviceAddress; + PciIoMapInfo->PciRootBridgeIoMapping =3D *Mapping; + *Mapping =3D PciIoMapInfo; + + switch (Operation) { + case EfiPciIoOperationBusMasterRead: + IoMmuAttribute =3D EDKII_IOMMU_ATTRIBUTE_READ; + break; + case EfiPciIoOperationBusMasterWrite: + IoMmuAttribute =3D EDKII_IOMMU_ATTRIBUTE_WRITE; + break; + case EfiPciIoOperationBusMasterCommonBuffer: + IoMmuAttribute =3D EDKII_IOMMU_ATTRIBUTE_READ | EDKII_IOMMU_ATTRIB= UTE_WRITE; + break; + default: + ASSERT(FALSE); + return Status; + } + // + // PciHostBridge should map IOMMU page aligned HostAddress. + // + gIoMmuProtocol->SetAttribute ( + gIoMmuProtocol, + PciIoDevice->Handle, + PciIoMapInfo->DeviceAddress, + ALIGN_VALUE(PciIoMapInfo->NumberOfBytes, mIoMmuPag= eSize), + IoMmuAttribute + ); + } + } return Status; } =20 @@ -1021,9 +1063,19 @@ PciIoUnmap ( { EFI_STATUS Status; PCI_IO_DEVICE *PciIoDevice; + PCI_IO_MAP_INFO *PciIoMapInfo; =20 PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); =20 + PciIoMapInfo =3D NULL; + if (gIoMmuProtocol !=3D NULL) { + PciIoMapInfo =3D Mapping; + if (PciIoMapInfo->Signature !=3D PCI_IO_MAP_INFO_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + Mapping =3D PciIoMapInfo->PciRootBridgeIoMapping; + } + Status =3D PciIoDevice->PciRootBridgeIo->Unmap ( PciIoDevice->PciRootBridgeIo, Mapping @@ -1037,6 +1089,22 @@ PciIoUnmap ( ); } =20 + if (gIoMmuProtocol !=3D NULL) { + if (!EFI_ERROR(Status)) { + // + // PciHostBridge should map IOMMU page aligned HostAddress. + // + gIoMmuProtocol->SetAttribute ( + gIoMmuProtocol, + PciIoDevice->Handle, + PciIoMapInfo->DeviceAddress, + ALIGN_VALUE(PciIoMapInfo->NumberOfBytes, mIoMmuPag= eSize), + 0 + ); + FreePool (PciIoMapInfo); + } + } + return Status; } =20 @@ -1073,6 +1141,7 @@ PciIoAllocateBuffer ( { EFI_STATUS Status; PCI_IO_DEVICE *PciIoDevice; + UINTN Size; =20 if ((Attributes & (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY= _CACHED))) !=3D 0){ @@ -1102,6 +1171,21 @@ PciIoAllocateBuffer ( ); } =20 + if (gIoMmuProtocol !=3D NULL) { + if (!EFI_ERROR(Status)) { + // + // PciHostBridge should allocate IOMMU page aligned HostAddress. + // + Size =3D EFI_PAGES_TO_SIZE(Pages); + gIoMmuProtocol->SetAttribute ( + gIoMmuProtocol, + PciIoDevice->Handle, + (UINTN)*HostAddress, + ALIGN_VALUE(Size, mIoMmuPageSize), + EDKII_IOMMU_ATTRIBUTE_READ | EDKII_IOMMU_ATTRIBUTE= _WRITE + ); + } + } return Status; } =20 @@ -1127,6 +1211,7 @@ PciIoFreeBuffer ( { EFI_STATUS Status; PCI_IO_DEVICE *PciIoDevice; + UINTN Size; =20 PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); =20 @@ -1144,6 +1229,21 @@ PciIoFreeBuffer ( ); } =20 + if (gIoMmuProtocol !=3D NULL) { + if (!EFI_ERROR(Status)) { + // + // PciHostBridge should allocate IOMMU page aligned HostAddress. + // + Size =3D EFI_PAGES_TO_SIZE(Pages); + gIoMmuProtocol->SetAttribute ( + gIoMmuProtocol, + PciIoDevice->Handle, + (UINTN)HostAddress, + ALIGN_VALUE(Size, mIoMmuPageSize), + 0 + ); + } + } return Status; } =20 --=20 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel