diff --git a/Makefile b/Makefile index 9d31d0d05..ea4966d84 100644 --- a/Makefile +++ b/Makefile @@ -1270,6 +1270,7 @@ $(eval $(call assert_numerics,\ ENABLE_FEAT_S1PIE \ ENABLE_FEAT_S2POE \ ENABLE_FEAT_S1POE \ + ENABLE_FEAT_SCTLR2 \ ENABLE_FEAT_GCS \ ENABLE_FEAT_VHE \ ENABLE_FEAT_MPAM \ @@ -1427,6 +1428,7 @@ $(eval $(call add_defines,\ ENABLE_FEAT_S1PIE \ ENABLE_FEAT_S2POE \ ENABLE_FEAT_S1POE \ + ENABLE_FEAT_SCTLR2 \ ENABLE_FEAT_GCS \ ENABLE_FEAT_MTE2 \ FEATURE_DETECTION \ diff --git a/common/feat_detect.c b/common/feat_detect.c index aa2ddfecd..e63eec408 100644 --- a/common/feat_detect.c +++ b/common/feat_detect.c @@ -263,6 +263,12 @@ static unsigned int read_feat_the_id_field(void) ID_AA64PFR1_EL1_THE_MASK); } +static unsigned int read_feat_sctlr2_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_SCTLR2_SHIFT, + ID_AA64MMFR3_EL1_SCTLR2_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 @@ -373,6 +379,8 @@ void detect_arch_features(void) "DEBUGV8P9", 11, 11); check_feature(ENABLE_FEAT_THE, read_feat_the_id_field(), "THE", 1, 1); + check_feature(ENABLE_FEAT_SCTLR2, read_feat_sctlr2_id_field(), + "SCTLR2", 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 c01d8839c..7776f5bca 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -463,6 +463,14 @@ Common build options This flag can take the values 0 to 2, to align with the ``ENABLE_FEAT`` mechanism. Default value is ``0``. +- ``ENABLE_FEAT_SCTLR2``: Numeric value to enable support for FEAT_SCTLR2 + (Extension to SCTLR_ELx) at EL2 and below, setting the bit + SCR_EL3.SCTLR2En in EL3 to allow access to SCTLR2_ELx registers and + context switch them. This feature is OPTIONAL from Armv8.0 implementations + and mandatory in Armv8.9 implementations. + 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 65247ec09..814561623 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -406,6 +406,10 @@ #define ID_AA64MMFR3_EL1_S1PIE_SHIFT U(8) #define ID_AA64MMFR3_EL1_S1PIE_MASK ULL(0xf) +#define ID_AA64MMFR3_EL1_SCTLR2_SHIFT U(4) +#define ID_AA64MMFR3_EL1_SCTLR2_MASK ULL(0xf) +#define SCTLR2_IMPLEMENTED ULL(1) + #define ID_AA64MMFR3_EL1_TCRX_SHIFT U(0) #define ID_AA64MMFR3_EL1_TCRX_MASK ULL(0xf) @@ -593,6 +597,7 @@ #define SCR_TWEDEL_SHIFT U(30) #define SCR_TWEDEL_MASK ULL(0xf) #define SCR_PIEN_BIT (UL(1) << 45) +#define SCR_SCTLR2En_BIT (UL(1) << 44) #define SCR_TCR2EN_BIT (UL(1) << 43) #define SCR_RCWMASKEn_BIT (UL(1) << 42) #define SCR_TRNDR_BIT (UL(1) << 40) @@ -1483,6 +1488,12 @@ #define RCWMASK_EL1 S3_0_C13_C0_6 #define RCWSMASK_EL1 S3_0_C13_C0_3 +/******************************************************************************* + * FEAT_SCTLR2 - Extension to SCTLR_ELx Registers + ******************************************************************************/ +#define SCTLR2_EL2 S3_4_C1_C0_3 +#define SCTLR2_EL1 S3_0_C1_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 fcd0ee6ba..de21feab7 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -136,6 +136,8 @@ CREATE_FEATURE_SUPPORTED(name, is_ ## name ## _present, guard) * +----------------------------+ * | FEAT_THE | * +----------------------------+ + * | FEAT_SCTLR2 | + * +----------------------------+ */ __attribute__((always_inline)) @@ -268,6 +270,11 @@ CREATE_FEATURE_FUNCS(feat_s1pie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1PIE_SHIFT, CREATE_FEATURE_FUNCS(feat_the, id_aa64pfr1_el1, ID_AA64PFR1_EL1_THE_SHIFT, ID_AA64PFR1_EL1_THE_MASK, THE_IMPLEMENTED, ENABLE_FEAT_THE) +/* FEAT_SCTLR2 */ +CREATE_FEATURE_FUNCS(feat_sctlr2, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_SCTLR2_SHIFT, + ID_AA64MMFR3_EL1_SCTLR2_MASK, SCTLR2_IMPLEMENTED, + ENABLE_FEAT_SCTLR2) + __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 49f134577..acaa1b8ee 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -674,6 +674,10 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el0, GCSPR_EL0) DEFINE_RENAME_SYSREG_RW_FUNCS(rcwmask_el1, RCWMASK_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(rcwsmask_el1, RCWSMASK_EL1) +/* FEAT_SCTLR2 Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el1, SCTLR2_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el2, SCTLR2_EL2) + /* 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 ab3be6357..94af21080 100644 --- a/include/lib/el3_runtime/context_el1.h +++ b/include/lib/el3_runtime/context_el1.h @@ -112,6 +112,10 @@ typedef struct el1_the_regs { uint64_t rcwsmask_el1; } el1_the_regs_t; +typedef struct el1_sctlr2_regs { + uint64_t sctlr2_el1; +} el1_sctlr2_regs_t; + typedef struct el1_sysregs { el1_common_regs_t common; @@ -164,6 +168,10 @@ typedef struct el1_sysregs { el1_the_regs_t the; #endif +#if ENABLE_FEAT_SCTLR2 + el1_sctlr2_regs_t sctlr2; +#endif + } el1_sysregs_t; @@ -285,6 +293,15 @@ typedef struct el1_sysregs { #define write_el1_ctx_the(ctx, reg, val) #endif /* ENABLE_FEAT_THE */ +#if ENABLE_FEAT_SCTLR2 +#define read_el1_ctx_sctlr2(ctx, reg) (((ctx)->sctlr2).reg) +#define write_el1_ctx_sctlr2(ctx, reg, val) ((((ctx)->sctlr2).reg) \ + = (uint64_t) (val)) +#else +#define read_el1_ctx_sctlr2(ctx, reg) ULL(0) +#define write_el1_ctx_sctlr2(ctx, reg, val) +#endif /* ENABLE_FEAT_SCTLR2 */ + /******************************************************************************/ #endif /* __ASSEMBLER__ */ diff --git a/include/lib/el3_runtime/context_el2.h b/include/lib/el3_runtime/context_el2.h index 14c1fb626..ad0b68f7c 100644 --- a/include/lib/el3_runtime/context_el2.h +++ b/include/lib/el3_runtime/context_el2.h @@ -135,6 +135,10 @@ typedef struct el2_mpam_regs { uint64_t mpamvpmv_el2; } el2_mpam_regs_t; +typedef struct el2_sctlr2_regs { + uint64_t sctlr2_el2; +} el2_sctlr2_regs_t; + typedef struct el2_sysregs { el2_common_regs_t common; @@ -203,6 +207,10 @@ typedef struct el2_sysregs { el2_mpam_regs_t mpam; #endif +#if ENABLE_FEAT_SCTLR2 + el2_sctlr2_regs_t sctlr2; +#endif + } el2_sysregs_t; /* @@ -358,6 +366,15 @@ typedef struct el2_sysregs { #define write_el2_ctx_mpam(ctx, reg, val) #endif /* CTX_INCLUDE_MPAM_REGS */ +#if ENABLE_FEAT_SCTLR2 +#define read_el2_ctx_sctlr2(ctx, reg) (((ctx)->sctlr2).reg) +#define write_el2_ctx_sctlr2(ctx, reg, val) ((((ctx)->sctlr2).reg) \ + = (uint64_t) (val)) +#else +#define read_el2_ctx_sctlr2(ctx, reg) ULL(0) +#define write_el2_ctx_sctlr2(ctx, reg, val) +#endif /* ENABLE_FEAT_SCTLR2 */ + /******************************************************************************/ #endif /* __ASSEMBLER__ */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index f1c872b19..7c84e0ee6 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -268,6 +268,13 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info * scr_el3 |= SCR_RCWMASKEn_BIT; } + if (is_feat_sctlr2_supported()) { + /* Set the SCTLR2En bit in SCR_EL3 to enable access to + * SCTLR2_ELx registers. + */ + scr_el3 |= SCR_SCTLR2En_BIT; + } + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); /* Initialize EL2 context registers */ @@ -1445,6 +1452,10 @@ void cm_el2_sysregs_context_save(uint32_t security_state) write_el2_ctx_gcs(el2_sysregs_ctx, gcscr_el2, read_gcscr_el2()); write_el2_ctx_gcs(el2_sysregs_ctx, gcspr_el2, read_gcspr_el2()); } + + if (is_feat_sctlr2_supported()) { + write_el2_ctx_sctlr2(el2_sysregs_ctx, sctlr2_el2, read_sctlr2_el2()); + } } /******************************************************************************* @@ -1532,6 +1543,10 @@ void cm_el2_sysregs_context_restore(uint32_t security_state) write_gcscr_el2(read_el2_ctx_gcs(el2_sysregs_ctx, gcscr_el2)); write_gcspr_el2(read_el2_ctx_gcs(el2_sysregs_ctx, gcspr_el2)); } + + if (is_feat_sctlr2_supported()) { + write_sctlr2_el2(read_el2_ctx_sctlr2(el2_sysregs_ctx, sctlr2_el2)); + } } #endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */ @@ -1726,6 +1741,10 @@ static void el1_sysregs_context_save(el1_sysregs_t *ctx) write_el1_ctx_the(ctx, rcwsmask_el1, read_rcwsmask_el1()); } + if (is_feat_sctlr2_supported()) { + write_el1_ctx_sctlr2(ctx, sctlr2_el1, read_sctlr2_el1()); + } + } static void el1_sysregs_context_restore(el1_sysregs_t *ctx) @@ -1826,6 +1845,11 @@ static void el1_sysregs_context_restore(el1_sysregs_t *ctx) write_rcwmask_el1(read_el1_ctx_the(ctx, rcwmask_el1)); write_rcwsmask_el1(read_el1_ctx_the(ctx, rcwsmask_el1)); } + + if (is_feat_sctlr2_supported()) { + write_sctlr2_el1(read_el1_ctx_sctlr2(ctx, sctlr2_el1)); + } + } /******************************************************************************* diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk index 9cd501157..9533e986c 100644 --- a/make_helpers/arch_features.mk +++ b/make_helpers/arch_features.mk @@ -90,7 +90,7 @@ endif # Enable the features which are mandatory from ARCH version 8.9 and upwards. ifeq "8.9" "$(word 1, $(sort 8.9 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" -armv8-9-a-feats := ENABLE_FEAT_TCR2 ENABLE_FEAT_DEBUGV8P9 +armv8-9-a-feats := ENABLE_FEAT_TCR2 ENABLE_FEAT_DEBUGV8P9 ENABLE_FEAT_SCTLR2 # 8.8 Compliant armv8-9-a-feats += ${armv8-8-a-feats} FEAT_LIST := ${armv8-9-a-feats} @@ -219,6 +219,9 @@ ENABLE_FEAT_HCX ?= 0 # Flag to enable access to TCR2 (FEAT_TCR2). ENABLE_FEAT_TCR2 ?= 0 +# Flag to enable access to SCTLR2 (FEAT_SCTLR2). +ENABLE_FEAT_SCTLR2 ?= 0 + # ################################################################################ # Optional Features defaulted to 0 or 2, if they are not enabled from diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 0a9ace6a4..33e1febac 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -77,6 +77,7 @@ ENABLE_FEAT_S2PIE := 2 ENABLE_FEAT_S1PIE := 2 ENABLE_FEAT_S2POE := 2 ENABLE_FEAT_S1POE := 2 +ENABLE_FEAT_SCTLR2 := 2 ENABLE_FEAT_MTE2 := 2 # The FVP platform depends on this macro to build with correct GIC driver.