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