MdeModulePkg/PciBus: Add IOMMU support.
authorJiewen Yao <jiewen.yao@intel.com>
Sat, 29 Apr 2017 08:57:54 +0000 (16:57 +0800)
committerJiewen Yao <jiewen.yao@intel.com>
Wed, 17 May 2017 08:05:17 +0000 (16:05 +0800)
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 <ruiyu.ni@intel.com>
Cc: Leo Duran <leo.duran@amd.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Previous patch Tested-by: Brijesh Singh <brijesh.singh@amd.com>
Previous patch Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Leo Duran <leo.duran@amd.com>
MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c

index f3be47a..950cacc 100644 (file)
@@ -42,6 +42,7 @@ UINT64                                        gAllZero             = 0;
 \r
 EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;\r
 EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;\r
+EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;\r
 \r
 \r
 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {\r
@@ -284,6 +285,14 @@ PciBusDriverBindingStart (
           );\r
   }  \r
 \r
+  if (mIoMmuProtocol == NULL) {\r
+    gBS->LocateProtocol (\r
+          &gEdkiiIoMmuProtocolGuid,\r
+          NULL,\r
+          (VOID **) &mIoMmuProtocol\r
+          );\r
+  }\r
+\r
   if (PcdGetBool (PcdPciDisableBusEnumeration)) {\r
     gFullEnumeration = FALSE;\r
   } else {\r
index 39ba8b9..3bcc134 100644 (file)
@@ -32,6 +32,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/IncompatiblePciDeviceSupport.h>\r
 #include <Protocol/PciOverride.h>\r
 #include <Protocol/PciEnumerationComplete.h>\r
+#include <Protocol/IoMmu.h>\r
 \r
 #include <Library/DebugLib.h>\r
 #include <Library/UefiDriverEntryPoint.h>\r
index a3ab11f..5da094f 100644 (file)
@@ -95,6 +95,7 @@
   gEfiPciRootBridgeIoProtocolGuid                 ## TO_START\r
   gEfiIncompatiblePciDeviceSupportProtocolGuid    ## SOMETIMES_CONSUMES\r
   gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES\r
+  gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES\r
 \r
 [FeaturePcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ## CONSUMES\r
index f72598d..3b3b53a 100644 (file)
@@ -14,6 +14,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "PciBus.h"\r
 \r
+extern EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;\r
+\r
 //\r
 // Pci Io Protocol Interface\r
 //\r
@@ -965,8 +967,10 @@ PciIoMap (
   OUT    VOID                           **Mapping\r
   )\r
 {\r
-  EFI_STATUS    Status;\r
-  PCI_IO_DEVICE *PciIoDevice;\r
+  EFI_STATUS                                 Status;\r
+  PCI_IO_DEVICE                              *PciIoDevice;\r
+  UINT64                                     IoMmuAttribute;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  RootBridgeIoOperation;\r
 \r
   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
 \r
@@ -978,13 +982,14 @@ PciIoMap (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation;\r
   if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
-    Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);\r
+    RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)(Operation + EfiPciOperationBusMasterRead64);\r
   }\r
 \r
   Status = PciIoDevice->PciRootBridgeIo->Map (\r
                                           PciIoDevice->PciRootBridgeIo,\r
-                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
+                                          RootBridgeIoOperation,\r
                                           HostAddress,\r
                                           NumberOfBytes,\r
                                           DeviceAddress,\r
@@ -999,6 +1004,31 @@ PciIoMap (
       );\r
   }\r
 \r
+  if (mIoMmuProtocol != NULL) {\r
+    if (!EFI_ERROR (Status)) {\r
+      switch (Operation) {\r
+      case EfiPciIoOperationBusMasterRead:\r
+        IoMmuAttribute = EDKII_IOMMU_ACCESS_READ;\r
+        break;\r
+      case EfiPciIoOperationBusMasterWrite:\r
+        IoMmuAttribute = EDKII_IOMMU_ACCESS_WRITE;\r
+        break;\r
+      case EfiPciIoOperationBusMasterCommonBuffer:\r
+        IoMmuAttribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;\r
+        break;\r
+      default:\r
+        ASSERT(FALSE);\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      mIoMmuProtocol->SetAttribute (\r
+                        mIoMmuProtocol,\r
+                        PciIoDevice->Handle,\r
+                        *Mapping,\r
+                        IoMmuAttribute\r
+                        );\r
+    }\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -1024,6 +1054,15 @@ PciIoUnmap (
 \r
   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
 \r
+  if (mIoMmuProtocol != NULL) {\r
+    mIoMmuProtocol->SetAttribute (\r
+                      mIoMmuProtocol,\r
+                      PciIoDevice->Handle,\r
+                      Mapping,\r
+                      0\r
+                      );\r
+  }\r
+\r
   Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
                                           PciIoDevice->PciRootBridgeIo,\r
                                           Mapping\r