From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.88; helo=mga01.intel.com; envelope-from=david.wei@intel.com; receiver=edk2-devel@lists.01.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (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 6236F21BADAB3 for ; Mon, 16 Jul 2018 18:38:40 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Jul 2018 18:38:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,363,1526367600"; d="scan'208";a="57032455" Received: from zwei4-mobl1.ccr.corp.intel.com ([10.239.193.155]) by orsmga007.jf.intel.com with ESMTP; 16 Jul 2018 18:37:59 -0700 From: zwei4 To: edk2-devel@lists.01.org Cc: David Wei , Mang Guo Date: Tue, 17 Jul 2018 09:37:48 +0800 Message-Id: <20180717013748.17148-1-david.wei@intel.com> X-Mailer: git-send-email 2.14.1.windows.1 Subject: [Patch][edk2-platforms/devel-IntelAtomProcessorE3900] Enhance Implementation of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 Jul 2018 01:38:40 -0000 Enhance implementation of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL by introducing EDKII_IOMMU_PROTOCOL to support DMA remapping when VT-d is enabled. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: David Wei CC: Mang Guo --- .../NorthCluster/PciHostBridge/Dxe/PciHostBridge.c | 34 +++++++++++ .../PciHostBridge/Dxe/PciHostBridge.inf | 2 + .../NorthCluster/PciHostBridge/Dxe/PciRootBridge.h | 1 + .../PciHostBridge/Dxe/PciRootBridgeIo.c | 71 +++++++++++++++++++--- 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciHostBridge.c b/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciHostBridge.c index 3f7a51d275..2cace7be07 100644 --- a/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciHostBridge.c +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciHostBridge.c @@ -22,6 +22,9 @@ #include #include +EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; +EFI_EVENT mIoMmuEvent; +VOID *mIoMmuRegistration; // // Support 64 K IO space // @@ -75,6 +78,28 @@ static PCI_ROOT_BRIDGE_RESOURCE_APPETURE mResAppeture[1][1] = { {{ 0, 255, 0, 0 static EFI_HANDLE mDriverImageHandle; +/** + 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); + } +} + // // Implementation // @@ -241,6 +266,15 @@ PciHostBridgeEntryPoint ( ASSERT_EFI_ERROR (Status); DEBUG ((EFI_D_INFO, "Successfully changed memory attribute for PCIe\n")); + + mIoMmuEvent = EfiCreateProtocolNotifyEvent ( + &gEdkiiIoMmuProtocolGuid, + TPL_CALLBACK, + IoMmuProtocolCallback, + NULL, + &mIoMmuRegistration + ); + return EFI_SUCCESS; } diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciHostBridge.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciHostBridge.inf index de77fd1552..ec0c593d5b 100644 --- a/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciHostBridge.inf +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciHostBridge.inf @@ -35,6 +35,7 @@ [Packages] MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec BroxtonSiPkg/BroxtonSiPkg.dec [LibraryClasses] @@ -55,6 +56,7 @@ gEfiPciHostBridgeResourceAllocationProtocolGuid ## PRODUCES gEfiMetronomeArchProtocolGuid ## CONSUMES gEfiCpuIo2ProtocolGuid ## CONSUMES + gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES [Depex] gEfiCpuIo2ProtocolGuid AND diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciRootBridge.h b/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciRootBridge.h index 81c143e6d1..1db17fc2da 100644 --- a/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciRootBridge.h +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciRootBridge.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciRootBridgeIo.c b/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciRootBridgeIo.c index e5e2e8605f..d8bdc20de1 100644 --- a/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciRootBridgeIo.c +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/NorthCluster/PciHostBridge/Dxe/PciRootBridgeIo.c @@ -16,6 +16,8 @@ #include "PciRootBridge.h" #include +extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; + typedef struct { EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[TypeMax]; EFI_ACPI_END_TAG_DESCRIPTOR EndDesp; @@ -1093,11 +1095,29 @@ RootBridgeIoMap ( if (Operation < 0 || Operation >= EfiPciOperationMaximum) { return EFI_INVALID_PARAMETER; } - // - // Most PCAT like chipsets can not handle performing DMA above 4GB. - // If any part of the DMA transfer being mapped is above 4GB, then - // map the DMA transfer to a buffer below 4GB. - // + + if (mIoMmuProtocol != NULL) { + // + // Clear 64bit support + // + if (Operation > EfiPciOperationBusMasterCommonBuffer) { + Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64); + } + return mIoMmuProtocol->Map ( + mIoMmuProtocol, + (EDKII_IOMMU_OPERATION) Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + } + + /// + /// Most PCAT like chipsets can not handle performing DMA above 4GB. + /// If any part of the DMA transfer being mapped is above 4GB, then + /// map the DMA transfer to a buffer below 4GB. + /// PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; if ((PhysicalAddress + *NumberOfBytes) > 0x100000000) { // @@ -1186,10 +1206,17 @@ RootBridgeIoUnmap ( { MAP_INFO *MapInfo; - // - // See if the Map() operation associated with this Unmap() required a mapping buffer. - // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS. - // + if (mIoMmuProtocol != NULL) { + return mIoMmuProtocol->Unmap ( + mIoMmuProtocol, + Mapping + ); + } + + /// + /// See if the Map() operation associated with this Unmap() required a mapping buffer. + /// If a mapping buffer was not required, then this function simply returns EFI_SUCCESS. + /// if (Mapping != NULL) { // // Get the MAP_INFO structure from Mapping @@ -1277,6 +1304,22 @@ RootBridgeIoAllocateBuffer ( if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { return EFI_INVALID_PARAMETER; } + + if (mIoMmuProtocol != NULL) { + // + // Clear DUAL_ADDRESS_CYCLE + // + Attributes &= ~((UINT64) EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE); + Status = mIoMmuProtocol->AllocateBuffer ( + mIoMmuProtocol, + Type, + MemoryType, + Pages, + HostAddress, + Attributes + ); + return Status; + } // // Limit allocations to memory below 4GB // @@ -1314,6 +1357,16 @@ RootBridgeIoFreeBuffer ( OUT VOID *HostAddress ) { + EFI_STATUS Status; + + if (mIoMmuProtocol != NULL) { + Status = mIoMmuProtocol->FreeBuffer ( + mIoMmuProtocol, + Pages, + HostAddress + ); + return Status; + } FreePages ((VOID *) HostAddress, Pages); return EFI_SUCCESS; } -- 2.14.1.windows.1