diff options
author | Boyan Karatotev <boyan.karatotev@arm.com> | 2023-03-08 11:56:49 +0000 |
---|---|---|
committer | Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com> | 2023-06-29 09:59:06 +0100 |
commit | 24a70738b2c119a95a78cd4c89b257c3e028c20d (patch) | |
tree | 886b729fb4dd4a9fa36239be45ca3e0c7ade9d36 | |
parent | 098312edf7c5809489ad44fa5e2a92c9e92c46da (diff) |
refactor(cm): introduce a real manage_extensions_nonsecure()
manage_extensions_nonsecure() is problematic because it updates both
context and in-place registers (unlike its secure/realm counterparts).
The in-place register updates make it particularly tricky, as those
never change for the lifetime of TF-A. However, they are only set when
exiting to NS world. As such, all of TF-A's execution before that
operates under a different context. This is inconsistent and could cause
problems.
This patch Introduce a real manage_extensions_nonsecure() which only
operates on the context structure. It also introduces a
cm_manage_extensions_el3() which only operates on register in-place that
are not context switched. It is called in BL31's entrypoints so that all
of TF-A executes with the same environment once all features have been
converted.
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Change-Id: Ic579f86c41026d2054863ef44893e0ba4c591da9
-rw-r--r-- | bl31/bl31_main.c | 3 | ||||
-rw-r--r-- | include/lib/el3_runtime/context_mgmt.h | 4 | ||||
-rw-r--r-- | lib/el3_runtime/aarch64/context_mgmt.c | 45 | ||||
-rw-r--r-- | lib/psci/psci_common.c | 3 |
4 files changed, 51 insertions, 4 deletions
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c index e70eb5584..8f1f043da 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -112,6 +112,9 @@ void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, ******************************************************************************/ void bl31_main(void) { + /* Init registers that never change for the lifetime of TF-A */ + cm_manage_extensions_el3(); + NOTICE("BL31: %s\n", version_string); NOTICE("BL31: %s\n", build_message); diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h index 1a76d8e2f..aa76f3b68 100644 --- a/include/lib/el3_runtime/context_mgmt.h +++ b/include/lib/el3_runtime/context_mgmt.h @@ -37,6 +37,9 @@ void cm_prepare_el3_exit(uint32_t security_state); void cm_prepare_el3_exit_ns(void); #ifdef __aarch64__ +#if IMAGE_BL31 +void cm_manage_extensions_el3(void); +#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); @@ -84,6 +87,7 @@ static inline void cm_set_next_context(void *context) #else void *cm_get_next_context(void); void cm_set_next_context(void *context); +static inline void cm_manage_extensions_el3(void) {} #endif /* __aarch64__ */ #endif /* CONTEXT_MGMT_H */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 3760b8f13..44177fa2f 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -37,6 +37,7 @@ CASSERT(((TWED_DELAY & ~SCR_TWEDEL_MASK) == 0U), assert_twed_delay_value_check); #endif /* ENABLE_FEAT_TWED */ +static void manage_extensions_nonsecure(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) @@ -288,6 +289,8 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info * HCRX_EL2_INIT_VAL); } #endif /* CTX_INCLUDE_EL2_REGS */ + + manage_extensions_nonsecure(ctx); } /******************************************************************************* @@ -504,9 +507,11 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) /******************************************************************************* * Enable architecture extensions on first entry to Non-secure world. * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise - * it is zero. + * it is zero. This function updates some registers in-place and its contents + * are being prepared to be moved to cm_manage_extensions_el3 and + * cm_manage_extensions_nonsecure. ******************************************************************************/ -static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx) +static void manage_extensions_nonsecure_mixed(bool el2_unused, cpu_context_t *ctx) { #if IMAGE_BL31 if (is_feat_spe_supported()) { @@ -549,6 +554,36 @@ static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx) } /******************************************************************************* + * Enable architecture extensions for EL3 execution. This function only updates + * registers in-place which are expected to either never change or be + * overwritten by el3_exit. + ******************************************************************************/ +#if IMAGE_BL31 +void cm_manage_extensions_el3(void) +{ +} +#endif /* IMAGE_BL31 */ + +/******************************************************************************* + * Enable architecture extensions on first entry to Non-secure world. + ******************************************************************************/ +static void manage_extensions_nonsecure(cpu_context_t *ctx) +{ +#if IMAGE_BL31 +#endif /* IMAGE_BL31 */ +} + +/******************************************************************************* + * Enable architecture extensions in-place at EL2 on first entry to Non-secure + * world when EL2 is empty and unused. + ******************************************************************************/ +static void manage_extensions_nonsecure_el2_unused(void) +{ +#if IMAGE_BL31 +#endif /* IMAGE_BL31 */ +} + +/******************************************************************************* * Enable architecture extensions on first entry to Secure world. ******************************************************************************/ static void manage_extensions_secure(cpu_context_t *ctx) @@ -845,8 +880,10 @@ void cm_prepare_el3_exit(uint32_t security_state) */ write_cnthp_ctl_el2(CNTHP_CTL_RESET_VAL & ~(CNTHP_CTL_ENABLE_BIT)); + + manage_extensions_nonsecure_el2_unused(); } - manage_extensions_nonsecure(el2_unused, ctx); + manage_extensions_nonsecure_mixed(el2_unused, ctx); } cm_el1_sysregs_context_restore(security_state); @@ -1167,7 +1204,7 @@ void cm_prepare_el3_exit_ns(void) * direct register updates. Therefore, do this here * instead of when setting up context. */ - manage_extensions_nonsecure(0, ctx); + manage_extensions_nonsecure_mixed(0, ctx); /* * Set the NS bit to be able to access the ICC_SRE_EL2 diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c index bfc09ccb2..8aa0cce71 100644 --- a/lib/psci/psci_common.c +++ b/lib/psci/psci_common.c @@ -985,6 +985,9 @@ void psci_warmboot_entrypoint(void) unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} }; + /* Init registers that never change for the lifetime of TF-A */ + cm_manage_extensions_el3(); + /* * Verify that we have been explicitly turned ON or resumed from * suspend. |