diff --git a/ArmPkg/Include/Chipset/AArch64.h b/ArmPkg/Include/Chipset/AArch64.h index 5390bf0a27..da4212f96b 100644 --- a/ArmPkg/Include/Chipset/AArch64.h +++ b/ArmPkg/Include/Chipset/AArch64.h @@ -26,6 +26,7 @@ // ID_AA64MMFR1 - AArch64 Memory Model Feature Register 0 definitions #define AARCH64_MMFR1_VH (0xF << 8) +#define AARCH64_MMFR1_PAN (0xF << 20) // ID_AA64PFR0 - AArch64 Processor Feature Register 0 definitions #define AARCH64_PFR0_FP (0xF << 16) @@ -234,6 +235,16 @@ ArmReadCurrentEL ( VOID ); +VOID +ArmSetPan ( + VOID + ); + +VOID +ArmClearPan ( + VOID + ); + UINTN ArmWriteCptr ( IN UINT64 Cptr diff --git a/ArmPkg/Include/Chipset/AArch64Mmu.h b/ArmPkg/Include/Chipset/AArch64Mmu.h index 2ea2cc0a87..1eb8e83f19 100644 --- a/ArmPkg/Include/Chipset/AArch64Mmu.h +++ b/ArmPkg/Include/Chipset/AArch64Mmu.h @@ -134,6 +134,8 @@ #define TCR_EL1_AS_FIELD (36) #define TCR_EL1_TBI0_FIELD (37) #define TCR_EL1_TBI1_FIELD (38) +#define TCR_EL1_HPD0_FIELD (41) +#define TCR_EL1_HPD1_FIELD (42) #define TCR_EL1_T0SZ_MASK (0x1FUL << TCR_EL1_T0SZ_FIELD) #define TCR_EL1_EPD0_MASK (0x01UL << TCR_EL1_EPD0_FIELD) #define TCR_EL1_IRGN0_MASK (0x03UL << TCR_EL1_IRGN0_FIELD) @@ -151,6 +153,8 @@ #define TCR_EL1_AS_MASK (0x01UL << TCR_EL1_AS_FIELD) #define TCR_EL1_TBI0_MASK (0x01UL << TCR_EL1_TBI0_FIELD) #define TCR_EL1_TBI1_MASK (0x01UL << TCR_EL1_TBI1_FIELD) +#define TCR_EL1_HPD0_MASK (0x01UL << TCR_EL1_HPD0_FIELD) +#define TCR_EL1_HPD1_MASK (0x01UL << TCR_EL1_HPD1_FIELD) #define TCR_EL23_T0SZ_FIELD (0) #define TCR_EL23_IRGN0_FIELD (8) diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h index 6aa8a48f07..e13f36ce53 100644 --- a/ArmPkg/Include/Library/ArmLib.h +++ b/ArmPkg/Include/Library/ArmLib.h @@ -781,6 +781,18 @@ ArmHasVhe ( VOID ); +/** + Checks whether the CPU implements the Privileged Access Never. + + @retval TRUE FEAT_PAN is implemented. + @retval FALSE FEAT_PAN is not mplemented. +**/ +BOOLEAN +EFIAPI +ArmHasPan ( + VOID + ); + /** Checks whether the CPU implements the Trace Buffer Extension. diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c index 8728546587..d9c9caeff7 100644 --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c @@ -120,6 +120,21 @@ ArmHasVhe ( return ((ArmReadIdAA64Mmfr1 () & AARCH64_MMFR1_VH) != 0); } +/** + Checks whether the CPU implements the Privileged Access Never. + + @retval TRUE FEAT_PAN is implemented. + @retval FALSE FEAT_PAN is not mplemented. +**/ +BOOLEAN +EFIAPI +ArmHasPan ( + VOID + ) +{ + return ((ArmReadIdAA64Mmfr1 () & AARCH64_MMFR1_PAN) != 0); +} + /** Checks whether the CPU implements the Trace Buffer Extension. diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S index a7111e5188..37c5ad0662 100644 --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S @@ -464,6 +464,16 @@ ASM_FUNC(ArmReadCurrentEL) mrs x0, CurrentEL ret +// VOID ArmSetPan(VOID) +ASM_FUNC(ArmSetPan) + msr pan, #1 + ret + +// VOID ArmClearPan(VOID) +ASM_FUNC(ArmClearPan) + msr pan, #0 + ret + // UINT32 ArmReadCntHctl(VOID) ASM_FUNC(ArmReadCntHctl) mrs x0, cnthctl_el2 diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c index ffd058f13b..f3507b2f27 100644 --- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c @@ -451,14 +451,28 @@ GcdAttributeToPageAttribute ( } } - if ((GcdAttributes & EFI_MEMORY_RO) != 0) { - PageAttributes |= TT_AP_NO_RO; - } - if ((GcdAttributes & EFI_MEMORY_RP) == 0) { PageAttributes |= TT_AF; } + if ((GcdAttributes & EFI_MEMORY_USER) != 0) { + PageAttributes |= TT_PXN_MASK; + + if ((GcdAttributes & EFI_MEMORY_RO) != 0) { + PageAttributes |= TT_AP_RO_RO; + } else { + PageAttributes |= TT_AP_RW_RW; + } + } else { + PageAttributes |= TT_UXN_MASK; + + if ((GcdAttributes & EFI_MEMORY_RO) != 0) { + PageAttributes |= TT_AP_NO_RO; + } else { + PageAttributes |= TT_AP_NO_RW; + } + } + return PageAttributes; } diff --git a/ArmPkg/Library/CpuArchLib/AArch64/Mmu.c b/ArmPkg/Library/CpuArchLib/AArch64/Mmu.c index ff14c2f814..922fdbbb14 100644 --- a/ArmPkg/Library/CpuArchLib/AArch64/Mmu.c +++ b/ArmPkg/Library/CpuArchLib/AArch64/Mmu.c @@ -385,13 +385,27 @@ EfiAttributeToArmAttribute ( } // Determine protection attributes - if ((EfiAttributes & EFI_MEMORY_RO) != 0) { - ArmAttributes |= TT_AP_NO_RO; + if ((EfiAttributes & EFI_MEMORY_USER) != 0) { + ArmAttributes |= TT_PXN_MASK; + + if ((EfiAttributes & EFI_MEMORY_RO) != 0) { + ArmAttributes |= TT_AP_RO_RO; + } else { + ArmAttributes |= TT_AP_RW_RW; + } + } else { + ArmAttributes |= TT_UXN_MASK; + + if ((EfiAttributes & EFI_MEMORY_RO) != 0) { + ArmAttributes |= TT_AP_NO_RO; + } else { + ArmAttributes |= TT_AP_NO_RW; + } } // Process eXecute Never attribute if ((EfiAttributes & EFI_MEMORY_XP) != 0) { - ArmAttributes |= TT_PXN_MASK; + ArmAttributes |= TT_PXN_MASK | TT_UXN_MASK; } return ArmAttributes; diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc index e0ec532f12..f513075652 100644 --- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc +++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc @@ -39,6 +39,7 @@ READ_LOCK_CAP = TRUE READ_LOCK_STATUS = TRUE APRIORI DXE { + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf INF MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf } diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template index da055561cb..f00a8db12b 100755 --- a/BaseTools/Conf/tools_def.template +++ b/BaseTools/Conf/tools_def.template @@ -787,7 +787,7 @@ DEFINE GCC5_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -Wl,-melf_ DEFINE GCC5_X64_DLINK2_FLAGS = DEF(GCC_DLINK2_FLAGS_COMMON) -Wno-error DEFINE GCC5_ASM_FLAGS = DEF(GCC_ASM_FLAGS) DEFINE GCC5_ARM_ASM_FLAGS = DEF(GCC_ASM_FLAGS) -mlittle-endian -march=armv7-a -DEFINE GCC5_AARCH64_ASM_FLAGS = DEF(GCC_ASM_FLAGS) -mlittle-endian +DEFINE GCC5_AARCH64_ASM_FLAGS = DEF(GCC_ASM_FLAGS) -mlittle-endian -mcpu=cortex-a76 DEFINE GCC5_ARM_CC_FLAGS = DEF(GCC_ARM_CC_FLAGS) -fstack-protector -mword-relocations DEFINE GCC5_AARCH64_CC_FLAGS = DEF(GCC5_ALL_CC_FLAGS) DEF(GCC_AARCH64_CC_FLAGS) -mcmodel=small DEFINE GCC5_ARM_DLINK_FLAGS = DEF(GCC_ARM_DLINK_FLAGS) -Wl,--oformat=elf32-littlearm @@ -1291,7 +1291,7 @@ DEFINE CLANGDWARF_AARCH64_DLINK_FLAGS = DEF(CLANGDWARF_AARCH64_TARGET) DEF(GCC_ *_CLANGDWARF_AARCH64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -fno-lto *_CLANGDWARF_AARCH64_ASLDLINK_FLAGS = DEF(CLANGDWARF_AARCH64_TARGET) DEF(GCC_AARCH64_ASLDLINK_FLAGS) -fuse-ld=lld -*_CLANGDWARF_AARCH64_ASM_FLAGS = DEF(GCC_ASM_FLAGS) DEF(CLANGDWARF_AARCH64_TARGET) -Qunused-arguments +*_CLANGDWARF_AARCH64_ASM_FLAGS = DEF(GCC_ASM_FLAGS) DEF(CLANGDWARF_AARCH64_TARGET) -Qunused-arguments -mcpu=cortex-a76 *_CLANGDWARF_AARCH64_DLINK_FLAGS = DEF(CLANGDWARF_AARCH64_TARGET) DEF(GCC_AARCH64_DLINK_FLAGS) DEF(GCC_ALIGN) *_CLANGDWARF_AARCH64_DLINK_SECPEIFLAGS = DEF(GCC_ALIGN) *_CLANGDWARF_AARCH64_DLINK2_FLAGS = DEF(GCC_DLINK2_FLAGS_COMMON) diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c index bc844910fd..a6466e0cf2 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c +++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c @@ -5,6 +5,9 @@ **/ +#include +#include + #include "DxeMain.h" VOID @@ -13,5 +16,28 @@ InitializeMsr ( VOID ) { + UINTN Tcr; + // + // If HCR_EL2.NV is 1 and the current Exception level is EL1, + // then EL1 read accesses to the CurrentEL register return a value of 0x2 in bits[3:2]. + // CurrentEL == 1 -> HCR_EL2.NV == 0 + // + // If stage 1 is enabled and stage 1 Base permissions use Direct permissions, + // then GCS access is not permitted and UnprivGCS and PrivGCS are not present. + // + // Disable Hierarchical permissions just in case. + // + Tcr = ArmGetTCR (); + Tcr |= TCR_EL1_HPD0_MASK | TCR_EL1_HPD1_MASK; + ArmSetTCR (Tcr); + if (ArmHasPan ()) { + // + // Enable Privileged Access Never feature. + // + ArmSetPan (); + } else { + DEBUG ((DEBUG_ERROR, "Core: Failed to initialize MSRs for Ring3.\n")); + ASSERT (FALSE); + } }