diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h index a53f60d988..fb1ae57b35 100644 --- a/ArmPkg/Include/Library/ArmLib.h +++ b/ArmPkg/Include/Library/ArmLib.h @@ -35,6 +35,12 @@ typedef enum { // Do NOT use below two attributes if you are not sure. ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_NONSHAREABLE, + // Special region types for memory that must be mapped with read-only or + // non-execute permissions from the very start, e.g., to support the use + // of the WXN virtual memory control. + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_RO, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XP, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE, } ARM_MEMORY_REGION_ATTRIBUTES; diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c index ee4c5c995c..7acfd2e89a 100644 --- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c @@ -37,12 +37,35 @@ ArmMemoryAttributeToPageAttribute ( IN ARM_MEMORY_REGION_ATTRIBUTES Attributes ) { + UINT64 Permissions; + + switch (Attributes) { + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_RO: + Permissions = TT_AP_NO_RO; + break; + + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XP: + case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE: + if (ArmReadCurrentEL () == AARCH64_EL2) { + Permissions = TT_XN_MASK; + } else { + Permissions = TT_UXN_MASK | TT_PXN_MASK; + } + + break; + default: + Permissions = 0; + break; + } + switch (Attributes) { case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_NONSHAREABLE: return TT_ATTR_INDX_MEMORY_WRITE_BACK; case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: - return TT_ATTR_INDX_MEMORY_WRITE_BACK | TT_SH_INNER_SHAREABLE; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_RO: + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XP: + return TT_ATTR_INDX_MEMORY_WRITE_BACK | TT_SH_INNER_SHAREABLE | Permissions; case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: return TT_ATTR_INDX_MEMORY_WRITE_THROUGH | TT_SH_INNER_SHAREABLE; @@ -54,11 +77,7 @@ ArmMemoryAttributeToPageAttribute ( default: ASSERT (0); case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE: - if (ArmReadCurrentEL () == AARCH64_EL2) { - return TT_ATTR_INDX_DEVICE_MEMORY | TT_XN_MASK; - } else { - return TT_ATTR_INDX_DEVICE_MEMORY | TT_UXN_MASK | TT_PXN_MASK; - } + return TT_ATTR_INDX_DEVICE_MEMORY | Permissions; } } diff --git a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c index 1542983574..00c5f42cd9 100644 --- a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c @@ -106,6 +106,14 @@ PopulateLevel2PageTable ( PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_BACK; PageAttributes &= ~TT_DESCRIPTOR_PAGE_S_SHARED; break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_RO: + PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_BACK; + PageAttributes |= TT_DESCRIPTOR_PAGE_AP_NO_RO; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XP: + PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_BACK; + PageAttributes |= TT_DESCRIPTOR_PAGE_XN_MASK; + break; case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_THROUGH; break; @@ -240,6 +248,14 @@ FillTranslationTable ( Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; Attributes &= ~TT_DESCRIPTOR_SECTION_S_SHARED; break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_RO: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; + Attributes |= TT_DESCRIPTOR_SECTION_AP_NO_RO; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XP: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; + Attributes |= TT_DESCRIPTOR_SECTION_XN_MASK; + break; case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH; break;