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
context_save(unsigned long security_state)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
context_restore(unsigned long security_state)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 ******************************************************************************/
pncd_context_switch_to(unsigned long security_state)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 ******************************************************************************/
pncd_sel1_interrupt_handler(uint32_t id,uint32_t flags,void * handle,void * cookie)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
plat_pncd_setup(void)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 ******************************************************************************/
pncd_setup(void)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 ******************************************************************************/
pncd_init(void)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 ******************************************************************************/
plat_pncd_smc_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void * cookie,void * handle,u_register_t flags)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 ******************************************************************************/
pncd_smc_handler_unsafe(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void * cookie,void * handle,u_register_t flags)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
pncd_smc_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void * cookie,void * handle,u_register_t flags)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