summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bl31/bl31_main.c9
-rw-r--r--changelog.yaml3
-rw-r--r--common/feat_detect.c128
-rw-r--r--include/arch/aarch64/arch_features.h74
-rw-r--r--include/arch/aarch64/arch_helpers.h50
-rw-r--r--include/common/feat_detect.h20
-rw-r--r--include/lib/el3_runtime/aarch64/context.h8
-rw-r--r--lib/el3_runtime/aarch64/context.S60
-rw-r--r--lib/el3_runtime/aarch64/context_mgmt.c57
-rw-r--r--plat/arm/board/fvp/platform.mk4
-rw-r--r--plat/qti/common/src/qti_pm.c3
11 files changed, 217 insertions, 199 deletions
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 2a3d838e4..e70eb5584 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -93,15 +93,6 @@ void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
/* Perform late platform-specific setup */
bl31_plat_arch_setup();
-#if ENABLE_FEAT_HCX
- /*
- * Assert that FEAT_HCX is supported on this system, without this check
- * an exception would occur during context save/restore if enabled but
- * not supported.
- */
- assert(is_feat_hcx_present());
-#endif /* ENABLE_FEAT_HCX */
-
#if CTX_INCLUDE_PAUTH_REGS
/*
* Assert that the ARMv8.3-PAuth registers are present or an access
diff --git a/changelog.yaml b/changelog.yaml
index 1e1f0a105..e100f8283 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -101,6 +101,9 @@ subsections:
- title: Extended Cache Index (FEAT_CCIDX)
scope: ccidx
+ - title: CPU feature / ID register handling in general
+ scope: cpufeat
+
- title: Support for the `HCRX_EL2` register (FEAT_HCX)
scope: hcx
diff --git a/common/feat_detect.c b/common/feat_detect.c
index ee3458865..a8c40f70d 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -4,24 +4,59 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <arch_features.h>
+#include <common/debug.h>
#include <common/feat_detect.h>
+static bool tainted;
+
/*******************************************************************************
* This section lists the wrapper modules for each feature to evaluate the
- * feature states (FEAT_STATE_1 and FEAT_STATE_2) and perform necessary action
- * as below:
+ * feature states (FEAT_STATE_ALWAYS and FEAT_STATE_CHECK) and perform
+ * necessary action as below:
*
* It verifies whether the FEAT_XXX (eg: FEAT_SB) is supported by the PE or not.
* Without this check an exception would occur during context save/restore
* routines, if the feature is enabled but not supported by PE.
******************************************************************************/
+#define feat_detect_panic(a, b) ((a) ? (void)0 : feature_panic(b))
+
+/*******************************************************************************
+ * Function : feature_panic
+ * Customised panic function with error logging mechanism to list the feature
+ * not supported by the PE.
+ ******************************************************************************/
+static inline void feature_panic(char *feat_name)
+{
+ ERROR("FEAT_%s not supported by the PE\n", feat_name);
+ panic();
+}
+
+/*******************************************************************************
+ * Function : check_feature
+ * Check for a valid combination of build time flags (ENABLE_FEAT_xxx) and
+ * feature availability on the hardware.
+ * Panics if a feature is forcefully enabled, but not available on the PE.
+ *
+ * We force inlining here to let the compiler optimise away the whole check
+ * if the feature is disabled at build time (FEAT_STATE_DISABLED).
+ ******************************************************************************/
+static inline void __attribute((__always_inline__))
+check_feature(int state, unsigned long field, const char *feat_name)
+{
+ if (state == FEAT_STATE_ALWAYS && field == 0U) {
+ ERROR("FEAT_%s not supported by the PE\n", feat_name);
+ tainted = true;
+ }
+}
+
/******************************************
* Feature : FEAT_SB (Speculation Barrier)
*****************************************/
static void read_feat_sb(void)
{
-#if (ENABLE_FEAT_SB == FEAT_STATE_1)
+#if (ENABLE_FEAT_SB == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_0_feat_sb_present(), "SB");
#endif
}
@@ -31,7 +66,7 @@ static void read_feat_sb(void)
*****************************************************/
static void read_feat_csv2_2(void)
{
-#if (ENABLE_FEAT_CSV2_2 == FEAT_STATE_1)
+#if (ENABLE_FEAT_CSV2_2 == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_0_feat_csv2_2_present(), "CSV2_2");
#endif
}
@@ -41,7 +76,7 @@ static void read_feat_csv2_2(void)
**********************************************/
static void read_feat_pan(void)
{
-#if (ENABLE_FEAT_PAN == FEAT_STATE_1)
+#if (ENABLE_FEAT_PAN == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_1_pan_present(), "PAN");
#endif
}
@@ -51,7 +86,7 @@ static void read_feat_pan(void)
*****************************************************/
static void read_feat_vhe(void)
{
-#if (ENABLE_FEAT_VHE == FEAT_STATE_1)
+#if (ENABLE_FEAT_VHE == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_1_vhe_present(), "VHE");
#endif
}
@@ -61,7 +96,7 @@ static void read_feat_vhe(void)
******************************************************************************/
static void read_feat_ras(void)
{
-#if (RAS_EXTENSION == FEAT_STATE_1)
+#if (RAS_EXTENSION == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_2_feat_ras_present(), "RAS");
#endif
}
@@ -71,7 +106,7 @@ static void read_feat_ras(void)
***********************************************/
static void read_feat_pauth(void)
{
-#if (ENABLE_PAUTH == FEAT_STATE_1) || (CTX_INCLUDE_PAUTH_REGS == FEAT_STATE_1)
+#if (ENABLE_PAUTH == FEAT_STATE_ALWAYS) || (CTX_INCLUDE_PAUTH_REGS == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_3_pauth_present(), "PAUTH");
#endif
}
@@ -81,27 +116,17 @@ static void read_feat_pauth(void)
***********************************************************/
static void read_feat_dit(void)
{
-#if (ENABLE_FEAT_DIT == FEAT_STATE_1)
+#if (ENABLE_FEAT_DIT == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_4_feat_dit_present(), "DIT");
#endif
}
-/*********************************************************
- * Feature : FEAT_AMUv1 (Activity Monitors Extensions v1)
- ********************************************************/
-static void read_feat_amuv1(void)
-{
-#if (ENABLE_FEAT_AMUv1 == FEAT_STATE_1)
- feat_detect_panic(is_armv8_4_feat_amuv1_present(), "AMUv1");
-#endif
-}
-
/****************************************************************************
* Feature : FEAT_MPAM (Memory Partitioning and Monitoring (MPAM) Extension)
***************************************************************************/
static void read_feat_mpam(void)
{
-#if (ENABLE_MPAM_FOR_LOWER_ELS == FEAT_STATE_1)
+#if (ENABLE_MPAM_FOR_LOWER_ELS == FEAT_STATE_ALWAYS)
feat_detect_panic(get_mpam_version() != 0U, "MPAM");
#endif
}
@@ -111,7 +136,7 @@ static void read_feat_mpam(void)
*************************************************************/
static void read_feat_nv2(void)
{
-#if (CTX_INCLUDE_NEVE_REGS == FEAT_STATE_1)
+#if (CTX_INCLUDE_NEVE_REGS == FEAT_STATE_ALWAYS)
unsigned int nv = get_armv8_4_feat_nv_support();
feat_detect_panic((nv == ID_AA64MMFR2_EL1_NV2_SUPPORTED), "NV2");
@@ -123,7 +148,7 @@ static void read_feat_nv2(void)
**********************************/
static void read_feat_sel2(void)
{
-#if (ENABLE_FEAT_SEL2 == FEAT_STATE_1)
+#if (ENABLE_FEAT_SEL2 == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_4_sel2_present(), "SEL2");
#endif
}
@@ -133,7 +158,7 @@ static void read_feat_sel2(void)
***************************************************/
static void read_feat_trf(void)
{
-#if (ENABLE_TRF_FOR_NS == FEAT_STATE_1)
+#if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS)
feat_detect_panic(is_arm8_4_feat_trf_present(), "TRF");
#endif
}
@@ -143,7 +168,7 @@ static void read_feat_trf(void)
***********************************************/
static void read_feat_mte(void)
{
-#if (CTX_INCLUDE_MTE_REGS == FEAT_STATE_1)
+#if (CTX_INCLUDE_MTE_REGS == FEAT_STATE_ALWAYS)
unsigned int mte = get_armv8_5_mte_support();
feat_detect_panic((mte != MTE_UNIMPLEMENTED), "MTE");
@@ -155,7 +180,7 @@ static void read_feat_mte(void)
**********************************************/
static void read_feat_rng(void)
{
-#if (ENABLE_FEAT_RNG == FEAT_STATE_1)
+#if (ENABLE_FEAT_RNG == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_5_rng_present(), "RNG");
#endif
}
@@ -165,27 +190,17 @@ static void read_feat_rng(void)
***************************************************/
static void read_feat_bti(void)
{
-#if (ENABLE_BTI == FEAT_STATE_1)
+#if (ENABLE_BTI == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_5_bti_present(), "BTI");
#endif
}
-/****************************************
- * Feature : FEAT_FGT (Fine Grain Traps)
- ***************************************/
-static void read_feat_fgt(void)
-{
-#if (ENABLE_FEAT_FGT == FEAT_STATE_1)
- feat_detect_panic(is_armv8_6_fgt_present(), "FGT");
-#endif
-}
-
/***********************************************
* Feature : FEAT_AMUv1p1 (AMU Extensions v1.1)
**********************************************/
static void read_feat_amuv1p1(void)
{
-#if (ENABLE_FEAT_AMUv1p1 == FEAT_STATE_1)
+#if (ENABLE_FEAT_AMUv1p1 == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_6_feat_amuv1p1_present(), "AMUv1p1");
#endif
}
@@ -195,7 +210,7 @@ static void read_feat_amuv1p1(void)
******************************************************/
static void read_feat_ecv(void)
{
-#if (ENABLE_FEAT_ECV == FEAT_STATE_1)
+#if (ENABLE_FEAT_ECV == FEAT_STATE_ALWAYS)
unsigned int ecv = get_armv8_6_ecv_support();
feat_detect_panic(((ecv == ID_AA64MMFR0_EL1_ECV_SUPPORTED) ||
@@ -208,27 +223,17 @@ static void read_feat_ecv(void)
**********************************************************/
static void read_feat_twed(void)
{
-#if (ENABLE_FEAT_TWED == FEAT_STATE_1)
+#if (ENABLE_FEAT_TWED == FEAT_STATE_ALWAYS)
feat_detect_panic(is_armv8_6_twed_present(), "TWED");
#endif
}
-/******************************************************************
- * Feature : FEAT_HCX (Extended Hypervisor Configuration Register)
- *****************************************************************/
-static void read_feat_hcx(void)
-{
-#if (ENABLE_FEAT_HCX == FEAT_STATE_1)
- feat_detect_panic(is_feat_hcx_present(), "HCX");
-#endif
-}
-
/**************************************************
* Feature : FEAT_RME (Realm Management Extension)
*************************************************/
static void read_feat_rme(void)
{
-#if (ENABLE_RME == FEAT_STATE_1)
+#if (ENABLE_RME == FEAT_STATE_ALWAYS)
feat_detect_panic((get_armv9_2_feat_rme_support() !=
ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED), "RME");
#endif
@@ -239,7 +244,7 @@ static void read_feat_rme(void)
*****************************************************/
static void read_feat_brbe(void)
{
-#if (ENABLE_BRBE_FOR_NS == FEAT_STATE_1)
+#if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS)
feat_detect_panic(is_feat_brbe_present(), "BRBE");
#endif
}
@@ -249,7 +254,7 @@ static void read_feat_brbe(void)
*****************************************************/
static void read_feat_trbe(void)
{
-#if (ENABLE_TRBE_FOR_NS == FEAT_STATE_1)
+#if (ENABLE_TRBE_FOR_NS == FEAT_STATE_ALWAYS)
feat_detect_panic(is_feat_trbe_present(), "TRBE");
#endif
}
@@ -259,7 +264,7 @@ static void read_feat_trbe(void)
*****************************************************************/
static void read_feat_rng_trap(void)
{
-#if (ENABLE_FEAT_RNG_TRAP == FEAT_STATE_1)
+#if (ENABLE_FEAT_RNG_TRAP == FEAT_STATE_ALWAYS)
feat_detect_panic(is_feat_rng_trap_present(), "RNG_TRAP");
#endif
}
@@ -283,11 +288,14 @@ static void read_feat_rng_trap(void)
* ENABLE_FEAT_xxx = 2 : The feature is enabled but dynamically enabled at runtime
* depending on hardware capability.
*
- * For better readability, state values are defined with macros namely:
- * { FEAT_STATE_0, FEAT_STATE_1, FEAT_STATE_2 } taking values as their naming.
+ * For better readability, state values are defined with macros, namely:
+ * { FEAT_STATE_DISABLED, FEAT_STATE_ALWAYS, FEAT_STATE_CHECK }, taking values
+ * { 0, 1, 2 }, respectively, as their naming.
**********************************************************************************/
void detect_arch_features(void)
{
+ tainted = false;
+
/* v8.0 features */
read_feat_sb();
read_feat_csv2_2();
@@ -304,7 +312,7 @@ void detect_arch_features(void)
/* v8.4 features */
read_feat_dit();
- read_feat_amuv1();
+ check_feature(ENABLE_FEAT_AMUv1, read_feat_amu_id_field(), "AMUv1");
read_feat_mpam();
read_feat_nv2();
read_feat_sel2();
@@ -318,12 +326,12 @@ void detect_arch_features(void)
/* v8.6 features */
read_feat_amuv1p1();
- read_feat_fgt();
+ check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT");
read_feat_ecv();
read_feat_twed();
/* v8.7 features */
- read_feat_hcx();
+ check_feature(ENABLE_FEAT_HCX, read_feat_hcx_id_field(), "HCX");
/* v9.0 features */
read_feat_brbe();
@@ -331,4 +339,8 @@ void detect_arch_features(void)
/* v9.2 features */
read_feat_rme();
+
+ if (tainted) {
+ panic();
+ }
}
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 932e8850a..2b801ac84 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -10,6 +10,7 @@
#include <stdbool.h>
#include <arch_helpers.h>
+#include <common/feat_detect.h>
static inline bool is_armv7_gentimer_present(void)
{
@@ -97,10 +98,23 @@ static inline bool is_armv8_6_twed_present(void)
ID_AA64MMFR1_EL1_TWED_MASK) == ID_AA64MMFR1_EL1_TWED_SUPPORTED);
}
-static inline bool is_armv8_6_fgt_present(void)
+static unsigned int read_feat_fgt_id_field(void)
{
- return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_FGT_SHIFT) &
- ID_AA64MMFR0_EL1_FGT_MASK) != 0U;
+ return (read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_FGT_SHIFT) &
+ ID_AA64MMFR0_EL1_FGT_MASK;
+}
+
+static inline bool is_feat_fgt_supported(void)
+{
+ if (ENABLE_FEAT_FGT == FEAT_STATE_DISABLED) {
+ return false;
+ }
+
+ if (ENABLE_FEAT_FGT == FEAT_STATE_ALWAYS) {
+ return true;
+ }
+
+ return read_feat_fgt_id_field() != 0U;
}
static inline unsigned long int get_armv8_6_ecv_support(void)
@@ -115,10 +129,31 @@ static inline bool is_armv8_5_rng_present(void)
ID_AA64ISAR0_RNDR_MASK);
}
+/*******************************************************************************
+ * Functions to identify the presence of the Activity Monitors Extension
+ ******************************************************************************/
+static unsigned int read_feat_amu_id_field(void)
+{
+ return (read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
+ ID_AA64PFR0_AMU_MASK;
+}
+
+static inline bool is_feat_amu_supported(void)
+{
+ if (ENABLE_FEAT_AMUv1 == FEAT_STATE_DISABLED) {
+ return false;
+ }
+
+ if (ENABLE_FEAT_AMUv1 == FEAT_STATE_ALWAYS) {
+ return true;
+ }
+
+ return read_feat_amu_id_field() >= ID_AA64PFR0_AMU_V1;
+}
+
static inline bool is_armv8_6_feat_amuv1p1_present(void)
{
- return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
- ID_AA64PFR0_AMU_MASK) >= ID_AA64PFR0_AMU_V1P1);
+ return read_feat_amu_id_field() >= ID_AA64PFR0_AMU_V1P1;
}
/*
@@ -138,10 +173,23 @@ static inline unsigned int get_mpam_version(void)
ID_AA64PFR1_MPAM_FRAC_SHIFT) & ID_AA64PFR1_MPAM_FRAC_MASK));
}
-static inline bool is_feat_hcx_present(void)
+static inline unsigned int read_feat_hcx_id_field(void)
+{
+ return (read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_HCX_SHIFT) &
+ ID_AA64MMFR1_EL1_HCX_MASK;
+}
+
+static inline bool is_feat_hcx_supported(void)
{
- return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_HCX_SHIFT) &
- ID_AA64MMFR1_EL1_HCX_MASK) == ID_AA64MMFR1_EL1_HCX_SUPPORTED);
+ if (ENABLE_FEAT_HCX == FEAT_STATE_DISABLED) {
+ return false;
+ }
+
+ if (ENABLE_FEAT_HCX == FEAT_STATE_ALWAYS) {
+ return true;
+ }
+
+ return read_feat_hcx_id_field() != 0U;
}
static inline bool is_feat_rng_trap_present(void)
@@ -226,16 +274,6 @@ static inline bool is_arm8_4_feat_trf_present(void)
ID_AA64DFR0_TRACEFILT_MASK) == ID_AA64DFR0_TRACEFILT_SUPPORTED);
}
-/*******************************************************************************
- * Function to identify the presence of FEAT_AMUv1 (Activity Monitors-
- * Extension v1)
- ******************************************************************************/
-static inline bool is_armv8_4_feat_amuv1_present(void)
-{
- return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
- ID_AA64PFR0_AMU_MASK) >= ID_AA64PFR0_AMU_V1);
-}
-
/********************************************************************************
* Function to identify the presence of FEAT_NV2 (Enhanced Nested Virtualization
* Support)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index fe9b5a563..86c1dbe27 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -27,6 +27,14 @@ static inline u_register_t read_ ## _name(void) \
return v; \
}
+#define _DEFINE_SYSREG_READ_FUNC_NV(_name, _reg_name) \
+static inline u_register_t read_ ## _name(void) \
+{ \
+ u_register_t v; \
+ __asm__ ("mrs %0, " #_reg_name : "=r" (v)); \
+ return v; \
+}
+
#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \
static inline void write_ ## _name(u_register_t v) \
{ \
@@ -58,6 +66,14 @@ static inline void write_ ## _name(u_register_t v) \
#define DEFINE_RENAME_SYSREG_WRITE_FUNC(_name, _reg_name) \
_DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)
+/* Define read function for ID register (w/o volatile qualifier) */
+#define DEFINE_IDREG_READ_FUNC(_name) \
+ _DEFINE_SYSREG_READ_FUNC_NV(_name, _name)
+
+/* Define read function for renamed ID register (w/o volatile qualifier) */
+#define DEFINE_RENAME_IDREG_READ_FUNC(_name, _reg_name) \
+ _DEFINE_SYSREG_READ_FUNC_NV(_name, _reg_name)
+
/**********************************************************************
* Macros to create inline functions for system instructions
*********************************************************************/
@@ -247,14 +263,14 @@ void disable_mpu_icache_el2(void);
#define write_daifset(val) SYSREG_WRITE_CONST(daifset, val)
DEFINE_SYSREG_RW_FUNCS(par_el1)
-DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
-DEFINE_SYSREG_READ_FUNC(id_aa64isar0_el1)
-DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1)
-DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64isar2_el1, ID_AA64ISAR2_EL1)
-DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
-DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1)
-DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1)
-DEFINE_SYSREG_READ_FUNC(id_afr0_el1)
+DEFINE_IDREG_READ_FUNC(id_pfr1_el1)
+DEFINE_IDREG_READ_FUNC(id_aa64isar0_el1)
+DEFINE_IDREG_READ_FUNC(id_aa64isar1_el1)
+DEFINE_RENAME_IDREG_READ_FUNC(id_aa64isar2_el1, ID_AA64ISAR2_EL1)
+DEFINE_IDREG_READ_FUNC(id_aa64pfr0_el1)
+DEFINE_IDREG_READ_FUNC(id_aa64pfr1_el1)
+DEFINE_IDREG_READ_FUNC(id_aa64dfr0_el1)
+DEFINE_IDREG_READ_FUNC(id_afr0_el1)
DEFINE_SYSREG_READ_FUNC(CurrentEl)
DEFINE_SYSREG_READ_FUNC(ctr_el0)
DEFINE_SYSREG_RW_FUNCS(daif)
@@ -367,10 +383,10 @@ void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3,
/*******************************************************************************
* System register accessor prototypes
******************************************************************************/
-DEFINE_SYSREG_READ_FUNC(midr_el1)
+DEFINE_IDREG_READ_FUNC(midr_el1)
DEFINE_SYSREG_READ_FUNC(mpidr_el1)
-DEFINE_SYSREG_READ_FUNC(id_aa64mmfr0_el1)
-DEFINE_SYSREG_READ_FUNC(id_aa64mmfr1_el1)
+DEFINE_IDREG_READ_FUNC(id_aa64mmfr0_el1)
+DEFINE_IDREG_READ_FUNC(id_aa64mmfr1_el1)
DEFINE_SYSREG_RW_FUNCS(scr_el3)
DEFINE_SYSREG_RW_FUNCS(hcr_el2)
@@ -516,7 +532,7 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1)
DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3)
DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2)
-DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64smfr0_el1, ID_AA64SMFR0_EL1)
+DEFINE_RENAME_IDREG_READ_FUNC(id_aa64smfr0_el1, ID_AA64SMFR0_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(smcr_el3, SMCR_EL3)
DEFINE_RENAME_SYSREG_READ_FUNC(erridr_el1, ERRIDR_EL1)
@@ -530,7 +546,7 @@ DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc0_el1, ERXMISC0_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1)
/* Armv8.2 Registers */
-DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1)
+DEFINE_RENAME_IDREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1)
/* Armv8.3 Pointer Authentication Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeyhi_el1, APIAKeyHi_EL1)
@@ -549,6 +565,14 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(rndr, RNDR)
DEFINE_RENAME_SYSREG_READ_FUNC(rndrrs, RNDRRS)
+/* Armv8.6 FEAT_FGT Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(hdfgrtr_el2, HDFGRTR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hafgrtr_el2, HAFGRTR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hdfgwtr_el2, HDFGWTR_EL2)
+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)
+
/* FEAT_HCX Register */
DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2)
diff --git a/include/common/feat_detect.h b/include/common/feat_detect.h
index 0f0f10596..788dfb31f 100644
--- a/include/common/feat_detect.h
+++ b/include/common/feat_detect.h
@@ -7,26 +7,12 @@
#ifndef FEAT_DETECT_H
#define FEAT_DETECT_H
-#include <arch_features.h>
-#include <common/debug.h>
-
/* Function Prototypes */
void detect_arch_features(void);
/* Macro Definitions */
-#define FEAT_STATE_1 1
-#define FEAT_STATE_2 2
-#define feat_detect_panic(a, b) ((a) ? (void)0 : feature_panic(b))
-
-/*******************************************************************************
- * Function : feature_panic
- * Customised panic module with error logging mechanism to list the feature
- * not supported by the PE.
- ******************************************************************************/
-static inline void feature_panic(char *feat_name)
-{
- ERROR("FEAT_%s not supported by the PE\n", feat_name);
- panic();
-}
+#define FEAT_STATE_DISABLED 0
+#define FEAT_STATE_ALWAYS 1
+#define FEAT_STATE_CHECK 2
#endif /* FEAT_DETECT_H */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 6c13166e3..6986e0e51 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_restore_mte(el2_sysregs_t *regs);
void el2_sysregs_context_save_mpam(el2_sysregs_t *regs);
void el2_sysregs_context_restore_mpam(el2_sysregs_t *regs);
#endif /* ENABLE_MPAM_FOR_LOWER_ELS */
-#if ENABLE_FEAT_FGT
-void el2_sysregs_context_save_fgt(el2_sysregs_t *regs);
-void el2_sysregs_context_restore_fgt(el2_sysregs_t *regs);
-#endif /* ENABLE_FEAT_FGT */
#if ENABLE_FEAT_ECV
void el2_sysregs_context_save_ecv(el2_sysregs_t *regs);
void el2_sysregs_context_restore_ecv(el2_sysregs_t *regs);
@@ -551,10 +547,6 @@ void el2_sysregs_context_restore_trf(el2_sysregs_t *regs);
void el2_sysregs_context_save_csv2(el2_sysregs_t *regs);
void el2_sysregs_context_restore_csv2(el2_sysregs_t *regs);
#endif /* ENABLE_FEAT_CSV2_2 */
-#if ENABLE_FEAT_HCX
-void el2_sysregs_context_save_hcx(el2_sysregs_t *regs);
-void el2_sysregs_context_restore_hcx(el2_sysregs_t *regs);
-#endif /* ENABLE_FEAT_HCX */
#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 aa0327b51..b5d61ff35 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -25,10 +25,6 @@
.global el2_sysregs_context_save_mpam
.global el2_sysregs_context_restore_mpam
#endif /* ENABLE_MPAM_FOR_LOWER_ELS */
-#if ENABLE_FEAT_FGT
- .global el2_sysregs_context_save_fgt
- .global el2_sysregs_context_restore_fgt
-#endif /* ENABLE_FEAT_FGT */
#if ENABLE_FEAT_ECV
.global el2_sysregs_context_save_ecv
.global el2_sysregs_context_restore_ecv
@@ -53,10 +49,6 @@
.global el2_sysregs_context_save_csv2
.global el2_sysregs_context_restore_csv2
#endif /* ENABLE_FEAT_CSV2_2 */
-#if ENABLE_FEAT_HCX
- .global el2_sysregs_context_save_hcx
- .global el2_sysregs_context_restore_hcx
-#endif /* ENABLE_FEAT_HCX */
#endif /* CTX_INCLUDE_EL2_REGS */
.global el1_sysregs_context_save
@@ -314,45 +306,6 @@ func el2_sysregs_context_restore_mpam
endfunc el2_sysregs_context_restore_mpam
#endif /* ENABLE_MPAM_FOR_LOWER_ELS */
-#if ENABLE_FEAT_FGT
-func el2_sysregs_context_save_fgt
- mrs x13, HDFGRTR_EL2
-#if ENABLE_FEAT_AMUv1
- mrs x14, HAFGRTR_EL2
- stp x13, x14, [x0, #CTX_HDFGRTR_EL2]
-#else
- str x13, [x0, #CTX_HDFGRTR_EL2]
-#endif /* ENABLE_FEAT_AMUv1 */
- mrs x15, HDFGWTR_EL2
- mrs x16, HFGITR_EL2
- stp x15, x16, [x0, #CTX_HDFGWTR_EL2]
-
- mrs x9, HFGRTR_EL2
- mrs x10, HFGWTR_EL2
- stp x9, x10, [x0, #CTX_HFGRTR_EL2]
- ret
-endfunc el2_sysregs_context_save_fgt
-
-func el2_sysregs_context_restore_fgt
- #if ENABLE_FEAT_AMUv1
- ldp x13, x14, [x0, #CTX_HDFGRTR_EL2]
- msr HAFGRTR_EL2, x14
-#else
- ldr x13, [x0, #CTX_HDFGRTR_EL2]
-#endif /* ENABLE_FEAT_AMUv1 */
- msr HDFGRTR_EL2, x13
-
- ldp x15, x16, [x0, #CTX_HDFGWTR_EL2]
- msr HDFGWTR_EL2, x15
- msr HFGITR_EL2, x16
-
- ldp x9, x10, [x0, #CTX_HFGRTR_EL2]
- msr HFGRTR_EL2, x9
- msr HFGWTR_EL2, x10
- ret
-endfunc el2_sysregs_context_restore_fgt
-#endif /* ENABLE_FEAT_FGT */
-
#if ENABLE_FEAT_ECV
func el2_sysregs_context_save_ecv
mrs x11, CNTPOFF_EL2
@@ -475,19 +428,6 @@ func el2_sysregs_context_restore_csv2
endfunc el2_sysregs_context_restore_csv2
#endif /* ENABLE_FEAT_CSV2_2 */
-#if ENABLE_FEAT_HCX
-func el2_sysregs_context_save_hcx
- mrs x14, hcrx_el2
- str x14, [x0, #CTX_HCRX_EL2]
- ret
-endfunc el2_sysregs_context_save_hcx
-
-func el2_sysregs_context_restore_hcx
- ldr x14, [x0, #CTX_HCRX_EL2]
- msr hcrx_el2, x14
- ret
-endfunc el2_sysregs_context_restore_hcx
-#endif /* ENABLE_FEAT_HCX */
#endif /* CTX_INCLUDE_EL2_REGS */
/* ------------------------------------------------------------------
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 866ac4154..3bcefdb5d 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -320,9 +320,9 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
* If FEAT_HCX is enabled, enable access to HCRX_EL2 by setting
* SCR_EL3.HXEn.
*/
-#if ENABLE_FEAT_HCX
- scr_el3 |= SCR_HXEn_BIT;
-#endif
+ if (is_feat_hcx_supported()) {
+ scr_el3 |= SCR_HXEn_BIT;
+ }
/*
* If FEAT_RNG_TRAP is enabled, all reads of the RNDR and RNDRRS
@@ -359,7 +359,7 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
&& (GET_M32(ep->spsr) == MODE32_hyp))) {
scr_el3 |= SCR_HCE_BIT;
- if (is_armv8_6_fgt_present()) {
+ if (is_feat_fgt_supported()) {
scr_el3 |= SCR_FGTEN_BIT;
}
@@ -792,6 +792,35 @@ void cm_prepare_el3_exit(uint32_t security_state)
}
#if CTX_INCLUDE_EL2_REGS
+
+static void el2_sysregs_context_save_fgt(el2_sysregs_t *ctx)
+{
+ if (is_feat_fgt_supported()) {
+ write_ctx_reg(ctx, CTX_HDFGRTR_EL2, read_hdfgrtr_el2());
+ if (is_feat_amu_supported()) {
+ write_ctx_reg(ctx, CTX_HAFGRTR_EL2, read_hafgrtr_el2());
+ }
+ write_ctx_reg(ctx, CTX_HDFGWTR_EL2, read_hdfgwtr_el2());
+ write_ctx_reg(ctx, CTX_HFGITR_EL2, read_hfgitr_el2());
+ write_ctx_reg(ctx, CTX_HFGRTR_EL2, read_hfgrtr_el2());
+ write_ctx_reg(ctx, CTX_HFGWTR_EL2, read_hfgwtr_el2());
+ }
+}
+
+static void el2_sysregs_context_restore_fgt(el2_sysregs_t *ctx)
+{
+ if (is_feat_fgt_supported()) {
+ write_hdfgrtr_el2(read_ctx_reg(ctx, CTX_HDFGRTR_EL2));
+ if (is_feat_amu_supported()) {
+ write_hafgrtr_el2(read_ctx_reg(ctx, CTX_HAFGRTR_EL2));
+ }
+ write_hdfgwtr_el2(read_ctx_reg(ctx, CTX_HDFGWTR_EL2));
+ write_hfgitr_el2(read_ctx_reg(ctx, CTX_HFGITR_EL2));
+ write_hfgrtr_el2(read_ctx_reg(ctx, CTX_HFGRTR_EL2));
+ write_hfgwtr_el2(read_ctx_reg(ctx, CTX_HFGWTR_EL2));
+ }
+}
+
/*******************************************************************************
* Save EL2 sysreg context
******************************************************************************/
@@ -823,9 +852,9 @@ void cm_el2_sysregs_context_save(uint32_t security_state)
#if ENABLE_MPAM_FOR_LOWER_ELS
el2_sysregs_context_save_mpam(el2_sysregs_ctx);
#endif
-#if ENABLE_FEAT_FGT
+
el2_sysregs_context_save_fgt(el2_sysregs_ctx);
-#endif
+
#if ENABLE_FEAT_ECV
el2_sysregs_context_save_ecv(el2_sysregs_ctx);
#endif
@@ -844,9 +873,9 @@ void cm_el2_sysregs_context_save(uint32_t security_state)
#if ENABLE_FEAT_CSV2_2
el2_sysregs_context_save_csv2(el2_sysregs_ctx);
#endif
-#if ENABLE_FEAT_HCX
- el2_sysregs_context_save_hcx(el2_sysregs_ctx);
-#endif
+ if (is_feat_hcx_supported()) {
+ write_ctx_reg(el2_sysregs_ctx, CTX_HCRX_EL2, read_hcrx_el2());
+ }
}
}
@@ -881,9 +910,9 @@ void cm_el2_sysregs_context_restore(uint32_t security_state)
#if ENABLE_MPAM_FOR_LOWER_ELS
el2_sysregs_context_restore_mpam(el2_sysregs_ctx);
#endif
-#if ENABLE_FEAT_FGT
+
el2_sysregs_context_restore_fgt(el2_sysregs_ctx);
-#endif
+
#if ENABLE_FEAT_ECV
el2_sysregs_context_restore_ecv(el2_sysregs_ctx);
#endif
@@ -902,9 +931,9 @@ void cm_el2_sysregs_context_restore(uint32_t security_state)
#if ENABLE_FEAT_CSV2_2
el2_sysregs_context_restore_csv2(el2_sysregs_ctx);
#endif
-#if ENABLE_FEAT_HCX
- el2_sysregs_context_restore_hcx(el2_sysregs_ctx);
-#endif
+ if (is_feat_hcx_supported()) {
+ write_hcrx_el2(read_ctx_reg(el2_sysregs_ctx, CTX_HCRX_EL2));
+ }
}
}
#endif /* CTX_INCLUDE_EL2_REGS */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index f28a6ff75..efbf68f00 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -463,6 +463,10 @@ ENABLE_SYS_REG_TRACE_FOR_NS := 1
# enable trace filter control registers access to NS by default
ENABLE_TRF_FOR_NS := 1
+# Linux relies on EL3 enablement if those features are present
+ENABLE_FEAT_FGT := 2
+ENABLE_FEAT_HCX := 2
+
ifeq (${SPMC_AT_EL3}, 1)
PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_el3_spmc.c
endif
diff --git a/plat/qti/common/src/qti_pm.c b/plat/qti/common/src/qti_pm.c
index 5f1b7aa1d..ae361e973 100644
--- a/plat/qti/common/src/qti_pm.c
+++ b/plat/qti/common/src/qti_pm.c
@@ -47,8 +47,7 @@
#define QTI_CORE_PWRDN_EN_MASK 1
/* cpu power control happens to be same across all CPUs */
-_DEFINE_SYSREG_WRITE_FUNC(cpu_pwrctrl_val, S3_0_C15_C2_7)
-_DEFINE_SYSREG_READ_FUNC(cpu_pwrctrl_val, S3_0_C15_C2_7)
+DEFINE_RENAME_SYSREG_RW_FUNCS(cpu_pwrctrl_val, S3_0_C15_C2_7)
const unsigned int qti_pm_idle_states[] = {
qti_make_pwrstate_lvl0(QTI_LOCAL_STATE_OFF,