Merge pull request #862 from vwadekar/spd-trusty-tlkd-changes
SPD changes for Trusty and TLKD
This commit is contained in:
commit
6abb19bf1c
|
@ -56,6 +56,22 @@
|
||||||
write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X3, (_x3)); \
|
write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X3, (_x3)); \
|
||||||
SMC_RET3(_h, (_x0), (_x1), (_x2)); \
|
SMC_RET3(_h, (_x0), (_x1), (_x2)); \
|
||||||
}
|
}
|
||||||
|
#define SMC_RET5(_h, _x0, _x1, _x2, _x3, _x4) { \
|
||||||
|
write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X4, (_x4)); \
|
||||||
|
SMC_RET4(_h, (_x0), (_x1), (_x2), (_x3)); \
|
||||||
|
}
|
||||||
|
#define SMC_RET6(_h, _x0, _x1, _x2, _x3, _x4, _x5) { \
|
||||||
|
write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X5, (_x5)); \
|
||||||
|
SMC_RET5(_h, (_x0), (_x1), (_x2), (_x3), (_x4)); \
|
||||||
|
}
|
||||||
|
#define SMC_RET7(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6) { \
|
||||||
|
write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X6, (_x6)); \
|
||||||
|
SMC_RET6(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5)); \
|
||||||
|
}
|
||||||
|
#define SMC_RET8(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7) { \
|
||||||
|
write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X7, (_x7)); \
|
||||||
|
SMC_RET7(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5), (_x6)); \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convenience macros to access general purpose registers using handle provided
|
* Convenience macros to access general purpose registers using handle provided
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -58,6 +58,11 @@ extern const spd_pm_ops_t tlkd_pm_ops;
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
tlk_context_t tlk_ctx;
|
tlk_context_t tlk_ctx;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* CPU number on which TLK booted up
|
||||||
|
******************************************************************************/
|
||||||
|
static int boot_cpu;
|
||||||
|
|
||||||
/* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */
|
/* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */
|
||||||
DEFINE_SVC_UUID(tlk_uuid,
|
DEFINE_SVC_UUID(tlk_uuid,
|
||||||
0xbd11e9c9, 0x2bba, 0x52ee, 0xb1, 0x72,
|
0xbd11e9c9, 0x2bba, 0x52ee, 0xb1, 0x72,
|
||||||
|
@ -132,6 +137,12 @@ int32_t tlkd_init(void)
|
||||||
|
|
||||||
cm_init_my_context(tlk_entry_point);
|
cm_init_my_context(tlk_entry_point);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLK runs only on a single CPU. Store the value of the boot
|
||||||
|
* CPU for sanity checking later.
|
||||||
|
*/
|
||||||
|
boot_cpu = plat_my_core_pos();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Arrange for an entry into the test secure payload.
|
* Arrange for an entry into the test secure payload.
|
||||||
*/
|
*/
|
||||||
|
@ -163,8 +174,8 @@ uint64_t tlkd_smc_handler(uint32_t smc_fid,
|
||||||
/* Passing a NULL context is a critical programming error */
|
/* Passing a NULL context is a critical programming error */
|
||||||
assert(handle);
|
assert(handle);
|
||||||
|
|
||||||
/* These SMCs are only supported by CPU0 */
|
/* These SMCs are only supported by a single CPU */
|
||||||
if ((read_mpidr() & MPIDR_CPU_MASK) != 0)
|
if (boot_cpu != plat_my_core_pos())
|
||||||
SMC_RET1(handle, SMC_UNK);
|
SMC_RET1(handle, SMC_UNK);
|
||||||
|
|
||||||
/* Determine which security state this SMC originated from */
|
/* Determine which security state this SMC originated from */
|
||||||
|
|
|
@ -94,5 +94,6 @@
|
||||||
|
|
||||||
#define SMC_SC_VDEV_RESET SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 23)
|
#define SMC_SC_VDEV_RESET SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 23)
|
||||||
#define SMC_SC_VDEV_KICK_VQ SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 24)
|
#define SMC_SC_VDEV_KICK_VQ SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 24)
|
||||||
|
#define SMC_SC_SET_ROT_PARAMS SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 65535)
|
||||||
|
|
||||||
#endif /* __LIB_SM_SMCALL_H */
|
#endif /* __LIB_SM_SMCALL_H */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -28,7 +28,8 @@
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <arch_helpers.h>
|
||||||
|
#include <assert.h> /* for context_mgmt.h */
|
||||||
#include <bl_common.h>
|
#include <bl_common.h>
|
||||||
#include <bl31.h>
|
#include <bl31.h>
|
||||||
#include <context_mgmt.h>
|
#include <context_mgmt.h>
|
||||||
|
@ -41,8 +42,15 @@
|
||||||
#include "smcall.h"
|
#include "smcall.h"
|
||||||
#include "sm_err.h"
|
#include "sm_err.h"
|
||||||
|
|
||||||
|
/* macro to check if Hypervisor is enabled in the HCR_EL2 register */
|
||||||
|
#define HYP_ENABLE_FLAG 0x286001
|
||||||
|
|
||||||
|
/* length of Trusty's input parameters (in bytes) */
|
||||||
|
#define TRUSTY_PARAMS_LEN_BYTES (4096*2)
|
||||||
|
|
||||||
struct trusty_stack {
|
struct trusty_stack {
|
||||||
uint8_t space[PLATFORM_STACK_SIZE] __aligned(16);
|
uint8_t space[PLATFORM_STACK_SIZE] __aligned(16);
|
||||||
|
uint32_t end;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct trusty_cpu_ctx {
|
struct trusty_cpu_ctx {
|
||||||
|
@ -65,31 +73,60 @@ struct args {
|
||||||
uint64_t r1;
|
uint64_t r1;
|
||||||
uint64_t r2;
|
uint64_t r2;
|
||||||
uint64_t r3;
|
uint64_t r3;
|
||||||
|
uint64_t r4;
|
||||||
|
uint64_t r5;
|
||||||
|
uint64_t r6;
|
||||||
|
uint64_t r7;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct trusty_cpu_ctx trusty_cpu_ctx[PLATFORM_CORE_COUNT];
|
struct trusty_cpu_ctx trusty_cpu_ctx[PLATFORM_CORE_COUNT];
|
||||||
|
|
||||||
struct args trusty_init_context_stack(void **sp, void *new_stack);
|
struct args trusty_init_context_stack(void **sp, void *new_stack);
|
||||||
struct args trusty_context_switch_helper(void **sp, uint64_t r0, uint64_t r1,
|
struct args trusty_context_switch_helper(void **sp, void *smc_params);
|
||||||
uint64_t r2, uint64_t r3);
|
|
||||||
|
static uint32_t current_vmid;
|
||||||
|
|
||||||
static struct trusty_cpu_ctx *get_trusty_ctx(void)
|
static struct trusty_cpu_ctx *get_trusty_ctx(void)
|
||||||
{
|
{
|
||||||
return &trusty_cpu_ctx[plat_my_core_pos()];
|
return &trusty_cpu_ctx[plat_my_core_pos()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t is_hypervisor_mode(void)
|
||||||
|
{
|
||||||
|
uint64_t hcr = read_hcr();
|
||||||
|
|
||||||
|
return !!(hcr & HYP_ENABLE_FLAG);
|
||||||
|
}
|
||||||
|
|
||||||
static struct args trusty_context_switch(uint32_t security_state, uint64_t r0,
|
static struct args trusty_context_switch(uint32_t security_state, uint64_t r0,
|
||||||
uint64_t r1, uint64_t r2, uint64_t r3)
|
uint64_t r1, uint64_t r2, uint64_t r3)
|
||||||
{
|
{
|
||||||
struct args ret;
|
struct args ret;
|
||||||
struct trusty_cpu_ctx *ctx = get_trusty_ctx();
|
struct trusty_cpu_ctx *ctx = get_trusty_ctx();
|
||||||
|
struct trusty_cpu_ctx *ctx_smc;
|
||||||
|
|
||||||
assert(ctx->saved_security_state != security_state);
|
assert(ctx->saved_security_state != security_state);
|
||||||
|
|
||||||
|
ret.r7 = 0;
|
||||||
|
if (is_hypervisor_mode()) {
|
||||||
|
/* According to the ARM DEN0028A spec, VMID is stored in x7 */
|
||||||
|
ctx_smc = cm_get_context(NON_SECURE);
|
||||||
|
assert(ctx_smc);
|
||||||
|
ret.r7 = SMC_GET_GP(ctx_smc, CTX_GPREG_X7);
|
||||||
|
}
|
||||||
|
/* r4, r5, r6 reserved for future use. */
|
||||||
|
ret.r6 = 0;
|
||||||
|
ret.r5 = 0;
|
||||||
|
ret.r4 = 0;
|
||||||
|
ret.r3 = r3;
|
||||||
|
ret.r2 = r2;
|
||||||
|
ret.r1 = r1;
|
||||||
|
ret.r0 = r0;
|
||||||
|
|
||||||
cm_el1_sysregs_context_save(security_state);
|
cm_el1_sysregs_context_save(security_state);
|
||||||
|
|
||||||
ctx->saved_security_state = security_state;
|
ctx->saved_security_state = security_state;
|
||||||
ret = trusty_context_switch_helper(&ctx->saved_sp, r0, r1, r2, r3);
|
ret = trusty_context_switch_helper(&ctx->saved_sp, &ret);
|
||||||
|
|
||||||
assert(ctx->saved_security_state == !security_state);
|
assert(ctx->saved_security_state == !security_state);
|
||||||
|
|
||||||
|
@ -200,11 +237,25 @@ static uint64_t trusty_smc_handler(uint32_t smc_fid,
|
||||||
uint64_t flags)
|
uint64_t flags)
|
||||||
{
|
{
|
||||||
struct args ret;
|
struct args ret;
|
||||||
|
uint32_t vmid = 0;
|
||||||
|
entry_point_info_t *ep_info = bl31_plat_get_next_image_ep_info(SECURE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return success for SET_ROT_PARAMS if Trusty is not present, as
|
||||||
|
* Verified Boot is not even supported and returning success here
|
||||||
|
* would not compromise the boot process.
|
||||||
|
*/
|
||||||
|
if (!ep_info && (smc_fid == SMC_SC_SET_ROT_PARAMS)) {
|
||||||
|
SMC_RET1(handle, 0);
|
||||||
|
} else if (!ep_info) {
|
||||||
|
SMC_RET1(handle, SMC_UNK);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_caller_secure(flags)) {
|
if (is_caller_secure(flags)) {
|
||||||
if (smc_fid == SMC_SC_NS_RETURN) {
|
if (smc_fid == SMC_SC_NS_RETURN) {
|
||||||
ret = trusty_context_switch(SECURE, x1, 0, 0, 0);
|
ret = trusty_context_switch(SECURE, x1, 0, 0, 0);
|
||||||
SMC_RET4(handle, ret.r0, ret.r1, ret.r2, ret.r3);
|
SMC_RET8(handle, ret.r0, ret.r1, ret.r2, ret.r3,
|
||||||
|
ret.r4, ret.r5, ret.r6, ret.r7);
|
||||||
}
|
}
|
||||||
INFO("%s (0x%x, 0x%lx, 0x%lx, 0x%lx, 0x%lx, %p, %p, 0x%lx) \
|
INFO("%s (0x%x, 0x%lx, 0x%lx, 0x%lx, 0x%lx, %p, %p, 0x%lx) \
|
||||||
cpu %d, unknown smc\n",
|
cpu %d, unknown smc\n",
|
||||||
|
@ -220,8 +271,21 @@ static uint64_t trusty_smc_handler(uint32_t smc_fid,
|
||||||
case SMC_FC_FIQ_EXIT:
|
case SMC_FC_FIQ_EXIT:
|
||||||
return trusty_fiq_exit(handle, x1, x2, x3);
|
return trusty_fiq_exit(handle, x1, x2, x3);
|
||||||
default:
|
default:
|
||||||
|
if (is_hypervisor_mode())
|
||||||
|
vmid = SMC_GET_GP(handle, CTX_GPREG_X7);
|
||||||
|
|
||||||
|
if ((current_vmid != 0) && (current_vmid != vmid)) {
|
||||||
|
/* This message will cause SMC mechanism
|
||||||
|
* abnormal in multi-guest environment.
|
||||||
|
* Change it to WARN in case you need it.
|
||||||
|
*/
|
||||||
|
VERBOSE("Previous SMC not finished.\n");
|
||||||
|
SMC_RET1(handle, SM_ERR_BUSY);
|
||||||
|
}
|
||||||
|
current_vmid = vmid;
|
||||||
ret = trusty_context_switch(NON_SECURE, smc_fid, x1,
|
ret = trusty_context_switch(NON_SECURE, smc_fid, x1,
|
||||||
x2, x3);
|
x2, x3);
|
||||||
|
current_vmid = 0;
|
||||||
SMC_RET1(handle, ret.r0);
|
SMC_RET1(handle, ret.r0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,6 +295,7 @@ static int32_t trusty_init(void)
|
||||||
{
|
{
|
||||||
void el3_exit(void);
|
void el3_exit(void);
|
||||||
entry_point_info_t *ep_info;
|
entry_point_info_t *ep_info;
|
||||||
|
struct args zero_args = {0};
|
||||||
struct trusty_cpu_ctx *ctx = get_trusty_ctx();
|
struct trusty_cpu_ctx *ctx = get_trusty_ctx();
|
||||||
uint32_t cpu = plat_my_core_pos();
|
uint32_t cpu = plat_my_core_pos();
|
||||||
int reg_width = GET_RW(read_ctx_reg(get_el3state_ctx(&ctx->cpu_ctx),
|
int reg_width = GET_RW(read_ctx_reg(get_el3state_ctx(&ctx->cpu_ctx),
|
||||||
|
@ -262,9 +327,9 @@ static int32_t trusty_init(void)
|
||||||
cm_set_next_eret_context(SECURE);
|
cm_set_next_eret_context(SECURE);
|
||||||
|
|
||||||
ctx->saved_security_state = ~0; /* initial saved state is invalid */
|
ctx->saved_security_state = ~0; /* initial saved state is invalid */
|
||||||
trusty_init_context_stack(&ctx->saved_sp, &ctx->secure_stack);
|
trusty_init_context_stack(&ctx->saved_sp, &ctx->secure_stack.end);
|
||||||
|
|
||||||
trusty_context_switch_helper(&ctx->saved_sp, 0, 0, 0, 0);
|
trusty_context_switch_helper(&ctx->saved_sp, &zero_args);
|
||||||
|
|
||||||
cm_el1_sysregs_context_restore(NON_SECURE);
|
cm_el1_sysregs_context_restore(NON_SECURE);
|
||||||
cm_set_next_eret_context(NON_SECURE);
|
cm_set_next_eret_context(NON_SECURE);
|
||||||
|
@ -332,43 +397,35 @@ static const spd_pm_ops_t trusty_pm = {
|
||||||
static int32_t trusty_setup(void)
|
static int32_t trusty_setup(void)
|
||||||
{
|
{
|
||||||
entry_point_info_t *ep_info;
|
entry_point_info_t *ep_info;
|
||||||
uint32_t instr;
|
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
int ret;
|
int ret;
|
||||||
int aarch32 = 0;
|
|
||||||
|
|
||||||
|
/* Get trusty's entry point info */
|
||||||
ep_info = bl31_plat_get_next_image_ep_info(SECURE);
|
ep_info = bl31_plat_get_next_image_ep_info(SECURE);
|
||||||
if (!ep_info) {
|
if (!ep_info) {
|
||||||
INFO("Trusty image missing.\n");
|
INFO("Trusty image missing.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
instr = *(uint32_t *)ep_info->pc;
|
/* Trusty runs in AARCH64 mode */
|
||||||
|
|
||||||
if (instr >> 24 == 0xea) {
|
|
||||||
INFO("trusty: Found 32 bit image\n");
|
|
||||||
aarch32 = 1;
|
|
||||||
} else if (instr >> 8 == 0xd53810) {
|
|
||||||
INFO("trusty: Found 64 bit image\n");
|
|
||||||
} else {
|
|
||||||
INFO("trusty: Found unknown image, 0x%x\n", instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_PARAM_HEAD(ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE);
|
SET_PARAM_HEAD(ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE);
|
||||||
if (!aarch32)
|
ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||||
ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
|
|
||||||
DISABLE_ALL_EXCEPTIONS);
|
|
||||||
else
|
|
||||||
ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
|
|
||||||
SPSR_E_LITTLE,
|
|
||||||
DAIF_FIQ_BIT |
|
|
||||||
DAIF_IRQ_BIT |
|
|
||||||
DAIF_ABT_BIT);
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* arg0 = TZDRAM aperture available for BL32
|
||||||
|
* arg1 = BL32 boot params
|
||||||
|
* arg2 = BL32 boot params length
|
||||||
|
*/
|
||||||
|
ep_info->args.arg1 = ep_info->args.arg2;
|
||||||
|
ep_info->args.arg2 = TRUSTY_PARAMS_LEN_BYTES;
|
||||||
|
|
||||||
|
/* register init handler */
|
||||||
bl31_register_bl32_init(trusty_init);
|
bl31_register_bl32_init(trusty_init);
|
||||||
|
|
||||||
|
/* register power management hooks */
|
||||||
psci_register_spd_pm_hook(&trusty_pm);
|
psci_register_spd_pm_hook(&trusty_pm);
|
||||||
|
|
||||||
|
/* register interrupt handler */
|
||||||
flags = 0;
|
flags = 0;
|
||||||
set_interrupt_rm_flag(flags, NON_SECURE);
|
set_interrupt_rm_flag(flags, NON_SECURE);
|
||||||
ret = register_interrupt_type_handler(INTR_TYPE_S_EL1,
|
ret = register_interrupt_type_handler(INTR_TYPE_S_EL1,
|
||||||
|
|
|
@ -60,8 +60,20 @@ func trusty_context_switch_helper
|
||||||
pop x21, x22
|
pop x21, x22
|
||||||
pop x19, x20
|
pop x19, x20
|
||||||
pop x8, xzr
|
pop x8, xzr
|
||||||
stp x1, x2, [x8]
|
|
||||||
stp x3, x4, [x8, #16]
|
ldr x2, [x1]
|
||||||
|
ldr x3, [x1, #0x08]
|
||||||
|
ldr x4, [x1, #0x10]
|
||||||
|
ldr x5, [x1, #0x18]
|
||||||
|
ldr x6, [x1, #0x20]
|
||||||
|
ldr x7, [x1, #0x28]
|
||||||
|
ldr x10, [x1, #0x30]
|
||||||
|
ldr x11, [x1, #0x38]
|
||||||
|
|
||||||
|
stp x2, x3, [x8]
|
||||||
|
stp x4, x5, [x8, #16]
|
||||||
|
stp x6, x7, [x8, #32]
|
||||||
|
stp x10, x11, [x8, #48]
|
||||||
|
|
||||||
ret
|
ret
|
||||||
endfunc trusty_context_switch_helper
|
endfunc trusty_context_switch_helper
|
||||||
|
|
Loading…
Reference in New Issue