From c15da8eb3587f2371df330bc4bcb5a31b2efac0d Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Sat, 29 Apr 2017 16:23:58 +0800 Subject: [PATCH 1/1] MdeModulePkg/PciHostBridge: Add IOMMU support. 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 Previous patch Tested-by: Brijesh Singh Previous patch Tested-by: Ard Biesheuvel Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao Reviewed-by: Ruiyu Ni Reviewed-by: Leo Duran --- .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c | 37 +++++++++++ .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf | 2 + .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h | 2 + .../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 9005deeac2..70726a6be8 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. @@ -312,6 +316,28 @@ FreeMemorySpaceMap: return Status; } +/** + 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 d8b0439699..42bd8a23cb 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 13185b41ac..1fec88b2f9 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 8af131b0af..068295b7c0 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.39.2