From nobody Tue Apr 23 10:11:24 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+51253+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51253+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1574723584; cv=none; d=zohomail.com; s=zohoarc; b=FGobICFKNJKLxzKFva82/7plBRWRhaj9hJz5zb2Tq6NL0iCQ6+DIbu5iSJme6D+TEqFiW62MvG+Y/O/kcKq4K242Gi7UiNkGpsv7WQ8yDGPHUalIMQV++89mJyaxHCyfRBEwFqeE+NYWvbFsceRh86EWet+YkDvwtnxSVMHa6tM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1574723584; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To; bh=eEEiI4T9xa8yUsbzHTQGs/cj0FUNUJOp/QVnbxPanUg=; b=hHwOvCa/NIQ5lUGo2iVmqgT0F6tEyWKLNOOI3D4vhxvoQpYewcjQVsvHHWR3aDFNpRb5D3KsvbzaKp9e6bxJc1eibyFp+Y3C9SzTlIT1ufy3P399Ce6mrXS09wYGsrPCAt6411h/CHv+W1QB5AINJOGCrmZQV2WQ7WccGD3dLEs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51253+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1574723584146545.3892916368214; Mon, 25 Nov 2019 15:13:04 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id aaaaYY1788612xaaaaaaaaaa; Mon, 25 Nov 2019 15:13:02 -0800 X-Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) by mx.groups.io with SMTP id smtpd.web09.4017.1574723581713201369 for ; Mon, 25 Nov 2019 15:13:02 -0800 X-Received: by mail-wr1-f44.google.com with SMTP id n1so20223955wra.10 for ; Mon, 25 Nov 2019 15:13:01 -0800 (PST) X-Gm-Message-State: aaaaaaaaaaaaaaaaaaaaaaaax1787277AA= X-Google-Smtp-Source: APXvYqwdK4TGFCvawyCHUjI8dixR86CyFJUnz9khFbeycZgSe+WrRQZRxjhkyQ3jBLfXsS4wnhKdLA== X-Received: by 2002:adf:a551:: with SMTP id j17mr32639346wrb.18.1574723580003; Mon, 25 Nov 2019 15:13:00 -0800 (PST) X-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.12.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Nov 2019 15:12:59 -0800 (PST) From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: leif.lindholm@linaro.org, Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 1/2] EmbeddedPkg/NonCoherentDmaLib: implement support for DMA range limits Date: Tue, 26 Nov 2019 00:12:41 +0100 Message-Id: <20191125231242.12193-2-ard.biesheuvel@linaro.org> In-Reply-To: <20191125231242.12193-1-ard.biesheuvel@linaro.org> References: <20191125231242.12193-1-ard.biesheuvel@linaro.org> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ard.biesheuvel@linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1574723582; bh=pq5GHRVxxY9xa8FyPUv4sIcZlG3VnudYmekWmFu7DIU=; h=Cc:Date:From:Reply-To:Subject:To; b=c+e2mFNBTNet33bGtUsYyXybi3s7oqeYXmWFxgW4W/lZdn2xUYzoHlmgQPONe0h6Xar cBn6/J1ndfR8Rx5BUnQq8GDxLekKs6rMYA3QfzmWPNDDWbQy7qQHauzgul37S3FCBzbVX Qlh0o4uh2Y7y2N5HNSYbXa0S4D6m0RHNsqg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Implement support for driving peripherals with limited DMA ranges to NonCoherentDmaLib, by adding a device address limit, and taking it, along with the device offset, into account when allocating or mapping DMA buffers. Signed-off-by: Ard Biesheuvel Acked-by: Leif Lindholm Acked-by: Philippe Mathieu-Daude Reviewed-by: Philippe Mathieu-Daude Tested-by: Pete Batard --- EmbeddedPkg/EmbeddedPkg.dec | 6 + EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c | 165 ++++++++= ++++++++++-- EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf | 1 + 3 files changed, 160 insertions(+), 12 deletions(-) diff --git a/EmbeddedPkg/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec index 8812a6db7c30..69922802f473 100644 --- a/EmbeddedPkg/EmbeddedPkg.dec +++ b/EmbeddedPkg/EmbeddedPkg.dec @@ -186,6 +186,12 @@ [PcdsFixedAtBuild.common, PcdsDynamic.common] # gEmbeddedTokenSpaceGuid.PcdDmaDeviceOffset|0x0|UINT64|0x0000058 =20 + # + # Highest address value supported by the device for DMA addressing. Note + # that this value should be strictly greater than PcdDmaDeviceOffset. + # + gEmbeddedTokenSpaceGuid.PcdDmaDeviceLimit|0xFFFFFFFFFFFFFFFF|UINT64|0x00= 0005A + # # Selection between DT and ACPI as a default # diff --git a/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c b/Em= beddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c index 78220f6358aa..115345765435 100644 --- a/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c +++ b/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c @@ -40,6 +40,8 @@ typedef struct { STATIC EFI_CPU_ARCH_PROTOCOL *mCpu; STATIC LIST_ENTRY UncachedAllocationList; =20 +STATIC PHYSICAL_ADDRESS mDmaHostAddressLimit; + STATIC PHYSICAL_ADDRESS HostToDeviceAddress ( @@ -49,6 +51,102 @@ HostToDeviceAddress ( return (PHYSICAL_ADDRESS)(UINTN)Address + PcdGet64 (PcdDmaDeviceOffset); } =20 +/** + Allocates one or more 4KB pages of a certain memory type at a specified + alignment. + + Allocates the number of 4KB pages specified by Pages of a certain memory= type + with an alignment specified by Alignment. The allocated buffer is return= ed. + If Pages is 0, then NULL is returned. If there is not enough memory at t= he + specified alignment remaining to satisfy the request, then NULL is retur= ned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment = is + used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +STATIC +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) =3D=3D 0); + + if (Pages =3D=3D 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Calculate the total number of pages since alignment is larger than = page + // size. + // + AlignmentMask =3D Alignment - 1; + RealPages =3D Pages + EFI_SIZE_TO_PAGES (Alignment); + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not + // overflow. + // + ASSERT (RealPages > Pages); + + Memory =3D mDmaHostAddressLimit; + Status =3D gBS->AllocatePages (AllocateMaxAddress, MemoryType, RealPag= es, + &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory =3D ((UINTN)Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages =3D EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN)Memory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status =3D gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory =3D AlignedMemory + EFI_PAGES_TO_SIZE (Pages); + UnalignedPages =3D RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status =3D gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Memory =3D mDmaHostAddressLimit; + Status =3D gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, + &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory =3D (UINTN)Memory; + } + return (VOID *)AlignedMemory; +} + /** Provides the DMA controller-specific addresses needed to access system m= emory. =20 @@ -111,7 +209,30 @@ DmaMap ( return EFI_OUT_OF_RESOURCES; } =20 - if (Operation !=3D MapOperationBusMasterRead && + if (((UINTN)HostAddress + *NumberOfBytes) > mDmaHostAddressLimit) { + + if (Operation =3D=3D MapOperationBusMasterCommonBuffer) { + goto CommonBufferError; + } + + AllocSize =3D ALIGN_VALUE (*NumberOfBytes, mCpu->DmaBufferAlignment); + Map->BufferAddress =3D InternalAllocateAlignedPages (EfiBootServicesDa= ta, + EFI_SIZE_TO_PAGES (AllocSize), + mCpu->DmaBufferAlignment); + if (Map->BufferAddress =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto FreeMapInfo; + } + + if (Map->Operation =3D=3D MapOperationBusMasterRead) { + CopyMem (Map->BufferAddress, (VOID *)(UINTN)Map->HostAddress, + *NumberOfBytes); + } + mCpu->FlushDataCache (mCpu, (UINTN)Map->BufferAddress, AllocSize, + EfiCpuFlushTypeWriteBack); + + *DeviceAddress =3D HostToDeviceAddress (Map->BufferAddress); + } else if (Operation !=3D MapOperationBusMasterRead && ((((UINTN)HostAddress & (mCpu->DmaBufferAlignment - 1)) !=3D 0) || ((*NumberOfBytes & (mCpu->DmaBufferAlignment - 1)) !=3D 0))) { =20 @@ -128,12 +249,7 @@ DmaMap ( // on uncached buffers. // if (Operation =3D=3D MapOperationBusMasterCommonBuffer) { - DEBUG ((DEBUG_ERROR, - "%a: Operation type 'MapOperationBusMasterCommonBuffer' is only " - "supported\non memory regions that were allocated using " - "DmaAllocateBuffer ()\n", __FUNCTION__)); - Status =3D EFI_UNSUPPORTED; - goto FreeMapInfo; + goto CommonBufferError; } =20 // @@ -199,6 +315,12 @@ DmaMap ( =20 return EFI_SUCCESS; =20 +CommonBufferError: + DEBUG ((DEBUG_ERROR, + "%a: Operation type 'MapOperationBusMasterCommonBuffer' is only " + "supported\non memory regions that were allocated using " + "DmaAllocateBuffer ()\n", __FUNCTION__)); + Status =3D EFI_UNSUPPORTED; FreeMapInfo: FreePool (Map); =20 @@ -229,6 +351,7 @@ DmaUnmap ( MAP_INFO_INSTANCE *Map; EFI_STATUS Status; VOID *Buffer; + UINTN AllocSize; =20 if (Mapping =3D=3D NULL) { ASSERT (FALSE); @@ -238,7 +361,17 @@ DmaUnmap ( Map =3D (MAP_INFO_INSTANCE *)Mapping; =20 Status =3D EFI_SUCCESS; - if (Map->DoubleBuffer) { + if (((UINTN)Map->HostAddress + Map->NumberOfBytes) > mDmaHostAddressLimi= t) { + AllocSize =3D ALIGN_VALUE (Map->NumberOfBytes, mCpu->DmaBufferAlignmen= t); + if (Map->Operation =3D=3D MapOperationBusMasterWrite) { + mCpu->FlushDataCache (mCpu, (UINTN)Map->BufferAddress, AllocSize, + EfiCpuFlushTypeInvalidate); + CopyMem ((VOID *)(UINTN)Map->HostAddress, Map->BufferAddress, + Map->NumberOfBytes); + } + FreePages (Map->BufferAddress, EFI_SIZE_TO_PAGES (AllocSize)); + } else if (Map->DoubleBuffer) { + ASSERT (Map->Operation =3D=3D MapOperationBusMasterWrite); =20 if (Map->Operation !=3D MapOperationBusMasterWrite) { @@ -335,10 +468,9 @@ DmaAllocateAlignedBuffer ( return EFI_INVALID_PARAMETER; } =20 - if (MemoryType =3D=3D EfiBootServicesData) { - Allocation =3D AllocateAlignedPages (Pages, Alignment); - } else if (MemoryType =3D=3D EfiRuntimeServicesData) { - Allocation =3D AllocateAlignedRuntimePages (Pages, Alignment); + if (MemoryType =3D=3D EfiBootServicesData || + MemoryType =3D=3D EfiRuntimeServicesData) { + Allocation =3D InternalAllocateAlignedPages (MemoryType, Pages, Alignm= ent); } else { return EFI_INVALID_PARAMETER; } @@ -479,6 +611,15 @@ NonCoherentDmaLibConstructor ( { InitializeListHead (&UncachedAllocationList); =20 + // + // Ensure that the combination of DMA addressing offset and limit produc= es + // a sane value. + // + ASSERT (PcdGet64 (PcdDmaDeviceLimit) > PcdGet64 (PcdDmaDeviceOffset)); + + mDmaHostAddressLimit =3D PcdGet64 (PcdDmaDeviceLimit) - + PcdGet64 (PcdDmaDeviceOffset); + // Get the Cpu protocol for later use return gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mC= pu); } diff --git a/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf b/= EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf index 2db751afee91..1a21cfe4ff23 100644 --- a/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf +++ b/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf @@ -38,6 +38,7 @@ [Protocols] =20 [Pcd] gEmbeddedTokenSpaceGuid.PcdDmaDeviceOffset + gEmbeddedTokenSpaceGuid.PcdDmaDeviceLimit =20 [Depex] gEfiCpuArchProtocolGuid --=20 2.17.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#51253): https://edk2.groups.io/g/devel/message/51253 Mute This Topic: https://groups.io/mt/61950463/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Tue Apr 23 10:11:24 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+51254+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51254+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1574723584; cv=none; d=zohomail.com; s=zohoarc; b=ZXKrmNNFRXE913qZVX9CiHkbMhHcNIYMMCo1XkH/1VEMMepcOp6s4ezTE7Pe75ceHFvkkhWgu5OEpmsShN+F9+al3uDblUsG2zYJ/+cH4bMvSIgNSQAJssBxNeOdV/62sFaAj+FjfjH90OIevXYHjU9NaMsrC68RqxD7rHbTYEg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1574723584; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To; bh=QnHsS74YSpnWA1OrfsoNMfnhNfzEzDqMLxgFDKs2tmU=; b=OAGPUr72ZVGwscID3CZH+t+JCZZaNKEH75VwGZU9XBJdka8sTKypNpY2+Pr6cRRPAJZMolxqxU01NXoTV561JXeHtGcYCD8n9Z7QOupMSO0RdceBt/Ei+Aj0vv3bC0LyCzWm9/UMzPHnCOJALs2KB7QxOkbkDLeikvQuWpObUE8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51254+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1574723584363753.8988483159168; Mon, 25 Nov 2019 15:13:04 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id aaaaYY1788612xaaaaaaaaaa; Mon, 25 Nov 2019 15:13:03 -0800 X-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 X-Received: by mail-wr1-f65.google.com with SMTP id s5so20198205wrw.2 for ; Mon, 25 Nov 2019 15:13:02 -0800 (PST) X-Gm-Message-State: aaaaaaaaaaaaaaaaaaaaaaaax1787277AA= 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) X-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: [edk2-devel] [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> In-Reply-To: <20191125231242.12193-1-ard.biesheuvel@linaro.org> References: <20191125231242.12193-1-ard.biesheuvel@linaro.org> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ard.biesheuvel@linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1574723583; bh=Fv6JbkesUyVHmLqvgM4P+KPnrNKsK38mRDkWsPpR8Gw=; h=Cc:Date:From:Reply-To:Subject:To; b=iT3Khqg70HOzy15Vq1ZLvThupmF+pFqF6mEcFyUE9g911662jH4ignwx6bMgC0+i8Rv OD79lelrYxCyPmlTArgDYk00n19bMoR+kt1QMKkM9KKjfywI587CWUsTqLg7F8FS/XiNd or0AwNovwtgNSxC3yleXdFikdEizEDhkmeI= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Philippe Mathieu-Daude Tested-by: Pete Batard --- 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 availa= ble + 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 IMP= LIED. + +**/ + +#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 devi= ce + 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 ran= ge + 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 combinat= ion + of access. + @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU. + @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor= ted + by the IOMMU. + @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran= ge + 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 mem= ory + from a DMA bus master. On SEV guest, the DMA operations must be performe= d on + shared buffer hence we allocate a bounce buffer to map the HostAddress t= o 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 re= ad 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 ou= tput + the number of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er + 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 comm= on + 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 requ= ested + 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 =3D MapOperationBusMasterRead; + break; + + case EdkiiIoMmuOperationBusMasterWrite: + case EdkiiIoMmuOperationBusMasterWrite64: + DmaOperation =3D MapOperationBusMasterWrite; + break; + + case EdkiiIoMmuOperationBusMasterCommonBuffer: + case EdkiiIoMmuOperationBusMasterCommonBuffer64: + DmaOperation =3D 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 s= ystem + 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 ign= ored. + @param MemoryType The type of memory to allocate, + EfiBootServicesData or EfiRuntimeServicesD= ata. + @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 t= he + 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 allo= cated + 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 AllocateBuffe= r(). + +**/ +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 =3D { + 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.in= f 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 avail= able +# 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 =3D 1.27 + BASE_NAME =3D NonCoherentIoMmuDxe + FILE_GUID =3D 7ed510aa-9cdc-49d2-a306-6e11e359f9b3 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D 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 =20 + EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf { + + DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf + } + [Components.ARM] EmbeddedPkg/Drivers/Isp1761UsbDxe/Isp1761UsbDxe.inf =20 --=20 2.17.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#51254): https://edk2.groups.io/g/devel/message/51254 Mute This Topic: https://groups.io/mt/61950464/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-