diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c index 7f85b636f..e9004c791 100644 --- a/services/std_svc/rmmd/rmmd_main.c +++ b/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: