mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 09:34:18 +00:00
refactor(cm): remove world differentiation for EL2 context restore
The EL2 context save/restore functions have an optimisation to not bother with the EL2 context when SEL2 is not in use. However, this decision is made on the current value of SCR_EL3.EEL2, which is not the value for the selected security state, but rather, for the security state that came before it. This relies on the EEL2 bit's value to propagate identically to all worlds. This has an unintended side effect that for the first entry into secure world, the restoring of the context is fully skipped, because SCR_EL3 is only initialized after the call to the restoring routine which means the EEL2 bit is not initialized (except when FEAT_RME is present). This is inconsistent with normal and realm worlds which always get their EL2 registers zeroed. Remove this optimization to remove all the complexity with managing the EEL2 bit's value. Instead unconditionally save/restore all registers. It is worth noting that there is no performance penalty in the case where SEL2 is empty with this change. This is because SEL2 will never be entered, and as such no secure save/restore will happen anyway, while normal world remains unchanged. Removing the value management of the EEL2 bit causes the CTX_ICC_SRE_EL2 register to be inaccessible in Secure world for some configurations. Make the SCR_EL3.NS workaround in cm_prepare_el3_exit_ns() generic on every access to the register. Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com> Change-Id: I1f56d85814c5897b468e82d4bd4a08e3a90a7f8f
This commit is contained in:
parent
5e8cc72786
commit
5c52d7e540
2 changed files with 132 additions and 162 deletions
|
@ -67,13 +67,6 @@
|
|||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
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
|
||||
* in context management. This will need to be refactored.
|
||||
*/
|
||||
orr x0, x0, #SCR_EEL2_BIT
|
||||
#endif
|
||||
msr scr_el3, x0
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
|
|
@ -339,18 +339,8 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
|
|||
write_ctx_reg(el2_ctx, CTX_ICC_SRE_EL2, icc_sre_el2);
|
||||
#endif /* CTX_INCLUDE_EL2_REGS */
|
||||
|
||||
/*
|
||||
* SCR_EL3 was initialised during reset sequence in macro
|
||||
* el3_arch_init_common. This code modifies the SCR_EL3 fields that
|
||||
* affect the next EL.
|
||||
*
|
||||
* The following fields are initially set to zero and then updated to
|
||||
* the required value depending on the state of the SPSR_EL3 and the
|
||||
* Security state and entrypoint attributes of the next EL.
|
||||
*/
|
||||
scr_el3 = read_scr();
|
||||
scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_EA_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT |
|
||||
SCR_ST_BIT | SCR_HCE_BIT | SCR_NSE_BIT);
|
||||
/* Start with a clean SCR_EL3 copy as all relevant values are set */
|
||||
scr_el3 = SCR_RESET_VAL;
|
||||
|
||||
/*
|
||||
* SCR_EL3.TWE: Set to zero so that execution of WFE instructions at
|
||||
|
@ -1094,7 +1084,20 @@ static void el2_sysregs_context_save_common(el2_sysregs_t *ctx)
|
|||
write_ctx_reg(ctx, CTX_HCR_EL2, read_hcr_el2());
|
||||
write_ctx_reg(ctx, CTX_HPFAR_EL2, read_hpfar_el2());
|
||||
write_ctx_reg(ctx, CTX_HSTR_EL2, read_hstr_el2());
|
||||
|
||||
/*
|
||||
* Set the NS bit to be able to access the ICC_SRE_EL2 register
|
||||
* TODO: remove with root context
|
||||
*/
|
||||
u_register_t scr_el3 = read_scr_el3();
|
||||
|
||||
write_scr_el3(scr_el3 | SCR_NS_BIT);
|
||||
isb();
|
||||
write_ctx_reg(ctx, CTX_ICC_SRE_EL2, read_icc_sre_el2());
|
||||
|
||||
write_scr_el3(scr_el3);
|
||||
isb();
|
||||
|
||||
write_ctx_reg(ctx, CTX_ICH_HCR_EL2, read_ich_hcr_el2());
|
||||
write_ctx_reg(ctx, CTX_ICH_VMCR_EL2, read_ich_vmcr_el2());
|
||||
write_ctx_reg(ctx, CTX_MAIR_EL2, read_mair_el2());
|
||||
|
@ -1131,7 +1134,20 @@ static void el2_sysregs_context_restore_common(el2_sysregs_t *ctx)
|
|||
write_hcr_el2(read_ctx_reg(ctx, CTX_HCR_EL2));
|
||||
write_hpfar_el2(read_ctx_reg(ctx, CTX_HPFAR_EL2));
|
||||
write_hstr_el2(read_ctx_reg(ctx, CTX_HSTR_EL2));
|
||||
|
||||
/*
|
||||
* Set the NS bit to be able to access the ICC_SRE_EL2 register
|
||||
* TODO: remove with root context
|
||||
*/
|
||||
u_register_t scr_el3 = read_scr_el3();
|
||||
|
||||
write_scr_el3(scr_el3 | SCR_NS_BIT);
|
||||
isb();
|
||||
write_icc_sre_el2(read_ctx_reg(ctx, CTX_ICC_SRE_EL2));
|
||||
|
||||
write_scr_el3(scr_el3);
|
||||
isb();
|
||||
|
||||
write_ich_hcr_el2(read_ctx_reg(ctx, CTX_ICH_HCR_EL2));
|
||||
write_ich_vmcr_el2(read_ctx_reg(ctx, CTX_ICH_VMCR_EL2));
|
||||
write_mair_el2(read_ctx_reg(ctx, CTX_MAIR_EL2));
|
||||
|
@ -1154,87 +1170,71 @@ static void el2_sysregs_context_restore_common(el2_sysregs_t *ctx)
|
|||
******************************************************************************/
|
||||
void cm_el2_sysregs_context_save(uint32_t security_state)
|
||||
{
|
||||
u_register_t scr_el3 = read_scr();
|
||||
cpu_context_t *ctx;
|
||||
el2_sysregs_t *el2_sysregs_ctx;
|
||||
|
||||
/*
|
||||
* Always save the non-secure and realm EL2 context, only save the
|
||||
* S-EL2 context if S-EL2 is enabled.
|
||||
*/
|
||||
if ((security_state != SECURE) ||
|
||||
((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) {
|
||||
cpu_context_t *ctx;
|
||||
el2_sysregs_t *el2_sysregs_ctx;
|
||||
ctx = cm_get_context(security_state);
|
||||
assert(ctx != NULL);
|
||||
|
||||
ctx = cm_get_context(security_state);
|
||||
assert(ctx != NULL);
|
||||
el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
|
||||
|
||||
el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
|
||||
|
||||
el2_sysregs_context_save_common(el2_sysregs_ctx);
|
||||
el2_sysregs_context_save_common(el2_sysregs_ctx);
|
||||
#if CTX_INCLUDE_MTE_REGS
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_TFSR_EL2, read_tfsr_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_TFSR_EL2, read_tfsr_el2());
|
||||
#endif
|
||||
if (is_feat_mpam_supported()) {
|
||||
el2_sysregs_context_save_mpam(el2_sysregs_ctx);
|
||||
}
|
||||
if (is_feat_mpam_supported()) {
|
||||
el2_sysregs_context_save_mpam(el2_sysregs_ctx);
|
||||
}
|
||||
|
||||
if (is_feat_fgt_supported()) {
|
||||
el2_sysregs_context_save_fgt(el2_sysregs_ctx);
|
||||
}
|
||||
if (is_feat_fgt_supported()) {
|
||||
el2_sysregs_context_save_fgt(el2_sysregs_ctx);
|
||||
}
|
||||
|
||||
if (is_feat_ecv_v2_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_CNTPOFF_EL2,
|
||||
read_cntpoff_el2());
|
||||
}
|
||||
if (is_feat_ecv_v2_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_CNTPOFF_EL2, read_cntpoff_el2());
|
||||
}
|
||||
|
||||
if (is_feat_vhe_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2,
|
||||
read_contextidr_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2,
|
||||
read_ttbr1_el2());
|
||||
}
|
||||
if (is_feat_vhe_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2, read_contextidr_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2, read_ttbr1_el2());
|
||||
}
|
||||
|
||||
if (is_feat_ras_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_VDISR_EL2,
|
||||
read_vdisr_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_VSESR_EL2,
|
||||
read_vsesr_el2());
|
||||
}
|
||||
if (is_feat_ras_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_VDISR_EL2, read_vdisr_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_VSESR_EL2, read_vsesr_el2());
|
||||
}
|
||||
|
||||
if (is_feat_nv2_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_VNCR_EL2,
|
||||
read_vncr_el2());
|
||||
}
|
||||
if (is_feat_nv2_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_VNCR_EL2, read_vncr_el2());
|
||||
}
|
||||
|
||||
if (is_feat_trf_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_TRFCR_EL2, read_trfcr_el2());
|
||||
}
|
||||
if (is_feat_trf_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_TRFCR_EL2, read_trfcr_el2());
|
||||
}
|
||||
|
||||
if (is_feat_csv2_2_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_SCXTNUM_EL2,
|
||||
read_scxtnum_el2());
|
||||
}
|
||||
if (is_feat_csv2_2_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_SCXTNUM_EL2, read_scxtnum_el2());
|
||||
}
|
||||
|
||||
if (is_feat_hcx_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_HCRX_EL2, read_hcrx_el2());
|
||||
}
|
||||
if (is_feat_tcr2_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_TCR2_EL2, read_tcr2_el2());
|
||||
}
|
||||
if (is_feat_sxpie_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_PIRE0_EL2, read_pire0_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_PIR_EL2, read_pir_el2());
|
||||
}
|
||||
if (is_feat_s2pie_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_S2PIR_EL2, read_s2pir_el2());
|
||||
}
|
||||
if (is_feat_sxpoe_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2, read_por_el2());
|
||||
}
|
||||
if (is_feat_gcs_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_GCSPR_EL2, read_gcspr_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_GCSCR_EL2, read_gcscr_el2());
|
||||
}
|
||||
if (is_feat_hcx_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_HCRX_EL2, read_hcrx_el2());
|
||||
}
|
||||
if (is_feat_tcr2_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_TCR2_EL2, read_tcr2_el2());
|
||||
}
|
||||
if (is_feat_sxpie_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_PIRE0_EL2, read_pire0_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_PIR_EL2, read_pir_el2());
|
||||
}
|
||||
if (is_feat_s2pie_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_S2PIR_EL2, read_s2pir_el2());
|
||||
}
|
||||
if (is_feat_sxpoe_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2, read_por_el2());
|
||||
}
|
||||
if (is_feat_gcs_supported()) {
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_GCSPR_EL2, read_gcspr_el2());
|
||||
write_ctx_reg(el2_sysregs_ctx, CTX_GCSCR_EL2, read_gcscr_el2());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1243,81 +1243,70 @@ void cm_el2_sysregs_context_save(uint32_t security_state)
|
|||
******************************************************************************/
|
||||
void cm_el2_sysregs_context_restore(uint32_t security_state)
|
||||
{
|
||||
u_register_t scr_el3 = read_scr();
|
||||
cpu_context_t *ctx;
|
||||
el2_sysregs_t *el2_sysregs_ctx;
|
||||
|
||||
/*
|
||||
* Always restore the non-secure and realm EL2 context, only restore the
|
||||
* S-EL2 context if S-EL2 is enabled.
|
||||
*/
|
||||
if ((security_state != SECURE) ||
|
||||
((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) {
|
||||
cpu_context_t *ctx;
|
||||
el2_sysregs_t *el2_sysregs_ctx;
|
||||
ctx = cm_get_context(security_state);
|
||||
assert(ctx != NULL);
|
||||
|
||||
ctx = cm_get_context(security_state);
|
||||
assert(ctx != NULL);
|
||||
el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
|
||||
|
||||
el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
|
||||
|
||||
el2_sysregs_context_restore_common(el2_sysregs_ctx);
|
||||
el2_sysregs_context_restore_common(el2_sysregs_ctx);
|
||||
#if CTX_INCLUDE_MTE_REGS
|
||||
write_tfsr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TFSR_EL2));
|
||||
write_tfsr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TFSR_EL2));
|
||||
#endif
|
||||
if (is_feat_mpam_supported()) {
|
||||
el2_sysregs_context_restore_mpam(el2_sysregs_ctx);
|
||||
}
|
||||
if (is_feat_mpam_supported()) {
|
||||
el2_sysregs_context_restore_mpam(el2_sysregs_ctx);
|
||||
}
|
||||
|
||||
if (is_feat_fgt_supported()) {
|
||||
el2_sysregs_context_restore_fgt(el2_sysregs_ctx);
|
||||
}
|
||||
if (is_feat_fgt_supported()) {
|
||||
el2_sysregs_context_restore_fgt(el2_sysregs_ctx);
|
||||
}
|
||||
|
||||
if (is_feat_ecv_v2_supported()) {
|
||||
write_cntpoff_el2(read_ctx_reg(el2_sysregs_ctx,
|
||||
CTX_CNTPOFF_EL2));
|
||||
}
|
||||
if (is_feat_ecv_v2_supported()) {
|
||||
write_cntpoff_el2(read_ctx_reg(el2_sysregs_ctx, CTX_CNTPOFF_EL2));
|
||||
}
|
||||
|
||||
if (is_feat_vhe_supported()) {
|
||||
write_contextidr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2));
|
||||
write_ttbr1_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2));
|
||||
}
|
||||
if (is_feat_vhe_supported()) {
|
||||
write_contextidr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_CONTEXTIDR_EL2));
|
||||
write_ttbr1_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TTBR1_EL2));
|
||||
}
|
||||
|
||||
if (is_feat_ras_supported()) {
|
||||
write_vdisr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VDISR_EL2));
|
||||
write_vsesr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VSESR_EL2));
|
||||
}
|
||||
if (is_feat_ras_supported()) {
|
||||
write_vdisr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VDISR_EL2));
|
||||
write_vsesr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VSESR_EL2));
|
||||
}
|
||||
|
||||
if (is_feat_nv2_supported()) {
|
||||
write_vncr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VNCR_EL2));
|
||||
}
|
||||
if (is_feat_trf_supported()) {
|
||||
write_trfcr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TRFCR_EL2));
|
||||
}
|
||||
if (is_feat_nv2_supported()) {
|
||||
write_vncr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_VNCR_EL2));
|
||||
}
|
||||
if (is_feat_trf_supported()) {
|
||||
write_trfcr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TRFCR_EL2));
|
||||
}
|
||||
|
||||
if (is_feat_csv2_2_supported()) {
|
||||
write_scxtnum_el2(read_ctx_reg(el2_sysregs_ctx,
|
||||
CTX_SCXTNUM_EL2));
|
||||
}
|
||||
if (is_feat_csv2_2_supported()) {
|
||||
write_scxtnum_el2(read_ctx_reg(el2_sysregs_ctx, CTX_SCXTNUM_EL2));
|
||||
}
|
||||
|
||||
if (is_feat_hcx_supported()) {
|
||||
write_hcrx_el2(read_ctx_reg(el2_sysregs_ctx, CTX_HCRX_EL2));
|
||||
}
|
||||
if (is_feat_tcr2_supported()) {
|
||||
write_tcr2_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TCR2_EL2));
|
||||
}
|
||||
if (is_feat_sxpie_supported()) {
|
||||
write_pire0_el2(read_ctx_reg(el2_sysregs_ctx, CTX_PIRE0_EL2));
|
||||
write_pir_el2(read_ctx_reg(el2_sysregs_ctx, CTX_PIR_EL2));
|
||||
}
|
||||
if (is_feat_s2pie_supported()) {
|
||||
write_s2pir_el2(read_ctx_reg(el2_sysregs_ctx, CTX_S2PIR_EL2));
|
||||
}
|
||||
if (is_feat_sxpoe_supported()) {
|
||||
write_por_el2(read_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2));
|
||||
}
|
||||
if (is_feat_gcs_supported()) {
|
||||
write_gcscr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_GCSCR_EL2));
|
||||
write_gcspr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_GCSPR_EL2));
|
||||
}
|
||||
if (is_feat_hcx_supported()) {
|
||||
write_hcrx_el2(read_ctx_reg(el2_sysregs_ctx, CTX_HCRX_EL2));
|
||||
}
|
||||
if (is_feat_tcr2_supported()) {
|
||||
write_tcr2_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TCR2_EL2));
|
||||
}
|
||||
if (is_feat_sxpie_supported()) {
|
||||
write_pire0_el2(read_ctx_reg(el2_sysregs_ctx, CTX_PIRE0_EL2));
|
||||
write_pir_el2(read_ctx_reg(el2_sysregs_ctx, CTX_PIR_EL2));
|
||||
}
|
||||
if (is_feat_s2pie_supported()) {
|
||||
write_s2pir_el2(read_ctx_reg(el2_sysregs_ctx, CTX_S2PIR_EL2));
|
||||
}
|
||||
if (is_feat_sxpoe_supported()) {
|
||||
write_por_el2(read_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2));
|
||||
}
|
||||
if (is_feat_gcs_supported()) {
|
||||
write_gcscr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_GCSCR_EL2));
|
||||
write_gcspr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_GCSPR_EL2));
|
||||
}
|
||||
}
|
||||
#endif /* CTX_INCLUDE_EL2_REGS */
|
||||
|
@ -1341,18 +1330,6 @@ void cm_prepare_el3_exit_ns(void)
|
|||
(el_implemented(2U) != EL_IMPL_NONE));
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/*
|
||||
* Set the NS bit to be able to access the ICC_SRE_EL2
|
||||
* register when restoring context.
|
||||
*/
|
||||
write_scr_el3(read_scr_el3() | SCR_NS_BIT);
|
||||
|
||||
/*
|
||||
* Ensure the NS bit change is committed before the EL2/EL1
|
||||
* state restoration.
|
||||
*/
|
||||
isb();
|
||||
|
||||
/* Restore EL2 and EL1 sysreg contexts */
|
||||
cm_el2_sysregs_context_restore(NON_SECURE);
|
||||
cm_el1_sysregs_context_restore(NON_SECURE);
|
||||
|
|
Loading…
Add table
Reference in a new issue