feat(el3-spmc): use spmd_smc_switch_state after secure interrupt
Switch the state back to non-secure after a secure interrupt
using spmd_smc_switch_state with FFA_NORMAL_WORLD_RESUME
to reduce the number of control flow paths for world switches.
Fixes an issue where FP registers were not correctly restored
after secure interrupts.
Upstreamed from https://r.android.com/3345999, tested on Trusty.
Change-Id: I3ce33f7657c13b999969ebb8957d5d4b6c3aa634
Signed-off-by: Andrei Homescu <ahomescu@google.com>
diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c
index c6ec30c..51fba58 100644
--- a/services/std_svc/spm/el3_spmc/spmc_main.c
+++ b/services/std_svc/spm/el3_spmc/spmc_main.c
@@ -610,19 +610,14 @@
/* Resume normal world if a secure interrupt was handled. */
if (sp->ec[idx].rt_model == RT_MODEL_INTR) {
- /* FFA_MSG_WAIT can only be called from the secure world. */
- unsigned int secure_state_in = SECURE;
- unsigned int secure_state_out = NON_SECURE;
-
- cm_el1_sysregs_context_save(secure_state_in);
- cm_el1_sysregs_context_restore(secure_state_out);
- cm_set_next_eret_context(secure_state_out);
-
if (sp->runtime_el == S_EL0) {
spin_unlock(&sp->rt_state_lock);
}
- SMC_RET0(cm_get_context(secure_state_out));
+ return spmd_smc_switch_state(FFA_NORMAL_WORLD_RESUME, secure_origin,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+ handle, flags);
}
/* Protect the runtime state of a S-EL0 SP with a lock. */
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 3953b24..4d82991 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -715,6 +715,10 @@
cm_set_next_eret_context(secure_state_out);
ctx_out = cm_get_context(secure_state_out);
+ if (smc_fid == FFA_NORMAL_WORLD_RESUME) {
+ SMC_RET0(ctx_out);
+ }
+
#if SPMD_SPM_AT_SEL2
/*
* If SPMC is at SEL2, save additional registers x8-x17, which may