refactor(cpufeat): enable FEAT_RAS for FEAT_STATE_CHECKED
At the moment we only support FEAT_RAS to be either unconditionally
compiled in, or to be not supported at all.
Add support for runtime detection (FEAT_RAS=2), by splitting
is_armv8_2_feat_ras_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 RAS related registers.
Also move the context saving code from assembly to C, and use the new
is_feat_ras_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: I30498f72fd80b136850856244687400456a03d0e
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Manish Pandey <manish.pandey2@arm.com>
diff --git a/Makefile b/Makefile
index d5e64ea..edd435c 100644
--- a/Makefile
+++ b/Makefile
@@ -809,8 +809,8 @@
endif
# When FAULT_INJECTION_SUPPORT is used, require that FEAT_RAS is enabled
ifeq ($(FAULT_INJECTION_SUPPORT),1)
- ifneq ($(ENABLE_FEAT_RAS),1)
- $(error For FAULT_INJECTION_SUPPORT, ENABLE_FEAT_RAS must also be 1)
+ ifeq ($(ENABLE_FEAT_RAS),0)
+ $(error For FAULT_INJECTION_SUPPORT, ENABLE_FEAT_RAS must not be 0)
endif
endif
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 9b3bffc..50b74d0 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -60,16 +60,6 @@
}
}
-/*******************************************************************************
- * Feature : FEAT_RAS (Reliability, Availability, and Serviceability Extension)
- ******************************************************************************/
-static void read_feat_ras(void)
-{
-#if (ENABLE_FEAT_RAS == FEAT_STATE_ALWAYS)
- feat_detect_panic(is_armv8_2_feat_ras_present(), "RAS");
-#endif
-}
-
/************************************************
* Feature : FEAT_PAUTH (Pointer Authentication)
***********************************************/
@@ -160,9 +150,9 @@
check_feature(ENABLE_FEAT_VHE, read_feat_vhe_id_field(), "VHE", 1, 1);
/* v8.2 features */
- read_feat_ras();
check_feature(ENABLE_SVE_FOR_NS, read_feat_sve_id_field(),
"SVE", 1, 1);
+ check_feature(ENABLE_FEAT_RAS, read_feat_ras_id_field(), "RAS", 1, 2);
/* v8.3 features */
read_feat_pauth();
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index ac5eae2..20206c1 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -393,6 +393,9 @@
#define ID_AA64PFR1_EL1_RNG_TRAP_SUPPORTED ULL(0x1)
#define ID_AA64PFR1_EL1_RNG_TRAP_NOT_SUPPORTED ULL(0x0)
+#define VDISR_EL2 S3_4_C12_C1_1
+#define VSESR_EL2 S3_4_C5_C2_3
+
/* Memory Tagging Extension is not implemented */
#define MTE_UNIMPLEMENTED U(0)
/* FEAT_MTE: MTE instructions accessible at EL0 are implemented */
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index a0141de..d6f12f3 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -499,14 +499,22 @@
return read_feat_sve_id_field() >= ID_AA64PFR0_SVE_SUPPORTED;
}
-/*******************************************************************************
- * Function to identify the presence of FEAT_RAS (Reliability,Availability,
- * and Serviceability Extension)
- ******************************************************************************/
-static inline bool is_armv8_2_feat_ras_present(void)
+static unsigned int read_feat_ras_id_field(void)
+{
+ return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_RAS);
+}
+
+static inline bool is_feat_ras_supported(void)
{
- return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_RAS_SHIFT) &
- ID_AA64PFR0_RAS_MASK) != ID_AA64PFR0_RAS_NOT_SUPPORTED);
+ if (ENABLE_FEAT_RAS == FEAT_STATE_DISABLED) {
+ return false;
+ }
+
+ if (ENABLE_FEAT_RAS == FEAT_STATE_ALWAYS) {
+ return true;
+ }
+
+ return read_feat_ras_id_field() != 0U;
}
static unsigned int read_feat_dit_id_field(void)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 1b4bc11..5b3d4c2 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -549,6 +549,10 @@
/* Armv8.2 ID Registers */
DEFINE_RENAME_IDREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1)
+/* Armv8.2 RAS Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(vdisr_el2, VDISR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(vsesr_el2, VSESR_EL2)
+
/* Armv8.2 MPAM Registers */
DEFINE_RENAME_SYSREG_READ_FUNC(mpamidr_el1, MPAMIDR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(mpam3_el3, MPAM3_EL3)
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index c9590d4..e6af43e 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -523,10 +523,6 @@
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_RAS
-void el2_sysregs_context_save_ras(el2_sysregs_t *regs);
-void el2_sysregs_context_restore_ras(el2_sysregs_t *regs);
-#endif /* ENABLE_FEAT_RAS */
#endif /* CTX_INCLUDE_EL2_REGS */
#if CTX_INCLUDE_FPREGS
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 63566da..0f2dfeb 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_RAS
- .global el2_sysregs_context_save_ras
- .global el2_sysregs_context_restore_ras
-#endif /* ENABLE_FEAT_RAS */
#endif /* CTX_INCLUDE_EL2_REGS */
.global el1_sysregs_context_save
@@ -210,30 +206,6 @@
endfunc el2_sysregs_context_restore_mte
#endif /* CTX_INCLUDE_MTE_REGS */
-#if ENABLE_FEAT_RAS
-func el2_sysregs_context_save_ras
- /*
- * VDISR_EL2 and VSESR_EL2 registers are saved only when
- * FEAT_RAS is supported.
- */
- mrs x11, vdisr_el2
- mrs x12, vsesr_el2
- stp x11, x12, [x0, #CTX_VDISR_EL2]
- ret
-endfunc el2_sysregs_context_save_ras
-
-func el2_sysregs_context_restore_ras
- /*
- * VDISR_EL2 and VSESR_EL2 registers are restored only when FEAT_RAS
- * is supported.
- */
- ldp x11, x12, [x0, #CTX_VDISR_EL2]
- msr vdisr_el2, x11
- msr vsesr_el2, x12
- ret
-endfunc el2_sysregs_context_restore_ras
-#endif /* ENABLE_FEAT_RAS */
-
#endif /* CTX_INCLUDE_EL2_REGS */
/* ------------------------------------------------------------------
@@ -855,7 +827,12 @@
1:
#endif /* IMAGE_BL31 && DYNAMIC_WORKAROUND_CVE_2018_3639 */
-#if IMAGE_BL31 && ENABLE_FEAT_RAS
+/*
+ * This is a hot path, so we don't want to do some actual FEAT_RAS runtime
+ * detection here. The "esb" is a cheaper variant, so using "dsb" in the
+ * ENABLE_FEAT_RAS==2 case is not ideal, but won't hurt.
+ */
+#if IMAGE_BL31 && ENABLE_FEAT_RAS == 1
/* ----------------------------------------------------------
* Issue Error Synchronization Barrier to synchronize SErrors
* before exiting EL3. We're running with EAs unmasked, so
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 3ddf5fa..e107f5a 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -1012,9 +1012,13 @@
write_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2,
read_ttbr1_el2());
}
-#if ENABLE_FEAT_RAS
- el2_sysregs_context_save_ras(el2_sysregs_ctx);
-#endif
+
+ if (is_feat_ras_supported()) {
+ write_ctx_reg(el2_sysregs_ctx, CTX_VDISR_EL2,
+ read_vdisr_el2());
+ write_ctx_reg(el2_sysregs_ctx, CTX_VSESR_EL2,
+ read_vsesr_el2());
+ }
if (is_feat_nv2_supported()) {
write_ctx_reg(el2_sysregs_ctx, CTX_VNCR_EL2,
@@ -1095,9 +1099,11 @@
write_contextidr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2));
write_ttbr1_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2));
}
-#if ENABLE_FEAT_RAS
- el2_sysregs_context_restore_ras(el2_sysregs_ctx);
-#endif
+
+ if (is_feat_ras_supported()) {
+ write_vdisr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VDISR_EL2));
+ write_vsesr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VSESR_EL2));
+ }
if (is_feat_nv2_supported()) {
write_vncr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VNCR_EL2));
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 29835d9..8a6aa00 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -50,6 +50,7 @@
ENABLE_FEAT_RNG := 2
ENABLE_FEAT_TWED := 2
ENABLE_FEAT_GCS := 2
+ ENABLE_FEAT_RAS := 2
ifeq (${ARCH}, aarch64)
ifneq (${SPD}, spmd)
ifeq (${SPM_MM}, 0)