From a0a7f158d2932117d57ec0d74113890a565e0cbc Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Fri, 13 Dec 2024 09:27:57 +0000 Subject: [PATCH] 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 --- services/std_svc/spm/el3_spmc/spmc_main.c | 13 ++++--------- services/std_svc/spmd/spmd_main.c | 4 ++++ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index c6ec30c3d..51fba5833 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 @@ static uint64_t msg_wait_handler(uint32_t smc_fid, /* 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 3953b245b..4d82991a2 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -715,6 +715,10 @@ uint64_t spmd_smc_switch_state(uint32_t smc_fid, 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