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/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;