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