1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu /******************************************************************************* 8*91f16700Schasinglulu * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a 9*91f16700Schasinglulu * plug-in component to the Secure Monitor, registered as a runtime service. The 10*91f16700Schasinglulu * SPD is expected to be a functional extension of the Secure Payload (SP) that 11*91f16700Schasinglulu * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting 12*91f16700Schasinglulu * the Trusted OS/Applications range to the dispatcher. The SPD will either 13*91f16700Schasinglulu * handle the request locally or delegate it to the Secure Payload. It is also 14*91f16700Schasinglulu * responsible for initialising and maintaining communication with the SP. 15*91f16700Schasinglulu ******************************************************************************/ 16*91f16700Schasinglulu 17*91f16700Schasinglulu #include <assert.h> 18*91f16700Schasinglulu #include <errno.h> 19*91f16700Schasinglulu #include <stddef.h> 20*91f16700Schasinglulu #include <string.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu #include <arch_helpers.h> 23*91f16700Schasinglulu #include <bl31/bl31.h> 24*91f16700Schasinglulu #include <bl31/interrupt_mgmt.h> 25*91f16700Schasinglulu #include <bl_common.h> 26*91f16700Schasinglulu #include <common/debug.h> 27*91f16700Schasinglulu #include <common/ep_info.h> 28*91f16700Schasinglulu #include <drivers/arm/gic_common.h> 29*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h> 30*91f16700Schasinglulu #include <lib/spinlock.h> 31*91f16700Schasinglulu #include <plat/common/platform.h> 32*91f16700Schasinglulu #include <pnc.h> 33*91f16700Schasinglulu #include "pncd_private.h" 34*91f16700Schasinglulu #include <runtime_svc.h> 35*91f16700Schasinglulu #include <tools_share/uuid.h> 36*91f16700Schasinglulu 37*91f16700Schasinglulu /******************************************************************************* 38*91f16700Schasinglulu * Structure to keep track of ProvenCore state 39*91f16700Schasinglulu ******************************************************************************/ 40*91f16700Schasinglulu static pnc_context_t pncd_sp_context; 41*91f16700Schasinglulu 42*91f16700Schasinglulu static bool ree_info; 43*91f16700Schasinglulu static uint64_t ree_base_addr; 44*91f16700Schasinglulu static uint64_t ree_length; 45*91f16700Schasinglulu static uint64_t ree_tag; 46*91f16700Schasinglulu 47*91f16700Schasinglulu static bool pnc_initialized; 48*91f16700Schasinglulu 49*91f16700Schasinglulu static spinlock_t smc_handler_lock; 50*91f16700Schasinglulu 51*91f16700Schasinglulu static int pncd_init(void); 52*91f16700Schasinglulu 53*91f16700Schasinglulu static void context_save(unsigned long security_state) 54*91f16700Schasinglulu { 55*91f16700Schasinglulu assert(sec_state_is_valid(security_state)); 56*91f16700Schasinglulu 57*91f16700Schasinglulu cm_el1_sysregs_context_save((uint32_t) security_state); 58*91f16700Schasinglulu #if CTX_INCLUDE_FPREGS 59*91f16700Schasinglulu fpregs_context_save(get_fpregs_ctx(cm_get_context(security_state))); 60*91f16700Schasinglulu #endif 61*91f16700Schasinglulu } 62*91f16700Schasinglulu 63*91f16700Schasinglulu static void *context_restore(unsigned long security_state) 64*91f16700Schasinglulu { 65*91f16700Schasinglulu void *handle; 66*91f16700Schasinglulu 67*91f16700Schasinglulu assert(sec_state_is_valid(security_state)); 68*91f16700Schasinglulu 69*91f16700Schasinglulu /* Get a reference to the next context */ 70*91f16700Schasinglulu handle = cm_get_context((uint32_t) security_state); 71*91f16700Schasinglulu assert(handle); 72*91f16700Schasinglulu 73*91f16700Schasinglulu /* Restore state */ 74*91f16700Schasinglulu cm_el1_sysregs_context_restore((uint32_t) security_state); 75*91f16700Schasinglulu #if CTX_INCLUDE_FPREGS 76*91f16700Schasinglulu fpregs_context_restore(get_fpregs_ctx(cm_get_context(security_state))); 77*91f16700Schasinglulu #endif 78*91f16700Schasinglulu 79*91f16700Schasinglulu cm_set_next_eret_context((uint32_t) security_state); 80*91f16700Schasinglulu 81*91f16700Schasinglulu return handle; 82*91f16700Schasinglulu } 83*91f16700Schasinglulu 84*91f16700Schasinglulu static uint64_t pncd_sel1_interrupt_handler(uint32_t id, 85*91f16700Schasinglulu uint32_t flags, void *handle, void *cookie); 86*91f16700Schasinglulu 87*91f16700Schasinglulu /******************************************************************************* 88*91f16700Schasinglulu * Switch context to the specified security state and return the targeted 89*91f16700Schasinglulu * handle. Note that the context may remain unchanged if the switch is not 90*91f16700Schasinglulu * allowed. 91*91f16700Schasinglulu ******************************************************************************/ 92*91f16700Schasinglulu void *pncd_context_switch_to(unsigned long security_state) 93*91f16700Schasinglulu { 94*91f16700Schasinglulu unsigned long sec_state_from = 95*91f16700Schasinglulu security_state == SECURE ? NON_SECURE : SECURE; 96*91f16700Schasinglulu 97*91f16700Schasinglulu assert(sec_state_is_valid(security_state)); 98*91f16700Schasinglulu 99*91f16700Schasinglulu /* Check if this is the first world switch */ 100*91f16700Schasinglulu if (!pnc_initialized) { 101*91f16700Schasinglulu int rc; 102*91f16700Schasinglulu uint32_t flags; 103*91f16700Schasinglulu 104*91f16700Schasinglulu assert(sec_state_from == SECURE); 105*91f16700Schasinglulu 106*91f16700Schasinglulu INFO("PnC initialization done\n"); 107*91f16700Schasinglulu 108*91f16700Schasinglulu /* 109*91f16700Schasinglulu * Register an interrupt handler for S-EL1 interrupts 110*91f16700Schasinglulu * when generated during code executing in the 111*91f16700Schasinglulu * non-secure state. 112*91f16700Schasinglulu */ 113*91f16700Schasinglulu flags = 0U; 114*91f16700Schasinglulu set_interrupt_rm_flag(flags, NON_SECURE); 115*91f16700Schasinglulu rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, 116*91f16700Schasinglulu pncd_sel1_interrupt_handler, 117*91f16700Schasinglulu flags); 118*91f16700Schasinglulu if (rc != 0) { 119*91f16700Schasinglulu ERROR("Failed to register S-EL1 interrupt handler (%d)\n", 120*91f16700Schasinglulu rc); 121*91f16700Schasinglulu panic(); 122*91f16700Schasinglulu } 123*91f16700Schasinglulu 124*91f16700Schasinglulu context_save(SECURE); 125*91f16700Schasinglulu 126*91f16700Schasinglulu pnc_initialized = true; 127*91f16700Schasinglulu 128*91f16700Schasinglulu /* 129*91f16700Schasinglulu * Release the lock before restoring the EL3 context to 130*91f16700Schasinglulu * bl31_main. 131*91f16700Schasinglulu */ 132*91f16700Schasinglulu spin_unlock(&smc_handler_lock); 133*91f16700Schasinglulu 134*91f16700Schasinglulu /* 135*91f16700Schasinglulu * SP reports completion. The SPD must have initiated 136*91f16700Schasinglulu * the original request through a synchronous entry 137*91f16700Schasinglulu * into the SP. Jump back to the original C runtime 138*91f16700Schasinglulu * context. 139*91f16700Schasinglulu */ 140*91f16700Schasinglulu pncd_synchronous_sp_exit(&pncd_sp_context, (uint64_t) 0x0); 141*91f16700Schasinglulu 142*91f16700Schasinglulu /* Unreachable */ 143*91f16700Schasinglulu ERROR("Returned from pncd_synchronous_sp_exit... Should not happen\n"); 144*91f16700Schasinglulu panic(); 145*91f16700Schasinglulu } 146*91f16700Schasinglulu 147*91f16700Schasinglulu /* Check that the world switch is allowed */ 148*91f16700Schasinglulu if (read_mpidr() != pncd_sp_context.mpidr) { 149*91f16700Schasinglulu if (sec_state_from == SECURE) { 150*91f16700Schasinglulu /* 151*91f16700Schasinglulu * Secure -> Non-Secure world switch initiated on a CPU where there 152*91f16700Schasinglulu * should be no Trusted OS running 153*91f16700Schasinglulu */ 154*91f16700Schasinglulu WARN("Secure to Non-Secure switch requested on CPU where ProvenCore is not supposed to be running...\n"); 155*91f16700Schasinglulu } 156*91f16700Schasinglulu 157*91f16700Schasinglulu /* 158*91f16700Schasinglulu * Secure or Non-Secure world wants to switch world but there is no Secure 159*91f16700Schasinglulu * software on this core 160*91f16700Schasinglulu */ 161*91f16700Schasinglulu return cm_get_context((uint32_t) sec_state_from); 162*91f16700Schasinglulu } 163*91f16700Schasinglulu 164*91f16700Schasinglulu context_save(sec_state_from); 165*91f16700Schasinglulu 166*91f16700Schasinglulu return context_restore(security_state); 167*91f16700Schasinglulu } 168*91f16700Schasinglulu 169*91f16700Schasinglulu /******************************************************************************* 170*91f16700Schasinglulu * This function is the handler registered for S-EL1 interrupts by the PNCD. It 171*91f16700Schasinglulu * validates the interrupt and upon success arranges entry into the PNC at 172*91f16700Schasinglulu * 'pnc_sel1_intr_entry()' for handling the interrupt. 173*91f16700Schasinglulu ******************************************************************************/ 174*91f16700Schasinglulu static uint64_t pncd_sel1_interrupt_handler(uint32_t id, 175*91f16700Schasinglulu uint32_t flags, 176*91f16700Schasinglulu void *handle, 177*91f16700Schasinglulu void *cookie) 178*91f16700Schasinglulu { 179*91f16700Schasinglulu /* Check the security state when the exception was generated */ 180*91f16700Schasinglulu assert(get_interrupt_src_ss(flags) == NON_SECURE); 181*91f16700Schasinglulu 182*91f16700Schasinglulu /* Sanity check the pointer to this cpu's context */ 183*91f16700Schasinglulu assert(handle == cm_get_context(NON_SECURE)); 184*91f16700Schasinglulu 185*91f16700Schasinglulu /* switch to PnC */ 186*91f16700Schasinglulu handle = pncd_context_switch_to(SECURE); 187*91f16700Schasinglulu 188*91f16700Schasinglulu assert(handle != NULL); 189*91f16700Schasinglulu 190*91f16700Schasinglulu SMC_RET0(handle); 191*91f16700Schasinglulu } 192*91f16700Schasinglulu 193*91f16700Schasinglulu #pragma weak plat_pncd_setup 194*91f16700Schasinglulu int plat_pncd_setup(void) 195*91f16700Schasinglulu { 196*91f16700Schasinglulu return 0; 197*91f16700Schasinglulu } 198*91f16700Schasinglulu 199*91f16700Schasinglulu /******************************************************************************* 200*91f16700Schasinglulu * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type 201*91f16700Schasinglulu * (aarch32/aarch64) if not already known and initialises the context for entry 202*91f16700Schasinglulu * into the SP for its initialisation. 203*91f16700Schasinglulu ******************************************************************************/ 204*91f16700Schasinglulu static int pncd_setup(void) 205*91f16700Schasinglulu { 206*91f16700Schasinglulu entry_point_info_t *pnc_ep_info; 207*91f16700Schasinglulu 208*91f16700Schasinglulu /* 209*91f16700Schasinglulu * Get information about the Secure Payload (BL32) image. Its 210*91f16700Schasinglulu * absence is a critical failure. 211*91f16700Schasinglulu * 212*91f16700Schasinglulu * TODO: Add support to conditionally include the SPD service 213*91f16700Schasinglulu */ 214*91f16700Schasinglulu pnc_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 215*91f16700Schasinglulu if (!pnc_ep_info) { 216*91f16700Schasinglulu WARN("No PNC provided by BL2 boot loader, Booting device without PNC initialization. SMC`s destined for PNC will return SMC_UNK\n"); 217*91f16700Schasinglulu return 1; 218*91f16700Schasinglulu } 219*91f16700Schasinglulu 220*91f16700Schasinglulu /* 221*91f16700Schasinglulu * If there's no valid entry point for SP, we return a non-zero value 222*91f16700Schasinglulu * signalling failure initializing the service. We bail out without 223*91f16700Schasinglulu * registering any handlers 224*91f16700Schasinglulu */ 225*91f16700Schasinglulu if (!pnc_ep_info->pc) { 226*91f16700Schasinglulu return 1; 227*91f16700Schasinglulu } 228*91f16700Schasinglulu 229*91f16700Schasinglulu pncd_init_pnc_ep_state(pnc_ep_info, 230*91f16700Schasinglulu pnc_ep_info->pc, 231*91f16700Schasinglulu &pncd_sp_context); 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* 234*91f16700Schasinglulu * All PNCD initialization done. Now register our init function with 235*91f16700Schasinglulu * BL31 for deferred invocation 236*91f16700Schasinglulu */ 237*91f16700Schasinglulu bl31_register_bl32_init(&pncd_init); 238*91f16700Schasinglulu bl31_set_next_image_type(NON_SECURE); 239*91f16700Schasinglulu 240*91f16700Schasinglulu return plat_pncd_setup(); 241*91f16700Schasinglulu } 242*91f16700Schasinglulu 243*91f16700Schasinglulu /******************************************************************************* 244*91f16700Schasinglulu * This function passes control to the Secure Payload image (BL32) for the first 245*91f16700Schasinglulu * time on the primary cpu after a cold boot. It assumes that a valid secure 246*91f16700Schasinglulu * context has already been created by pncd_setup() which can be directly used. 247*91f16700Schasinglulu * It also assumes that a valid non-secure context has been initialised by PSCI 248*91f16700Schasinglulu * so it does not need to save and restore any non-secure state. This function 249*91f16700Schasinglulu * performs a synchronous entry into the Secure payload. The SP passes control 250*91f16700Schasinglulu * back to this routine through a SMC. 251*91f16700Schasinglulu ******************************************************************************/ 252*91f16700Schasinglulu static int32_t pncd_init(void) 253*91f16700Schasinglulu { 254*91f16700Schasinglulu entry_point_info_t *pnc_entry_point; 255*91f16700Schasinglulu uint64_t rc = 0; 256*91f16700Schasinglulu 257*91f16700Schasinglulu /* 258*91f16700Schasinglulu * Get information about the Secure Payload (BL32) image. Its 259*91f16700Schasinglulu * absence is a critical failure. 260*91f16700Schasinglulu */ 261*91f16700Schasinglulu pnc_entry_point = bl31_plat_get_next_image_ep_info(SECURE); 262*91f16700Schasinglulu assert(pnc_entry_point); 263*91f16700Schasinglulu 264*91f16700Schasinglulu cm_init_my_context(pnc_entry_point); 265*91f16700Schasinglulu 266*91f16700Schasinglulu /* 267*91f16700Schasinglulu * Arrange for an entry into the test secure payload. It will be 268*91f16700Schasinglulu * returned via PNC_ENTRY_DONE case 269*91f16700Schasinglulu */ 270*91f16700Schasinglulu rc = pncd_synchronous_sp_entry(&pncd_sp_context); 271*91f16700Schasinglulu 272*91f16700Schasinglulu /* 273*91f16700Schasinglulu * If everything went well at this point, the return value should be 0. 274*91f16700Schasinglulu */ 275*91f16700Schasinglulu return rc == 0; 276*91f16700Schasinglulu } 277*91f16700Schasinglulu 278*91f16700Schasinglulu #pragma weak plat_pncd_smc_handler 279*91f16700Schasinglulu /******************************************************************************* 280*91f16700Schasinglulu * This function is responsible for handling the platform-specific SMCs in the 281*91f16700Schasinglulu * Trusted OS/App range as defined in the SMC Calling Convention Document. 282*91f16700Schasinglulu ******************************************************************************/ 283*91f16700Schasinglulu uintptr_t plat_pncd_smc_handler(uint32_t smc_fid, 284*91f16700Schasinglulu u_register_t x1, 285*91f16700Schasinglulu u_register_t x2, 286*91f16700Schasinglulu u_register_t x3, 287*91f16700Schasinglulu u_register_t x4, 288*91f16700Schasinglulu void *cookie, 289*91f16700Schasinglulu void *handle, 290*91f16700Schasinglulu u_register_t flags) 291*91f16700Schasinglulu { 292*91f16700Schasinglulu (void) smc_fid; 293*91f16700Schasinglulu (void) x1; 294*91f16700Schasinglulu (void) x2; 295*91f16700Schasinglulu (void) x3; 296*91f16700Schasinglulu (void) x4; 297*91f16700Schasinglulu (void) cookie; 298*91f16700Schasinglulu (void) flags; 299*91f16700Schasinglulu 300*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 301*91f16700Schasinglulu } 302*91f16700Schasinglulu 303*91f16700Schasinglulu /******************************************************************************* 304*91f16700Schasinglulu * This function is responsible for handling all SMCs in the Trusted OS/App 305*91f16700Schasinglulu * range as defined in the SMC Calling Convention Document. It is also 306*91f16700Schasinglulu * responsible for communicating with the Secure payload to delegate work and 307*91f16700Schasinglulu * return results back to the non-secure state. Lastly it will also return any 308*91f16700Schasinglulu * information that the secure payload needs to do the work assigned to it. 309*91f16700Schasinglulu * 310*91f16700Schasinglulu * It should only be called with the smc_handler_lock held. 311*91f16700Schasinglulu ******************************************************************************/ 312*91f16700Schasinglulu static uintptr_t pncd_smc_handler_unsafe(uint32_t smc_fid, 313*91f16700Schasinglulu u_register_t x1, 314*91f16700Schasinglulu u_register_t x2, 315*91f16700Schasinglulu u_register_t x3, 316*91f16700Schasinglulu u_register_t x4, 317*91f16700Schasinglulu void *cookie, 318*91f16700Schasinglulu void *handle, 319*91f16700Schasinglulu u_register_t flags) 320*91f16700Schasinglulu { 321*91f16700Schasinglulu uint32_t ns; 322*91f16700Schasinglulu 323*91f16700Schasinglulu /* Determine which security state this SMC originated from */ 324*91f16700Schasinglulu ns = is_caller_non_secure(flags); 325*91f16700Schasinglulu 326*91f16700Schasinglulu assert(ns != 0 || read_mpidr() == pncd_sp_context.mpidr); 327*91f16700Schasinglulu 328*91f16700Schasinglulu switch (smc_fid) { 329*91f16700Schasinglulu case SMC_CONFIG_SHAREDMEM: 330*91f16700Schasinglulu if (ree_info) { 331*91f16700Schasinglulu /* Do not Yield */ 332*91f16700Schasinglulu SMC_RET0(handle); 333*91f16700Schasinglulu } 334*91f16700Schasinglulu 335*91f16700Schasinglulu /* 336*91f16700Schasinglulu * Fetch the physical base address (x1) and size (x2) of the 337*91f16700Schasinglulu * shared memory allocated by the Non-Secure world. This memory 338*91f16700Schasinglulu * will be used by PNC to communicate with the Non-Secure world. 339*91f16700Schasinglulu * Verifying the validity of these values is up to the Trusted 340*91f16700Schasinglulu * OS. 341*91f16700Schasinglulu */ 342*91f16700Schasinglulu ree_base_addr = x1 | (x2 << 32); 343*91f16700Schasinglulu ree_length = x3; 344*91f16700Schasinglulu ree_tag = x4; 345*91f16700Schasinglulu 346*91f16700Schasinglulu INFO("IN SMC_CONFIG_SHAREDMEM: addr=%lx, length=%lx, tag=%lx\n", 347*91f16700Schasinglulu (unsigned long) ree_base_addr, 348*91f16700Schasinglulu (unsigned long) ree_length, 349*91f16700Schasinglulu (unsigned long) ree_tag); 350*91f16700Schasinglulu 351*91f16700Schasinglulu if ((ree_base_addr % 0x200000) != 0) { 352*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 353*91f16700Schasinglulu } 354*91f16700Schasinglulu 355*91f16700Schasinglulu if ((ree_length % 0x200000) != 0) { 356*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 357*91f16700Schasinglulu } 358*91f16700Schasinglulu 359*91f16700Schasinglulu ree_info = true; 360*91f16700Schasinglulu 361*91f16700Schasinglulu /* Do not Yield */ 362*91f16700Schasinglulu SMC_RET4(handle, 0, 0, 0, 0); 363*91f16700Schasinglulu 364*91f16700Schasinglulu break; 365*91f16700Schasinglulu 366*91f16700Schasinglulu case SMC_GET_SHAREDMEM: 367*91f16700Schasinglulu if (ree_info) { 368*91f16700Schasinglulu x1 = (1U << 16) | ree_tag; 369*91f16700Schasinglulu x2 = ree_base_addr & 0xFFFFFFFF; 370*91f16700Schasinglulu x3 = (ree_base_addr >> 32) & 0xFFFFFFFF; 371*91f16700Schasinglulu x4 = ree_length & 0xFFFFFFFF; 372*91f16700Schasinglulu SMC_RET4(handle, x1, x2, x3, x4); 373*91f16700Schasinglulu } else { 374*91f16700Schasinglulu SMC_RET4(handle, 0, 0, 0, 0); 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu break; 378*91f16700Schasinglulu 379*91f16700Schasinglulu case SMC_ACTION_FROM_NS: 380*91f16700Schasinglulu if (ns == 0) { 381*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 382*91f16700Schasinglulu } 383*91f16700Schasinglulu 384*91f16700Schasinglulu if (SPD_PNCD_S_IRQ < MIN_PPI_ID) { 385*91f16700Schasinglulu plat_ic_raise_s_el1_sgi(SPD_PNCD_S_IRQ, 386*91f16700Schasinglulu pncd_sp_context.mpidr); 387*91f16700Schasinglulu } else { 388*91f16700Schasinglulu plat_ic_set_interrupt_pending(SPD_PNCD_S_IRQ); 389*91f16700Schasinglulu } 390*91f16700Schasinglulu 391*91f16700Schasinglulu SMC_RET0(handle); 392*91f16700Schasinglulu 393*91f16700Schasinglulu break; 394*91f16700Schasinglulu 395*91f16700Schasinglulu case SMC_ACTION_FROM_S: 396*91f16700Schasinglulu if (ns != 0) { 397*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 398*91f16700Schasinglulu } 399*91f16700Schasinglulu 400*91f16700Schasinglulu if (SPD_PNCD_NS_IRQ < MIN_PPI_ID) { 401*91f16700Schasinglulu /* 402*91f16700Schasinglulu * NS SGI is sent to the same core as the one running 403*91f16700Schasinglulu * PNC 404*91f16700Schasinglulu */ 405*91f16700Schasinglulu plat_ic_raise_ns_sgi(SPD_PNCD_NS_IRQ, read_mpidr()); 406*91f16700Schasinglulu } else { 407*91f16700Schasinglulu plat_ic_set_interrupt_pending(SPD_PNCD_NS_IRQ); 408*91f16700Schasinglulu } 409*91f16700Schasinglulu 410*91f16700Schasinglulu SMC_RET0(handle); 411*91f16700Schasinglulu 412*91f16700Schasinglulu break; 413*91f16700Schasinglulu 414*91f16700Schasinglulu case SMC_YIELD: 415*91f16700Schasinglulu assert(handle == cm_get_context(ns != 0 ? NON_SECURE : SECURE)); 416*91f16700Schasinglulu handle = pncd_context_switch_to(ns != 0 ? SECURE : NON_SECURE); 417*91f16700Schasinglulu 418*91f16700Schasinglulu assert(handle != NULL); 419*91f16700Schasinglulu 420*91f16700Schasinglulu SMC_RET0(handle); 421*91f16700Schasinglulu 422*91f16700Schasinglulu break; 423*91f16700Schasinglulu 424*91f16700Schasinglulu default: 425*91f16700Schasinglulu INFO("Unknown smc: %x\n", smc_fid); 426*91f16700Schasinglulu break; 427*91f16700Schasinglulu } 428*91f16700Schasinglulu 429*91f16700Schasinglulu return plat_pncd_smc_handler(smc_fid, x1, x2, x3, x4, 430*91f16700Schasinglulu cookie, handle, flags); 431*91f16700Schasinglulu } 432*91f16700Schasinglulu 433*91f16700Schasinglulu static uintptr_t pncd_smc_handler(uint32_t smc_fid, 434*91f16700Schasinglulu u_register_t x1, 435*91f16700Schasinglulu u_register_t x2, 436*91f16700Schasinglulu u_register_t x3, 437*91f16700Schasinglulu u_register_t x4, 438*91f16700Schasinglulu void *cookie, 439*91f16700Schasinglulu void *handle, 440*91f16700Schasinglulu u_register_t flags) 441*91f16700Schasinglulu { 442*91f16700Schasinglulu uintptr_t ret; 443*91f16700Schasinglulu 444*91f16700Schasinglulu /* SMC handling is serialized */ 445*91f16700Schasinglulu spin_lock(&smc_handler_lock); 446*91f16700Schasinglulu ret = pncd_smc_handler_unsafe(smc_fid, x1, x2, x3, x4, cookie, handle, 447*91f16700Schasinglulu flags); 448*91f16700Schasinglulu spin_unlock(&smc_handler_lock); 449*91f16700Schasinglulu 450*91f16700Schasinglulu return ret; 451*91f16700Schasinglulu } 452*91f16700Schasinglulu 453*91f16700Schasinglulu /* Define a SPD runtime service descriptor for fast SMC calls */ 454*91f16700Schasinglulu DECLARE_RT_SVC( 455*91f16700Schasinglulu pncd_fast, 456*91f16700Schasinglulu OEN_TOS_START, 457*91f16700Schasinglulu OEN_TOS_END, 458*91f16700Schasinglulu SMC_TYPE_FAST, 459*91f16700Schasinglulu pncd_setup, 460*91f16700Schasinglulu pncd_smc_handler 461*91f16700Schasinglulu ); 462*91f16700Schasinglulu 463*91f16700Schasinglulu /* Define a SPD runtime service descriptor for standard SMC calls */ 464*91f16700Schasinglulu DECLARE_RT_SVC( 465*91f16700Schasinglulu pncd_std, 466*91f16700Schasinglulu OEN_TOS_START, 467*91f16700Schasinglulu OEN_TOS_END, 468*91f16700Schasinglulu SMC_TYPE_YIELD, 469*91f16700Schasinglulu NULL, 470*91f16700Schasinglulu pncd_smc_handler 471*91f16700Schasinglulu ); 472