mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-18 02:24:18 +00:00
fix(trp): preserve RMI SMC X4 when not used as return
This patch adds X2-X6 and 'smc_ret' parameters to trp_rmi_handler(). The last 'smc_ret' parameter passed in X7 contains address of 'trp_smc_result' structure on stack to return result of RMI SMC call. This allows to preserve X4 if not used as a return argument as per SMCCCv1.2. The patch also removes use of trp_args_t in RMI handling. Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com> Change-Id: I9e3387a7380b37863eeccc53d13e92e0ac5cffbd
This commit is contained in:
parent
0125e86b3b
commit
b96253db08
3 changed files with 73 additions and 34 deletions
|
@ -39,5 +39,12 @@ trp_args_t *set_smc_args(uint64_t arg0,
|
|||
|
||||
__dead2 void trp_boot_abort(uint64_t err);
|
||||
|
||||
/* TRP SMC result registers X0-X4 */
|
||||
#define TRP_SMC_RESULT_REGS 5
|
||||
|
||||
struct trp_smc_result {
|
||||
unsigned long long x[TRP_SMC_RESULT_REGS];
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLER __ */
|
||||
#endif /* TRP_HELPERS_H */
|
||||
|
|
|
@ -115,7 +115,29 @@ endfunc trp_smc
|
|||
* ---------------------------------------------
|
||||
*/
|
||||
func trp_handler
|
||||
/*
|
||||
* Save Link Register and X4, as per SMCCC v1.2 its value
|
||||
* must be preserved unless it contains result, as specified
|
||||
* in the function definition.
|
||||
*/
|
||||
stp x4, lr, [sp, #-16]!
|
||||
|
||||
/*
|
||||
* Zero the space for X0-X3 in trp_smc_result structure
|
||||
* and pass its address as the last argument.
|
||||
*/
|
||||
stp xzr, xzr, [sp, #-16]!
|
||||
stp xzr, xzr, [sp, #-16]!
|
||||
mov x7, sp
|
||||
|
||||
bl trp_rmi_handler
|
||||
restore_args_call_smc
|
||||
|
||||
ldp x1, x2, [sp], #16
|
||||
ldp x3, x4, [sp], #16
|
||||
ldp x5, lr, [sp], #16
|
||||
|
||||
ldr x0, =RMM_RMI_REQ_COMPLETE
|
||||
smc #0
|
||||
|
||||
b trp_handler
|
||||
endfunc trp_handler
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <services/rmm_core_manifest.h>
|
||||
|
@ -31,11 +30,11 @@ void trp_setup(uint64_t x0,
|
|||
uint64_t x3)
|
||||
{
|
||||
/*
|
||||
* Validate boot parameters.
|
||||
* Validate boot parameters
|
||||
*
|
||||
* According to the Boot Interface ABI v.0.1, the
|
||||
* parameters recived from EL3 are:
|
||||
* x0: CPUID (verified earlier so not used)
|
||||
* According to the Boot Interface ABI v.0.1,
|
||||
* the parameters received from EL3 are:
|
||||
* x0: CPUID (verified earlier, so not used)
|
||||
* x1: Boot Interface version
|
||||
* x2: PLATFORM_CORE_COUNT
|
||||
* x3: Pointer to the shared memory area.
|
||||
|
@ -73,14 +72,14 @@ void trp_main(void)
|
|||
NOTICE("TRP: %s\n", build_message);
|
||||
NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
|
||||
TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
|
||||
NOTICE("TRP: Boot Manifest Version : v.%u.%u\n",
|
||||
NOTICE("TRP: Boot Manifest Version: v.%u.%u\n",
|
||||
RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version),
|
||||
RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version));
|
||||
INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE);
|
||||
INFO("TRP: Base address for the shared region : 0x%lx\n",
|
||||
INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE);
|
||||
INFO("TRP: Shared region base address: 0x%lx\n",
|
||||
(unsigned long)trp_shared_region_start);
|
||||
INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END
|
||||
- RMM_BASE));
|
||||
INFO("TRP: Total size: 0x%lx bytes\n",
|
||||
(unsigned long)(RMM_END - RMM_BASE));
|
||||
INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
|
||||
TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
|
||||
TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
|
||||
|
@ -89,62 +88,73 @@ void trp_main(void)
|
|||
/*******************************************************************************
|
||||
* Returning RMI version back to Normal World
|
||||
******************************************************************************/
|
||||
static trp_args_t *trp_ret_rmi_version(void)
|
||||
static void trp_ret_rmi_version(struct trp_smc_result *smc_ret)
|
||||
{
|
||||
VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
|
||||
RMI_ABI_VERSION_MINOR);
|
||||
return set_smc_args(RMM_RMI_REQ_COMPLETE, RMI_ABI_VERSION,
|
||||
0, 0, 0, 0, 0, 0);
|
||||
smc_ret->x[0] = RMI_ABI_VERSION;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Transitioning granule of NON-SECURE type to REALM type
|
||||
******************************************************************************/
|
||||
static trp_args_t *trp_asc_mark_realm(unsigned long long x1)
|
||||
static void trp_asc_mark_realm(unsigned long long x1,
|
||||
struct trp_smc_result *smc_ret)
|
||||
{
|
||||
unsigned long long ret;
|
||||
|
||||
VERBOSE("Delegating granule 0x%llx\n", x1);
|
||||
ret = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1, 0, 0, 0, 0, 0, 0));
|
||||
smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1,
|
||||
0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
|
||||
|
||||
if (ret != 0ULL) {
|
||||
if (smc_ret->x[0] != 0ULL) {
|
||||
ERROR("Granule transition from NON-SECURE type to REALM type "
|
||||
"failed 0x%llx\n", ret);
|
||||
"failed 0x%llx\n", smc_ret->x[0]);
|
||||
}
|
||||
return set_smc_args(RMM_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Transitioning granule of REALM type to NON-SECURE type
|
||||
******************************************************************************/
|
||||
static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1)
|
||||
static void trp_asc_mark_nonsecure(unsigned long long x1,
|
||||
struct trp_smc_result *smc_ret)
|
||||
{
|
||||
unsigned long long ret;
|
||||
|
||||
VERBOSE("Undelegating granule 0x%llx\n", x1);
|
||||
ret = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1, 0, 0, 0, 0, 0, 0));
|
||||
smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1,
|
||||
0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
|
||||
|
||||
if (ret != 0ULL) {
|
||||
if (smc_ret->x[0] != 0ULL) {
|
||||
ERROR("Granule transition from REALM type to NON-SECURE type "
|
||||
"failed 0x%llx\n", ret);
|
||||
"failed 0x%llx\n", smc_ret->x[0]);
|
||||
}
|
||||
return set_smc_args(RMM_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Main RMI SMC handler function
|
||||
******************************************************************************/
|
||||
trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1)
|
||||
void trp_rmi_handler(unsigned long fid,
|
||||
unsigned long long x1, unsigned long long x2,
|
||||
unsigned long long x3, unsigned long long x4,
|
||||
unsigned long long x5, unsigned long long x6,
|
||||
struct trp_smc_result *smc_ret)
|
||||
{
|
||||
/* Not used in the current implementation */
|
||||
(void)x2;
|
||||
(void)x3;
|
||||
(void)x4;
|
||||
(void)x5;
|
||||
(void)x6;
|
||||
|
||||
switch (fid) {
|
||||
case RMI_RMM_REQ_VERSION:
|
||||
return trp_ret_rmi_version();
|
||||
trp_ret_rmi_version(smc_ret);
|
||||
break;
|
||||
case RMI_RMM_GRANULE_DELEGATE:
|
||||
return trp_asc_mark_realm(x1);
|
||||
trp_asc_mark_realm(x1, smc_ret);
|
||||
break;
|
||||
case RMI_RMM_GRANULE_UNDELEGATE:
|
||||
return trp_asc_mark_nonsecure(x1);
|
||||
trp_asc_mark_nonsecure(x1, smc_ret);
|
||||
break;
|
||||
default:
|
||||
ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid);
|
||||
ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid);
|
||||
smc_ret->x[0] = SMC_UNK;
|
||||
}
|
||||
return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue