1*54fd6939SJiyong Park /* 2*54fd6939SJiyong Park * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. 3*54fd6939SJiyong Park * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4*54fd6939SJiyong Park * 5*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause 6*54fd6939SJiyong Park */ 7*54fd6939SJiyong Park 8*54fd6939SJiyong Park #include <assert.h> 9*54fd6939SJiyong Park #include <inttypes.h> 10*54fd6939SJiyong Park #include <lib/xlat_tables/xlat_tables_v2.h> 11*54fd6939SJiyong Park #include <stdbool.h> 12*54fd6939SJiyong Park #include <stdint.h> 13*54fd6939SJiyong Park #include <string.h> 14*54fd6939SJiyong Park 15*54fd6939SJiyong Park #include <arch_helpers.h> 16*54fd6939SJiyong Park #include <bl31/bl31.h> 17*54fd6939SJiyong Park #include <bl31/interrupt_mgmt.h> 18*54fd6939SJiyong Park #include <common/bl_common.h> 19*54fd6939SJiyong Park #include <common/debug.h> 20*54fd6939SJiyong Park #include <common/runtime_svc.h> 21*54fd6939SJiyong Park #include <lib/el3_runtime/context_mgmt.h> 22*54fd6939SJiyong Park #include <lib/smccc.h> 23*54fd6939SJiyong Park #include <plat/common/platform.h> 24*54fd6939SJiyong Park #include <tools_share/uuid.h> 25*54fd6939SJiyong Park 26*54fd6939SJiyong Park #include "sm_err.h" 27*54fd6939SJiyong Park #include "smcall.h" 28*54fd6939SJiyong Park 29*54fd6939SJiyong Park /* Trusty UID: RFC-4122 compliant UUID version 4 */ 30*54fd6939SJiyong Park DEFINE_SVC_UUID2(trusty_uuid, 31*54fd6939SJiyong Park 0x40ee25f0, 0xa2bc, 0x304c, 0x8c, 0x4c, 32*54fd6939SJiyong Park 0xa1, 0x73, 0xc5, 0x7d, 0x8a, 0xf1); 33*54fd6939SJiyong Park 34*54fd6939SJiyong Park /* macro to check if Hypervisor is enabled in the HCR_EL2 register */ 35*54fd6939SJiyong Park #define HYP_ENABLE_FLAG 0x286001U 36*54fd6939SJiyong Park 37*54fd6939SJiyong Park /* length of Trusty's input parameters (in bytes) */ 38*54fd6939SJiyong Park #define TRUSTY_PARAMS_LEN_BYTES (4096U * 2) 39*54fd6939SJiyong Park 40*54fd6939SJiyong Park struct trusty_stack { 41*54fd6939SJiyong Park uint8_t space[PLATFORM_STACK_SIZE] __aligned(16); 42*54fd6939SJiyong Park uint32_t end; 43*54fd6939SJiyong Park }; 44*54fd6939SJiyong Park 45*54fd6939SJiyong Park struct trusty_cpu_ctx { 46*54fd6939SJiyong Park cpu_context_t cpu_ctx; 47*54fd6939SJiyong Park void *saved_sp; 48*54fd6939SJiyong Park uint32_t saved_security_state; 49*54fd6939SJiyong Park int32_t fiq_handler_active; 50*54fd6939SJiyong Park uint64_t fiq_handler_pc; 51*54fd6939SJiyong Park uint64_t fiq_handler_cpsr; 52*54fd6939SJiyong Park uint64_t fiq_handler_sp; 53*54fd6939SJiyong Park uint64_t fiq_pc; 54*54fd6939SJiyong Park uint64_t fiq_cpsr; 55*54fd6939SJiyong Park uint64_t fiq_sp_el1; 56*54fd6939SJiyong Park gp_regs_t fiq_gpregs; 57*54fd6939SJiyong Park struct trusty_stack secure_stack; 58*54fd6939SJiyong Park }; 59*54fd6939SJiyong Park 60*54fd6939SJiyong Park struct smc_args { 61*54fd6939SJiyong Park uint64_t r0; 62*54fd6939SJiyong Park uint64_t r1; 63*54fd6939SJiyong Park uint64_t r2; 64*54fd6939SJiyong Park uint64_t r3; 65*54fd6939SJiyong Park uint64_t r4; 66*54fd6939SJiyong Park uint64_t r5; 67*54fd6939SJiyong Park uint64_t r6; 68*54fd6939SJiyong Park uint64_t r7; 69*54fd6939SJiyong Park }; 70*54fd6939SJiyong Park 71*54fd6939SJiyong Park static struct trusty_cpu_ctx trusty_cpu_ctx[PLATFORM_CORE_COUNT]; 72*54fd6939SJiyong Park 73*54fd6939SJiyong Park struct smc_args trusty_init_context_stack(void **sp, void *new_stack); 74*54fd6939SJiyong Park struct smc_args trusty_context_switch_helper(void **sp, void *smc_params); 75*54fd6939SJiyong Park 76*54fd6939SJiyong Park static uint32_t current_vmid; 77*54fd6939SJiyong Park 78*54fd6939SJiyong Park static struct trusty_cpu_ctx *get_trusty_ctx(void) 79*54fd6939SJiyong Park { 80*54fd6939SJiyong Park return &trusty_cpu_ctx[plat_my_core_pos()]; 81*54fd6939SJiyong Park } 82*54fd6939SJiyong Park 83*54fd6939SJiyong Park static bool is_hypervisor_mode(void) 84*54fd6939SJiyong Park { 85*54fd6939SJiyong Park uint64_t hcr = read_hcr(); 86*54fd6939SJiyong Park 87*54fd6939SJiyong Park return ((hcr & HYP_ENABLE_FLAG) != 0U) ? true : false; 88*54fd6939SJiyong Park } 89*54fd6939SJiyong Park 90*54fd6939SJiyong Park static struct smc_args trusty_context_switch(uint32_t security_state, uint64_t r0, 91*54fd6939SJiyong Park uint64_t r1, uint64_t r2, uint64_t r3) 92*54fd6939SJiyong Park { 93*54fd6939SJiyong Park struct smc_args args, ret_args; 94*54fd6939SJiyong Park struct trusty_cpu_ctx *ctx = get_trusty_ctx(); 95*54fd6939SJiyong Park struct trusty_cpu_ctx *ctx_smc; 96*54fd6939SJiyong Park 97*54fd6939SJiyong Park assert(ctx->saved_security_state != security_state); 98*54fd6939SJiyong Park 99*54fd6939SJiyong Park args.r7 = 0; 100*54fd6939SJiyong Park if (is_hypervisor_mode()) { 101*54fd6939SJiyong Park /* According to the ARM DEN0028A spec, VMID is stored in x7 */ 102*54fd6939SJiyong Park ctx_smc = cm_get_context(NON_SECURE); 103*54fd6939SJiyong Park assert(ctx_smc != NULL); 104*54fd6939SJiyong Park args.r7 = SMC_GET_GP(ctx_smc, CTX_GPREG_X7); 105*54fd6939SJiyong Park } 106*54fd6939SJiyong Park /* r4, r5, r6 reserved for future use. */ 107*54fd6939SJiyong Park args.r6 = 0; 108*54fd6939SJiyong Park args.r5 = 0; 109*54fd6939SJiyong Park args.r4 = 0; 110*54fd6939SJiyong Park args.r3 = r3; 111*54fd6939SJiyong Park args.r2 = r2; 112*54fd6939SJiyong Park args.r1 = r1; 113*54fd6939SJiyong Park args.r0 = r0; 114*54fd6939SJiyong Park 115*54fd6939SJiyong Park /* 116*54fd6939SJiyong Park * To avoid the additional overhead in PSCI flow, skip FP context 117*54fd6939SJiyong Park * saving/restoring in case of CPU suspend and resume, assuming that 118*54fd6939SJiyong Park * when it's needed the PSCI caller has preserved FP context before 119*54fd6939SJiyong Park * going here. 120*54fd6939SJiyong Park */ 121*54fd6939SJiyong Park if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME) 122*54fd6939SJiyong Park fpregs_context_save(get_fpregs_ctx(cm_get_context(security_state))); 123*54fd6939SJiyong Park cm_el1_sysregs_context_save(security_state); 124*54fd6939SJiyong Park 125*54fd6939SJiyong Park ctx->saved_security_state = security_state; 126*54fd6939SJiyong Park ret_args = trusty_context_switch_helper(&ctx->saved_sp, &args); 127*54fd6939SJiyong Park 128*54fd6939SJiyong Park assert(ctx->saved_security_state == ((security_state == 0U) ? 1U : 0U)); 129*54fd6939SJiyong Park 130*54fd6939SJiyong Park cm_el1_sysregs_context_restore(security_state); 131*54fd6939SJiyong Park if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME) 132*54fd6939SJiyong Park fpregs_context_restore(get_fpregs_ctx(cm_get_context(security_state))); 133*54fd6939SJiyong Park 134*54fd6939SJiyong Park cm_set_next_eret_context(security_state); 135*54fd6939SJiyong Park 136*54fd6939SJiyong Park return ret_args; 137*54fd6939SJiyong Park } 138*54fd6939SJiyong Park 139*54fd6939SJiyong Park static uint64_t trusty_fiq_handler(uint32_t id, 140*54fd6939SJiyong Park uint32_t flags, 141*54fd6939SJiyong Park void *handle, 142*54fd6939SJiyong Park void *cookie) 143*54fd6939SJiyong Park { 144*54fd6939SJiyong Park struct smc_args ret; 145*54fd6939SJiyong Park struct trusty_cpu_ctx *ctx = get_trusty_ctx(); 146*54fd6939SJiyong Park 147*54fd6939SJiyong Park assert(!is_caller_secure(flags)); 148*54fd6939SJiyong Park 149*54fd6939SJiyong Park ret = trusty_context_switch(NON_SECURE, SMC_FC_FIQ_ENTER, 0, 0, 0); 150*54fd6939SJiyong Park if (ret.r0 != 0U) { 151*54fd6939SJiyong Park SMC_RET0(handle); 152*54fd6939SJiyong Park } 153*54fd6939SJiyong Park 154*54fd6939SJiyong Park if (ctx->fiq_handler_active != 0) { 155*54fd6939SJiyong Park INFO("%s: fiq handler already active\n", __func__); 156*54fd6939SJiyong Park SMC_RET0(handle); 157*54fd6939SJiyong Park } 158*54fd6939SJiyong Park 159*54fd6939SJiyong Park ctx->fiq_handler_active = 1; 160*54fd6939SJiyong Park (void)memcpy(&ctx->fiq_gpregs, get_gpregs_ctx(handle), sizeof(ctx->fiq_gpregs)); 161*54fd6939SJiyong Park ctx->fiq_pc = SMC_GET_EL3(handle, CTX_ELR_EL3); 162*54fd6939SJiyong Park ctx->fiq_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3); 163*54fd6939SJiyong Park ctx->fiq_sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1); 164*54fd6939SJiyong Park 165*54fd6939SJiyong Park write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp); 166*54fd6939SJiyong Park cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, (uint32_t)ctx->fiq_handler_cpsr); 167*54fd6939SJiyong Park 168*54fd6939SJiyong Park SMC_RET0(handle); 169*54fd6939SJiyong Park } 170*54fd6939SJiyong Park 171*54fd6939SJiyong Park static uint64_t trusty_set_fiq_handler(void *handle, uint64_t cpu, 172*54fd6939SJiyong Park uint64_t handler, uint64_t stack) 173*54fd6939SJiyong Park { 174*54fd6939SJiyong Park struct trusty_cpu_ctx *ctx; 175*54fd6939SJiyong Park 176*54fd6939SJiyong Park if (cpu >= (uint64_t)PLATFORM_CORE_COUNT) { 177*54fd6939SJiyong Park ERROR("%s: cpu %" PRId64 " >= %d\n", __func__, cpu, PLATFORM_CORE_COUNT); 178*54fd6939SJiyong Park return (uint64_t)SM_ERR_INVALID_PARAMETERS; 179*54fd6939SJiyong Park } 180*54fd6939SJiyong Park 181*54fd6939SJiyong Park ctx = &trusty_cpu_ctx[cpu]; 182*54fd6939SJiyong Park ctx->fiq_handler_pc = handler; 183*54fd6939SJiyong Park ctx->fiq_handler_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3); 184*54fd6939SJiyong Park ctx->fiq_handler_sp = stack; 185*54fd6939SJiyong Park 186*54fd6939SJiyong Park SMC_RET1(handle, 0); 187*54fd6939SJiyong Park } 188*54fd6939SJiyong Park 189*54fd6939SJiyong Park static uint64_t trusty_get_fiq_regs(void *handle) 190*54fd6939SJiyong Park { 191*54fd6939SJiyong Park struct trusty_cpu_ctx *ctx = get_trusty_ctx(); 192*54fd6939SJiyong Park uint64_t sp_el0 = read_ctx_reg(&ctx->fiq_gpregs, CTX_GPREG_SP_EL0); 193*54fd6939SJiyong Park 194*54fd6939SJiyong Park SMC_RET4(handle, ctx->fiq_pc, ctx->fiq_cpsr, sp_el0, ctx->fiq_sp_el1); 195*54fd6939SJiyong Park } 196*54fd6939SJiyong Park 197*54fd6939SJiyong Park static uint64_t trusty_fiq_exit(void *handle, uint64_t x1, uint64_t x2, uint64_t x3) 198*54fd6939SJiyong Park { 199*54fd6939SJiyong Park struct smc_args ret; 200*54fd6939SJiyong Park struct trusty_cpu_ctx *ctx = get_trusty_ctx(); 201*54fd6939SJiyong Park 202*54fd6939SJiyong Park if (ctx->fiq_handler_active == 0) { 203*54fd6939SJiyong Park NOTICE("%s: fiq handler not active\n", __func__); 204*54fd6939SJiyong Park SMC_RET1(handle, (uint64_t)SM_ERR_INVALID_PARAMETERS); 205*54fd6939SJiyong Park } 206*54fd6939SJiyong Park 207*54fd6939SJiyong Park ret = trusty_context_switch(NON_SECURE, SMC_FC_FIQ_EXIT, 0, 0, 0); 208*54fd6939SJiyong Park if (ret.r0 != 1U) { 209*54fd6939SJiyong Park INFO("%s(%p) SMC_FC_FIQ_EXIT returned unexpected value, %" PRId64 "\n", 210*54fd6939SJiyong Park __func__, handle, ret.r0); 211*54fd6939SJiyong Park } 212*54fd6939SJiyong Park 213*54fd6939SJiyong Park /* 214*54fd6939SJiyong Park * Restore register state to state recorded on fiq entry. 215*54fd6939SJiyong Park * 216*54fd6939SJiyong Park * x0, sp_el1, pc and cpsr need to be restored because el1 cannot 217*54fd6939SJiyong Park * restore them. 218*54fd6939SJiyong Park * 219*54fd6939SJiyong Park * x1-x4 and x8-x17 need to be restored here because smc_handler64 220*54fd6939SJiyong Park * corrupts them (el1 code also restored them). 221*54fd6939SJiyong Park */ 222*54fd6939SJiyong Park (void)memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs)); 223*54fd6939SJiyong Park ctx->fiq_handler_active = 0; 224*54fd6939SJiyong Park write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1); 225*54fd6939SJiyong Park cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, (uint32_t)ctx->fiq_cpsr); 226*54fd6939SJiyong Park 227*54fd6939SJiyong Park SMC_RET0(handle); 228*54fd6939SJiyong Park } 229*54fd6939SJiyong Park 230*54fd6939SJiyong Park static uintptr_t trusty_smc_handler(uint32_t smc_fid, 231*54fd6939SJiyong Park u_register_t x1, 232*54fd6939SJiyong Park u_register_t x2, 233*54fd6939SJiyong Park u_register_t x3, 234*54fd6939SJiyong Park u_register_t x4, 235*54fd6939SJiyong Park void *cookie, 236*54fd6939SJiyong Park void *handle, 237*54fd6939SJiyong Park u_register_t flags) 238*54fd6939SJiyong Park { 239*54fd6939SJiyong Park struct smc_args ret; 240*54fd6939SJiyong Park uint32_t vmid = 0U; 241*54fd6939SJiyong Park entry_point_info_t *ep_info = bl31_plat_get_next_image_ep_info(SECURE); 242*54fd6939SJiyong Park 243*54fd6939SJiyong Park /* 244*54fd6939SJiyong Park * Return success for SET_ROT_PARAMS if Trusty is not present, as 245*54fd6939SJiyong Park * Verified Boot is not even supported and returning success here 246*54fd6939SJiyong Park * would not compromise the boot process. 247*54fd6939SJiyong Park */ 248*54fd6939SJiyong Park if ((ep_info == NULL) && (smc_fid == SMC_YC_SET_ROT_PARAMS)) { 249*54fd6939SJiyong Park SMC_RET1(handle, 0); 250*54fd6939SJiyong Park } else if (ep_info == NULL) { 251*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK); 252*54fd6939SJiyong Park } else { 253*54fd6939SJiyong Park ; /* do nothing */ 254*54fd6939SJiyong Park } 255*54fd6939SJiyong Park 256*54fd6939SJiyong Park if (is_caller_secure(flags)) { 257*54fd6939SJiyong Park if (smc_fid == SMC_YC_NS_RETURN) { 258*54fd6939SJiyong Park ret = trusty_context_switch(SECURE, x1, 0, 0, 0); 259*54fd6939SJiyong Park SMC_RET8(handle, ret.r0, ret.r1, ret.r2, ret.r3, 260*54fd6939SJiyong Park ret.r4, ret.r5, ret.r6, ret.r7); 261*54fd6939SJiyong Park } 262*54fd6939SJiyong Park INFO("%s (0x%x, 0x%lx, 0x%lx, 0x%lx, 0x%lx, %p, %p, 0x%lx) \ 263*54fd6939SJiyong Park cpu %d, unknown smc\n", 264*54fd6939SJiyong Park __func__, smc_fid, x1, x2, x3, x4, cookie, handle, flags, 265*54fd6939SJiyong Park plat_my_core_pos()); 266*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK); 267*54fd6939SJiyong Park } else { 268*54fd6939SJiyong Park switch (smc_fid) { 269*54fd6939SJiyong Park case SMC_FC64_GET_UUID: 270*54fd6939SJiyong Park case SMC_FC_GET_UUID: 271*54fd6939SJiyong Park /* provide the UUID for the service to the client */ 272*54fd6939SJiyong Park SMC_UUID_RET(handle, trusty_uuid); 273*54fd6939SJiyong Park break; 274*54fd6939SJiyong Park case SMC_FC64_SET_FIQ_HANDLER: 275*54fd6939SJiyong Park return trusty_set_fiq_handler(handle, x1, x2, x3); 276*54fd6939SJiyong Park case SMC_FC64_GET_FIQ_REGS: 277*54fd6939SJiyong Park return trusty_get_fiq_regs(handle); 278*54fd6939SJiyong Park case SMC_FC_FIQ_EXIT: 279*54fd6939SJiyong Park return trusty_fiq_exit(handle, x1, x2, x3); 280*54fd6939SJiyong Park default: 281*54fd6939SJiyong Park /* Not all OENs greater than SMC_ENTITY_SECURE_MONITOR are supported */ 282*54fd6939SJiyong Park if (SMC_ENTITY(smc_fid) > SMC_ENTITY_SECURE_MONITOR) { 283*54fd6939SJiyong Park VERBOSE("%s: unsupported SMC FID (0x%x)\n", __func__, smc_fid); 284*54fd6939SJiyong Park SMC_RET1(handle, SMC_UNK); 285*54fd6939SJiyong Park } 286*54fd6939SJiyong Park 287*54fd6939SJiyong Park if (is_hypervisor_mode()) 288*54fd6939SJiyong Park vmid = SMC_GET_GP(handle, CTX_GPREG_X7); 289*54fd6939SJiyong Park 290*54fd6939SJiyong Park if ((current_vmid != 0) && (current_vmid != vmid)) { 291*54fd6939SJiyong Park /* This message will cause SMC mechanism 292*54fd6939SJiyong Park * abnormal in multi-guest environment. 293*54fd6939SJiyong Park * Change it to WARN in case you need it. 294*54fd6939SJiyong Park */ 295*54fd6939SJiyong Park VERBOSE("Previous SMC not finished.\n"); 296*54fd6939SJiyong Park SMC_RET1(handle, SM_ERR_BUSY); 297*54fd6939SJiyong Park } 298*54fd6939SJiyong Park current_vmid = vmid; 299*54fd6939SJiyong Park ret = trusty_context_switch(NON_SECURE, smc_fid, x1, 300*54fd6939SJiyong Park x2, x3); 301*54fd6939SJiyong Park current_vmid = 0; 302*54fd6939SJiyong Park SMC_RET1(handle, ret.r0); 303*54fd6939SJiyong Park } 304*54fd6939SJiyong Park } 305*54fd6939SJiyong Park } 306*54fd6939SJiyong Park 307*54fd6939SJiyong Park static int32_t trusty_init(void) 308*54fd6939SJiyong Park { 309*54fd6939SJiyong Park entry_point_info_t *ep_info; 310*54fd6939SJiyong Park struct smc_args zero_args = {0}; 311*54fd6939SJiyong Park struct trusty_cpu_ctx *ctx = get_trusty_ctx(); 312*54fd6939SJiyong Park uint32_t cpu = plat_my_core_pos(); 313*54fd6939SJiyong Park uint64_t reg_width = GET_RW(read_ctx_reg(get_el3state_ctx(&ctx->cpu_ctx), 314*54fd6939SJiyong Park CTX_SPSR_EL3)); 315*54fd6939SJiyong Park 316*54fd6939SJiyong Park /* 317*54fd6939SJiyong Park * Get information about the Trusty image. Its absence is a critical 318*54fd6939SJiyong Park * failure. 319*54fd6939SJiyong Park */ 320*54fd6939SJiyong Park ep_info = bl31_plat_get_next_image_ep_info(SECURE); 321*54fd6939SJiyong Park assert(ep_info != NULL); 322*54fd6939SJiyong Park 323*54fd6939SJiyong Park fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE))); 324*54fd6939SJiyong Park cm_el1_sysregs_context_save(NON_SECURE); 325*54fd6939SJiyong Park 326*54fd6939SJiyong Park cm_set_context(&ctx->cpu_ctx, SECURE); 327*54fd6939SJiyong Park cm_init_my_context(ep_info); 328*54fd6939SJiyong Park 329*54fd6939SJiyong Park /* 330*54fd6939SJiyong Park * Adjust secondary cpu entry point for 32 bit images to the 331*54fd6939SJiyong Park * end of exception vectors 332*54fd6939SJiyong Park */ 333*54fd6939SJiyong Park if ((cpu != 0U) && (reg_width == MODE_RW_32)) { 334*54fd6939SJiyong Park INFO("trusty: cpu %d, adjust entry point to 0x%lx\n", 335*54fd6939SJiyong Park cpu, ep_info->pc + (1U << 5)); 336*54fd6939SJiyong Park cm_set_elr_el3(SECURE, ep_info->pc + (1U << 5)); 337*54fd6939SJiyong Park } 338*54fd6939SJiyong Park 339*54fd6939SJiyong Park cm_el1_sysregs_context_restore(SECURE); 340*54fd6939SJiyong Park fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE))); 341*54fd6939SJiyong Park cm_set_next_eret_context(SECURE); 342*54fd6939SJiyong Park 343*54fd6939SJiyong Park ctx->saved_security_state = ~0U; /* initial saved state is invalid */ 344*54fd6939SJiyong Park (void)trusty_init_context_stack(&ctx->saved_sp, &ctx->secure_stack.end); 345*54fd6939SJiyong Park 346*54fd6939SJiyong Park (void)trusty_context_switch_helper(&ctx->saved_sp, &zero_args); 347*54fd6939SJiyong Park 348*54fd6939SJiyong Park cm_el1_sysregs_context_restore(NON_SECURE); 349*54fd6939SJiyong Park fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE))); 350*54fd6939SJiyong Park cm_set_next_eret_context(NON_SECURE); 351*54fd6939SJiyong Park 352*54fd6939SJiyong Park return 1; 353*54fd6939SJiyong Park } 354*54fd6939SJiyong Park 355*54fd6939SJiyong Park static void trusty_cpu_suspend(uint32_t off) 356*54fd6939SJiyong Park { 357*54fd6939SJiyong Park struct smc_args ret; 358*54fd6939SJiyong Park 359*54fd6939SJiyong Park ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_SUSPEND, off, 0, 0); 360*54fd6939SJiyong Park if (ret.r0 != 0U) { 361*54fd6939SJiyong Park INFO("%s: cpu %d, SMC_FC_CPU_SUSPEND returned unexpected value, %" PRId64 "\n", 362*54fd6939SJiyong Park __func__, plat_my_core_pos(), ret.r0); 363*54fd6939SJiyong Park } 364*54fd6939SJiyong Park } 365*54fd6939SJiyong Park 366*54fd6939SJiyong Park static void trusty_cpu_resume(uint32_t on) 367*54fd6939SJiyong Park { 368*54fd6939SJiyong Park struct smc_args ret; 369*54fd6939SJiyong Park 370*54fd6939SJiyong Park ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_RESUME, on, 0, 0); 371*54fd6939SJiyong Park if (ret.r0 != 0U) { 372*54fd6939SJiyong Park INFO("%s: cpu %d, SMC_FC_CPU_RESUME returned unexpected value, %" PRId64 "\n", 373*54fd6939SJiyong Park __func__, plat_my_core_pos(), ret.r0); 374*54fd6939SJiyong Park } 375*54fd6939SJiyong Park } 376*54fd6939SJiyong Park 377*54fd6939SJiyong Park static int32_t trusty_cpu_off_handler(u_register_t max_off_lvl) 378*54fd6939SJiyong Park { 379*54fd6939SJiyong Park trusty_cpu_suspend(max_off_lvl); 380*54fd6939SJiyong Park 381*54fd6939SJiyong Park return 0; 382*54fd6939SJiyong Park } 383*54fd6939SJiyong Park 384*54fd6939SJiyong Park static void trusty_cpu_on_finish_handler(u_register_t max_off_lvl) 385*54fd6939SJiyong Park { 386*54fd6939SJiyong Park struct trusty_cpu_ctx *ctx = get_trusty_ctx(); 387*54fd6939SJiyong Park 388*54fd6939SJiyong Park if (ctx->saved_sp == NULL) { 389*54fd6939SJiyong Park (void)trusty_init(); 390*54fd6939SJiyong Park } else { 391*54fd6939SJiyong Park trusty_cpu_resume(max_off_lvl); 392*54fd6939SJiyong Park } 393*54fd6939SJiyong Park } 394*54fd6939SJiyong Park 395*54fd6939SJiyong Park static void trusty_cpu_suspend_handler(u_register_t max_off_lvl) 396*54fd6939SJiyong Park { 397*54fd6939SJiyong Park trusty_cpu_suspend(max_off_lvl); 398*54fd6939SJiyong Park } 399*54fd6939SJiyong Park 400*54fd6939SJiyong Park static void trusty_cpu_suspend_finish_handler(u_register_t max_off_lvl) 401*54fd6939SJiyong Park { 402*54fd6939SJiyong Park trusty_cpu_resume(max_off_lvl); 403*54fd6939SJiyong Park } 404*54fd6939SJiyong Park 405*54fd6939SJiyong Park static const spd_pm_ops_t trusty_pm = { 406*54fd6939SJiyong Park .svc_off = trusty_cpu_off_handler, 407*54fd6939SJiyong Park .svc_suspend = trusty_cpu_suspend_handler, 408*54fd6939SJiyong Park .svc_on_finish = trusty_cpu_on_finish_handler, 409*54fd6939SJiyong Park .svc_suspend_finish = trusty_cpu_suspend_finish_handler, 410*54fd6939SJiyong Park }; 411*54fd6939SJiyong Park 412*54fd6939SJiyong Park void plat_trusty_set_boot_args(aapcs64_params_t *args); 413*54fd6939SJiyong Park 414*54fd6939SJiyong Park #if !defined(TSP_SEC_MEM_SIZE) && defined(BL32_MEM_SIZE) 415*54fd6939SJiyong Park #define TSP_SEC_MEM_SIZE BL32_MEM_SIZE 416*54fd6939SJiyong Park #endif 417*54fd6939SJiyong Park 418*54fd6939SJiyong Park #ifdef TSP_SEC_MEM_SIZE 419*54fd6939SJiyong Park #pragma weak plat_trusty_set_boot_args 420*54fd6939SJiyong Park void plat_trusty_set_boot_args(aapcs64_params_t *args) 421*54fd6939SJiyong Park { 422*54fd6939SJiyong Park args->arg0 = TSP_SEC_MEM_SIZE; 423*54fd6939SJiyong Park } 424*54fd6939SJiyong Park #endif 425*54fd6939SJiyong Park 426*54fd6939SJiyong Park static int32_t trusty_setup(void) 427*54fd6939SJiyong Park { 428*54fd6939SJiyong Park entry_point_info_t *ep_info; 429*54fd6939SJiyong Park uint32_t instr; 430*54fd6939SJiyong Park uint32_t flags; 431*54fd6939SJiyong Park int32_t ret; 432*54fd6939SJiyong Park bool aarch32 = false; 433*54fd6939SJiyong Park 434*54fd6939SJiyong Park /* Get trusty's entry point info */ 435*54fd6939SJiyong Park ep_info = bl31_plat_get_next_image_ep_info(SECURE); 436*54fd6939SJiyong Park if (ep_info == NULL) { 437*54fd6939SJiyong Park VERBOSE("Trusty image missing.\n"); 438*54fd6939SJiyong Park return -1; 439*54fd6939SJiyong Park } 440*54fd6939SJiyong Park 441*54fd6939SJiyong Park /* memmap first page of trusty's code memory before peeking */ 442*54fd6939SJiyong Park ret = mmap_add_dynamic_region(ep_info->pc, /* PA */ 443*54fd6939SJiyong Park ep_info->pc, /* VA */ 444*54fd6939SJiyong Park PAGE_SIZE, /* size */ 445*54fd6939SJiyong Park MT_SECURE | MT_RW_DATA); /* attrs */ 446*54fd6939SJiyong Park assert(ret == 0); 447*54fd6939SJiyong Park 448*54fd6939SJiyong Park /* peek into trusty's code to see if we have a 32-bit or 64-bit image */ 449*54fd6939SJiyong Park instr = *(uint32_t *)ep_info->pc; 450*54fd6939SJiyong Park 451*54fd6939SJiyong Park if (instr >> 24 == 0xeaU) { 452*54fd6939SJiyong Park INFO("trusty: Found 32 bit image\n"); 453*54fd6939SJiyong Park aarch32 = true; 454*54fd6939SJiyong Park } else if (instr >> 8 == 0xd53810U || instr >> 16 == 0x9400U) { 455*54fd6939SJiyong Park INFO("trusty: Found 64 bit image\n"); 456*54fd6939SJiyong Park } else { 457*54fd6939SJiyong Park ERROR("trusty: Found unknown image, 0x%x\n", instr); 458*54fd6939SJiyong Park return -1; 459*54fd6939SJiyong Park } 460*54fd6939SJiyong Park 461*54fd6939SJiyong Park /* unmap trusty's memory page */ 462*54fd6939SJiyong Park (void)mmap_remove_dynamic_region(ep_info->pc, PAGE_SIZE); 463*54fd6939SJiyong Park 464*54fd6939SJiyong Park SET_PARAM_HEAD(ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); 465*54fd6939SJiyong Park if (!aarch32) 466*54fd6939SJiyong Park ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 467*54fd6939SJiyong Park DISABLE_ALL_EXCEPTIONS); 468*54fd6939SJiyong Park else 469*54fd6939SJiyong Park ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, 470*54fd6939SJiyong Park SPSR_E_LITTLE, 471*54fd6939SJiyong Park DAIF_FIQ_BIT | 472*54fd6939SJiyong Park DAIF_IRQ_BIT | 473*54fd6939SJiyong Park DAIF_ABT_BIT); 474*54fd6939SJiyong Park (void)memset(&ep_info->args, 0, sizeof(ep_info->args)); 475*54fd6939SJiyong Park plat_trusty_set_boot_args(&ep_info->args); 476*54fd6939SJiyong Park 477*54fd6939SJiyong Park /* register init handler */ 478*54fd6939SJiyong Park bl31_register_bl32_init(trusty_init); 479*54fd6939SJiyong Park 480*54fd6939SJiyong Park /* register power management hooks */ 481*54fd6939SJiyong Park psci_register_spd_pm_hook(&trusty_pm); 482*54fd6939SJiyong Park 483*54fd6939SJiyong Park /* register interrupt handler */ 484*54fd6939SJiyong Park flags = 0; 485*54fd6939SJiyong Park set_interrupt_rm_flag(flags, NON_SECURE); 486*54fd6939SJiyong Park ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, 487*54fd6939SJiyong Park trusty_fiq_handler, 488*54fd6939SJiyong Park flags); 489*54fd6939SJiyong Park if (ret != 0) { 490*54fd6939SJiyong Park VERBOSE("trusty: failed to register fiq handler, ret = %d\n", ret); 491*54fd6939SJiyong Park } 492*54fd6939SJiyong Park 493*54fd6939SJiyong Park if (aarch32) { 494*54fd6939SJiyong Park entry_point_info_t *ns_ep_info; 495*54fd6939SJiyong Park uint32_t spsr; 496*54fd6939SJiyong Park 497*54fd6939SJiyong Park ns_ep_info = bl31_plat_get_next_image_ep_info(NON_SECURE); 498*54fd6939SJiyong Park if (ns_ep_info == NULL) { 499*54fd6939SJiyong Park NOTICE("Trusty: non-secure image missing.\n"); 500*54fd6939SJiyong Park return -1; 501*54fd6939SJiyong Park } 502*54fd6939SJiyong Park spsr = ns_ep_info->spsr; 503*54fd6939SJiyong Park if (GET_RW(spsr) == MODE_RW_64 && GET_EL(spsr) == MODE_EL2) { 504*54fd6939SJiyong Park spsr &= ~(MODE_EL_MASK << MODE_EL_SHIFT); 505*54fd6939SJiyong Park spsr |= MODE_EL1 << MODE_EL_SHIFT; 506*54fd6939SJiyong Park } 507*54fd6939SJiyong Park if (GET_RW(spsr) == MODE_RW_32 && GET_M32(spsr) == MODE32_hyp) { 508*54fd6939SJiyong Park spsr &= ~(MODE32_MASK << MODE32_SHIFT); 509*54fd6939SJiyong Park spsr |= MODE32_svc << MODE32_SHIFT; 510*54fd6939SJiyong Park } 511*54fd6939SJiyong Park if (spsr != ns_ep_info->spsr) { 512*54fd6939SJiyong Park NOTICE("Trusty: Switch bl33 from EL2 to EL1 (spsr 0x%x -> 0x%x)\n", 513*54fd6939SJiyong Park ns_ep_info->spsr, spsr); 514*54fd6939SJiyong Park ns_ep_info->spsr = spsr; 515*54fd6939SJiyong Park } 516*54fd6939SJiyong Park } 517*54fd6939SJiyong Park 518*54fd6939SJiyong Park return 0; 519*54fd6939SJiyong Park } 520*54fd6939SJiyong Park 521*54fd6939SJiyong Park /* Define a SPD runtime service descriptor for fast SMC calls */ 522*54fd6939SJiyong Park DECLARE_RT_SVC( 523*54fd6939SJiyong Park trusty_fast, 524*54fd6939SJiyong Park 525*54fd6939SJiyong Park OEN_TOS_START, 526*54fd6939SJiyong Park OEN_TOS_END, 527*54fd6939SJiyong Park SMC_TYPE_FAST, 528*54fd6939SJiyong Park trusty_setup, 529*54fd6939SJiyong Park trusty_smc_handler 530*54fd6939SJiyong Park ); 531*54fd6939SJiyong Park 532*54fd6939SJiyong Park /* Define a SPD runtime service descriptor for yielding SMC calls */ 533*54fd6939SJiyong Park DECLARE_RT_SVC( 534*54fd6939SJiyong Park trusty_std, 535*54fd6939SJiyong Park 536*54fd6939SJiyong Park OEN_TAP_START, 537*54fd6939SJiyong Park SMC_ENTITY_SECURE_MONITOR, 538*54fd6939SJiyong Park SMC_TYPE_YIELD, 539*54fd6939SJiyong Park NULL, 540*54fd6939SJiyong Park trusty_smc_handler 541*54fd6939SJiyong Park ); 542