xref: /rk3399_ARM-atf/services/spd/pncd/pncd_main.c (revision 4b6e4e618e141a4ba7eef6f4bfd0fc6455dc2cba)
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