From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f65.google.com (mail-wr1-f65.google.com [209.85.221.65]) by mx.groups.io with SMTP id smtpd.web10.4080.1574723583048214747 for ; Mon, 25 Nov 2019 15:13:03 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linaro.org header.s=google header.b=XMCD7wvX; spf=pass (domain: linaro.org, ip: 209.85.221.65, mailfrom: ard.biesheuvel@linaro.org) Received: by mail-wr1-f65.google.com with SMTP id s5so20198205wrw.2 for ; Mon, 25 Nov 2019 15:13:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ispPv8Y8Zje0jvFT92+Lk1IL1h806DILBNCaGn0swug=; b=XMCD7wvXUAqHQD0M9FcOcUvexKBVg/2OT8nBekaD0kWxVm8SCos+IA+yg4Psei0qj/ FnGbTfQw/avAiJvzhZw+ZAYSd+RSoo+w4YZmOzy1ueTuOebtHMKRS4gtXndj7wJdSamy lOu5hy0zs2T7D5zuJPvqxYgYTlOdXKrcegLMig+/VzqW6IqZmhXD0UyXoNNeBKnKc9gw t1rxi6oiVXGHXxeaOj/T72RvYWJw8C/cKGgjNtuoJfj1fEuyiP75bGHykND7TbdUL7Yr Fw8Fb5sSYFLXmuMHTid9DbzsmRpyWA3BkCW+mhHwdNjrGmjjSevrj9QMHRaiGsbohqUZ elXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ispPv8Y8Zje0jvFT92+Lk1IL1h806DILBNCaGn0swug=; b=ZUIrXjWGWS4cIbpyNPIHuSGsnFJNaYmQdB8pS1z3LYfJH8oG1sP605QsfjE3z9PUSL 1II9pGAXLeNL31Jx+qmCAiaE5H9wk++G95s+CsuH2+/huwXsyIfkbejKlShIPjm6mVIi oCBDx+hzKCv2vVJHkCCbuTcnfRww1yV7HkR/dHMX1up5N0mmKFBiTP+Sz5JrAmO8vlBJ uBvzDrJZ/N8k/a+wo/IxcTO4ad2yghkX4MXHB8IJLdSVGZQzmi+feEl40z1NtxY2Zu9d LhnkTvWOKI78uzkyC2adUwBanGF5Gj/3zaS+gYmqD1bEQTUZfn41e4M85SwCqnXS99Vz dguw== X-Gm-Message-State: APjAAAXlHTStF3HBhRuGCwloA9anRCfl9Gv2+8C6AMtpqoToFL1piAOv bJF5cCmvNrFi5LWFk4CRL5Yc9KHaBGIBpvt/ X-Google-Smtp-Source: APXvYqzXVKiwgZGKuSi8C3BunAYOIHBfjFuf23KNW0MhVkHs3QEzh1xwwdHquEEnCb9yQtJFpoAtKQ== X-Received: by 2002:a5d:6350:: with SMTP id b16mr13126785wrw.132.1574723581219; Mon, 25 Nov 2019 15:13:01 -0800 (PST) Return-Path: Received: from e123331-lin.home (lfbn-mar-1-643-104.w90-118.abo.wanadoo.fr. [90.118.215.104]) by smtp.gmail.com with ESMTPSA id y6sm12601488wrr.19.2019.11.25.15.13.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Nov 2019 15:13:00 -0800 (PST) From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: leif.lindholm@linaro.org, Ard Biesheuvel Subject: [PATCH v2 2/2] EmbeddedPkg: implement EDK2 IoMmu protocol wrapping DmaLib Date: Tue, 26 Nov 2019 00:12:42 +0100 Message-Id: <20191125231242.12193-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191125231242.12193-1-ard.biesheuvel@linaro.org> References: <20191125231242.12193-1-ard.biesheuvel@linaro.org> 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 Reviewed-by: Leif Lindholm --- EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c | 257 ++++++++++++++++++++ EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf | 43 ++++ EmbeddedPkg/EmbeddedPkg.dsc | 5 + 3 files changed, 305 insertions(+) diff --git a/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c b/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c new file mode 100644 index 000000000000..4b0afe47de4c --- /dev/null +++ b/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c @@ -0,0 +1,257 @@ +/** @file + + Copyright (c) 2019, Linaro, Ltd. All rights reserved.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + +/** + Set IOMMU attribute for a system memory. + + If the IOMMU protocol exists, the system memory cannot be used + for DMA by default. + + When a device requests a DMA access for a system memory, + the device driver need use SetAttribute() to update the IOMMU + attribute to request DMA access (read and/or write). + + The DeviceHandle is used to identify which device submits the request. + The IOMMU implementation need translate the device path to an IOMMU device + ID, and set IOMMU hardware register accordingly. + 1) DeviceHandle can be a standard PCI device. + The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ. + The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE. + The memory for BusMasterCommonBuffer need set + EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE. + After the memory is used, the memory need set 0 to keep it being + protected. + 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc). + The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or + EDKII_IOMMU_ACCESS_WRITE. + + @param[in] This The protocol instance pointer. + @param[in] DeviceHandle The device who initiates the DMA access + request. + @param[in] Mapping The mapping value returned from Map(). + @param[in] IoMmuAccess The IOMMU access. + + @retval EFI_SUCCESS The IoMmuAccess is set for the memory range + specified by DeviceAddress and Length. + @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by + Map(). + @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination + of access. + @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU. + @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported + by the IOMMU. + @retval EFI_UNSUPPORTED The IOMMU does not support the memory range + specified by Mapping. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to + modify the IOMMU access. + @retval EFI_DEVICE_ERROR The IOMMU device reported an error while + attempting the operation. + +**/ +STATIC +EFI_STATUS +EFIAPI +NonCoherentIoMmuSetAttribute ( + IN EDKII_IOMMU_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN VOID *Mapping, + IN UINT64 IoMmuAccess + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Provides the controller-specific addresses required to access system memory + from a DMA bus master. On SEV guest, the DMA operations must be performed on + shared buffer hence we allocate a bounce buffer to map the HostAddress to a + DeviceAddress. The Encryption attribute is removed from the DeviceAddress + buffer. + + @param This The protocol instance pointer. + @param Operation Indicates if the bus master is going to read or + write to system memory. + @param HostAddress The system memory address to map to the PCI + controller. + @param NumberOfBytes On input the number of bytes to map. On output + the number of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master + PCI controller to use to access the hosts + HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned + NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common + buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a + lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested + address. + +**/ +STATIC +EFI_STATUS +EFIAPI +NonCoherentIoMmuMap ( + IN EDKII_IOMMU_PROTOCOL *This, + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + DMA_MAP_OPERATION DmaOperation; + + switch (Operation) { + case EdkiiIoMmuOperationBusMasterRead: + case EdkiiIoMmuOperationBusMasterRead64: + DmaOperation = MapOperationBusMasterRead; + break; + + case EdkiiIoMmuOperationBusMasterWrite: + case EdkiiIoMmuOperationBusMasterWrite64: + DmaOperation = MapOperationBusMasterWrite; + break; + + case EdkiiIoMmuOperationBusMasterCommonBuffer: + case EdkiiIoMmuOperationBusMasterCommonBuffer64: + DmaOperation = MapOperationBusMasterCommonBuffer; + break; + + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + return DmaMap (DmaOperation, HostAddress, NumberOfBytes, + DeviceAddress, Mapping); +} + +/** + Completes the Map() operation and releases any corresponding resources. + + @param This The protocol instance pointer. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by + Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system + memory. +**/ +STATIC +EFI_STATUS +EFIAPI +NonCoherentIoMmuUnmap ( + IN EDKII_IOMMU_PROTOCOL *This, + IN VOID *Mapping + ) +{ + return DmaUnmap (Mapping); +} + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer or + OperationBusMasterCommonBuffer64 mapping. + + @param This The protocol instance pointer. + @param Type This parameter is not used and must be ignored. + @param MemoryType The type of memory to allocate, + EfiBootServicesData or EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory + address of the allocated range. + @param Attributes The requested bit mask of attributes for the + allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal + attribute bits are MEMORY_WRITE_COMBINE and + MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +STATIC +EFI_STATUS +EFIAPI +NonCoherentIoMmuAllocateBuffer ( + IN EDKII_IOMMU_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + return DmaAllocateBuffer (MemoryType, Pages, HostAddress); +} + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param This The protocol instance pointer. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated + range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and + Pages was not allocated with AllocateBuffer(). + +**/ +STATIC +EFI_STATUS +EFIAPI +NonCoherentIoMmuFreeBuffer ( + IN EDKII_IOMMU_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + return DmaFreeBuffer (Pages, HostAddress); +} + +STATIC EDKII_IOMMU_PROTOCOL mNonCoherentIoMmuOps = { + EDKII_IOMMU_PROTOCOL_REVISION, + NonCoherentIoMmuSetAttribute, + NonCoherentIoMmuMap, + NonCoherentIoMmuUnmap, + NonCoherentIoMmuAllocateBuffer, + NonCoherentIoMmuFreeBuffer, +}; + + +EFI_STATUS +EFIAPI +NonCoherentIoMmuDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return gBS->InstallMultipleProtocolInterfaces (&ImageHandle, + &gEdkiiIoMmuProtocolGuid, &mNonCoherentIoMmuOps, + NULL); +} diff --git a/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf b/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf new file mode 100644 index 000000000000..de70cfb4cad7 --- /dev/null +++ b/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf @@ -0,0 +1,43 @@ +#/** @file +# +# Copyright (c) 2019, Linaro, Ltd. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR +# IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 1.27 + BASE_NAME = NonCoherentIoMmuDxe + FILE_GUID = 7ed510aa-9cdc-49d2-a306-6e11e359f9b3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = NonCoherentIoMmuDxeEntryPoint + +[Sources] + NonCoherentIoMmuDxe.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DmaLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEdkiiIoMmuProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc index a8a151eb40cb..8842acc4cbf4 100644 --- a/EmbeddedPkg/EmbeddedPkg.dsc +++ b/EmbeddedPkg/EmbeddedPkg.dsc @@ -238,6 +238,11 @@ [Components.common] EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.inf EmbeddedPkg/Drivers/DtPlatformDxe/DtPlatformDxe.inf + EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf { + + DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf + } + [Components.ARM] EmbeddedPkg/Drivers/Isp1761UsbDxe/Isp1761UsbDxe.inf -- 2.17.1