summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoyan Karatotev <boyan.karatotev@arm.com>2023-04-20 11:00:50 +0100
committerJayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>2023-10-05 17:42:23 +0100
commitf0c96a2e35cc1f154e00a842ddab2958fc903a71 (patch)
tree81f6fc13f0f3d95337727491419cbc32110e6b89
parent18b47a9ca4597091fbb62203fd107b52d65ac93b (diff)
refactor(cm): clean up SCR_EL3 and CPTR_EL3 initialization
As with MDCR_EL3, setting some bits of these registers is redundant at reset since they do not matter for EL3 execution and the registers get context switched so they get overwritten anyway. The SCR_EL3.{TWE, TWI, SMD, API, APK} bits only affect lower ELs so their place is in context management. The API and APK bits are a bit special as they would get implicitly unset for secure world when CTX_INCLUDE_PAUTH_REGS is unset. This is now explicit with their normal world values being always set as PAuth defaults to enabled. The same sequence is also added to realm world too. The reasoning is the same as for Secure world - PAuth will be enabled for NS, and unless explicitly handled by firmware, it should not leak to realm. The CPTR_EL3.{ESM, EZ, TAM} bits are set by the relevant feat_enable()s in lib/extensions so they can be skipped too. CPTR_EL3.TFP is special as it's needed for access to generic floating point registers even when SVE is not present. So keep it but move to context management. This leaves CPTR_EL3.TCPAC which affects several extensions. This bit was set centrally at reset, however the earliest need for it is in BL2. So set it in cm_setup_context_common(). However, this CPTR_EL3 is only restored for BL31 which is clearly not the case. So always restore it. Finally, setting CPTR_EL3 to a fresh RESET_VAL for each security state prevents any bits from leaking between them. Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com> Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com> Change-Id: Ie7095e967bd4a6d6ca6acf314c7086d89fec8900
-rw-r--r--include/arch/aarch64/el3_common_macros.S44
-rw-r--r--lib/el3_runtime/aarch64/context.S2
-rw-r--r--lib/el3_runtime/aarch64/context_mgmt.c79
-rw-r--r--lib/extensions/amu/aarch64/amu.c15
4 files changed, 74 insertions, 66 deletions
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index fa9310ef1..d15feb0ce 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -59,36 +59,14 @@
* zero here but are updated ahead of transitioning to a lower EL in the
* function cm_init_context_common().
*
- * SCR_EL3.TWE: Set to zero so that execution of WFE instructions at
- * EL2, EL1 and EL0 are not trapped to EL3.
- *
- * SCR_EL3.TWI: Set to zero so that execution of WFI instructions at
- * EL2, EL1 and EL0 are not trapped to EL3.
- *
* SCR_EL3.SIF: Set to one to disable instruction fetches from
* Non-secure memory.
*
- * SCR_EL3.SMD: Set to zero to enable SMC calls at EL1 and above, from
- * both Security states and both Execution states.
- *
* SCR_EL3.EA: Set to one to route External Aborts and SError Interrupts
* to EL3 when executing at any EL.
- *
- * SCR_EL3.{API,APK}: For Armv8.3 pointer authentication feature,
- * disable traps to EL3 when accessing key registers or using pointer
- * authentication instructions from lower ELs.
* ---------------------------------------------------------------------
*/
- mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT) \
- & ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT))
-#if CTX_INCLUDE_PAUTH_REGS
- /*
- * If the pointer authentication registers are saved during world
- * switches, enable pointer authentication everywhere, as it is safe to
- * do so.
- */
- orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT)
-#endif
+ mov_imm x0, (SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT)
#if ENABLE_RME
/*
* TODO: Settting the EEL2 bit to allow EL3 access to secure only registers
@@ -132,25 +110,9 @@
/* ---------------------------------------------------------------------
* Initialise CPTR_EL3, setting all fields rather than relying on hw.
* All fields are architecturally UNKNOWN on reset.
- *
- * CPTR_EL3.TCPAC: Set to zero so that any accesses to CPACR_EL1,
- * CPTR_EL2, CPACR, or HCPTR do not trap to EL3.
- *
- * CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers
- * by Advanced SIMD, floating-point or SVE instructions (if implemented)
- * do not trap to EL3.
- *
- * CPTR_EL3.TAM: Set to one so that Activity Monitor access is
- * trapped to EL3 by default.
- *
- * CPTR_EL3.EZ: Set to zero so that all SVE functionality is trapped
- * to EL3 by default.
- *
- * CPTR_EL3.ESM: Set to zero so that all SME functionality is trapped
- * to EL3 by default.
+ * ---------------------------------------------------------------------
*/
-
- mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TFP_BIT))
+ mov_imm x0, CPTR_EL3_RESET_VAL
msr cptr_el3, x0
/*
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index f47e7795f..290a93a8a 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -557,7 +557,6 @@ func el3_exit
msr spsel, #MODE_SP_ELX
str x17, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
-#if IMAGE_BL31
/* ----------------------------------------------------------
* Restore CPTR_EL3.
* ZCR is only restored if SVE is supported and enabled.
@@ -567,6 +566,7 @@ func el3_exit
ldp x19, x20, [sp, #CTX_EL3STATE_OFFSET + CTX_CPTR_EL3]
msr cptr_el3, x19
+#if IMAGE_BL31
ands x19, x19, #CPTR_EZ_BIT
beq sve_not_enabled
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index b16c1139c..8b688fdeb 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -197,21 +197,33 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info *
/* SCR_NS: Set the NS bit */
scr_el3 |= SCR_NS_BIT;
+ /* Allow access to Allocation Tags when MTE is implemented. */
+ scr_el3 |= SCR_ATA_BIT;
+
#if !CTX_INCLUDE_PAUTH_REGS
/*
- * If the pointer authentication registers aren't saved during world
- * switches the value of the registers can be leaked from the Secure to
- * the Non-secure world. To prevent this, rather than enabling pointer
- * authentication everywhere, we only enable it in the Non-secure world.
+ * Pointer Authentication feature, if present, is always enabled by default
+ * for Non secure lower exception levels. We do not have an explicit
+ * flag to set it.
+ * CTX_INCLUDE_PAUTH_REGS flag, is explicitly used to enable for lower
+ * exception levels of secure and realm worlds.
+ *
+ * To prevent the leakage between the worlds during world switch,
+ * we enable it only for the non-secure world.
*
- * If the Secure world wants to use pointer authentication,
- * CTX_INCLUDE_PAUTH_REGS must be set to 1.
+ * If the Secure/realm world wants to use pointer authentication,
+ * CTX_INCLUDE_PAUTH_REGS must be explicitly set to 1, in which case
+ * it will be enabled globally for all the contexts.
+ *
+ * SCR_EL3.API: Set to one to not trap any PAuth instructions at ELs
+ * other than EL3
+ *
+ * SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
+ * than EL3
*/
scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
-#endif /* !CTX_INCLUDE_PAUTH_REGS */
- /* Allow access to Allocation Tags when MTE is implemented. */
- scr_el3 |= SCR_ATA_BIT;
+#endif /* CTX_INCLUDE_PAUTH_REGS */
#if HANDLE_EA_EL3_FIRST_NS
/* SCR_EL3.EA: Route External Abort and SError Interrupt to EL3. */
@@ -308,10 +320,13 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info *
******************************************************************************/
static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *ep)
{
+ u_register_t cptr_el3;
u_register_t scr_el3;
el3_state_t *state;
gp_regs_t *gp_regs;
+ state = get_el3state_ctx(ctx);
+
/* Clear any residual register values from the context */
zeromem(ctx, sizeof(*ctx));
@@ -329,6 +344,23 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
SCR_ST_BIT | SCR_HCE_BIT | SCR_NSE_BIT);
/*
+ * SCR_EL3.TWE: Set to zero so that execution of WFE instructions at
+ * EL2, EL1 and EL0 are not trapped to EL3.
+ *
+ * SCR_EL3.TWI: Set to zero so that execution of WFI instructions at
+ * EL2, EL1 and EL0 are not trapped to EL3.
+ *
+ * SCR_EL3.SMD: Set to zero to enable SMC calls at EL1 and above, from
+ * both Security states and both Execution states.
+ *
+ * SCR_EL3.SIF: Set to one to disable secure instruction execution from
+ * Non-secure memory.
+ */
+ scr_el3 &= ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT);
+
+ scr_el3 |= SCR_SIF_BIT;
+
+ /*
* SCR_EL3.RW: Set the execution state, AArch32 or AArch64, for next
* Exception level as specified by SPSR.
*/
@@ -368,6 +400,19 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
scr_el3 |= SCR_FIEN_BIT;
#endif
+#if CTX_INCLUDE_PAUTH_REGS
+ /*
+ * Enable Pointer Authentication globally for all the worlds.
+ *
+ * SCR_EL3.API: Set to one to not trap any PAuth instructions at ELs
+ * other than EL3
+ *
+ * SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
+ * than EL3
+ */
+ scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+#endif /* CTX_INCLUDE_PAUTH_REGS */
+
/*
* SCR_EL3.TCR2EN: Enable access to TCR2_ELx for AArch64 if present.
*/
@@ -391,10 +436,19 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
}
/*
- * CPTR_EL3 was initialized out of reset, copy that value to the
- * context register.
+ * Initialise CPTR_EL3, setting all fields rather than relying on hw.
+ * All fields are architecturally UNKNOWN on reset.
+ *
+ * CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers
+ * by Advanced SIMD, floating-point or SVE instructions (if
+ * implemented) do not trap to EL3.
+ *
+ * CPTR_EL3.TCPAC: Set to zero so that accesses to CPACR_EL1,
+ * CPTR_EL2,CPACR, or HCPTR do not trap to EL3.
*/
- write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, read_cptr_el3());
+ cptr_el3 = CPTR_EL3_RESET_VAL & ~(TFP_BIT | TCPAC_BIT);
+
+ write_ctx_reg(state, CTX_CPTR_EL3, cptr_el3);
/*
* SCR_EL3.HCE: Enable HVC instructions if next execution state is
@@ -436,7 +490,6 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
* Populate EL3 state so that we've the right context
* before doing ERET
*/
- state = get_el3state_ctx(ctx);
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
write_ctx_reg(state, CTX_ELR_EL3, ep->pc);
write_ctx_reg(state, CTX_SPSR_EL3, ep->spsr);
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index 8c5ef0bb0..53bdb5504 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -69,16 +69,6 @@ static inline __unused void write_cptr_el2_tam(uint64_t value)
((value << CPTR_EL2_TAM_SHIFT) & CPTR_EL2_TAM_BIT));
}
-static inline __unused void ctx_write_cptr_el3_tam(cpu_context_t *ctx, uint64_t tam)
-{
- uint64_t value = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3);
-
- value &= ~TAM_BIT;
- value |= (tam << TAM_SHIFT) & TAM_BIT;
-
- write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, value);
-}
-
static inline __unused void ctx_write_scr_el3_amvoffen(cpu_context_t *ctx, uint64_t amvoffen)
{
uint64_t value = read_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3);
@@ -194,7 +184,10 @@ void amu_enable(cpu_context_t *ctx)
* Set CPTR_EL3.TAM to zero so that any accesses to the Activity Monitor
* registers do not trap to EL3.
*/
- ctx_write_cptr_el3_tam(ctx, 0U);
+ u_register_t cptr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3);
+
+ cptr_el3 &= ~TAM_BIT;
+ write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, cptr_el3);
/* Initialize FEAT_AMUv1p1 features if present. */
if (is_feat_amuv1p1_supported()) {