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>
This commit is contained in:
Jayanth Dodderi Chidanand 2023-12-11 11:22:02 +00:00
parent 9118bdf401
commit 4087ed6c12
5 changed files with 34 additions and 5 deletions

View file

@ -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__

View file

@ -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);

View file

@ -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

View file

@ -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) {

View file

@ -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.