diff --git a/include/services/spmd_svc.h b/include/services/spmd_svc.h index 29dfdad34..95f070753 100644 --- a/include/services/spmd_svc.h +++ b/include/services/spmd_svc.h @@ -34,7 +34,8 @@ uint64_t spmd_smc_switch_state(uint32_t smc_fid, uint64_t x2, uint64_t x3, uint64_t x4, - void *handle); + void *handle, + uint64_t flags); #endif /* __ASSEMBLER__ */ #endif /* SPMD_SVC_H */ diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index 9cfcd87ea..247e2c817 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -234,7 +234,7 @@ static uint64_t spmc_smc_return(uint32_t smc_fid, /* If we originated in the normal world then switch contexts. */ else if (!secure_origin && ffa_is_secure_world_id(dst_id)) { return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2, - x3, x4, handle); + x3, x4, handle, flags); } else { /* Unknown State. */ panic(); @@ -2490,9 +2490,11 @@ static uint64_t spmc_sp_interrupt_handler(uint32_t id, /* * Forward the interrupt to the S-EL1 SP. The interrupt ID is not * populated as the SP can determine this by itself. + * The flags field is forced to 0 mainly to pass the SVE hint bit + * cleared for consumption by the lower EL. */ return spmd_smc_switch_state(FFA_INTERRUPT, false, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, - handle); + handle, 0ULL); } diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c index 5d19868a2..49d70581d 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -667,11 +667,22 @@ uint64_t spmd_smc_switch_state(uint32_t smc_fid, uint64_t x2, uint64_t x3, uint64_t x4, - void *handle) + void *handle, + uint64_t flags) { unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE; unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE; +#if SPMD_SPM_AT_SEL2 + if ((secure_state_out == SECURE) && (is_sve_hint_set(flags) == true)) { + /* + * Set the SVE hint bit in x0 and pass to the lower secure EL, + * if it was set by the caller. + */ + smc_fid |= (FUNCID_SVE_HINT_MASK << FUNCID_SVE_HINT_SHIFT); + } +#endif + /* Save incoming security state */ #if SPMD_SPM_AT_SEL2 if (secure_state_in == NON_SECURE) { @@ -746,8 +757,9 @@ static uint64_t spmd_smc_forward(uint32_t smc_fid, return spmc_smc_handler(smc_fid, secure_origin, x1, x2, x3, x4, cookie, handle, flags); } + return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2, x3, x4, - handle); + handle, flags); }