From 4087ed6c125e5352ba612df50228006eb7abab2f Mon Sep 17 00:00:00 2001 From: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com> Date: Mon, 11 Dec 2023 11:22:02 +0000 Subject: [PATCH] refactor(cm): reset the cptr_el3 before perworld context setup Currently, the registers which are maintained per-world, does not take into account the reset value while configuring the context for the respective world. This leads to an issue, wherein the register retains the same value across world switch, which is an error. This patch addresses this problem, by configuring the register (cptr_el3) precisely according to the world, the cpu is in execution via resetting it before initializing the world specific context. Change-Id: I592d82af373155fca67eed109c199341c305f0b9 Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com> --- include/lib/el3_runtime/aarch64/context.h | 6 ++--- include/lib/el3_runtime/context_mgmt.h | 2 ++ lib/el3_runtime/aarch64/context.S | 2 +- lib/el3_runtime/aarch64/context_mgmt.c | 27 ++++++++++++++++++++++- services/std_svc/rmmd/rmmd_main.c | 2 ++ 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index 47d91de0d..235b2cf41 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -341,9 +341,9 @@ /******************************************************************************* * Registers initialised in a per-world context. ******************************************************************************/ -#define CTX_CPTR_EL3 U(0x0) -#define CTX_ZCR_EL3 U(0x8) -#define CTX_GLOBAL_EL3STATE_END U(0x10) +#define CTX_CPTR_EL3 U(0x0) +#define CTX_ZCR_EL3 U(0x8) +#define CTX_PERWORLD_EL3STATE_END U(0x10) #ifndef __ASSEMBLER__ diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h index b2bdaf5a2..f631125f0 100644 --- a/include/lib/el3_runtime/context_mgmt.h +++ b/include/lib/el3_runtime/context_mgmt.h @@ -40,7 +40,9 @@ void cm_prepare_el3_exit_ns(void); #if IMAGE_BL31 void cm_manage_extensions_el3(void); void manage_extensions_nonsecure_per_world(void); +void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx); #endif + #if CTX_INCLUDE_EL2_REGS void cm_el2_sysregs_context_save(uint32_t security_state); void cm_el2_sysregs_context_restore(uint32_t security_state); diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 631094f73..18bdca82e 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -581,7 +581,7 @@ endfunc save_and_update_ptw_el1_sys_regs .macro get_per_world_context _reg:req ldr x10, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] get_security_state x9, x10 - mov_imm x10, (CTX_GLOBAL_EL3STATE_END - CTX_CPTR_EL3) + mov_imm x10, (CTX_PERWORLD_EL3STATE_END - CTX_CPTR_EL3) mul x9, x9, x10 adrp x10, per_world_context add x10, x10, :lo12:per_world_context diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index fdd1388cb..a0212c6b6 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -600,6 +600,28 @@ void cm_manage_extensions_el3(void) } #endif /* IMAGE_BL31 */ +/****************************************************************************** + * Function to initialise the registers with the RESET values in the context + * memory, which are maintained per world. + ******************************************************************************/ +#if IMAGE_BL31 +void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx) +{ + /* + * Initialise CPTR_EL3, setting all fields rather than relying on hw. + * + * 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. + */ + uint64_t cptr_el3 = CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TFP_BIT); + per_world_ctx->ctx_cptr_el3 = cptr_el3; +} +#endif /* IMAGE_BL31 */ + /******************************************************************************* * Initialise per_world_context for Non-Secure world. * This function enables the architecture extensions, which have same value @@ -608,6 +630,8 @@ void cm_manage_extensions_el3(void) #if IMAGE_BL31 void manage_extensions_nonsecure_per_world(void) { + cm_el3_arch_init_per_world(&per_world_context[CPU_CONTEXT_NS]); + if (is_feat_sme_supported()) { sme_enable_per_world(&per_world_context[CPU_CONTEXT_NS]); } @@ -631,10 +655,11 @@ void manage_extensions_nonsecure_per_world(void) * This function enables the architecture extensions, which have same value * across the cores for the secure world. ******************************************************************************/ - static void manage_extensions_secure_per_world(void) { #if IMAGE_BL31 + cm_el3_arch_init_per_world(&per_world_context[CPU_CONTEXT_SECURE]); + if (is_feat_sme_supported()) { if (ENABLE_SME_FOR_SWD) { diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c index 8b78b1357..4ea074fd6 100644 --- a/services/std_svc/rmmd/rmmd_main.c +++ b/services/std_svc/rmmd/rmmd_main.c @@ -134,6 +134,8 @@ static void manage_extensions_realm(cpu_context_t *ctx) static void manage_extensions_realm_per_world(void) { + cm_el3_arch_init_per_world(&per_world_context[CPU_CONTEXT_REALM]); + if (is_feat_sve_supported()) { /* * Enable SVE and FPU in realm context when it is enabled for NS.