From nobody Wed May 8 13:02:14 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+51006+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51006+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1574325147; cv=none; d=zoho.com; s=zohoarc; b=XHJobEXxf9IBI49hbjdtlSul/1dT30Mab6dbrgNdxvG5Pwn8NxkK5Zx54C3BfONwSLdlmcai0W5Q4RoWA0DdiEwOvyrhTaw4+3pTqhfGfoRsC2s0ftIYIuHixY/cmRJD5KZGMeI6cg3iMJ8p7u0dTcZTG1KIFFZR9+LURDnFhsQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1574325147; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To; bh=OK49CIUIJ5/Xdmwo2ddkBfNFzyuhnkteBH278WkP858=; b=EuBgd8zfgKyIfPAkTEH7qaOH+ANL5wN+Z7Cjl/UukLvCOzZMzC43VdKICAfGCvLlmbxhjDyY0XCasJpcGNL+ZOVY1llqYeNeNqxBI4K803yZF/L8HcDfXM3RGcY11OdmAwY9w1YqAwitsYPYtFl5wBNPbo6WBc4PV15xuOlki4M= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51006+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 1574325147061149.12734111637872; Thu, 21 Nov 2019 00:32:27 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id aaaaYY1788612xaaaaaaaaaa; Thu, 21 Nov 2019 00:32:26 -0800 X-Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) by mx.groups.io with SMTP id smtpd.web09.21124.1574325145378110454 for ; Thu, 21 Nov 2019 00:32:25 -0800 X-Received: by mail-wr1-f66.google.com with SMTP id i12so3209274wrn.11 for ; Thu, 21 Nov 2019 00:32:25 -0800 (PST) X-Gm-Message-State: aaaaaaaaaaaaaaaaaaaaaaaax1787277AA= X-Google-Smtp-Source: APXvYqyfyTzX5MajdFQZaRQG3j8U7JyVx6wsTMuUiwVzX+E3vUbRJO8mW/LJ7jp50b096hom7BmFfA== X-Received: by 2002:adf:cf10:: with SMTP id o16mr9139560wrj.334.1574325143449; Thu, 21 Nov 2019 00:32:23 -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 u18sm2435667wrp.14.2019.11.21.00.32.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Nov 2019 00:32:22 -0800 (PST) From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: leif.lindholm@linaro.org, Ard Biesheuvel Subject: [edk2-devel] [PATCH 1/2] EmbeddedPkg/NonCoherentDmaLib: implement support for DMA range limits Date: Thu, 21 Nov 2019 09:32:26 +0100 Message-Id: <20191121083227.2850-2-ard.biesheuvel@linaro.org> In-Reply-To: <20191121083227.2850-1-ard.biesheuvel@linaro.org> References: <20191121083227.2850-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=1574325146; bh=KSIdOtVaxpN2MFKc1joYl+1hrUh6PHks+pkzZrOzQy0=; h=Cc:Date:From:Reply-To:Subject:To; b=lSMXRU2gAi09UbfQKKpu9rBv7kbjMDLEjiAA93zvIrCYxstkMNW4oDT/cHixV8AOkV1 tEwcBvx7XKe8jzUrGzPpv1vpet8FU5HATZwunrZ9RT9TfU2Zrt9aVHmj8t39pHafe3TWP mg/pqVfXw5sWk6rYksTEb/KfOivTdYfwR48= 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 --- EmbeddedPkg/EmbeddedPkg.dec | 6 + EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c | 176 ++++++++= +++++++++--- EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf | 1 + 3 files changed, 158 insertions(+), 25 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..dd3d111e7eb9 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,22 @@ 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; + } + *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 +241,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 // @@ -154,14 +262,6 @@ DmaMap ( =20 Buffer =3D ALIGN_POINTER (Map->BufferAddress, mCpu->DmaBufferAlignme= nt); *DeviceAddress =3D HostToDeviceAddress (Buffer); - - // - // Get rid of any dirty cachelines covering the double buffer. This - // prevents them from being written back unexpectedly, potentially - // overwriting the data we receive from the device. - // - mCpu->FlushDataCache (mCpu, (UINTN)Buffer, *NumberOfBytes, - EfiCpuFlushTypeWriteBack); } else { Map->DoubleBuffer =3D FALSE; } @@ -184,13 +284,13 @@ DmaMap ( (GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) = =3D=3D 0); =20 DEBUG_CODE_END (); - - // Flush the Data Cache (should not have any effect if the memory regi= on is - // uncached) - mCpu->FlushDataCache (mCpu, (UINTN)HostAddress, *NumberOfBytes, - EfiCpuFlushTypeWriteBackInvalidate); } =20 + // Flush the Data Cache (should not have any effect if the memory region= is + // uncached) + mCpu->FlushDataCache (mCpu, (UINTN)HostAddress, *NumberOfBytes, + EfiCpuFlushTypeWriteBack); + Map->HostAddress =3D (UINTN)HostAddress; Map->NumberOfBytes =3D *NumberOfBytes; Map->Operation =3D Operation; @@ -199,6 +299,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 +335,7 @@ DmaUnmap ( MAP_INFO_INSTANCE *Map; EFI_STATUS Status; VOID *Buffer; + UINTN AllocSize; =20 if (Mapping =3D=3D NULL) { ASSERT (FALSE); @@ -238,7 +345,18 @@ DmaUnmap ( Map =3D (MAP_INFO_INSTANCE *)Mapping; =20 Status =3D EFI_SUCCESS; - if (Map->DoubleBuffer) { + if (((UINTN)Map->HostAddress + Map->NumberOfBytes) > mDmaHostAddressLimi= t) { + + mCpu->FlushDataCache (mCpu, (UINTN)Map->BufferAddress, Map->NumberOfBy= tes, + EfiCpuFlushTypeInvalidate); + + CopyMem ((VOID *)(UINTN)Map->HostAddress, Map->BufferAddress, + Map->NumberOfBytes); + + AllocSize =3D ALIGN_VALUE (Map->NumberOfBytes, mCpu->DmaBufferAlignmen= t); + 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 +453,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 +596,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 (#51006): https://edk2.groups.io/g/devel/message/51006 Mute This Topic: https://groups.io/mt/61068915/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 Wed May 8 13:02:14 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+51007+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51007+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1574325147; cv=none; d=zoho.com; s=zohoarc; b=gCS2YmXlygXUJRImjwqBrTT3LGH13Xl6HsCaBO46UMuRyWHfa4lrsPQpKdIB4bKfHPq5IKbQ3X1LHWwk60Qb0IO4Q4Pn7biELJHiYh7ldOdMQCvJHbldwdhZYlkXEvDQbKXJgMUE6yGFrQ+GSLJcUOoYJd0Qm91VUiwGWuliiQ8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1574325147; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To; bh=zgTHZjxYwxU/eE0+OAyNtNuQe8btxVTWufHhbGLe6Ac=; b=HBEMJ5wjT3QI0h/ZEA8sllnjgIYldCUmOLVmtvX1P/7hjc9XdUn4NE8UHcJOvHyXMO3Mt3K51xSKSk5bKCQ63ep/dqVrNGDx/kM0bB6qNvGfcaNd57+Z1WI4ZwgcbRcU6l+Y7asv2LvhEPbRb44oGOEwLB/a0azqWQTB8t/It9I= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51007+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 157432514788159.66214762419929; Thu, 21 Nov 2019 00:32:27 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id aaaaYY1788612xaaaaaaaaaa; Thu, 21 Nov 2019 00:32:27 -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.web12.21008.1574325146555384608 for ; Thu, 21 Nov 2019 00:32:27 -0800 X-Received: by mail-wr1-f65.google.com with SMTP id a15so3234544wrf.9 for ; Thu, 21 Nov 2019 00:32:26 -0800 (PST) X-Gm-Message-State: aaaaaaaaaaaaaaaaaaaaaaaax1787277AA= X-Google-Smtp-Source: APXvYqyoGoaBTThEAELAej/eurGhVKSxkZCeNmEQAAz0T7YzJwdyR7ciQ0LlknwlMnEIaL5HSeTjHA== X-Received: by 2002:adf:edc5:: with SMTP id v5mr8940537wro.322.1574325144438; Thu, 21 Nov 2019 00:32:24 -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 u18sm2435667wrp.14.2019.11.21.00.32.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Nov 2019 00:32:23 -0800 (PST) From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: leif.lindholm@linaro.org, Ard Biesheuvel Subject: [edk2-devel] [PATCH 2/2] EmbeddedPkg: implement EDK2 IoMmu protocol wrapping DmaLib Date: Thu, 21 Nov 2019 09:32:27 +0100 Message-Id: <20191121083227.2850-3-ard.biesheuvel@linaro.org> In-Reply-To: <20191121083227.2850-1-ard.biesheuvel@linaro.org> References: <20191121083227.2850-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=1574325147; bh=qx+ld6kjvmH1n3jSj2PmA6mqa6rFUukYxyKhjkRizpQ=; h=Cc:Date:From:Reply-To:Subject:To; b=mxdTDsbp7TTNTmAa4V4MucVwY3ZFQqEuOU74PPquECkSzYiWYnlklObm4hpN8uIWKPK MSFPwT3qWYbOEI9EYPGO2VHe6t9C72TiNnZa7W4brcmK4f1JkO0mfOCn6ufr6oCi2p8CB RoAeq32Hd33tLiVPQXKL8e7ln40eCO+p4tY= 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 --- 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 (#51007): https://edk2.groups.io/g/devel/message/51007 Mute This Topic: https://groups.io/mt/61068919/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-