From 062b6c6bf23f9656332b0aa3fed59c15f34f9361 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 14 Mar 2023 20:48:43 +0000 Subject: [PATCH] feat(pie/por): support permission indirection and overlay Arm v8.9 introduces a series of features providing a new way to set memory permissions. Instead of directly encoding the permissions in the page tables the PTEs contain indexes into an array of permissions stored in system registers, allowing greater flexibility and density of encoding. Enable access to these features for EL2 and below, context switching the newly added EL2 registers as appropriate. Since all of FEAT_S[12]P[IO]E are separately discoverable we have separate build time options for enabling them, but note that there is overlap in the registers that they implement and the enable bit required for lower EL access. Change the FVP platform to default to handling them as dynamic options so the right decision can be made by the code at runtime. Signed-off-by: Mark Brown Change-Id: Icf89e444e39e1af768739668b505661df18fb234 --- Makefile | 8 +++ common/feat_detect.c | 8 +++ docs/getting_started/build-options.rst | 20 ++++++ include/arch/aarch64/arch.h | 22 ++++++ include/arch/aarch64/arch_features.h | 82 +++++++++++++++++++++++ include/arch/aarch64/arch_helpers.h | 8 +++ include/lib/el3_runtime/aarch64/context.h | 6 +- lib/el3_runtime/aarch64/context_mgmt.c | 28 ++++++++ make_helpers/defaults.mk | 12 ++++ plat/arm/board/fvp/platform.mk | 4 ++ 10 files changed, 197 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4b6086333..98e448fab 100644 --- a/Makefile +++ b/Makefile @@ -1185,6 +1185,10 @@ $(eval $(call assert_numerics,\ ENABLE_FEAT_RNG_TRAP \ ENABLE_FEAT_SEL2 \ ENABLE_FEAT_TCR2 \ + ENABLE_FEAT_S2PIE \ + ENABLE_FEAT_S1PIE \ + ENABLE_FEAT_S2POE \ + ENABLE_FEAT_S1POE \ ENABLE_FEAT_VHE \ ENABLE_MPAM_FOR_LOWER_ELS \ ENABLE_RME \ @@ -1321,6 +1325,10 @@ $(eval $(call add_defines,\ ENABLE_FEAT_CSV2_2 \ ENABLE_FEAT_PAN \ ENABLE_FEAT_TCR2 \ + ENABLE_FEAT_S2PIE \ + ENABLE_FEAT_S1PIE \ + ENABLE_FEAT_S2POE \ + ENABLE_FEAT_S1POE \ FEATURE_DETECTION \ TWED_DELAY \ ENABLE_FEAT_TWED \ diff --git a/common/feat_detect.c b/common/feat_detect.c index 9394304bf..1582b9dcb 100644 --- a/common/feat_detect.c +++ b/common/feat_detect.c @@ -210,6 +210,14 @@ void detect_arch_features(void) /* v8.9 features */ check_feature(ENABLE_FEAT_TCR2, read_feat_tcrx_id_field(), "TCR2", 1, 1); + check_feature(ENABLE_FEAT_S2PIE, read_feat_s2pie_id_field(), + "S2PIE", 1, 1); + check_feature(ENABLE_FEAT_S1PIE, read_feat_s1pie_id_field(), + "S1PIE", 1, 1); + check_feature(ENABLE_FEAT_S2POE, read_feat_s2poe_id_field(), + "S2POE", 1, 1); + check_feature(ENABLE_FEAT_S1POE, read_feat_s1poe_id_field(), + "S1POE", 1, 1); /* v9.0 features */ check_feature(ENABLE_BRBE_FOR_NS, read_feat_brbe_id_field(), diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index e078e47c6..03be7862e 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -354,6 +354,26 @@ Common build options flag can take the values 0 to 2, to align with the ``FEATURE_DETECTION`` mechanism. Default value is ``0``. +- ``ENABLE_FEAT_S2PIE``: Numeric value to enable support for FEAT_S2PIE + at EL2 and below, and context switch relevant registers. This flag + can take the values 0 to 2, to align with the ``FEATURE_DETECTION`` + mechanism. Default value is ``0``. + +- ``ENABLE_FEAT_S1PIE``: Numeric value to enable support for FEAT_S1PIE + at EL2 and below, and context switch relevant registers. This flag + can take the values 0 to 2, to align with the ``FEATURE_DETECTION`` + mechanism. Default value is ``0``. + +- ``ENABLE_FEAT_S2POE``: Numeric value to enable support for FEAT_S2POE + at EL2 and below, and context switch relevant registers. This flag + can take the values 0 to 2, to align with the ``FEATURE_DETECTION`` + mechanism. Default value is ``0``. + +- ``ENABLE_FEAT_S1POE``: Numeric value to enable support for FEAT_S1POE + at EL2 and below, and context switch relevant registers. This flag + can take the values 0 to 2, to align with the ``FEATURE_DETECTION`` + mechanism. Default value is ``0``. + - ``ENABLE_LTO``: Boolean option to enable Link Time Optimization (LTO) support in GCC for TF-A. This option is currently only supported for AArch64. Default is 0. diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index dee7fdcff..9b55658ff 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -355,6 +355,18 @@ /* ID_AA64MMFR3_EL1 definitions */ #define ID_AA64MMFR3_EL1 S3_0_C0_C7_3 +#define ID_AA64MMFR3_EL1_S2POE_SHIFT U(20) +#define ID_AA64MMFR3_EL1_S2POE_MASK ULL(0xf) + +#define ID_AA64MMFR3_EL1_S1POE_SHIFT U(16) +#define ID_AA64MMFR3_EL1_S1POE_MASK ULL(0xf) + +#define ID_AA64MMFR3_EL1_S2PIE_SHIFT U(12) +#define ID_AA64MMFR3_EL1_S2PIE_MASK ULL(0xf) + +#define ID_AA64MMFR3_EL1_S1PIE_SHIFT U(8) +#define ID_AA64MMFR3_EL1_S1PIE_MASK ULL(0xf) + #define ID_AA64MMFR3_EL1_TCRX_SHIFT U(0) #define ID_AA64MMFR3_EL1_TCRX_MASK ULL(0xf) @@ -512,6 +524,7 @@ #define SCR_GPF_BIT (UL(1) << 48) #define SCR_TWEDEL_SHIFT U(30) #define SCR_TWEDEL_MASK ULL(0xf) +#define SCR_PIEN_BIT (UL(1) << 45) #define SCR_TCR2EN_BIT (UL(1) << 43) #define SCR_TRNDR_BIT (UL(1) << 40) #define SCR_HXEn_BIT (UL(1) << 38) @@ -1320,6 +1333,15 @@ ******************************************************************************/ #define TCR2_EL2 S3_4_C2_C0_3 +/******************************************************************************* + * Permission indirection and overlay + ******************************************************************************/ + +#define PIRE0_EL2 S3_4_C10_C2_2 +#define PIR_EL2 S3_4_C10_C2_3 +#define POR_EL2 S3_4_C10_C2_4 +#define S2PIR_EL2 S3_4_C10_C2_5 + /******************************************************************************* * Definitions for DynamicIQ Shared Unit registers ******************************************************************************/ diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index 3ea08a665..840b117a0 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -234,6 +234,88 @@ static inline bool is_feat_tcr2_supported(void) return read_feat_tcrx_id_field() != 0U; } +static unsigned int read_feat_s2poe_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S2POE); +} + +static inline bool is_feat_s2poe_supported(void) +{ + if (ENABLE_FEAT_S2POE == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_FEAT_S2POE == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_s2poe_id_field() != 0U; +} + +static unsigned int read_feat_s1poe_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S1POE); +} + +static inline bool is_feat_s1poe_supported(void) +{ + if (ENABLE_FEAT_S1POE == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_FEAT_S1POE == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_s1poe_id_field() != 0U; +} + +static inline bool is_feat_sxpoe_supported(void) +{ + return is_feat_s1poe_supported() || is_feat_s2poe_supported(); +} + +static unsigned int read_feat_s2pie_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S2PIE); +} + +static inline bool is_feat_s2pie_supported(void) +{ + if (ENABLE_FEAT_S2PIE == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_FEAT_S2PIE == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_s2pie_id_field() != 0U; +} + +static unsigned int read_feat_s1pie_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S1PIE); +} + +static inline bool is_feat_s1pie_supported(void) +{ + if (ENABLE_FEAT_S1PIE == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_FEAT_S1PIE == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_s1pie_id_field() != 0U; +} + +static inline bool is_feat_sxpie_supported(void) +{ + return is_feat_s1pie_supported() || is_feat_s2pie_supported(); +} + /******************************************************************************* * Functions to identify the presence of the Activity Monitors Extension ******************************************************************************/ diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index 04b64be5c..f877f5bc8 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -605,6 +605,14 @@ DEFINE_RENAME_IDREG_READ_FUNC(id_aa64mmfr3_el1, ID_AA64MMFR3_EL1) /* FEAT_TCR2 Register */ DEFINE_RENAME_SYSREG_RW_FUNCS(tcr2_el2, TCR2_EL2) +/* FEAT_SxPIE Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(pire0_el2, PIRE0_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(pir_el2, PIR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(s2pir_el2, S2PIR_EL2) + +/* FEAT_SxPOE Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(por_el2, POR_EL2) + /* DynamIQ Shared Unit power management */ DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index e5e7e7422..a8e6d8ad2 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -230,9 +230,13 @@ // Starting with Armv8.9 #define CTX_TCR2_EL2 U(0x1d8) +#define CTX_POR_EL2 U(0x1e0) +#define CTX_PIRE0_EL2 U(0x1e8) +#define CTX_PIR_EL2 U(0x1f0) +#define CTX_S2PIR_EL2 U(0x1f8) /* Align to the next 16 byte boundary */ -#define CTX_EL2_SYSREGS_END U(0x1e0) +#define CTX_EL2_SYSREGS_END U(0x200) #endif /* CTX_INCLUDE_EL2_REGS */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 42166eb99..94d5ee1d2 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -354,6 +354,14 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e scr_el3 |= SCR_TCR2EN_BIT; } + /* + * SCR_EL3.PIEN: Enable permission indirection and overlay + * registers for AArch64 if present. + */ + if (is_feat_sxpie_supported() || is_feat_sxpoe_supported()) { + scr_el3 |= SCR_PIEN_BIT; + } + /* * CPTR_EL3 was initialized out of reset, copy that value to the * context register. @@ -994,6 +1002,16 @@ void cm_el2_sysregs_context_save(uint32_t security_state) if (is_feat_tcr2_supported()) { write_ctx_reg(el2_sysregs_ctx, CTX_TCR2_EL2, read_tcr2_el2()); } + if (is_feat_sxpie_supported()) { + write_ctx_reg(el2_sysregs_ctx, CTX_PIRE0_EL2, read_pire0_el2()); + write_ctx_reg(el2_sysregs_ctx, CTX_PIR_EL2, read_pir_el2()); + } + if (is_feat_s2pie_supported()) { + write_ctx_reg(el2_sysregs_ctx, CTX_S2PIR_EL2, read_s2pir_el2()); + } + if (is_feat_sxpoe_supported()) { + write_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2, read_por_el2()); + } } } @@ -1061,6 +1079,16 @@ void cm_el2_sysregs_context_restore(uint32_t security_state) if (is_feat_tcr2_supported()) { write_tcr2_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TCR2_EL2)); } + if (is_feat_sxpie_supported()) { + write_pire0_el2(read_ctx_reg(el2_sysregs_ctx, CTX_PIRE0_EL2)); + write_pir_el2(read_ctx_reg(el2_sysregs_ctx, CTX_PIR_EL2)); + } + if (is_feat_s2pie_supported()) { + write_s2pir_el2(read_ctx_reg(el2_sysregs_ctx, CTX_S2PIR_EL2)); + } + if (is_feat_sxpoe_supported()) { + write_por_el2(read_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2)); + } } } #endif /* CTX_INCLUDE_EL2_REGS */ diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index af980f518..808a058b2 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -176,6 +176,18 @@ ENABLE_FEAT_TWED := 0 # Flag to enable access to TCR2 (FEAT_TCR2) ENABLE_FEAT_TCR2 := 0 +# Flag to enable access to Stage 2 Permission Indirection (FEAT_S2PIE) +ENABLE_FEAT_S2PIE := 0 + +# Flag to enable access to Stage 1 Permission Indirection (FEAT_S1PIE) +ENABLE_FEAT_S1PIE := 0 + +# Flag to enable access to Stage 2 Permission Overlay (FEAT_S2POE) +ENABLE_FEAT_S2POE := 0 + +# Flag to enable access to Stage 1 Permission Overlay (FEAT_S1POE) +ENABLE_FEAT_S1POE := 0 + # By default BL31 encryption disabled ENCRYPT_BL31 := 0 diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index ab6e0bf5e..3fb323bd4 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -77,6 +77,10 @@ ENABLE_TRF_FOR_NS := 2 ENABLE_FEAT_ECV := 2 ENABLE_FEAT_FGT := 2 ENABLE_FEAT_TCR2 := 2 +ENABLE_FEAT_S2PIE := 2 +ENABLE_FEAT_S1PIE := 2 +ENABLE_FEAT_S2POE := 2 +ENABLE_FEAT_S1POE := 2 endif # The FVP platform depends on this macro to build with correct GIC driver.