diff --git a/Makefile b/Makefile index 98e448fab..5306ddfe5 100644 --- a/Makefile +++ b/Makefile @@ -1189,6 +1189,7 @@ $(eval $(call assert_numerics,\ ENABLE_FEAT_S1PIE \ ENABLE_FEAT_S2POE \ ENABLE_FEAT_S1POE \ + ENABLE_FEAT_GCS \ ENABLE_FEAT_VHE \ ENABLE_MPAM_FOR_LOWER_ELS \ ENABLE_RME \ @@ -1329,6 +1330,7 @@ $(eval $(call add_defines,\ ENABLE_FEAT_S1PIE \ ENABLE_FEAT_S2POE \ ENABLE_FEAT_S1POE \ + ENABLE_FEAT_GCS \ FEATURE_DETECTION \ TWED_DELAY \ ENABLE_FEAT_TWED \ diff --git a/changelog.yaml b/changelog.yaml index 7dcb4dfda..e416ad15f 100644 --- a/changelog.yaml +++ b/changelog.yaml @@ -104,6 +104,9 @@ subsections: - title: CPU feature / ID register handling in general scope: cpufeat + - title: Guarded Control Stack (FEAT_GCS) + scope: gcs + - title: Support for the `HCRX_EL2` register (FEAT_HCX) scope: hcx diff --git a/common/feat_detect.c b/common/feat_detect.c index 1582b9dcb..98b420a33 100644 --- a/common/feat_detect.c +++ b/common/feat_detect.c @@ -228,6 +228,10 @@ void detect_arch_features(void) /* v9.2 features */ check_feature(ENABLE_SME_FOR_NS, read_feat_sme_id_field(), "SME", 1, 2); + + /* v9.4 features */ + check_feature(ENABLE_FEAT_GCS, read_feat_gcs_id_field(), "GCS", 1, 1); + read_feat_rme(); if (tainted) { diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index 03be7862e..d2f463fab 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -374,6 +374,12 @@ Common build options can take the values 0 to 2, to align with the ``FEATURE_DETECTION`` mechanism. Default value is ``0``. +- ``ENABLE_FEAT_GCS``: Numeric value to set the bit SCR_EL3.GCSEn in EL3 to + allow use of Guarded Control Stack from EL2 as well as adding the GCS + registers to the EL2 context save/restore operations. 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 89f4b40bd..9e061bfb4 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -371,6 +371,9 @@ #define ID_AA64MMFR3_EL1_TCRX_MASK ULL(0xf) /* ID_AA64PFR1_EL1 definitions */ +#define ID_AA64PFR1_EL1_GCS_SHIFT U(44) +#define ID_AA64PFR1_EL1_GCS_MASK ULL(0xf) + #define ID_AA64PFR1_EL1_SSBS_SHIFT U(4) #define ID_AA64PFR1_EL1_SSBS_MASK ULL(0xf) @@ -527,6 +530,7 @@ #define SCR_PIEN_BIT (UL(1) << 45) #define SCR_TCR2EN_BIT (UL(1) << 43) #define SCR_TRNDR_BIT (UL(1) << 40) +#define SCR_GCSEn_BIT (UL(1) << 39) #define SCR_HXEn_BIT (UL(1) << 38) #define SCR_ENTP2_SHIFT U(41) #define SCR_ENTP2_BIT (UL(1) << SCR_ENTP2_SHIFT) @@ -1350,6 +1354,12 @@ #define POR_EL2 S3_4_C10_C2_4 #define S2PIR_EL2 S3_4_C10_C2_5 +/******************************************************************************* + * FEAT_GCS - Guarded Control Stack Registers + ******************************************************************************/ +#define GCSCR_EL2 S3_4_C2_C5_0 +#define GCSPR_EL2 S3_4_C2_C5_1 + /******************************************************************************* * Definitions for DynamicIQ Shared Unit registers ******************************************************************************/ diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index 840b117a0..16f4fb996 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -316,6 +316,24 @@ static inline bool is_feat_sxpie_supported(void) return is_feat_s1pie_supported() || is_feat_s2pie_supported(); } +static unsigned int read_feat_gcs_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_GCS); +} + +static inline bool is_feat_gcs_supported(void) +{ + if (ENABLE_FEAT_GCS == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_FEAT_GCS == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_gcs_id_field() != 0U; +} + /******************************************************************************* * 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 f877f5bc8..1b4bc1113 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -613,6 +613,10 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(s2pir_el2, S2PIR_EL2) /* FEAT_SxPOE Registers */ DEFINE_RENAME_SYSREG_RW_FUNCS(por_el2, POR_EL2) +/* FEAT_GCS Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(gcscr_el2, GCSCR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el2, GCSPR_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 a8e6d8ad2..dd2b83681 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -234,9 +234,11 @@ #define CTX_PIRE0_EL2 U(0x1e8) #define CTX_PIR_EL2 U(0x1f0) #define CTX_S2PIR_EL2 U(0x1f8) +#define CTX_GCSCR_EL2 U(0x200) +#define CTX_GCSPR_EL2 U(0x208) /* Align to the next 16 byte boundary */ -#define CTX_EL2_SYSREGS_END U(0x200) +#define CTX_EL2_SYSREGS_END U(0x210) #endif /* CTX_INCLUDE_EL2_REGS */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index c411b73ab..e38b34dcd 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -375,6 +375,13 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e scr_el3 |= SCR_PIEN_BIT; } + /* + * SCR_EL3.GCSEn: Enable GCS registers for AArch64 if present. + */ + if ((is_feat_gcs_supported()) && (GET_RW(ep->spsr) == MODE_RW_64)) { + scr_el3 |= SCR_GCSEn_BIT; + } + /* * CPTR_EL3 was initialized out of reset, copy that value to the * context register. @@ -1039,6 +1046,10 @@ void cm_el2_sysregs_context_save(uint32_t security_state) if (is_feat_sxpoe_supported()) { write_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2, read_por_el2()); } + if (is_feat_gcs_supported()) { + write_ctx_reg(el2_sysregs_ctx, CTX_GCSPR_EL2, read_gcspr_el2()); + write_ctx_reg(el2_sysregs_ctx, CTX_GCSCR_EL2, read_gcscr_el2()); + } } } @@ -1116,6 +1127,10 @@ void cm_el2_sysregs_context_restore(uint32_t security_state) if (is_feat_sxpoe_supported()) { write_por_el2(read_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2)); } + if (is_feat_gcs_supported()) { + write_gcscr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_GCSCR_EL2)); + write_gcspr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_GCSPR_EL2)); + } } } #endif /* CTX_INCLUDE_EL2_REGS */ diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 808a058b2..34a9bc6b9 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -188,6 +188,9 @@ ENABLE_FEAT_S2POE := 0 # Flag to enable access to Stage 1 Permission Overlay (FEAT_S1POE) ENABLE_FEAT_S1POE := 0 +# Flag to enable access to Guarded Control Stack (FEAT_GCS) +ENABLE_FEAT_GCS := 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 3fb323bd4..e81f1eb65 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -49,6 +49,7 @@ ifneq (${SPD}, tspd) ENABLE_MPAM_FOR_LOWER_ELS := 2 ENABLE_FEAT_RNG := 2 ENABLE_FEAT_TWED := 2 + ENABLE_FEAT_GCS := 2 ifeq (${ARCH},aarch64) ifeq (${SPM_MM}, 0) ifeq (${ENABLE_RME}, 0)