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 <andre.przywara@arm.com>
This commit is contained in:
Andre Przywara 2022-11-17 17:30:43 +00:00
parent 4f5ef849c1
commit b8f03d29e1
7 changed files with 44 additions and 47 deletions

View file

@ -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 */

View file

@ -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)

View file

@ -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)

View file

@ -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);

View file

@ -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
/*

View file

@ -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));

View file

@ -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