refactor(cpufeat): separate the EL2 and EL3 enablement code
Combining the EL2 and EL3 enablement code necessitates that it must be
called at el3_exit, which is the only place with enough context to make
the decision of what needs to be set.
Decouple them to allow them to be called from elsewhere.
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Change-Id: I147764c42771e7d4100699ec8fae98dac0a505c0
diff --git a/lib/extensions/brbe/brbe.c b/lib/extensions/brbe/brbe.c
index 329cf98..37bd834 100644
--- a/lib/extensions/brbe/brbe.c
+++ b/lib/extensions/brbe/brbe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,8 +7,9 @@
#include <arch.h>
#include <arch_features.h>
#include <arch_helpers.h>
+#include <lib/extensions/brbe.h>
-void brbe_enable(void)
+void brbe_init_el3(void)
{
uint64_t val;
diff --git a/lib/extensions/mpam/mpam.c b/lib/extensions/mpam/mpam.c
index 62533fc..6462c97 100644
--- a/lib/extensions/mpam/mpam.c
+++ b/lib/extensions/mpam/mpam.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,7 +11,7 @@
#include <arch_helpers.h>
#include <lib/extensions/mpam.h>
-void mpam_enable(bool el2_unused)
+void mpam_init_el3(void)
{
/*
* Enable MPAM, and disable trapping to EL3 when lower ELs access their
@@ -19,15 +19,18 @@
*/
write_mpam3_el3(MPAM3_EL3_MPAMEN_BIT);
- /*
- * If EL2 is implemented but unused, disable trapping to EL2 when lower
- * ELs access their own MPAM registers.
- */
- if (el2_unused) {
- write_mpam2_el2(0ULL);
+}
+
+/*
+ * If EL2 is implemented but unused, disable trapping to EL2 when lower ELs
+ * access their own MPAM registers.
+ */
+void mpam_init_el2_unused(void)
+{
+ write_mpam2_el2(0ULL);
- if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) {
- write_mpamhcr_el2(0ULL);
- }
+ if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) {
+ write_mpamhcr_el2(0ULL);
}
+
}
diff --git a/lib/extensions/pmuv3/aarch32/pmuv3.c b/lib/extensions/pmuv3/aarch32/pmuv3.c
index fe4205e..effb7e0 100644
--- a/lib/extensions/pmuv3/aarch32/pmuv3.c
+++ b/lib/extensions/pmuv3/aarch32/pmuv3.c
@@ -29,7 +29,7 @@
* Applies to all PMU versions. Name is PMUv3 for compatibility with aarch64 and
* to not clash with platforms which reuse the PMU name
*/
-void pmuv3_disable_el3(void)
+void pmuv3_init_el3(void)
{
u_register_t sdcr = read_sdcr();
diff --git a/lib/extensions/pmuv3/aarch64/pmuv3.c b/lib/extensions/pmuv3/aarch64/pmuv3.c
index f83a5ee..fda71aa 100644
--- a/lib/extensions/pmuv3/aarch64/pmuv3.c
+++ b/lib/extensions/pmuv3/aarch64/pmuv3.c
@@ -48,7 +48,7 @@
return mdcr_el3;
}
-void pmuv3_disable_el3(void)
+void pmuv3_init_el3(void)
{
u_register_t mdcr_el3 = read_mdcr_el3();
diff --git a/lib/extensions/sme/sme.c b/lib/extensions/sme/sme.c
index 3423dba..d705b64 100644
--- a/lib/extensions/sme/sme.c
+++ b/lib/extensions/sme/sme.c
@@ -17,7 +17,6 @@
void sme_enable(cpu_context_t *context)
{
u_register_t reg;
- u_register_t cptr_el3;
el3_state_t *state;
/* Get the context state. */
@@ -32,9 +31,14 @@
reg = read_ctx_reg(state, CTX_SCR_EL3);
reg |= SCR_ENTP2_BIT;
write_ctx_reg(state, CTX_SCR_EL3, reg);
+}
- /* Set CPTR_EL3.ESM bit so we can write SMCR_EL3 without trapping. */
- cptr_el3 = read_cptr_el3();
+void sme_init_el3(void)
+{
+ u_register_t cptr_el3 = read_cptr_el3();
+ u_register_t smcr_el3;
+
+ /* Set CPTR_EL3.ESM bit so we can access SMCR_EL3 without trapping. */
write_cptr_el3(cptr_el3 | ESM_BIT);
isb();
@@ -43,11 +47,10 @@
* to be the least restrictive, then lower ELs can restrict as needed
* using SMCR_EL2 and SMCR_EL1.
*/
- reg = SMCR_ELX_LEN_MAX;
-
+ smcr_el3 = SMCR_ELX_LEN_MAX;
if (read_feat_sme_fa64_id_field() != 0U) {
VERBOSE("[SME] FA64 enabled\n");
- reg |= SMCR_ELX_FA64_BIT;
+ smcr_el3 |= SMCR_ELX_FA64_BIT;
}
/*
@@ -58,15 +61,24 @@
*/
if (is_feat_sme2_supported()) {
VERBOSE("SME2 enabled\n");
- reg |= SMCR_ELX_EZT0_BIT;
+ smcr_el3 |= SMCR_ELX_EZT0_BIT;
}
- write_smcr_el3(reg);
+ write_smcr_el3(smcr_el3);
/* Reset CPTR_EL3 value. */
write_cptr_el3(cptr_el3);
isb();
}
+void sme_init_el2_unused(void)
+{
+ /*
+ * CPTR_EL2.TCPAC: Set to zero so that Non-secure EL1 accesses to the
+ * CPACR_EL1 or CPACR from both Execution states do not trap to EL2.
+ */
+ write_cptr_el2(read_cptr_el2() & ~CPTR_EL2_TCPAC_BIT);
+}
+
void sme_disable(cpu_context_t *context)
{
u_register_t reg;
diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c
index b1fe39f..236b102 100644
--- a/lib/extensions/spe/spe.c
+++ b/lib/extensions/spe/spe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,25 +21,10 @@
__asm__ volatile("hint #17");
}
-void spe_enable(bool el2_unused)
+void spe_init_el3(void)
{
uint64_t v;
- if (el2_unused) {
- /*
- * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
- * profiling controls to EL2.
- *
- * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
- * state. Accesses to profiling buffer controls at
- * Non-secure EL1 are not trapped to EL2.
- */
- v = read_mdcr_el2();
- v &= ~MDCR_EL2_TPMS;
- v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
- write_mdcr_el2(v);
- }
-
/*
* MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state
* and disabled in secure state. Accesses to SPE registers at
@@ -55,6 +40,24 @@
write_mdcr_el3(v);
}
+void spe_init_el2_unused(void)
+{
+ uint64_t v;
+
+ /*
+ * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
+ * profiling controls to EL2.
+ *
+ * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
+ * state. Accesses to profiling buffer controls at
+ * Non-secure EL1 are not trapped to EL2.
+ */
+ v = read_mdcr_el2();
+ v &= ~MDCR_EL2_TPMS;
+ v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
+ write_mdcr_el2(v);
+}
+
void spe_disable(void)
{
uint64_t v;
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
index f551ca7..eb4ac8d 100644
--- a/lib/extensions/sve/sve.c
+++ b/lib/extensions/sve/sve.c
@@ -37,6 +37,16 @@
(ZCR_EL3_LEN_MASK & CONVERT_SVE_LENGTH(SVE_VECTOR_LEN)));
}
+void sve_init_el2_unused(void)
+{
+ /*
+ * CPTR_EL2.TFP: Set to zero so that Non-secure accesses to Advanced
+ * SIMD and floating-point functionality from both Execution states do
+ * not trap to EL2.
+ */
+ write_cptr_el2(read_cptr_el2() & ~CPTR_EL2_TFP_BIT);
+}
+
void sve_disable(cpu_context_t *context)
{
u_register_t reg;
diff --git a/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c b/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
index b3f44b7..6da504e 100644
--- a/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
+++ b/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,7 +10,7 @@
#include <arch_helpers.h>
#include <lib/extensions/sys_reg_trace.h>
-void sys_reg_trace_enable(void)
+void sys_reg_trace_init_el3(void)
{
uint32_t val;
diff --git a/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c b/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
index e61cb90..4b57f67 100644
--- a/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
+++ b/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -24,3 +24,14 @@
val &= ~TTA_BIT;
write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, val);
}
+
+void sys_reg_trace_init_el2_unused(void)
+{
+ /*
+ * CPTR_EL2.TTA: Set to zero so that Non-secure System register accesses
+ * to the trace registers from both Execution states do not trap to
+ * EL2. If PE trace unit System registers are not implemented then this
+ * bit is reserved, and must be set to zero.
+ */
+ write_cptr_el2(read_cptr_el2() & ~CPTR_EL2_TTA_BIT);
+}
diff --git a/lib/extensions/trbe/trbe.c b/lib/extensions/trbe/trbe.c
index fa139ca..461ea73 100644
--- a/lib/extensions/trbe/trbe.c
+++ b/lib/extensions/trbe/trbe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -19,9 +19,9 @@
__asm__ volatile("hint #18");
}
-void trbe_enable(void)
+void trbe_init_el3(void)
{
- uint64_t val;
+ u_register_t val;
/*
* MDCR_EL3.NSTB = 0b11
@@ -34,6 +34,17 @@
write_mdcr_el3(val);
}
+void trbe_init_el2_unused(void)
+{
+ /*
+ * MDCR_EL2.E2TB: Set to zero so that the trace Buffer
+ * owning exception level is NS-EL1 and, tracing is
+ * prohibited at NS-EL2. These bits are RES0 when
+ * FEAT_TRBE is not implemented.
+ */
+ write_mdcr_el2(read_mdcr_el2() & ~MDCR_EL2_E2TB(MDCR_EL2_E2TB_EL1));
+}
+
static void *trbe_drain_trace_buffers_hook(const void *arg __unused)
{
if (is_feat_trbe_supported()) {
diff --git a/lib/extensions/trf/aarch32/trf.c b/lib/extensions/trf/aarch32/trf.c
index 0c63efa..e13b4db 100644
--- a/lib/extensions/trf/aarch32/trf.c
+++ b/lib/extensions/trf/aarch32/trf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,7 +10,7 @@
#include <arch_helpers.h>
#include <lib/extensions/trf.h>
-void trf_enable(void)
+void trf_init_el3(void)
{
uint32_t val;
diff --git a/lib/extensions/trf/aarch64/trf.c b/lib/extensions/trf/aarch64/trf.c
index 941692b..f681b28 100644
--- a/lib/extensions/trf/aarch64/trf.c
+++ b/lib/extensions/trf/aarch64/trf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,9 +9,9 @@
#include <arch_helpers.h>
#include <lib/extensions/trf.h>
-void trf_enable(void)
+void trf_init_el3(void)
{
- uint64_t val;
+ u_register_t val;
/*
* MDCR_EL3.TTRF = b0
@@ -22,3 +22,15 @@
val &= ~MDCR_TTRF_BIT;
write_mdcr_el3(val);
}
+
+void trf_init_el2_unused(void)
+{
+ /*
+ * MDCR_EL2.TTRF: Set to zero so that access to Trace
+ * Filter Control register TRFCR_EL1 at EL1 is not
+ * trapped to EL2. This bit is RES0 in versions of
+ * the architecture earlier than ARMv8.4.
+ *
+ */
+ write_mdcr_el2(read_mdcr_el2() & ~MDCR_EL2_TTRF);
+}