From 11a6cc5bda811513d2fbe47d8cb1a70b48077800 Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Sat, 29 Apr 2017 16:57:54 +0800 Subject: [PATCH] MdeModulePkg/PciBus: Add IOMMU support. If IOMMU protocol is installed, PciBus need call IOMMU to set access attribute for the PCI device in Map/Ummap. Only after the access attribute is set, the PCI device can access the DMA memory. 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 --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c | 9 ++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 47 ++++++++++++++++++-- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c index f3be47a496..950cacc120 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c @@ -42,6 +42,7 @@ UINT64 gAllZero = 0; EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol; +EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = { @@ -284,6 +285,14 @@ PciBusDriverBindingStart ( ); } + if (mIoMmuProtocol == NULL) { + gBS->LocateProtocol ( + &gEdkiiIoMmuProtocolGuid, + NULL, + (VOID **) &mIoMmuProtocol + ); + } + if (PcdGetBool (PcdPciDisableBusEnumeration)) { gFullEnumeration = FALSE; } else { diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h index 39ba8b9f33..3bcc134d0b 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 #include #include diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf index a3ab11fd8d..5da094f582 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 [FeaturePcd] gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## CONSUMES diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c index f72598d3ae..3b3b53abce 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c @@ -14,6 +14,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "PciBus.h" +extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; + // // Pci Io Protocol Interface // @@ -965,8 +967,10 @@ PciIoMap ( OUT VOID **Mapping ) { - EFI_STATUS Status; - PCI_IO_DEVICE *PciIoDevice; + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + UINT64 IoMmuAttribute; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION RootBridgeIoOperation; PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); @@ -978,13 +982,14 @@ PciIoMap ( return EFI_INVALID_PARAMETER; } + RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation; if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) { - Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64); + RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)(Operation + EfiPciOperationBusMasterRead64); } Status = PciIoDevice->PciRootBridgeIo->Map ( PciIoDevice->PciRootBridgeIo, - (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation, + RootBridgeIoOperation, HostAddress, NumberOfBytes, DeviceAddress, @@ -999,6 +1004,31 @@ PciIoMap ( ); } + if (mIoMmuProtocol != NULL) { + if (!EFI_ERROR (Status)) { + switch (Operation) { + case EfiPciIoOperationBusMasterRead: + IoMmuAttribute = EDKII_IOMMU_ACCESS_READ; + break; + case EfiPciIoOperationBusMasterWrite: + IoMmuAttribute = EDKII_IOMMU_ACCESS_WRITE; + break; + case EfiPciIoOperationBusMasterCommonBuffer: + IoMmuAttribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; + break; + default: + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + mIoMmuProtocol->SetAttribute ( + mIoMmuProtocol, + PciIoDevice->Handle, + *Mapping, + IoMmuAttribute + ); + } + } + return Status; } @@ -1024,6 +1054,15 @@ PciIoUnmap ( PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + if (mIoMmuProtocol != NULL) { + mIoMmuProtocol->SetAttribute ( + mIoMmuProtocol, + PciIoDevice->Handle, + Mapping, + 0 + ); + } + Status = PciIoDevice->PciRootBridgeIo->Unmap ( PciIoDevice->PciRootBridgeIo, Mapping -- 2.39.2