From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (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 2355B21A1348C for ; Thu, 4 May 2017 09:34:17 -0700 (PDT) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 May 2017 09:34:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.38,287,1491289200"; d="scan'208";a="97285352" Received: from rhe-mobl1.ccr.corp.intel.com (HELO jyao1-MOBL.ccr.corp.intel.com) ([10.254.211.48]) by fmsmga005.fm.intel.com with ESMTP; 04 May 2017 09:34:15 -0700 From: Jiewen Yao To: edk2-devel@lists.01.org Cc: Ruiyu Ni , Leo Duran , Brijesh Singh , Ard Biesheuvel Date: Fri, 5 May 2017 00:32:40 +0800 Message-Id: <1493915561-8500-3-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1493915561-8500-1-git-send-email-jiewen.yao@intel.com> References: <1493915561-8500-1-git-send-email-jiewen.yao@intel.com> Subject: [PATCH V5 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: Thu, 04 May 2017 16:34:17 -0000 If IOMMU protocol is installed, PciHostBridge just calls IOMMU AllocateBuffer/FreeBuffer/Map/Unmap. PciHostBridge does not set IOMMU access 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 | 37 ++++++++++++ MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf | 2 + MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h | 2 + MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 61 ++++++++++++++++++++ 4 files changed, 102 insertions(+) diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c index 9005dee..70726a6 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c @@ -28,6 +28,10 @@ GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = { L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus" }; +EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; +EFI_EVENT mIoMmuEvent; +VOID *mIoMmuRegistration; + /** Ensure the compatibility of an IO space descriptor with the IO aperture. @@ -313,6 +317,28 @@ FreeMemorySpaceMap: } /** + Event notification that is fired when IOMMU protocol is installed. + + @param Event The Event that is being processed. + @param Context Event Context. + +**/ +VOID +EFIAPI +IoMmuProtocolCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol); + if (!EFI_ERROR(Status)) { + gBS->CloseEvent (mIoMmuEvent); + } +} + +/** Entry point of this driver. @@ -489,6 +515,17 @@ InitializePciHostBridge ( ASSERT_EFI_ERROR (Status); } PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount); + + if (!EFI_ERROR (Status)) { + mIoMmuEvent = EfiCreateProtocolNotifyEvent ( + &gEdkiiIoMmuProtocolGuid, + TPL_CALLBACK, + IoMmuProtocolCallback, + NULL, + &mIoMmuRegistration + ); + } + return Status; } diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf index d8b0439..42bd8a2 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf @@ -41,6 +41,7 @@ BaseMemoryLib BaseLib PciSegmentLib + UefiLib PciHostBridgeLib [Protocols] @@ -49,6 +50,7 @@ gEfiDevicePathProtocolGuid ## BY_START gEfiPciRootBridgeIoProtocolGuid ## BY_START gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START + gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES [Depex] gEfiCpuIo2ProtocolGuid AND diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h index 13185b4..1fec88b 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 @@ -34,6 +35,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include "PciHostResource.h" diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c index 8af131b..068295b 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c @@ -17,6 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "PciRootBridge.h" #include "PciHostResource.h" +extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; + #define NO_MAPPING (VOID *) (UINTN) -1 // @@ -1072,6 +1074,26 @@ RootBridgeIoMap ( RootBridge = ROOT_BRIDGE_FROM_THIS (This); + if (mIoMmuProtocol != NULL) { + if (!RootBridge->DmaAbove4G) { + // + // Clear 64bit support + // + if (Operation > EfiPciOperationBusMasterCommonBuffer) { + Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64); + } + } + Status = mIoMmuProtocol->Map ( + mIoMmuProtocol, + Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + return Status; + } + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; if ((!RootBridge->DmaAbove4G || (Operation != EfiPciOperationBusMasterRead64 && @@ -1194,8 +1216,18 @@ RootBridgeIoUnmap ( MAP_INFO *MapInfo; LIST_ENTRY *Link; PCI_ROOT_BRIDGE_INSTANCE *RootBridge; + EFI_STATUS Status; + + if (mIoMmuProtocol != NULL) { + Status = mIoMmuProtocol->Unmap ( + mIoMmuProtocol, + Mapping + ); + return Status; + } RootBridge = ROOT_BRIDGE_FROM_THIS (This); + // // See if the Map() operation associated with this Unmap() required a mapping // buffer. If a mapping buffer was not required, then this function simply @@ -1312,6 +1344,24 @@ RootBridgeIoAllocateBuffer ( RootBridge = ROOT_BRIDGE_FROM_THIS (This); + if (mIoMmuProtocol != NULL) { + if (!RootBridge->DmaAbove4G) { + // + // Clear DUAL_ADDRESS_CYCLE + // + Attributes &= ~EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE; + } + Status = mIoMmuProtocol->AllocateBuffer ( + mIoMmuProtocol, + Type, + MemoryType, + Pages, + HostAddress, + Attributes + ); + return Status; + } + AllocateType = AllocateAnyPages; if (!RootBridge->DmaAbove4G || (Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) { @@ -1356,6 +1406,17 @@ RootBridgeIoFreeBuffer ( OUT VOID *HostAddress ) { + EFI_STATUS Status; + + if (mIoMmuProtocol != NULL) { + Status = mIoMmuProtocol->FreeBuffer ( + mIoMmuProtocol, + Pages, + HostAddress + ); + return Status; + } + return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages); } -- 2.7.4.windows.1