]> git.proxmox.com Git - mirror_edk2.git/commitdiff
EmbeddedPkg: implement EDK2 IoMmu protocol wrapping DmaLib
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Thu, 21 Nov 2019 08:32:27 +0000 (09:32 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 6 Dec 2019 14:55:45 +0000 (14:55 +0000)
Implement a version of the EDK2 IoMmu protocol that is a simple wrapper
around DmaLib. This is intended to be used to wrap NonCoherentDmaLib so
that the generic PCI infrastructure can be used to implement support for
non cache-coherent DMA.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Tested-by: Pete Batard <pete@akeo.ie>
EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c [new file with mode: 0644]
EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf [new file with mode: 0644]
EmbeddedPkg/EmbeddedPkg.dsc

diff --git a/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c b/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c
new file mode 100644 (file)
index 0000000..4b0afe4
--- /dev/null
@@ -0,0 +1,257 @@
+/** @file\r
+\r
+  Copyright (c) 2019, Linaro, Ltd. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DmaLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Protocol/IoMmu.h>\r
+\r
+/**\r
+  Set IOMMU attribute for a system memory.\r
+\r
+  If the IOMMU protocol exists, the system memory cannot be used\r
+  for DMA by default.\r
+\r
+  When a device requests a DMA access for a system memory,\r
+  the device driver need use SetAttribute() to update the IOMMU\r
+  attribute to request DMA access (read and/or write).\r
+\r
+  The DeviceHandle is used to identify which device submits the request.\r
+  The IOMMU implementation need translate the device path to an IOMMU device\r
+  ID, and set IOMMU hardware register accordingly.\r
+  1) DeviceHandle can be a standard PCI device.\r
+     The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.\r
+     The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.\r
+     The memory for BusMasterCommonBuffer need set\r
+     EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE.\r
+     After the memory is used, the memory need set 0 to keep it being\r
+     protected.\r
+  2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).\r
+     The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or\r
+     EDKII_IOMMU_ACCESS_WRITE.\r
+\r
+  @param[in]  This              The protocol instance pointer.\r
+  @param[in]  DeviceHandle      The device who initiates the DMA access\r
+                                request.\r
+  @param[in]  Mapping           The mapping value returned from Map().\r
+  @param[in]  IoMmuAccess       The IOMMU access.\r
+\r
+  @retval EFI_SUCCESS            The IoMmuAccess is set for the memory range\r
+                                 specified by DeviceAddress and Length.\r
+  @retval EFI_INVALID_PARAMETER  DeviceHandle is an invalid handle.\r
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by\r
+                                 Map().\r
+  @retval EFI_INVALID_PARAMETER  IoMmuAccess specified an illegal combination\r
+                                 of access.\r
+  @retval EFI_UNSUPPORTED        DeviceHandle is unknown by the IOMMU.\r
+  @retval EFI_UNSUPPORTED        The bit mask of IoMmuAccess is not supported\r
+                                 by the IOMMU.\r
+  @retval EFI_UNSUPPORTED        The IOMMU does not support the memory range\r
+                                 specified by Mapping.\r
+  @retval EFI_OUT_OF_RESOURCES   There are not enough resources available to\r
+                                 modify the IOMMU access.\r
+  @retval EFI_DEVICE_ERROR       The IOMMU device reported an error while\r
+                                 attempting the operation.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+NonCoherentIoMmuSetAttribute (\r
+  IN EDKII_IOMMU_PROTOCOL  *This,\r
+  IN EFI_HANDLE            DeviceHandle,\r
+  IN VOID                  *Mapping,\r
+  IN UINT64                IoMmuAccess\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Provides the controller-specific addresses required to access system memory\r
+  from a DMA bus master. On SEV guest, the DMA operations must be performed on\r
+  shared buffer hence we allocate a bounce buffer to map the HostAddress to a\r
+  DeviceAddress. The Encryption attribute is removed from the DeviceAddress\r
+  buffer.\r
+\r
+  @param  This                  The protocol instance pointer.\r
+  @param  Operation             Indicates if the bus master is going to read or\r
+                                write to system memory.\r
+  @param  HostAddress           The system memory address to map to the PCI\r
+                                controller.\r
+  @param  NumberOfBytes         On input the number of bytes to map. On output\r
+                                the number of bytes that were mapped.\r
+  @param  DeviceAddress         The resulting map address for the bus master\r
+                                PCI controller to use to access the hosts\r
+                                HostAddress.\r
+  @param  Mapping               A resulting value to pass to Unmap().\r
+\r
+  @retval EFI_SUCCESS           The range was mapped for the returned\r
+                                NumberOfBytes.\r
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common\r
+                                buffer.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a\r
+                                lack of resources.\r
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested\r
+                                address.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+NonCoherentIoMmuMap (\r
+  IN     EDKII_IOMMU_PROTOCOL                       *This,\r
+  IN     EDKII_IOMMU_OPERATION                      Operation,\r
+  IN     VOID                                       *HostAddress,\r
+  IN OUT UINTN                                      *NumberOfBytes,\r
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,\r
+  OUT    VOID                                       **Mapping\r
+  )\r
+{\r
+  DMA_MAP_OPERATION     DmaOperation;\r
+\r
+  switch (Operation) {\r
+    case EdkiiIoMmuOperationBusMasterRead:\r
+    case EdkiiIoMmuOperationBusMasterRead64:\r
+      DmaOperation = MapOperationBusMasterRead;\r
+      break;\r
+\r
+    case EdkiiIoMmuOperationBusMasterWrite:\r
+    case EdkiiIoMmuOperationBusMasterWrite64:\r
+      DmaOperation = MapOperationBusMasterWrite;\r
+      break;\r
+\r
+    case EdkiiIoMmuOperationBusMasterCommonBuffer:\r
+    case EdkiiIoMmuOperationBusMasterCommonBuffer64:\r
+      DmaOperation = MapOperationBusMasterCommonBuffer;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return DmaMap (DmaOperation, HostAddress, NumberOfBytes,\r
+           DeviceAddress, Mapping);\r
+}\r
+\r
+/**\r
+  Completes the Map() operation and releases any corresponding resources.\r
+\r
+  @param  This                  The protocol instance pointer.\r
+  @param  Mapping               The mapping value returned from Map().\r
+\r
+  @retval EFI_SUCCESS           The range was unmapped.\r
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by\r
+                                Map().\r
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system\r
+                                memory.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+NonCoherentIoMmuUnmap (\r
+  IN  EDKII_IOMMU_PROTOCOL                     *This,\r
+  IN  VOID                                     *Mapping\r
+  )\r
+{\r
+  return DmaUnmap (Mapping);\r
+}\r
+\r
+/**\r
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
+  OperationBusMasterCommonBuffer64 mapping.\r
+\r
+  @param  This                  The protocol instance pointer.\r
+  @param  Type                  This parameter is not used and must be ignored.\r
+  @param  MemoryType            The type of memory to allocate,\r
+                                EfiBootServicesData or EfiRuntimeServicesData.\r
+  @param  Pages                 The number of pages to allocate.\r
+  @param  HostAddress           A pointer to store the base system memory\r
+                                address of the allocated range.\r
+  @param  Attributes            The requested bit mask of attributes for the\r
+                                allocated range.\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were allocated.\r
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal\r
+                                attribute bits are MEMORY_WRITE_COMBINE and\r
+                                MEMORY_CACHED.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+NonCoherentIoMmuAllocateBuffer (\r
+  IN     EDKII_IOMMU_PROTOCOL                     *This,\r
+  IN     EFI_ALLOCATE_TYPE                        Type,\r
+  IN     EFI_MEMORY_TYPE                          MemoryType,\r
+  IN     UINTN                                    Pages,\r
+  IN OUT VOID                                     **HostAddress,\r
+  IN     UINT64                                   Attributes\r
+  )\r
+{\r
+  return DmaAllocateBuffer (MemoryType, Pages, HostAddress);\r
+}\r
+\r
+/**\r
+  Frees memory that was allocated with AllocateBuffer().\r
+\r
+  @param  This                  The protocol instance pointer.\r
+  @param  Pages                 The number of pages to free.\r
+  @param  HostAddress           The base system memory address of the allocated\r
+                                range.\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were freed.\r
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and\r
+                                Pages was not allocated with AllocateBuffer().\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+NonCoherentIoMmuFreeBuffer (\r
+  IN  EDKII_IOMMU_PROTOCOL                     *This,\r
+  IN  UINTN                                    Pages,\r
+  IN  VOID                                     *HostAddress\r
+  )\r
+{\r
+  return DmaFreeBuffer (Pages, HostAddress);\r
+}\r
+\r
+STATIC EDKII_IOMMU_PROTOCOL  mNonCoherentIoMmuOps = {\r
+  EDKII_IOMMU_PROTOCOL_REVISION,\r
+  NonCoherentIoMmuSetAttribute,\r
+  NonCoherentIoMmuMap,\r
+  NonCoherentIoMmuUnmap,\r
+  NonCoherentIoMmuAllocateBuffer,\r
+  NonCoherentIoMmuFreeBuffer,\r
+};\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+NonCoherentIoMmuDxeEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  return gBS->InstallMultipleProtocolInterfaces (&ImageHandle,\r
+                &gEdkiiIoMmuProtocolGuid, &mNonCoherentIoMmuOps,\r
+                NULL);\r
+}\r
diff --git a/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf b/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf
new file mode 100644 (file)
index 0000000..de70cfb
--- /dev/null
@@ -0,0 +1,43 @@
+#/** @file\r
+#\r
+#  Copyright (c) 2019, Linaro, Ltd. All rights reserved.<BR>\r
+#\r
+#  This program and the accompanying materials are licensed and made available\r
+#  under the terms and conditions of the BSD License which accompanies this\r
+#  distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR\r
+#  IMPLIED.\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 1.27\r
+  BASE_NAME                      = NonCoherentIoMmuDxe\r
+  FILE_GUID                      = 7ed510aa-9cdc-49d2-a306-6e11e359f9b3\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = NonCoherentIoMmuDxeEntryPoint\r
+\r
+[Sources]\r
+  NonCoherentIoMmuDxe.c\r
+\r
+[Packages]\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  DebugLib\r
+  DmaLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+\r
+[Protocols]\r
+  gEdkiiIoMmuProtocolGuid                     ## PRODUCES\r
+\r
+[Depex]\r
+  TRUE\r
index a8a151eb40cbaccde4c27dadea9f3b1b697a13fa..8842acc4cbf4f22b7514087813bf2bfc4b07894a 100644 (file)
   EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.inf\r
   EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.inf\r
 \r
+  EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf {\r
+    <LibraryClasses>\r
+      DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf\r
+  }\r
+\r
 [Components.ARM]\r
   EmbeddedPkg/Drivers/Isp1761UsbDxe/Isp1761UsbDxe.inf\r
 \r