mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-26 14:55:16 +00:00
refactor(context mgmt): refactor initialization of EL1 context registers
When SPMC is present at S-EL2, EL1 context registers don't need to be initialized for Secure state. This patch makes sure that EL1 context registers are initialized only for Non-secure state, and when SPMC is not present at S-EL2 Signed-off-by: Zelalem Aweke <zelalem.aweke@arm.com> Change-Id: I4a60b258c31ce5f6472a243e2687159cc495259b
This commit is contained in:
parent
0dc2b51681
commit
b515f5414b
1 changed files with 81 additions and 60 deletions
|
@ -36,6 +36,64 @@ CASSERT(((TWED_DELAY & ~SCR_TWEDEL_MASK) == 0U), assert_twed_delay_value_check);
|
||||||
#endif /* ENABLE_FEAT_TWED */
|
#endif /* ENABLE_FEAT_TWED */
|
||||||
|
|
||||||
static void manage_extensions_secure(cpu_context_t *ctx);
|
static void manage_extensions_secure(cpu_context_t *ctx);
|
||||||
|
|
||||||
|
static void setup_el1_context(cpu_context_t *ctx, const struct entry_point_info *ep)
|
||||||
|
{
|
||||||
|
u_register_t sctlr_elx, actlr_elx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise SCTLR_EL1 to the reset value corresponding to the target
|
||||||
|
* execution state setting all fields rather than relying on the hw.
|
||||||
|
* Some fields have architecturally UNKNOWN reset values and these are
|
||||||
|
* set to zero.
|
||||||
|
*
|
||||||
|
* SCTLR.EE: Endianness is taken from the entrypoint attributes.
|
||||||
|
*
|
||||||
|
* SCTLR.M, SCTLR.C and SCTLR.I: These fields must be zero (as
|
||||||
|
* required by PSCI specification)
|
||||||
|
*/
|
||||||
|
sctlr_elx = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0UL;
|
||||||
|
if (GET_RW(ep->spsr) == MODE_RW_64) {
|
||||||
|
sctlr_elx |= SCTLR_EL1_RES1;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If the target execution state is AArch32 then the following
|
||||||
|
* fields need to be set.
|
||||||
|
*
|
||||||
|
* SCTRL_EL1.nTWE: Set to one so that EL0 execution of WFE
|
||||||
|
* instructions are not trapped to EL1.
|
||||||
|
*
|
||||||
|
* SCTLR_EL1.nTWI: Set to one so that EL0 execution of WFI
|
||||||
|
* instructions are not trapped to EL1.
|
||||||
|
*
|
||||||
|
* SCTLR_EL1.CP15BEN: Set to one to enable EL0 execution of the
|
||||||
|
* CP15DMB, CP15DSB, and CP15ISB instructions.
|
||||||
|
*/
|
||||||
|
sctlr_elx |= SCTLR_AARCH32_EL1_RES1 | SCTLR_CP15BEN_BIT
|
||||||
|
| SCTLR_NTWI_BIT | SCTLR_NTWE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ERRATA_A75_764081
|
||||||
|
/*
|
||||||
|
* If workaround of errata 764081 for Cortex-A75 is used then set
|
||||||
|
* SCTLR_EL1.IESB to enable Implicit Error Synchronization Barrier.
|
||||||
|
*/
|
||||||
|
sctlr_elx |= SCTLR_IESB_BIT;
|
||||||
|
#endif
|
||||||
|
/* Store the initialised SCTLR_EL1 value in the cpu_context */
|
||||||
|
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Base the context ACTLR_EL1 on the current value, as it is
|
||||||
|
* implementation defined. The context restore process will write
|
||||||
|
* the value from the context to the actual register and can cause
|
||||||
|
* problems for processor cores that don't expect certain bits to
|
||||||
|
* be zero.
|
||||||
|
*/
|
||||||
|
actlr_elx = read_actlr_el1();
|
||||||
|
write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* This function performs initializations that are specific to SECURE state
|
* This function performs initializations that are specific to SECURE state
|
||||||
* and updates the cpu context specified by 'ctx'.
|
* and updates the cpu context specified by 'ctx'.
|
||||||
|
@ -85,6 +143,14 @@ static void setup_secure_context(cpu_context_t *ctx, const struct entry_point_in
|
||||||
|
|
||||||
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
|
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize EL1 context registers unless SPMC is running
|
||||||
|
* at S-EL2.
|
||||||
|
*/
|
||||||
|
#if !SPMD_SPM_AT_SEL2
|
||||||
|
setup_el1_context(ctx, ep);
|
||||||
|
#endif
|
||||||
|
|
||||||
manage_extensions_secure(ctx);
|
manage_extensions_secure(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +213,9 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info *
|
||||||
#endif
|
#endif
|
||||||
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
|
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
|
||||||
|
|
||||||
|
/* Initialize EL1 context registers */
|
||||||
|
setup_el1_context(ctx, ep);
|
||||||
|
|
||||||
/* Initialize EL2 context registers */
|
/* Initialize EL2 context registers */
|
||||||
#if CTX_INCLUDE_EL2_REGS
|
#if CTX_INCLUDE_EL2_REGS
|
||||||
|
|
||||||
|
@ -186,7 +255,6 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
|
||||||
u_register_t scr_el3;
|
u_register_t scr_el3;
|
||||||
el3_state_t *state;
|
el3_state_t *state;
|
||||||
gp_regs_t *gp_regs;
|
gp_regs_t *gp_regs;
|
||||||
u_register_t sctlr_elx, actlr_elx;
|
|
||||||
|
|
||||||
/* Clear any residual register values from the context */
|
/* Clear any residual register values from the context */
|
||||||
zeromem(ctx, sizeof(*ctx));
|
zeromem(ctx, sizeof(*ctx));
|
||||||
|
@ -215,7 +283,9 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
|
||||||
/*
|
/*
|
||||||
* SCR_EL3.ST: Traps Secure EL1 accesses to the Counter-timer Physical
|
* SCR_EL3.ST: Traps Secure EL1 accesses to the Counter-timer Physical
|
||||||
* Secure timer registers to EL3, from AArch64 state only, if specified
|
* Secure timer registers to EL3, from AArch64 state only, if specified
|
||||||
* by the entrypoint attributes.
|
* by the entrypoint attributes. If SEL2 is present and enabled, the ST
|
||||||
|
* bit always behaves as 1 (i.e. secure physical timer register access
|
||||||
|
* is not trapped)
|
||||||
*/
|
*/
|
||||||
if (EP_GET_ST(ep->h.attr) != 0U) {
|
if (EP_GET_ST(ep->h.attr) != 0U) {
|
||||||
scr_el3 |= SCR_ST_BIT;
|
scr_el3 |= SCR_ST_BIT;
|
||||||
|
@ -283,46 +353,6 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialise SCTLR_EL1 to the reset value corresponding to the target
|
|
||||||
* execution state setting all fields rather than relying of the hw.
|
|
||||||
* Some fields have architecturally UNKNOWN reset values and these are
|
|
||||||
* set to zero.
|
|
||||||
*
|
|
||||||
* SCTLR.EE: Endianness is taken from the entrypoint attributes.
|
|
||||||
*
|
|
||||||
* SCTLR.M, SCTLR.C and SCTLR.I: These fields must be zero (as
|
|
||||||
* required by PSCI specification)
|
|
||||||
*/
|
|
||||||
sctlr_elx = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0U;
|
|
||||||
if (GET_RW(ep->spsr) == MODE_RW_64) {
|
|
||||||
sctlr_elx |= SCTLR_EL1_RES1;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* If the target execution state is AArch32 then the following
|
|
||||||
* fields need to be set.
|
|
||||||
*
|
|
||||||
* SCTRL_EL1.nTWE: Set to one so that EL0 execution of WFE
|
|
||||||
* instructions are not trapped to EL1.
|
|
||||||
*
|
|
||||||
* SCTLR_EL1.nTWI: Set to one so that EL0 execution of WFI
|
|
||||||
* instructions are not trapped to EL1.
|
|
||||||
*
|
|
||||||
* SCTLR_EL1.CP15BEN: Set to one to enable EL0 execution of the
|
|
||||||
* CP15DMB, CP15DSB, and CP15ISB instructions.
|
|
||||||
*/
|
|
||||||
sctlr_elx |= SCTLR_AARCH32_EL1_RES1 | SCTLR_CP15BEN_BIT
|
|
||||||
| SCTLR_NTWI_BIT | SCTLR_NTWE_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ERRATA_A75_764081
|
|
||||||
/*
|
|
||||||
* If workaround of errata 764081 for Cortex-A75 is used then set
|
|
||||||
* SCTLR_EL1.IESB to enable Implicit Error Synchronization Barrier.
|
|
||||||
*/
|
|
||||||
sctlr_elx |= SCTLR_IESB_BIT;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLE_FEAT_TWED
|
#if ENABLE_FEAT_TWED
|
||||||
/* Enable WFE trap delay in SCR_EL3 if supported and configured */
|
/* Enable WFE trap delay in SCR_EL3 if supported and configured */
|
||||||
/* Set delay in SCR_EL3 */
|
/* Set delay in SCR_EL3 */
|
||||||
|
@ -334,23 +364,6 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
|
||||||
scr_el3 |= SCR_TWEDEn_BIT;
|
scr_el3 |= SCR_TWEDEn_BIT;
|
||||||
#endif /* ENABLE_FEAT_TWED */
|
#endif /* ENABLE_FEAT_TWED */
|
||||||
|
|
||||||
/*
|
|
||||||
* Store the initialised SCTLR_EL1 value in the cpu_context - SCTLR_EL2
|
|
||||||
* and other EL2 registers are set up by cm_prepare_el3_exit() as they
|
|
||||||
* are not part of the stored cpu_context.
|
|
||||||
*/
|
|
||||||
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Base the context ACTLR_EL1 on the current value, as it is
|
|
||||||
* implementation defined. The context restore process will write
|
|
||||||
* the value from the context to the actual register and can cause
|
|
||||||
* problems for processor cores that don't expect certain bits to
|
|
||||||
* be zero.
|
|
||||||
*/
|
|
||||||
actlr_elx = read_actlr_el1();
|
|
||||||
write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Populate EL3 state so that we've the right context
|
* Populate EL3 state so that we've the right context
|
||||||
* before doing ERET
|
* before doing ERET
|
||||||
|
@ -820,6 +833,14 @@ void cm_prepare_el3_exit_ns(void)
|
||||||
cpu_context_t *ctx = cm_get_context(NON_SECURE);
|
cpu_context_t *ctx = cm_get_context(NON_SECURE);
|
||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
|
|
||||||
|
/* Assert that EL2 is used. */
|
||||||
|
#if ENABLE_ASSERTIONS
|
||||||
|
el3_state_t *state = get_el3state_ctx(ctx);
|
||||||
|
u_register_t scr_el3 = read_ctx_reg(state, CTX_SCR_EL3);
|
||||||
|
#endif
|
||||||
|
assert(((scr_el3 & SCR_HCE_BIT) != 0UL) &&
|
||||||
|
(el_implemented(2U) != EL_IMPL_NONE));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Currently some extensions are configured using
|
* Currently some extensions are configured using
|
||||||
* direct register updates. Therefore, do this here
|
* direct register updates. Therefore, do this here
|
||||||
|
|
Loading…
Add table
Reference in a new issue