feat(cm): context switch MDCR_EL3 register
Currently MDCR_EL3 register value is same for all the
worlds(Non-secure, Secure, Realm and Root).
With this approach, features enable/disable settings
remain same across all the worlds. This is not ideal as
there must be flexibility in controlling feature as per
the requirements for individual world.
The patch addresses this by providing MDCR_EL3 a per world
value. Features with identical values for all the worlds are
grouped under ``manage_extensions_common`` API.
Change-Id: Ibc068d985fe165d8cb6d0ffb84119bffd743b3d1
Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 1937c30..058f7fa 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -42,6 +42,7 @@
per_world_context_t per_world_context[CPU_DATA_CONTEXT_NUM];
static bool has_secure_perworld_init;
+static void manage_extensions_common(cpu_context_t *ctx);
static void manage_extensions_nonsecure(cpu_context_t *ctx);
static void manage_extensions_secure(cpu_context_t *ctx);
static void manage_extensions_secure_per_world(void);
@@ -312,6 +313,7 @@
static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *ep)
{
u_register_t scr_el3;
+ u_register_t mdcr_el3;
el3_state_t *state;
gp_regs_t *gp_regs;
@@ -484,6 +486,37 @@
write_ctx_reg(state, CTX_ELR_EL3, ep->pc);
write_ctx_reg(state, CTX_SPSR_EL3, ep->spsr);
+ /* Start with a clean MDCR_EL3 copy as all relevant values are set */
+ mdcr_el3 = MDCR_EL3_RESET_VAL;
+
+ /* ---------------------------------------------------------------------
+ * Initialise MDCR_EL3, setting all fields rather than relying on hw.
+ * Some fields are architecturally UNKNOWN on reset.
+ *
+ * MDCR_EL3.SDD: Set to one to disable AArch64 Secure self-hosted debug.
+ * Debug exceptions, other than Breakpoint Instruction exceptions, are
+ * disabled from all ELs in Secure state.
+ *
+ * MDCR_EL3.SPD32: Set to 0b10 to disable AArch32 Secure self-hosted
+ * privileged debug from S-EL1.
+ *
+ * MDCR_EL3.TDOSA: Set to zero so that EL2 and EL2 System register
+ * access to the powerdown debug registers do not trap to EL3.
+ *
+ * MDCR_EL3.TDA: Set to zero to allow EL0, EL1 and EL2 access to the
+ * debug registers, other than those registers that are controlled by
+ * MDCR_EL3.TDOSA.
+ */
+ mdcr_el3 |= ((MDCR_SDD_BIT | MDCR_SPD32(MDCR_SPD32_DISABLE))
+ & ~(MDCR_TDA_BIT | MDCR_TDOSA_BIT)) ;
+ write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3);
+
+ /*
+ * Configure MDCR_EL3 register as applicable for each world
+ * (NS/Secure/Realm) context.
+ */
+ manage_extensions_common(ctx);
+
/*
* Store the X0-X7 value from the entrypoint into the context
* Use memcpy as we are in control of the layout of the structures
@@ -560,10 +593,6 @@
#if IMAGE_BL31
void cm_manage_extensions_el3(void)
{
- if (is_feat_spe_supported()) {
- spe_init_el3();
- }
-
if (is_feat_amu_supported()) {
amu_init_el3();
}
@@ -572,18 +601,6 @@
sme_init_el3();
}
- if (is_feat_trbe_supported()) {
- trbe_init_el3();
- }
-
- if (is_feat_brbe_supported()) {
- brbe_init_el3();
- }
-
- if (is_feat_trf_supported()) {
- trf_init_el3();
- }
-
pmuv3_init_el3();
}
#endif /* IMAGE_BL31 */
@@ -704,6 +721,48 @@
}
/*******************************************************************************
+ * Enable architecture extensions on first entry to Non-secure world only
+ * and disable for secure world.
+ *
+ * NOTE: Arch features which have been provided with the capability of getting
+ * enabled only for non-secure world and being disabled for secure world are
+ * grouped here, as the MDCR_EL3 context value remains same across the worlds.
+ ******************************************************************************/
+static void manage_extensions_common(cpu_context_t *ctx)
+{
+#if IMAGE_BL31
+ if (is_feat_spe_supported()) {
+ /*
+ * Enable FEAT_SPE for Non-Secure and prohibit for Secure state.
+ */
+ spe_enable(ctx);
+ }
+
+ if (is_feat_trbe_supported()) {
+ /*
+ * Enable FEAT_SPE for Non-Secure and prohibit for Secure and
+ * Realm state.
+ */
+ trbe_enable(ctx);
+ }
+
+ if (is_feat_trf_supported()) {
+ /*
+ * Enable FEAT_SPE for Non-Secure and prohibit for Secure state.
+ */
+ trf_enable(ctx);
+ }
+
+ if (is_feat_brbe_supported()) {
+ /*
+ * Enable FEAT_SPE for Non-Secure and prohibit for Secure state.
+ */
+ brbe_enable(ctx);
+ }
+#endif /* IMAGE_BL31 */
+}
+
+/*******************************************************************************
* Enable architecture extensions on first entry to Non-secure world.
******************************************************************************/
static void manage_extensions_nonsecure(cpu_context_t *ctx)