From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by mx.groups.io with SMTP id smtpd.web10.68447.1675722079360355261 for ; Mon, 06 Feb 2023 14:21:19 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=UM86taBX; spf=pass (domain: kernel.org, ip: 139.178.84.217, mailfrom: ardb@kernel.org) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id D72A960F73; Mon, 6 Feb 2023 22:21:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2347EC4339C; Mon, 6 Feb 2023 22:21:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1675722078; bh=lOHSykKlTShJdV7FkwfQQSlaUv1wazgzh1OaIauapJw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UM86taBXFcwG5pGilO2/r+xV+tkRpIAUuzjO6yYHWjfIg6oT0Z3OvGXLXLLUYgxYh rzY6+jRmX7LL4uuGzVqo0afpEo/CtvWC9eLuDi1m+00NUah3BP1hIEQAYFdMzdZdcY ozPp5zD+lZdZ4OamEqGzhVpX0lZIRC0Pm/S7URbjvJ4Q45zqlMytUXaveKDoGzejFL gKIO9F/3GaEnntsYIka/IiEyZk0yUxdJwLSna00ot3bbrJzkv6Gp3PG3540ZX+pGoK GpY7dY0YGZbL+rTez02glJlWVNTqhoNRFX03iRGPncS4xk33kT9mxj28rcGYlBFfh9 rOjRuNx1JscLg== From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Michael Kinney , Liming Gao , Jiewen Yao , Michael Kubacki , Sean Brogan , Rebecca Cran , Leif Lindholm , Sami Mujawar , Taylor Beebe Subject: [PATCH v3 4/5] ArmPkg/CpuDxe: Implement EFI memory attributes protocol Date: Mon, 6 Feb 2023 23:20:59 +0100 Message-Id: <20230206222100.411169-5-ardb@kernel.org> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20230206222100.411169-1-ardb@kernel.org> References: <20230206222100.411169-1-ardb@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Expose the protocol introduced in v2.10 that permits the caller to manage mapping permissions in the page tables. Signed-off-by: Ard Biesheuvel --- ArmPkg/Drivers/CpuDxe/CpuDxe.c | 2 + ArmPkg/Drivers/CpuDxe/CpuDxe.h | 3 + ArmPkg/Drivers/CpuDxe/CpuDxe.inf | 2 + ArmPkg/Drivers/CpuDxe/MemoryAttribute.c | 252 ++++++++++++++++++++ 4 files changed, 259 insertions(+) diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.c b/ArmPkg/Drivers/CpuDxe/CpuDxe.c index e6742f0a25fc..d04958e79e52 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.c +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.c @@ -244,6 +244,8 @@ CpuDxeInitialize ( &mCpuHandle,=0D &gEfiCpuArchProtocolGuid,=0D &mCpu,=0D + &gEfiMemoryAttributeProtocolGuid,=0D + &mMemoryAttribute,=0D NULL=0D );=0D =0D diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.h b/ArmPkg/Drivers/CpuDxe/CpuDxe.h index 5a9f1ef1f969..6cb5cd3d2e70 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.h +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.h @@ -30,9 +30,12 @@ #include =0D #include =0D #include =0D +#include =0D =0D extern BOOLEAN mIsFlushingGCD;=0D =0D +extern EFI_MEMORY_ATTRIBUTE_PROTOCOL mMemoryAttribute;=0D +=0D /**=0D This function registers and enables the handler specified by InterruptHa= ndler for a processor=0D interrupt or exception type specified by InterruptType. If InterruptHand= ler is NULL, then the=0D diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDx= e.inf index 10792b393fc8..e732e21cb94a 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf @@ -23,6 +23,7 @@ [Sources.Common] CpuDxe.h=0D CpuMmuCommon.c=0D Exception.c=0D + MemoryAttribute.c=0D =0D [Sources.ARM]=0D Arm/Mmu.c=0D @@ -53,6 +54,7 @@ [LibraryClasses] =0D [Protocols]=0D gEfiCpuArchProtocolGuid=0D + gEfiMemoryAttributeProtocolGuid=0D =0D [Guids]=0D gEfiDebugImageInfoTableGuid=0D diff --git a/ArmPkg/Drivers/CpuDxe/MemoryAttribute.c b/ArmPkg/Drivers/CpuDx= e/MemoryAttribute.c new file mode 100644 index 000000000000..379e90bd9d1d --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/MemoryAttribute.c @@ -0,0 +1,252 @@ +/** @file=0D +=0D + Copyright (c) 2023, Google LLC. All rights reserved.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include "CpuDxe.h"=0D +=0D +/**=0D + This function retrieves the attributes of the memory region specified by= =0D + BaseAddress and Length. If different attributes are got from different p= art=0D + of the memory region, EFI_NO_MAPPING will be returned.=0D +=0D + @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance.=0D + @param BaseAddress The physical address that is the start address= of=0D + a memory region.=0D + @param Length The size in bytes of the memory region.=0D + @param Attributes Pointer to attributes returned.=0D +=0D + @retval EFI_SUCCESS The attributes got for the memory region.= =0D + @retval EFI_INVALID_PARAMETER Length is zero.=0D + Attributes is NULL.=0D + @retval EFI_NO_MAPPING Attributes are not consistent cross the me= mory=0D + region.=0D + @retval EFI_UNSUPPORTED The processor does not support one or more= =0D + bytes of the memory resource range specifi= ed=0D + by BaseAddress and Length.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +GetMemoryAttributes (=0D + IN EFI_MEMORY_ATTRIBUTE_PROTOCOL *This,=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length,=0D + OUT UINT64 *Attributes=0D + )=0D +{=0D + UINTN RegionAddress;=0D + UINTN RegionLength;=0D + UINTN RegionAttributes;=0D + UINTN Union;=0D + UINTN Intersection;=0D + EFI_STATUS Status;=0D +=0D + if ((Length =3D=3D 0) || (Attributes =3D=3D NULL)) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + DEBUG ((DEBUG_VERBOSE,=0D + "%a: BaseAddress =3D=3D 0x%lx, Length =3D=3D 0x%lx\n",=0D + __FUNCTION__,=0D + BaseAddress,=0D + Length=0D + ));=0D +=0D + Union =3D 0;=0D + Intersection =3D MAX_UINTN;=0D +=0D + for (RegionAddress =3D (UINTN)BaseAddress;=0D + RegionAddress < (UINTN)(BaseAddress + Length);=0D + RegionAddress +=3D RegionLength) {=0D +=0D + Status =3D GetMemoryRegion (&RegionAddress,=0D + &RegionLength,=0D + &RegionAttributes=0D + );=0D +=0D + DEBUG ((DEBUG_VERBOSE,=0D + "%a: RegionAddress =3D=3D 0x%lx, RegionLength =3D=3D 0x%lx, Re= gionAttributes =3D=3D 0x%lx\n",=0D + __FUNCTION__,=0D + (UINT64)RegionAddress,=0D + (UINT64)RegionLength,=0D + (UINT64)RegionAttributes=0D + ));=0D +=0D + if (EFI_ERROR (Status)) {=0D + return EFI_NO_MAPPING;=0D + }=0D +=0D + Union |=3D RegionAttributes;=0D + Intersection &=3D RegionAttributes;=0D + }=0D +=0D + DEBUG ((DEBUG_VERBOSE,=0D + "%a: Union =3D=3D %lx, Intersection =3D=3D %lx\n",=0D + __FUNCTION__,=0D + (UINT64)Union,=0D + (UINT64)Intersection=0D + ));=0D +=0D + if (Union !=3D Intersection) {=0D + return EFI_NO_MAPPING;=0D + }=0D +=0D + *Attributes =3D RegionAttributeToGcdAttribute (Union) & (EFI_MEMORY_RO |= EFI_MEMORY_XP);=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + This function set given attributes of the memory region specified by=0D + BaseAddress and Length.=0D +=0D + The valid Attributes is EFI_MEMORY_RP, EFI_MEMORY_XP, and EFI_MEMORY_RO.= =0D +=0D + @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance.=0D + @param BaseAddress The physical address that is the start address= of=0D + a memory region.=0D + @param Length The size in bytes of the memory region.=0D + @param Attributes The bit mask of attributes to set for the memo= ry=0D + region.=0D +=0D + @retval EFI_SUCCESS The attributes were set for the memory reg= ion.=0D + @retval EFI_INVALID_PARAMETER Length is zero.=0D + Attributes specified an illegal combinatio= n of=0D + attributes that cannot be set together.=0D + @retval EFI_UNSUPPORTED The processor does not support one or more= =0D + bytes of the memory resource range specifi= ed=0D + by BaseAddress and Length.=0D + The bit mask of attributes is not supporte= d for=0D + the memory resource range specified by=0D + BaseAddress and Length.=0D + @retval EFI_OUT_OF_RESOURCES Requested attributes cannot be applied due= to=0D + lack of system resources.=0D + @retval EFI_ACCESS_DENIED Attributes for the requested memory region= are=0D + controlled by system firmware and cannot b= e=0D + updated via the protocol.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +SetMemoryAttributes (=0D + IN EFI_MEMORY_ATTRIBUTE_PROTOCOL *This,=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length,=0D + IN UINT64 Attributes=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + DEBUG ((DEBUG_INFO,=0D + "%a: BaseAddress =3D=3D 0x%lx, Length =3D=3D 0x%lx, Attributes = =3D=3D 0x%lx\n",=0D + __FUNCTION__,=0D + (UINTN)BaseAddress,=0D + (UINTN)Length,=0D + (UINTN)Attributes=0D + ));=0D +=0D + if ((Length =3D=3D 0) ||=0D + ((Attributes & ~(EFI_MEMORY_RO | EFI_MEMORY_RP | EFI_MEMORY_XP)) != =3D 0)) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + if ((Attributes & EFI_MEMORY_RP) !=3D 0) {=0D + return EFI_UNSUPPORTED;=0D + }=0D +=0D + if ((Attributes & EFI_MEMORY_RO) !=3D 0) {=0D + Status =3D ArmSetMemoryRegionReadOnly (BaseAddress, Length);=0D + if (EFI_ERROR (Status)) {=0D + return EFI_UNSUPPORTED;=0D + }=0D + }=0D +=0D + if ((Attributes & EFI_MEMORY_XP) !=3D 0) {=0D + Status =3D ArmSetMemoryRegionNoExec (BaseAddress, Length);=0D + if (EFI_ERROR (Status)) {=0D + return EFI_UNSUPPORTED;=0D + }=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + This function clears given attributes of the memory region specified by= =0D + BaseAddress and Length.=0D +=0D + The valid Attributes is EFI_MEMORY_RP, EFI_MEMORY_XP, and EFI_MEMORY_RO.= =0D +=0D + @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance.=0D + @param BaseAddress The physical address that is the start address= of=0D + a memory region.=0D + @param Length The size in bytes of the memory region.=0D + @param Attributes The bit mask of attributes to clear for the me= mory=0D + region.=0D +=0D + @retval EFI_SUCCESS The attributes were cleared for the memory= region.=0D + @retval EFI_INVALID_PARAMETER Length is zero.=0D + Attributes specified an illegal combinatio= n of=0D + attributes that cannot be cleared together= .=0D + @retval EFI_UNSUPPORTED The processor does not support one or more= =0D + bytes of the memory resource range specifi= ed=0D + by BaseAddress and Length.=0D + The bit mask of attributes is not supporte= d for=0D + the memory resource range specified by=0D + BaseAddress and Length.=0D + @retval EFI_OUT_OF_RESOURCES Requested attributes cannot be applied due= to=0D + lack of system resources.=0D + @retval EFI_ACCESS_DENIED Attributes for the requested memory region= are=0D + controlled by system firmware and cannot b= e=0D + updated via the protocol.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +ClearMemoryAttributes (=0D + IN EFI_MEMORY_ATTRIBUTE_PROTOCOL *This,=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length,=0D + IN UINT64 Attributes=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + DEBUG ((DEBUG_INFO,=0D + "%a: BaseAddress =3D=3D 0x%lx, Length =3D=3D 0x%lx, Attributes = =3D=3D 0x%lx\n",=0D + __FUNCTION__,=0D + (UINTN)BaseAddress,=0D + (UINTN)Length,=0D + (UINTN)Attributes=0D + ));=0D +=0D + if ((Length =3D=3D 0) ||=0D + ((Attributes & ~(EFI_MEMORY_RO | EFI_MEMORY_RP | EFI_MEMORY_XP)) != =3D 0)) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + if ((Attributes & EFI_MEMORY_RO) !=3D 0) {=0D + Status =3D ArmClearMemoryRegionReadOnly (BaseAddress, Length);=0D + if (EFI_ERROR (Status)) {=0D + return EFI_UNSUPPORTED;=0D + }=0D + }=0D +=0D + if ((Attributes & EFI_MEMORY_XP) !=3D 0) {=0D + Status =3D ArmClearMemoryRegionNoExec (BaseAddress, Length);=0D + if (EFI_ERROR (Status)) {=0D + return EFI_UNSUPPORTED;=0D + }=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +EFI_MEMORY_ATTRIBUTE_PROTOCOL mMemoryAttribute =3D {=0D + GetMemoryAttributes,=0D + SetMemoryAttributes,=0D + ClearMemoryAttributes=0D +};=0D --=20 2.39.1