diff --git a/Makefile b/Makefile index cc9060a05..9d31d0d05 100644 --- a/Makefile +++ b/Makefile @@ -1264,6 +1264,7 @@ $(eval $(call assert_numerics,\ ENABLE_FEAT_RNG_TRAP \ ENABLE_FEAT_SEL2 \ ENABLE_FEAT_TCR2 \ + ENABLE_FEAT_THE \ ENABLE_FEAT_SB \ ENABLE_FEAT_S2PIE \ ENABLE_FEAT_S1PIE \ @@ -1421,6 +1422,7 @@ $(eval $(call add_defines,\ ENABLE_FEAT_CSV2_3 \ ENABLE_FEAT_PAN \ ENABLE_FEAT_TCR2 \ + ENABLE_FEAT_THE \ ENABLE_FEAT_S2PIE \ ENABLE_FEAT_S1PIE \ ENABLE_FEAT_S2POE \ diff --git a/common/feat_detect.c b/common/feat_detect.c index 9b9f7b435..aa2ddfecd 100644 --- a/common/feat_detect.c +++ b/common/feat_detect.c @@ -257,6 +257,12 @@ static unsigned int read_feat_mtpmu_id_field(void) } +static unsigned int read_feat_the_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_THE_SHIFT, + ID_AA64PFR1_EL1_THE_MASK); +} + /*********************************************************************************** * TF-A supports many Arm architectural features starting from arch version * (8.0 till 8.7+). These features are mostly enabled through build flags. This @@ -365,6 +371,8 @@ void detect_arch_features(void) "CSV2_3", 3, 3); check_feature(ENABLE_FEAT_DEBUGV8P9, read_feat_debugv8p9_id_field(), "DEBUGV8P9", 11, 11); + check_feature(ENABLE_FEAT_THE, read_feat_the_id_field(), + "THE", 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 203bf0f7d..c01d8839c 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -455,6 +455,14 @@ Common build options the values 0 to 2, to align with the ``ENABLE_FEAT`` mechanism. Default value is ``0``. +- ``ENABLE_FEAT_THE``: Numeric value to enable support for FEAT_THE + (Translation Hardening Extension) at EL2 and below, setting the bit + SCR_EL3.RCWMASKEn in EL3 to allow access to RCWMASK_EL1 and RCWSMASK_EL1 + registers and context switch them. + Its an optional architectural feature and is available from v8.8 and upwards. + This flag can take the values 0 to 2, to align with the ``ENABLE_FEAT`` + 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 d8ad8814d..65247ec09 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -433,6 +433,10 @@ #define ID_AA64PFR1_EL1_GCS_MASK ULL(0xf) #define GCS_IMPLEMENTED ULL(1) +#define ID_AA64PFR1_EL1_THE_SHIFT U(48) +#define ID_AA64PFR1_EL1_THE_MASK ULL(0xf) +#define THE_IMPLEMENTED ULL(1) + #define RNG_TRAP_IMPLEMENTED ULL(0x1) /* ID_AA64PFR2_EL1 definitions */ @@ -590,6 +594,7 @@ #define SCR_TWEDEL_MASK ULL(0xf) #define SCR_PIEN_BIT (UL(1) << 45) #define SCR_TCR2EN_BIT (UL(1) << 43) +#define SCR_RCWMASKEn_BIT (UL(1) << 42) #define SCR_TRNDR_BIT (UL(1) << 40) #define SCR_GCSEn_BIT (UL(1) << 39) #define SCR_HXEn_BIT (UL(1) << 38) @@ -1472,6 +1477,12 @@ #define TRFCR_EL2 S3_4_C1_C2_1 #define TRFCR_EL1 S3_0_C1_C2_1 +/******************************************************************************* + * FEAT_THE - Translation Hardening Extension Registers + ******************************************************************************/ +#define RCWMASK_EL1 S3_0_C13_C0_6 +#define RCWSMASK_EL1 S3_0_C13_C0_3 + /******************************************************************************* * Definitions for DynamicIQ Shared Unit registers ******************************************************************************/ diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index f03c9d598..fcd0ee6ba 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -134,6 +134,8 @@ CREATE_FEATURE_SUPPORTED(name, is_ ## name ## _present, guard) * +----------------------------+ * | FEAT_FGT2 | * +----------------------------+ + * | FEAT_THE | + * +----------------------------+ */ __attribute__((always_inline)) @@ -262,6 +264,10 @@ CREATE_FEATURE_FUNCS(feat_s2pie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S2PIE_SHIFT, CREATE_FEATURE_FUNCS(feat_s1pie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1PIE_SHIFT, ID_AA64MMFR3_EL1_S1PIE_MASK, 1U, ENABLE_FEAT_S1PIE) +/* FEAT_THE: Translation Hardening Extension */ +CREATE_FEATURE_FUNCS(feat_the, id_aa64pfr1_el1, ID_AA64PFR1_EL1_THE_SHIFT, + ID_AA64PFR1_EL1_THE_MASK, THE_IMPLEMENTED, ENABLE_FEAT_THE) + __attribute__((always_inline)) static inline bool is_feat_sxpie_supported(void) { diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index a8926547e..49f134577 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -670,6 +670,10 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(gcscre0_el1, GCSCRE0_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el1, GCSPR_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el0, GCSPR_EL0) +/* FEAT_THE Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(rcwmask_el1, RCWMASK_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(rcwsmask_el1, RCWSMASK_EL1) + /* DynamIQ Control registers */ DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmcr_el1, CLUSTERPMCR_EL1) diff --git a/include/lib/el3_runtime/context_el1.h b/include/lib/el3_runtime/context_el1.h index 038de253b..ab3be6357 100644 --- a/include/lib/el3_runtime/context_el1.h +++ b/include/lib/el3_runtime/context_el1.h @@ -107,6 +107,11 @@ typedef struct el1_gcs_regs { uint64_t gcspr_el0; } el1_gcs_regs_t; +typedef struct el1_the_regs { + uint64_t rcwmask_el1; + uint64_t rcwsmask_el1; +} el1_the_regs_t; + typedef struct el1_sysregs { el1_common_regs_t common; @@ -155,6 +160,10 @@ typedef struct el1_sysregs { el1_gcs_regs_t gcs; #endif +#if ENABLE_FEAT_THE + el1_the_regs_t the; +#endif + } el1_sysregs_t; @@ -266,6 +275,16 @@ typedef struct el1_sysregs { #define read_el1_ctx_gcs(ctx, reg) ULL(0) #define write_el1_ctx_gcs(ctx, reg, val) #endif /* ENABLE_FEAT_GCS */ + +#if ENABLE_FEAT_THE +#define read_el1_ctx_the(ctx, reg) (((ctx)->the).reg) +#define write_el1_ctx_the(ctx, reg, val) ((((ctx)->the).reg) \ + = (uint64_t) (val)) +#else +#define read_el1_ctx_the(ctx, reg) ULL(0) +#define write_el1_ctx_the(ctx, reg, val) +#endif /* ENABLE_FEAT_THE */ + /******************************************************************************/ #endif /* __ASSEMBLER__ */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 62103565b..f1c872b19 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -260,6 +260,14 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info * */ scr_el3 |= get_scr_el3_from_routing_model(NON_SECURE); #endif + + if (is_feat_the_supported()) { + /* Set the RCWMASKEn bit in SCR_EL3 to enable access to + * RCWMASK_EL1 and RCWSMASK_EL1 registers. + */ + scr_el3 |= SCR_RCWMASKEn_BIT; + } + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); /* Initialize EL2 context registers */ @@ -1712,6 +1720,12 @@ static void el1_sysregs_context_save(el1_sysregs_t *ctx) write_el1_ctx_gcs(ctx, gcspr_el1, read_gcspr_el1()); write_el1_ctx_gcs(ctx, gcspr_el0, read_gcspr_el0()); } + + if (is_feat_the_supported()) { + write_el1_ctx_the(ctx, rcwmask_el1, read_rcwmask_el1()); + write_el1_ctx_the(ctx, rcwsmask_el1, read_rcwsmask_el1()); + } + } static void el1_sysregs_context_restore(el1_sysregs_t *ctx) @@ -1807,6 +1821,11 @@ static void el1_sysregs_context_restore(el1_sysregs_t *ctx) write_gcspr_el1(read_el1_ctx_gcs(ctx, gcspr_el1)); write_gcspr_el0(read_el1_ctx_gcs(ctx, gcspr_el0)); } + + if (is_feat_the_supported()) { + write_rcwmask_el1(read_el1_ctx_the(ctx, rcwmask_el1)); + write_rcwsmask_el1(read_el1_ctx_the(ctx, rcwsmask_el1)); + } } /******************************************************************************* diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk index 675779fde..9cd501157 100644 --- a/make_helpers/arch_features.mk +++ b/make_helpers/arch_features.mk @@ -340,6 +340,13 @@ DISABLE_MTPMU ?= 0 # Flag to enable FEAT_FGT2 (Fine Granular Traps 2) ENABLE_FEAT_FGT2 ?= 0 +#---- +# 8.8 +#---- + +# Flag to enable FEAT_THE (Translation Hardening Extension) +ENABLE_FEAT_THE ?= 0 + #---- # 8.9 #---- diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index ec2a5e961..0a9ace6a4 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -71,6 +71,7 @@ ENABLE_TRF_FOR_NS := 2 ENABLE_FEAT_ECV := 2 ENABLE_FEAT_FGT := 2 ENABLE_FEAT_FGT2 := 2 +ENABLE_FEAT_THE := 2 ENABLE_FEAT_TCR2 := 2 ENABLE_FEAT_S2PIE := 2 ENABLE_FEAT_S1PIE := 2