From b8f03d29e172af7bd576eafbce9d485a9f626e2e Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 17 Nov 2022 17:30:43 +0000 Subject: [PATCH] refactor(cpufeat): enable FEAT_ECV for FEAT_STATE_CHECKED At the moment we only support FEAT_ECV to be either unconditionally compiled in, or to be not supported at all. Add support for runtime detection (ENABLE_FEAT_ECV=2), by splitting is_feat_ecv_present() into an ID register reading function and a second function to report the support status. That function considers both build time settings and runtime information (if needed), and is used before we access the CNTPOFF_EL2 system register. Also move the context saving code from assembly to C, and use the new is_feat_ecv_supported() function to guard its execution. Change the FVP platform default to the now supported dynamic option (=2), so the right decision can be made by the code at runtime. Change-Id: I4acd5384929f1902b62a87ae073aafa1472cd66b Signed-off-by: Andre Przywara --- common/feat_detect.c | 15 +---------- include/arch/aarch64/arch_features.h | 31 ++++++++++++++++++++--- include/arch/aarch64/arch_helpers.h | 3 +++ include/lib/el3_runtime/aarch64/context.h | 4 --- lib/el3_runtime/aarch64/context.S | 18 ------------- lib/el3_runtime/aarch64/context_mgmt.c | 19 ++++++++------ plat/arm/board/fvp/platform.mk | 1 + 7 files changed, 44 insertions(+), 47 deletions(-) diff --git a/common/feat_detect.c b/common/feat_detect.c index c51da966c..2f64deb51 100644 --- a/common/feat_detect.c +++ b/common/feat_detect.c @@ -164,19 +164,6 @@ static void read_feat_amuv1p1(void) #endif } -/******************************************************* - * Feature : FEAT_ECV (Enhanced Counter Virtualization) - ******************************************************/ -static void read_feat_ecv(void) -{ -#if (ENABLE_FEAT_ECV == FEAT_STATE_ALWAYS) - unsigned int ecv = get_armv8_6_ecv_support(); - - feat_detect_panic(((ecv == ID_AA64MMFR0_EL1_ECV_SUPPORTED) || - (ecv == ID_AA64MMFR0_EL1_ECV_SELF_SYNCH)), "ECV"); -#endif -} - /*********************************************************** * Feature : FEAT_TWED (Delayed Trapping of WFE Instruction) **********************************************************/ @@ -269,7 +256,7 @@ void detect_arch_features(void) /* v8.6 features */ read_feat_amuv1p1(); check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT", 1, 1); - read_feat_ecv(); + check_feature(ENABLE_FEAT_ECV, read_feat_ecv_id_field(), "ECV", 1, 2); read_feat_twed(); /* v8.7 features */ diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index bdfdc4cce..029cdd112 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -143,10 +143,35 @@ static inline bool is_feat_fgt_supported(void) return read_feat_fgt_id_field() != 0U; } -static inline unsigned long int get_armv8_6_ecv_support(void) +static unsigned int read_feat_ecv_id_field(void) { - return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_ECV_SHIFT) & - ID_AA64MMFR0_EL1_ECV_MASK); + return ISOLATE_FIELD(read_id_aa64mmfr0_el1(), ID_AA64MMFR0_EL1_ECV); +} + +static inline bool is_feat_ecv_supported(void) +{ + if (ENABLE_FEAT_ECV == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_FEAT_ECV == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_ecv_id_field() != 0U; +} + +static inline bool is_feat_ecv_v2_supported(void) +{ + if (ENABLE_FEAT_ECV == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_FEAT_ECV == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_ecv_id_field() >= ID_AA64MMFR0_EL1_ECV_SELF_SYNCH; } static inline bool is_armv8_5_rng_present(void) diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index 6d115c7e5..720f6f3bd 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -590,6 +590,9 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(hfgitr_el2, HFGITR_EL2) DEFINE_RENAME_SYSREG_RW_FUNCS(hfgrtr_el2, HFGRTR_EL2) DEFINE_RENAME_SYSREG_RW_FUNCS(hfgwtr_el2, HFGWTR_EL2) +/* ARMv8.6 FEAT_ECV Register */ +DEFINE_RENAME_SYSREG_RW_FUNCS(cntpoff_el2, CNTPOFF_EL2) + /* FEAT_HCX Register */ DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index 9b50f3319..7d7fb5272 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -517,10 +517,6 @@ void el2_sysregs_context_restore_common(el2_sysregs_t *regs); void el2_sysregs_context_save_mte(el2_sysregs_t *regs); void el2_sysregs_context_restore_mte(el2_sysregs_t *regs); #endif /* CTX_INCLUDE_MTE_REGS */ -#if ENABLE_FEAT_ECV -void el2_sysregs_context_save_ecv(el2_sysregs_t *regs); -void el2_sysregs_context_restore_ecv(el2_sysregs_t *regs); -#endif /* ENABLE_FEAT_ECV */ #if RAS_EXTENSION void el2_sysregs_context_save_ras(el2_sysregs_t *regs); void el2_sysregs_context_restore_ras(el2_sysregs_t *regs); diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index a5b64a5f2..baabd3ba5 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -17,10 +17,6 @@ .global el2_sysregs_context_save_mte .global el2_sysregs_context_restore_mte #endif /* CTX_INCLUDE_MTE_REGS */ -#if ENABLE_FEAT_ECV - .global el2_sysregs_context_save_ecv - .global el2_sysregs_context_restore_ecv -#endif /* ENABLE_FEAT_ECV */ #if RAS_EXTENSION .global el2_sysregs_context_save_ras .global el2_sysregs_context_restore_ras @@ -222,20 +218,6 @@ func el2_sysregs_context_restore_mte endfunc el2_sysregs_context_restore_mte #endif /* CTX_INCLUDE_MTE_REGS */ -#if ENABLE_FEAT_ECV -func el2_sysregs_context_save_ecv - mrs x11, CNTPOFF_EL2 - str x11, [x0, #CTX_CNTPOFF_EL2] - ret -endfunc el2_sysregs_context_save_ecv - -func el2_sysregs_context_restore_ecv - ldr x11, [x0, #CTX_CNTPOFF_EL2] - msr CNTPOFF_EL2, x11 - ret -endfunc el2_sysregs_context_restore_ecv -#endif /* ENABLE_FEAT_ECV */ - #if RAS_EXTENSION func el2_sysregs_context_save_ras /* diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index c91070ece..cf4bb3043 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -380,8 +380,7 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e scr_el3 |= SCR_FGTEN_BIT; } - if (get_armv8_6_ecv_support() - == ID_AA64MMFR0_EL1_ECV_SELF_SYNCH) { + if (is_feat_ecv_supported()) { scr_el3 |= SCR_ECVEN_BIT; } } @@ -957,9 +956,11 @@ void cm_el2_sysregs_context_save(uint32_t security_state) el2_sysregs_context_save_fgt(el2_sysregs_ctx); } -#if ENABLE_FEAT_ECV - el2_sysregs_context_save_ecv(el2_sysregs_ctx); -#endif + if (is_feat_ecv_v2_supported()) { + write_ctx_reg(el2_sysregs_ctx, CTX_CNTPOFF_EL2, + read_cntpoff_el2()); + } + if (is_feat_vhe_supported()) { write_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2, read_contextidr_el2()); @@ -1020,9 +1021,11 @@ void cm_el2_sysregs_context_restore(uint32_t security_state) el2_sysregs_context_restore_fgt(el2_sysregs_ctx); } -#if ENABLE_FEAT_ECV - el2_sysregs_context_restore_ecv(el2_sysregs_ctx); -#endif + if (is_feat_ecv_v2_supported()) { + write_cntpoff_el2(read_ctx_reg(el2_sysregs_ctx, + CTX_CNTPOFF_EL2)); + } + if (is_feat_vhe_supported()) { write_contextidr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2)); write_ttbr1_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2)); diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 3f1811253..683234f16 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -470,6 +470,7 @@ ENABLE_FEAT_FGT := 2 ENABLE_FEAT_HCX := 2 ENABLE_FEAT_TCR2 := 2 +ENABLE_FEAT_ECV := 2 ENABLE_FEAT_PAN := 2 ENABLE_FEAT_VHE := 2 ENABLE_MPAM_FOR_LOWER_ELS := 2