1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu /******************************************************************************* 9*91f16700Schasinglulu * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a 10*91f16700Schasinglulu * plug-in component to the Secure Monitor, registered as a runtime service. The 11*91f16700Schasinglulu * SPD is expected to be a functional extension of the Secure Payload (SP) that 12*91f16700Schasinglulu * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting 13*91f16700Schasinglulu * the Trusted OS/Applications range to the dispatcher. The SPD will either 14*91f16700Schasinglulu * handle the request locally or delegate it to the Secure Payload. It is also 15*91f16700Schasinglulu * responsible for initialising and maintaining communication with the SP. 16*91f16700Schasinglulu ******************************************************************************/ 17*91f16700Schasinglulu #include <assert.h> 18*91f16700Schasinglulu #include <bl31/interrupt_mgmt.h> 19*91f16700Schasinglulu #include <errno.h> 20*91f16700Schasinglulu #include <stddef.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu #include <arch_helpers.h> 23*91f16700Schasinglulu #include <bl31/bl31.h> 24*91f16700Schasinglulu #include <bl32/payloads/tlk.h> 25*91f16700Schasinglulu #include <common/bl_common.h> 26*91f16700Schasinglulu #include <common/debug.h> 27*91f16700Schasinglulu #include <common/runtime_svc.h> 28*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h> 29*91f16700Schasinglulu #include <plat/common/platform.h> 30*91f16700Schasinglulu #include <tools_share/uuid.h> 31*91f16700Schasinglulu 32*91f16700Schasinglulu #include "tlkd_private.h" 33*91f16700Schasinglulu 34*91f16700Schasinglulu extern const spd_pm_ops_t tlkd_pm_ops; 35*91f16700Schasinglulu 36*91f16700Schasinglulu /******************************************************************************* 37*91f16700Schasinglulu * Per-cpu Secure Payload state 38*91f16700Schasinglulu ******************************************************************************/ 39*91f16700Schasinglulu tlk_context_t tlk_ctx; 40*91f16700Schasinglulu 41*91f16700Schasinglulu /******************************************************************************* 42*91f16700Schasinglulu * CPU number on which TLK booted up 43*91f16700Schasinglulu ******************************************************************************/ 44*91f16700Schasinglulu static uint32_t boot_cpu; 45*91f16700Schasinglulu 46*91f16700Schasinglulu /* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */ 47*91f16700Schasinglulu DEFINE_SVC_UUID2(tlk_uuid, 48*91f16700Schasinglulu 0xc9e911bd, 0xba2b, 0xee52, 0xb1, 0x72, 49*91f16700Schasinglulu 0x46, 0x1f, 0xba, 0x97, 0x7f, 0x63); 50*91f16700Schasinglulu 51*91f16700Schasinglulu static int32_t tlkd_init(void); 52*91f16700Schasinglulu 53*91f16700Schasinglulu /******************************************************************************* 54*91f16700Schasinglulu * Secure Payload Dispatcher's timer interrupt handler 55*91f16700Schasinglulu ******************************************************************************/ 56*91f16700Schasinglulu static uint64_t tlkd_interrupt_handler(uint32_t id, 57*91f16700Schasinglulu uint32_t flags, 58*91f16700Schasinglulu void *handle, 59*91f16700Schasinglulu void *cookie) 60*91f16700Schasinglulu { 61*91f16700Schasinglulu cpu_context_t *s_cpu_context; 62*91f16700Schasinglulu int irq = plat_ic_get_pending_interrupt_id(); 63*91f16700Schasinglulu 64*91f16700Schasinglulu /* acknowledge the interrupt and mark it complete */ 65*91f16700Schasinglulu (void)plat_ic_acknowledge_interrupt(); 66*91f16700Schasinglulu plat_ic_end_of_interrupt(irq); 67*91f16700Schasinglulu 68*91f16700Schasinglulu /* 69*91f16700Schasinglulu * Disable the routing of NS interrupts from secure world to 70*91f16700Schasinglulu * EL3 while interrupted on this core. 71*91f16700Schasinglulu */ 72*91f16700Schasinglulu disable_intr_rm_local(INTR_TYPE_S_EL1, SECURE); 73*91f16700Schasinglulu 74*91f16700Schasinglulu /* Check the security state when the exception was generated */ 75*91f16700Schasinglulu assert(get_interrupt_src_ss(flags) == NON_SECURE); 76*91f16700Schasinglulu assert(handle == cm_get_context(NON_SECURE)); 77*91f16700Schasinglulu 78*91f16700Schasinglulu /* Save non-secure state */ 79*91f16700Schasinglulu cm_el1_sysregs_context_save(NON_SECURE); 80*91f16700Schasinglulu 81*91f16700Schasinglulu /* Get a reference to the secure context */ 82*91f16700Schasinglulu s_cpu_context = cm_get_context(SECURE); 83*91f16700Schasinglulu assert(s_cpu_context); 84*91f16700Schasinglulu 85*91f16700Schasinglulu /* 86*91f16700Schasinglulu * Restore non-secure state. There is no need to save the 87*91f16700Schasinglulu * secure system register context since the SP was supposed 88*91f16700Schasinglulu * to preserve it during S-EL1 interrupt handling. 89*91f16700Schasinglulu */ 90*91f16700Schasinglulu cm_el1_sysregs_context_restore(SECURE); 91*91f16700Schasinglulu cm_set_next_eret_context(SECURE); 92*91f16700Schasinglulu 93*91f16700Schasinglulu /* Provide the IRQ number to the SPD */ 94*91f16700Schasinglulu SMC_RET4(s_cpu_context, (uint32_t)TLK_IRQ_FIRED, 0, (uint32_t)irq, 0); 95*91f16700Schasinglulu } 96*91f16700Schasinglulu 97*91f16700Schasinglulu /******************************************************************************* 98*91f16700Schasinglulu * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type 99*91f16700Schasinglulu * (aarch32/aarch64) if not already known and initialises the context for entry 100*91f16700Schasinglulu * into the SP for its initialisation. 101*91f16700Schasinglulu ******************************************************************************/ 102*91f16700Schasinglulu static int32_t tlkd_setup(void) 103*91f16700Schasinglulu { 104*91f16700Schasinglulu entry_point_info_t *tlk_ep_info; 105*91f16700Schasinglulu uint32_t flags; 106*91f16700Schasinglulu int32_t ret; 107*91f16700Schasinglulu 108*91f16700Schasinglulu /* 109*91f16700Schasinglulu * Get information about the Secure Payload (BL32) image. Its 110*91f16700Schasinglulu * absence is a critical failure. 111*91f16700Schasinglulu */ 112*91f16700Schasinglulu tlk_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 113*91f16700Schasinglulu if (!tlk_ep_info) { 114*91f16700Schasinglulu WARN("No SP provided. Booting device without SP" 115*91f16700Schasinglulu " initialization. SMC`s destined for SP" 116*91f16700Schasinglulu " will return SMC_UNK\n"); 117*91f16700Schasinglulu return 1; 118*91f16700Schasinglulu } 119*91f16700Schasinglulu 120*91f16700Schasinglulu /* 121*91f16700Schasinglulu * If there's no valid entry point for SP, we return a non-zero value 122*91f16700Schasinglulu * signalling failure initializing the service. We bail out without 123*91f16700Schasinglulu * registering any handlers 124*91f16700Schasinglulu */ 125*91f16700Schasinglulu if (!tlk_ep_info->pc) 126*91f16700Schasinglulu return 1; 127*91f16700Schasinglulu 128*91f16700Schasinglulu /* 129*91f16700Schasinglulu * Inspect the SP image's SPSR and determine it's execution state 130*91f16700Schasinglulu * i.e whether AArch32 or AArch64. 131*91f16700Schasinglulu */ 132*91f16700Schasinglulu tlkd_init_tlk_ep_state(tlk_ep_info, 133*91f16700Schasinglulu (tlk_ep_info->spsr >> MODE_RW_SHIFT) & MODE_RW_MASK, 134*91f16700Schasinglulu tlk_ep_info->pc, 135*91f16700Schasinglulu &tlk_ctx); 136*91f16700Schasinglulu 137*91f16700Schasinglulu /* get a list of all S-EL1 IRQs from the platform */ 138*91f16700Schasinglulu 139*91f16700Schasinglulu /* register interrupt handler */ 140*91f16700Schasinglulu flags = 0; 141*91f16700Schasinglulu set_interrupt_rm_flag(flags, NON_SECURE); 142*91f16700Schasinglulu ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, 143*91f16700Schasinglulu tlkd_interrupt_handler, 144*91f16700Schasinglulu flags); 145*91f16700Schasinglulu if (ret != 0) { 146*91f16700Schasinglulu ERROR("failed to register tlkd interrupt handler (%d)\n", ret); 147*91f16700Schasinglulu } 148*91f16700Schasinglulu 149*91f16700Schasinglulu /* 150*91f16700Schasinglulu * All TLK SPD initialization done. Now register our init function 151*91f16700Schasinglulu * with BL31 for deferred invocation 152*91f16700Schasinglulu */ 153*91f16700Schasinglulu bl31_register_bl32_init(&tlkd_init); 154*91f16700Schasinglulu 155*91f16700Schasinglulu return 0; 156*91f16700Schasinglulu } 157*91f16700Schasinglulu 158*91f16700Schasinglulu /******************************************************************************* 159*91f16700Schasinglulu * This function passes control to the Secure Payload image (BL32) for the first 160*91f16700Schasinglulu * time on the primary cpu after a cold boot. It assumes that a valid secure 161*91f16700Schasinglulu * context has already been created by tlkd_setup() which can be directly 162*91f16700Schasinglulu * used. This function performs a synchronous entry into the Secure payload. 163*91f16700Schasinglulu * The SP passes control back to this routine through a SMC. 164*91f16700Schasinglulu ******************************************************************************/ 165*91f16700Schasinglulu static int32_t tlkd_init(void) 166*91f16700Schasinglulu { 167*91f16700Schasinglulu entry_point_info_t *tlk_entry_point; 168*91f16700Schasinglulu 169*91f16700Schasinglulu /* 170*91f16700Schasinglulu * Get information about the Secure Payload (BL32) image. Its 171*91f16700Schasinglulu * absence is a critical failure. 172*91f16700Schasinglulu */ 173*91f16700Schasinglulu tlk_entry_point = bl31_plat_get_next_image_ep_info(SECURE); 174*91f16700Schasinglulu assert(tlk_entry_point); 175*91f16700Schasinglulu 176*91f16700Schasinglulu cm_init_my_context(tlk_entry_point); 177*91f16700Schasinglulu 178*91f16700Schasinglulu /* 179*91f16700Schasinglulu * TLK runs only on a single CPU. Store the value of the boot 180*91f16700Schasinglulu * CPU for sanity checking later. 181*91f16700Schasinglulu */ 182*91f16700Schasinglulu boot_cpu = plat_my_core_pos(); 183*91f16700Schasinglulu 184*91f16700Schasinglulu /* 185*91f16700Schasinglulu * Arrange for an entry into the test secure payload. 186*91f16700Schasinglulu */ 187*91f16700Schasinglulu return tlkd_synchronous_sp_entry(&tlk_ctx); 188*91f16700Schasinglulu } 189*91f16700Schasinglulu 190*91f16700Schasinglulu /******************************************************************************* 191*91f16700Schasinglulu * This function is responsible for handling all SMCs in the Trusted OS/App 192*91f16700Schasinglulu * range from the non-secure state as defined in the SMC Calling Convention 193*91f16700Schasinglulu * Document. It is also responsible for communicating with the Secure payload 194*91f16700Schasinglulu * to delegate work and return results back to the non-secure state. Lastly it 195*91f16700Schasinglulu * will also return any information that the secure payload needs to do the 196*91f16700Schasinglulu * work assigned to it. 197*91f16700Schasinglulu ******************************************************************************/ 198*91f16700Schasinglulu static uintptr_t tlkd_smc_handler(uint32_t smc_fid, 199*91f16700Schasinglulu u_register_t x1, 200*91f16700Schasinglulu u_register_t x2, 201*91f16700Schasinglulu u_register_t x3, 202*91f16700Schasinglulu u_register_t x4, 203*91f16700Schasinglulu void *cookie, 204*91f16700Schasinglulu void *handle, 205*91f16700Schasinglulu u_register_t flags) 206*91f16700Schasinglulu { 207*91f16700Schasinglulu cpu_context_t *ns_cpu_context; 208*91f16700Schasinglulu gp_regs_t *gp_regs; 209*91f16700Schasinglulu uint32_t ns; 210*91f16700Schasinglulu uint64_t par; 211*91f16700Schasinglulu 212*91f16700Schasinglulu /* Passing a NULL context is a critical programming error */ 213*91f16700Schasinglulu assert(handle); 214*91f16700Schasinglulu 215*91f16700Schasinglulu /* These SMCs are only supported by a single CPU */ 216*91f16700Schasinglulu if (boot_cpu != plat_my_core_pos()) 217*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 218*91f16700Schasinglulu 219*91f16700Schasinglulu /* Determine which security state this SMC originated from */ 220*91f16700Schasinglulu ns = is_caller_non_secure(flags); 221*91f16700Schasinglulu 222*91f16700Schasinglulu switch (smc_fid) { 223*91f16700Schasinglulu 224*91f16700Schasinglulu /* 225*91f16700Schasinglulu * This function ID is used by SP to indicate that it was 226*91f16700Schasinglulu * preempted by a non-secure world IRQ. 227*91f16700Schasinglulu */ 228*91f16700Schasinglulu case TLK_PREEMPTED: 229*91f16700Schasinglulu 230*91f16700Schasinglulu if (ns) 231*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 232*91f16700Schasinglulu 233*91f16700Schasinglulu assert(handle == cm_get_context(SECURE)); 234*91f16700Schasinglulu cm_el1_sysregs_context_save(SECURE); 235*91f16700Schasinglulu 236*91f16700Schasinglulu /* Get a reference to the non-secure context */ 237*91f16700Schasinglulu ns_cpu_context = cm_get_context(NON_SECURE); 238*91f16700Schasinglulu assert(ns_cpu_context); 239*91f16700Schasinglulu 240*91f16700Schasinglulu /* 241*91f16700Schasinglulu * Restore non-secure state. There is no need to save the 242*91f16700Schasinglulu * secure system register context since the SP was supposed 243*91f16700Schasinglulu * to preserve it during S-EL1 interrupt handling. 244*91f16700Schasinglulu */ 245*91f16700Schasinglulu cm_el1_sysregs_context_restore(NON_SECURE); 246*91f16700Schasinglulu cm_set_next_eret_context(NON_SECURE); 247*91f16700Schasinglulu 248*91f16700Schasinglulu SMC_RET1(ns_cpu_context, x1); 249*91f16700Schasinglulu 250*91f16700Schasinglulu /* 251*91f16700Schasinglulu * This is a request from the non-secure context to: 252*91f16700Schasinglulu * 253*91f16700Schasinglulu * a. register shared memory with the SP for storing it's 254*91f16700Schasinglulu * activity logs. 255*91f16700Schasinglulu * b. register shared memory with the SP for passing args 256*91f16700Schasinglulu * required for maintaining sessions with the Trusted 257*91f16700Schasinglulu * Applications. 258*91f16700Schasinglulu * c. register shared persistent buffers for secure storage 259*91f16700Schasinglulu * d. register NS DRAM ranges passed by Cboot 260*91f16700Schasinglulu * e. register Root of Trust parameters from Cboot for Verified Boot 261*91f16700Schasinglulu * f. open/close sessions 262*91f16700Schasinglulu * g. issue commands to the Trusted Apps 263*91f16700Schasinglulu * h. resume the preempted yielding SMC call. 264*91f16700Schasinglulu */ 265*91f16700Schasinglulu case TLK_REGISTER_LOGBUF: 266*91f16700Schasinglulu case TLK_REGISTER_REQBUF: 267*91f16700Schasinglulu case TLK_SS_REGISTER_HANDLER: 268*91f16700Schasinglulu case TLK_REGISTER_NS_DRAM_RANGES: 269*91f16700Schasinglulu case TLK_SET_ROOT_OF_TRUST: 270*91f16700Schasinglulu case TLK_OPEN_TA_SESSION: 271*91f16700Schasinglulu case TLK_CLOSE_TA_SESSION: 272*91f16700Schasinglulu case TLK_TA_LAUNCH_OP: 273*91f16700Schasinglulu case TLK_TA_SEND_EVENT: 274*91f16700Schasinglulu case TLK_RESUME_FID: 275*91f16700Schasinglulu case TLK_SET_BL_VERSION: 276*91f16700Schasinglulu case TLK_LOCK_BL_INTERFACE: 277*91f16700Schasinglulu case TLK_BL_RPMB_SERVICE: 278*91f16700Schasinglulu 279*91f16700Schasinglulu if (!ns) 280*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 281*91f16700Schasinglulu 282*91f16700Schasinglulu /* 283*91f16700Schasinglulu * This is a fresh request from the non-secure client. 284*91f16700Schasinglulu * The parameters are in x1 and x2. Figure out which 285*91f16700Schasinglulu * registers need to be preserved, save the non-secure 286*91f16700Schasinglulu * state and send the request to the secure payload. 287*91f16700Schasinglulu */ 288*91f16700Schasinglulu assert(handle == cm_get_context(NON_SECURE)); 289*91f16700Schasinglulu 290*91f16700Schasinglulu /* 291*91f16700Schasinglulu * Check if we are already processing a yielding SMC 292*91f16700Schasinglulu * call. Of all the supported fids, only the "resume" 293*91f16700Schasinglulu * fid expects the flag to be set. 294*91f16700Schasinglulu */ 295*91f16700Schasinglulu if (smc_fid == TLK_RESUME_FID) { 296*91f16700Schasinglulu if (!get_yield_smc_active_flag(tlk_ctx.state)) 297*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 298*91f16700Schasinglulu } else { 299*91f16700Schasinglulu if (get_yield_smc_active_flag(tlk_ctx.state)) 300*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 301*91f16700Schasinglulu } 302*91f16700Schasinglulu 303*91f16700Schasinglulu cm_el1_sysregs_context_save(NON_SECURE); 304*91f16700Schasinglulu 305*91f16700Schasinglulu /* 306*91f16700Schasinglulu * Verify if there is a valid context to use. 307*91f16700Schasinglulu */ 308*91f16700Schasinglulu assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE)); 309*91f16700Schasinglulu 310*91f16700Schasinglulu /* 311*91f16700Schasinglulu * Mark the SP state as active. 312*91f16700Schasinglulu */ 313*91f16700Schasinglulu set_yield_smc_active_flag(tlk_ctx.state); 314*91f16700Schasinglulu 315*91f16700Schasinglulu /* 316*91f16700Schasinglulu * We are done stashing the non-secure context. Ask the 317*91f16700Schasinglulu * secure payload to do the work now. 318*91f16700Schasinglulu */ 319*91f16700Schasinglulu cm_el1_sysregs_context_restore(SECURE); 320*91f16700Schasinglulu cm_set_next_eret_context(SECURE); 321*91f16700Schasinglulu 322*91f16700Schasinglulu /* 323*91f16700Schasinglulu * TLK is a 32-bit Trusted OS and so expects the SMC 324*91f16700Schasinglulu * arguments via r0-r7. TLK expects the monitor frame 325*91f16700Schasinglulu * registers to be 64-bits long. Hence, we pass x0 in 326*91f16700Schasinglulu * r0-r1, x1 in r2-r3, x3 in r4-r5 and x4 in r6-r7. 327*91f16700Schasinglulu * 328*91f16700Schasinglulu * As smc_fid is a uint32 value, r1 contains 0. 329*91f16700Schasinglulu */ 330*91f16700Schasinglulu gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); 331*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X4, (uint32_t)x2); 332*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X5, (uint32_t)(x2 >> 32)); 333*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X6, (uint32_t)x3); 334*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X7, (uint32_t)(x3 >> 32)); 335*91f16700Schasinglulu SMC_RET4(&tlk_ctx.cpu_ctx, smc_fid, 0, (uint32_t)x1, 336*91f16700Schasinglulu (uint32_t)(x1 >> 32)); 337*91f16700Schasinglulu 338*91f16700Schasinglulu /* 339*91f16700Schasinglulu * Translate NS/EL1-S virtual addresses. 340*91f16700Schasinglulu * 341*91f16700Schasinglulu * x1 = virtual address 342*91f16700Schasinglulu * x3 = type (NS/S) 343*91f16700Schasinglulu * 344*91f16700Schasinglulu * Returns PA:lo in r0, PA:hi in r1. 345*91f16700Schasinglulu */ 346*91f16700Schasinglulu case TLK_VA_TRANSLATE: 347*91f16700Schasinglulu 348*91f16700Schasinglulu /* Should be invoked only by secure world */ 349*91f16700Schasinglulu if (ns) 350*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 351*91f16700Schasinglulu 352*91f16700Schasinglulu /* NS virtual addresses are 64-bit long */ 353*91f16700Schasinglulu if (x3 & TLK_TRANSLATE_NS_VADDR) 354*91f16700Schasinglulu x1 = (uint32_t)x1 | (x2 << 32); 355*91f16700Schasinglulu 356*91f16700Schasinglulu if (!x1) 357*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 358*91f16700Schasinglulu 359*91f16700Schasinglulu /* 360*91f16700Schasinglulu * TODO: Sanity check x1. This would require platform 361*91f16700Schasinglulu * support. 362*91f16700Schasinglulu */ 363*91f16700Schasinglulu 364*91f16700Schasinglulu /* virtual address and type: ns/s */ 365*91f16700Schasinglulu par = tlkd_va_translate(x1, x3); 366*91f16700Schasinglulu 367*91f16700Schasinglulu /* return physical address in r0-r1 */ 368*91f16700Schasinglulu SMC_RET4(handle, (uint32_t)par, (uint32_t)(par >> 32), 0, 0); 369*91f16700Schasinglulu 370*91f16700Schasinglulu /* 371*91f16700Schasinglulu * This is a request from the SP to mark completion of 372*91f16700Schasinglulu * a yielding function ID. 373*91f16700Schasinglulu */ 374*91f16700Schasinglulu case TLK_REQUEST_DONE: 375*91f16700Schasinglulu if (ns) 376*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 377*91f16700Schasinglulu 378*91f16700Schasinglulu /* 379*91f16700Schasinglulu * Mark the SP state as inactive. 380*91f16700Schasinglulu */ 381*91f16700Schasinglulu clr_yield_smc_active_flag(tlk_ctx.state); 382*91f16700Schasinglulu 383*91f16700Schasinglulu /* Get a reference to the non-secure context */ 384*91f16700Schasinglulu ns_cpu_context = cm_get_context(NON_SECURE); 385*91f16700Schasinglulu assert(ns_cpu_context); 386*91f16700Schasinglulu 387*91f16700Schasinglulu /* 388*91f16700Schasinglulu * This is a request completion SMC and we must switch to 389*91f16700Schasinglulu * the non-secure world to pass the result. 390*91f16700Schasinglulu */ 391*91f16700Schasinglulu cm_el1_sysregs_context_save(SECURE); 392*91f16700Schasinglulu 393*91f16700Schasinglulu /* 394*91f16700Schasinglulu * We are done stashing the secure context. Switch to the 395*91f16700Schasinglulu * non-secure context and return the result. 396*91f16700Schasinglulu */ 397*91f16700Schasinglulu cm_el1_sysregs_context_restore(NON_SECURE); 398*91f16700Schasinglulu cm_set_next_eret_context(NON_SECURE); 399*91f16700Schasinglulu SMC_RET1(ns_cpu_context, x1); 400*91f16700Schasinglulu 401*91f16700Schasinglulu /* 402*91f16700Schasinglulu * This function ID is used only by the SP to indicate it has 403*91f16700Schasinglulu * finished initialising itself after a cold boot 404*91f16700Schasinglulu */ 405*91f16700Schasinglulu case TLK_ENTRY_DONE: 406*91f16700Schasinglulu if (ns) 407*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 408*91f16700Schasinglulu 409*91f16700Schasinglulu /* 410*91f16700Schasinglulu * SP has been successfully initialized. Register power 411*91f16700Schasinglulu * management hooks with PSCI 412*91f16700Schasinglulu */ 413*91f16700Schasinglulu psci_register_spd_pm_hook(&tlkd_pm_ops); 414*91f16700Schasinglulu 415*91f16700Schasinglulu /* 416*91f16700Schasinglulu * TLK reports completion. The SPD must have initiated 417*91f16700Schasinglulu * the original request through a synchronous entry 418*91f16700Schasinglulu * into the SP. Jump back to the original C runtime 419*91f16700Schasinglulu * context. 420*91f16700Schasinglulu */ 421*91f16700Schasinglulu tlkd_synchronous_sp_exit(&tlk_ctx, x1); 422*91f16700Schasinglulu break; 423*91f16700Schasinglulu 424*91f16700Schasinglulu /* 425*91f16700Schasinglulu * These function IDs are used only by TLK to indicate it has 426*91f16700Schasinglulu * finished: 427*91f16700Schasinglulu * 1. suspending itself after an earlier psci cpu_suspend 428*91f16700Schasinglulu * request. 429*91f16700Schasinglulu * 2. resuming itself after an earlier psci cpu_suspend 430*91f16700Schasinglulu * request. 431*91f16700Schasinglulu * 3. powering down after an earlier psci system_off/system_reset 432*91f16700Schasinglulu * request. 433*91f16700Schasinglulu */ 434*91f16700Schasinglulu case TLK_SUSPEND_DONE: 435*91f16700Schasinglulu case TLK_RESUME_DONE: 436*91f16700Schasinglulu 437*91f16700Schasinglulu if (ns) 438*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 439*91f16700Schasinglulu 440*91f16700Schasinglulu /* 441*91f16700Schasinglulu * TLK reports completion. TLKD must have initiated the 442*91f16700Schasinglulu * original request through a synchronous entry into the SP. 443*91f16700Schasinglulu * Jump back to the original C runtime context, and pass x1 as 444*91f16700Schasinglulu * return value to the caller 445*91f16700Schasinglulu */ 446*91f16700Schasinglulu tlkd_synchronous_sp_exit(&tlk_ctx, x1); 447*91f16700Schasinglulu break; 448*91f16700Schasinglulu 449*91f16700Schasinglulu /* 450*91f16700Schasinglulu * This function ID is used by SP to indicate that it has completed 451*91f16700Schasinglulu * handling the secure interrupt. 452*91f16700Schasinglulu */ 453*91f16700Schasinglulu case TLK_IRQ_DONE: 454*91f16700Schasinglulu 455*91f16700Schasinglulu if (ns) 456*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 457*91f16700Schasinglulu 458*91f16700Schasinglulu assert(handle == cm_get_context(SECURE)); 459*91f16700Schasinglulu 460*91f16700Schasinglulu /* save secure world context */ 461*91f16700Schasinglulu cm_el1_sysregs_context_save(SECURE); 462*91f16700Schasinglulu 463*91f16700Schasinglulu /* Get a reference to the non-secure context */ 464*91f16700Schasinglulu ns_cpu_context = cm_get_context(NON_SECURE); 465*91f16700Schasinglulu assert(ns_cpu_context); 466*91f16700Schasinglulu 467*91f16700Schasinglulu /* 468*91f16700Schasinglulu * Restore non-secure state. There is no need to save the 469*91f16700Schasinglulu * secure system register context since the SP was supposed 470*91f16700Schasinglulu * to preserve it during S-EL1 interrupt handling. 471*91f16700Schasinglulu */ 472*91f16700Schasinglulu cm_el1_sysregs_context_restore(NON_SECURE); 473*91f16700Schasinglulu cm_set_next_eret_context(NON_SECURE); 474*91f16700Schasinglulu 475*91f16700Schasinglulu SMC_RET0(ns_cpu_context); 476*91f16700Schasinglulu 477*91f16700Schasinglulu /* 478*91f16700Schasinglulu * Return the number of service function IDs implemented to 479*91f16700Schasinglulu * provide service to non-secure 480*91f16700Schasinglulu */ 481*91f16700Schasinglulu case TOS_CALL_COUNT: 482*91f16700Schasinglulu SMC_RET1(handle, TLK_NUM_FID); 483*91f16700Schasinglulu 484*91f16700Schasinglulu /* 485*91f16700Schasinglulu * Return TLK's UID to the caller 486*91f16700Schasinglulu */ 487*91f16700Schasinglulu case TOS_UID: 488*91f16700Schasinglulu SMC_UUID_RET(handle, tlk_uuid); 489*91f16700Schasinglulu 490*91f16700Schasinglulu /* 491*91f16700Schasinglulu * Return the version of current implementation 492*91f16700Schasinglulu */ 493*91f16700Schasinglulu case TOS_CALL_VERSION: 494*91f16700Schasinglulu SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR); 495*91f16700Schasinglulu 496*91f16700Schasinglulu default: 497*91f16700Schasinglulu WARN("%s: Unhandled SMC: 0x%x\n", __func__, smc_fid); 498*91f16700Schasinglulu break; 499*91f16700Schasinglulu } 500*91f16700Schasinglulu 501*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 502*91f16700Schasinglulu } 503*91f16700Schasinglulu 504*91f16700Schasinglulu /* Define a SPD runtime service descriptor for fast SMC calls */ 505*91f16700Schasinglulu DECLARE_RT_SVC( 506*91f16700Schasinglulu tlkd_tos_fast, 507*91f16700Schasinglulu 508*91f16700Schasinglulu OEN_TOS_START, 509*91f16700Schasinglulu OEN_TOS_END, 510*91f16700Schasinglulu SMC_TYPE_FAST, 511*91f16700Schasinglulu tlkd_setup, 512*91f16700Schasinglulu tlkd_smc_handler 513*91f16700Schasinglulu ); 514*91f16700Schasinglulu 515*91f16700Schasinglulu /* Define a SPD runtime service descriptor for yielding SMC calls */ 516*91f16700Schasinglulu DECLARE_RT_SVC( 517*91f16700Schasinglulu tlkd_tos_std, 518*91f16700Schasinglulu 519*91f16700Schasinglulu OEN_TOS_START, 520*91f16700Schasinglulu OEN_TOS_END, 521*91f16700Schasinglulu SMC_TYPE_YIELD, 522*91f16700Schasinglulu NULL, 523*91f16700Schasinglulu tlkd_smc_handler 524*91f16700Schasinglulu ); 525*91f16700Schasinglulu 526*91f16700Schasinglulu /* Define a SPD runtime service descriptor for fast SMC calls */ 527*91f16700Schasinglulu DECLARE_RT_SVC( 528*91f16700Schasinglulu tlkd_tap_fast, 529*91f16700Schasinglulu 530*91f16700Schasinglulu OEN_TAP_START, 531*91f16700Schasinglulu OEN_TAP_END, 532*91f16700Schasinglulu SMC_TYPE_FAST, 533*91f16700Schasinglulu NULL, 534*91f16700Schasinglulu tlkd_smc_handler 535*91f16700Schasinglulu ); 536*91f16700Schasinglulu 537*91f16700Schasinglulu /* Define a SPD runtime service descriptor for yielding SMC calls */ 538*91f16700Schasinglulu DECLARE_RT_SVC( 539*91f16700Schasinglulu tlkd_tap_std, 540*91f16700Schasinglulu 541*91f16700Schasinglulu OEN_TAP_START, 542*91f16700Schasinglulu OEN_TAP_END, 543*91f16700Schasinglulu SMC_TYPE_YIELD, 544*91f16700Schasinglulu NULL, 545*91f16700Schasinglulu tlkd_smc_handler 546*91f16700Schasinglulu ); 547