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