Browse Source

fix(rmmd): preserve x4-x7 as per SMCCCv1.1

The RMI command handling in RMMD did not preserve x4 to x7 when
returning to NS caller. Although this is allowed for SMCCCv1.0, this is
not correct as per v1.1. This fixes the same by differentiating the
onward and backward path during SMC handling.

This patch also fixes an issue with the backward path wherein the first
argument was being truncated to 32 bits.

Change-Id: Ibc85d574d5a2178a763975ddb32e456a12e7dc88
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
pull/1978/merge
Soby Mathew 3 years ago
parent
commit
11578303fd
  1. 34
      services/std_svc/rmmd/rmmd_main.c

34
services/std_svc/rmmd/rmmd_main.c

@ -48,10 +48,6 @@ static entry_point_info_t *rmm_ep_info;
* Static function declaration.
******************************************************************************/
static int32_t rmm_init(void);
static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
uint32_t dst_sec_state, uint64_t x1,
uint64_t x2, uint64_t x3, uint64_t x4,
void *handle);
/*******************************************************************************
* This function takes an RMM context pointer and performs a synchronous entry
@ -191,10 +187,10 @@ int rmmd_setup(void)
/*******************************************************************************
* Forward SMC to the other security state
******************************************************************************/
static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
uint32_t dst_sec_state, uint64_t x1,
uint64_t x2, uint64_t x3, uint64_t x4,
void *handle)
static uint64_t rmmd_smc_forward(uint32_t src_sec_state,
uint32_t dst_sec_state, uint64_t x0,
uint64_t x1, uint64_t x2, uint64_t x3,
uint64_t x4, void *handle)
{
/* Save incoming security state */
cm_el1_sysregs_context_save(src_sec_state);
@ -205,10 +201,20 @@ static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
cm_el2_sysregs_context_restore(dst_sec_state);
cm_set_next_eret_context(dst_sec_state);
SMC_RET8(cm_get_context(dst_sec_state), smc_fid, x1, x2, x3, x4,
SMC_GET_GP(handle, CTX_GPREG_X5),
SMC_GET_GP(handle, CTX_GPREG_X6),
SMC_GET_GP(handle, CTX_GPREG_X7));
/*
* As per SMCCCv1.1, we need to preserve x4 to x7 unless
* being used as return args. Hence we differentiate the
* onward and backward path. Support upto 8 args in the
* onward path and 4 args in return path.
*/
if (src_sec_state == NON_SECURE) {
SMC_RET8(cm_get_context(dst_sec_state), x0, x1, x2, x3, x4,
SMC_GET_GP(handle, CTX_GPREG_X5),
SMC_GET_GP(handle, CTX_GPREG_X6),
SMC_GET_GP(handle, CTX_GPREG_X7));
} else {
SMC_RET4(cm_get_context(dst_sec_state), x0, x1, x2, x3);
}
}
/*******************************************************************************
@ -237,7 +243,7 @@ uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
*/
if (src_sec_state == SMC_FROM_NON_SECURE) {
VERBOSE("RMM: RMI call from non-secure world.\n");
return rmmd_smc_forward(smc_fid, NON_SECURE, REALM,
return rmmd_smc_forward(NON_SECURE, REALM, smc_fid,
x1, x2, x3, x4, handle);
}
@ -250,7 +256,7 @@ uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
rmmd_rmm_sync_exit(x1);
}
return rmmd_smc_forward(x1, REALM, NON_SECURE,
return rmmd_smc_forward(REALM, NON_SECURE, x1,
x2, x3, x4, 0, handle);
default:

Loading…
Cancel
Save