Browse Source

feat(spmd): pass SMCCCv1.3 SVE hint to lower EL

A normal world caller can emit an SMC with the SVE hint bit set such
that the callee can perform an optimization by omitting to save/restore
the SVE context. Update the SPMD to pass this information to the SPMC
when set by the caller in the SMC flags parameter.
For now, restrict this behavior to the SPMC living at S-EL2.

Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: Icf46eb8a391dd3ddd2ee6aff8581a2f1c8a1c274
pull/1999/merge
Olivier Deprez 2 years ago
parent
commit
c925867ec1
  1. 3
      include/services/spmd_svc.h
  2. 6
      services/std_svc/spm/el3_spmc/spmc_main.c
  3. 16
      services/std_svc/spmd/spmd_main.c

3
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 */

6
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);
}

16
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);
}

Loading…
Cancel
Save