xref: /arm-trusted-firmware/services/spd/opteed/opteed_main.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu 
8*91f16700Schasinglulu /*******************************************************************************
9*91f16700Schasinglulu  * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a
10*91f16700Schasinglulu  * plug-in component to the Secure Monitor, registered as a runtime service. The
11*91f16700Schasinglulu  * SPD is expected to be a functional extension of the Secure Payload (SP) that
12*91f16700Schasinglulu  * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting
13*91f16700Schasinglulu  * the Trusted OS/Applications range to the dispatcher. The SPD will either
14*91f16700Schasinglulu  * handle the request locally or delegate it to the Secure Payload. It is also
15*91f16700Schasinglulu  * responsible for initialising and maintaining communication with the SP.
16*91f16700Schasinglulu  ******************************************************************************/
17*91f16700Schasinglulu #include <assert.h>
18*91f16700Schasinglulu #include <errno.h>
19*91f16700Schasinglulu #include <inttypes.h>
20*91f16700Schasinglulu #include <stddef.h>
21*91f16700Schasinglulu 
22*91f16700Schasinglulu #include <arch_helpers.h>
23*91f16700Schasinglulu #include <bl31/bl31.h>
24*91f16700Schasinglulu #include <common/bl_common.h>
25*91f16700Schasinglulu #include <common/debug.h>
26*91f16700Schasinglulu #include <common/runtime_svc.h>
27*91f16700Schasinglulu #include <lib/coreboot.h>
28*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h>
29*91f16700Schasinglulu #include <lib/optee_utils.h>
30*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h>
31*91f16700Schasinglulu #if OPTEE_ALLOW_SMC_LOAD
32*91f16700Schasinglulu #include <libfdt.h>
33*91f16700Schasinglulu #endif  /* OPTEE_ALLOW_SMC_LOAD */
34*91f16700Schasinglulu #include <plat/common/platform.h>
35*91f16700Schasinglulu #include <tools_share/uuid.h>
36*91f16700Schasinglulu 
37*91f16700Schasinglulu #include "opteed_private.h"
38*91f16700Schasinglulu #include "teesmc_opteed.h"
39*91f16700Schasinglulu 
40*91f16700Schasinglulu /*******************************************************************************
41*91f16700Schasinglulu  * Address of the entrypoint vector table in OPTEE. It is
42*91f16700Schasinglulu  * initialised once on the primary core after a cold boot.
43*91f16700Schasinglulu  ******************************************************************************/
44*91f16700Schasinglulu struct optee_vectors *optee_vector_table;
45*91f16700Schasinglulu 
46*91f16700Schasinglulu /*******************************************************************************
47*91f16700Schasinglulu  * Array to keep track of per-cpu OPTEE state
48*91f16700Schasinglulu  ******************************************************************************/
49*91f16700Schasinglulu optee_context_t opteed_sp_context[OPTEED_CORE_COUNT];
50*91f16700Schasinglulu uint32_t opteed_rw;
51*91f16700Schasinglulu 
52*91f16700Schasinglulu #if OPTEE_ALLOW_SMC_LOAD
53*91f16700Schasinglulu static bool opteed_allow_load;
54*91f16700Schasinglulu /* OP-TEE image loading service UUID */
55*91f16700Schasinglulu DEFINE_SVC_UUID2(optee_image_load_uuid,
56*91f16700Schasinglulu 	0xb1eafba3, 0x5d31, 0x4612, 0xb9, 0x06,
57*91f16700Schasinglulu 	0xc4, 0xc7, 0xa4, 0xbe, 0x3c, 0xc0);
58*91f16700Schasinglulu 
59*91f16700Schasinglulu #define OPTEED_FDT_SIZE 256
60*91f16700Schasinglulu static uint8_t fdt_buf[OPTEED_FDT_SIZE] __aligned(CACHE_WRITEBACK_GRANULE);
61*91f16700Schasinglulu 
62*91f16700Schasinglulu #else
63*91f16700Schasinglulu static int32_t opteed_init(void);
64*91f16700Schasinglulu #endif
65*91f16700Schasinglulu 
66*91f16700Schasinglulu uint64_t dual32to64(uint32_t high, uint32_t low)
67*91f16700Schasinglulu {
68*91f16700Schasinglulu 	return ((uint64_t)high << 32) | low;
69*91f16700Schasinglulu }
70*91f16700Schasinglulu 
71*91f16700Schasinglulu /*******************************************************************************
72*91f16700Schasinglulu  * This function is the handler registered for S-EL1 interrupts by the
73*91f16700Schasinglulu  * OPTEED. It validates the interrupt and upon success arranges entry into
74*91f16700Schasinglulu  * the OPTEE at 'optee_fiq_entry()' for handling the interrupt.
75*91f16700Schasinglulu  ******************************************************************************/
76*91f16700Schasinglulu static __attribute__((__unused__))
77*91f16700Schasinglulu uint64_t opteed_sel1_interrupt_handler(uint32_t id,
78*91f16700Schasinglulu 					    uint32_t flags,
79*91f16700Schasinglulu 					    void *handle,
80*91f16700Schasinglulu 					    void *cookie)
81*91f16700Schasinglulu {
82*91f16700Schasinglulu 	uint32_t linear_id;
83*91f16700Schasinglulu 	optee_context_t *optee_ctx;
84*91f16700Schasinglulu 
85*91f16700Schasinglulu 	/* Check the security state when the exception was generated */
86*91f16700Schasinglulu 	assert(get_interrupt_src_ss(flags) == NON_SECURE);
87*91f16700Schasinglulu 
88*91f16700Schasinglulu 	/* Sanity check the pointer to this cpu's context */
89*91f16700Schasinglulu 	assert(handle == cm_get_context(NON_SECURE));
90*91f16700Schasinglulu 
91*91f16700Schasinglulu 	/* Save the non-secure context before entering the OPTEE */
92*91f16700Schasinglulu 	cm_el1_sysregs_context_save(NON_SECURE);
93*91f16700Schasinglulu 
94*91f16700Schasinglulu 	/* Get a reference to this cpu's OPTEE context */
95*91f16700Schasinglulu 	linear_id = plat_my_core_pos();
96*91f16700Schasinglulu 	optee_ctx = &opteed_sp_context[linear_id];
97*91f16700Schasinglulu 	assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE));
98*91f16700Schasinglulu 
99*91f16700Schasinglulu 	cm_set_elr_el3(SECURE, (uint64_t)&optee_vector_table->fiq_entry);
100*91f16700Schasinglulu 	cm_el1_sysregs_context_restore(SECURE);
101*91f16700Schasinglulu 	cm_set_next_eret_context(SECURE);
102*91f16700Schasinglulu 
103*91f16700Schasinglulu 	/*
104*91f16700Schasinglulu 	 * Tell the OPTEE that it has to handle an FIQ (synchronously).
105*91f16700Schasinglulu 	 * Also the instruction in normal world where the interrupt was
106*91f16700Schasinglulu 	 * generated is passed for debugging purposes. It is safe to
107*91f16700Schasinglulu 	 * retrieve this address from ELR_EL3 as the secure context will
108*91f16700Schasinglulu 	 * not take effect until el3_exit().
109*91f16700Schasinglulu 	 */
110*91f16700Schasinglulu 	SMC_RET1(&optee_ctx->cpu_ctx, read_elr_el3());
111*91f16700Schasinglulu }
112*91f16700Schasinglulu 
113*91f16700Schasinglulu /*******************************************************************************
114*91f16700Schasinglulu  * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type
115*91f16700Schasinglulu  * (aarch32/aarch64) if not already known and initialises the context for entry
116*91f16700Schasinglulu  * into OPTEE for its initialization.
117*91f16700Schasinglulu  ******************************************************************************/
118*91f16700Schasinglulu static int32_t opteed_setup(void)
119*91f16700Schasinglulu {
120*91f16700Schasinglulu #if OPTEE_ALLOW_SMC_LOAD
121*91f16700Schasinglulu 	opteed_allow_load = true;
122*91f16700Schasinglulu 	INFO("Delaying OP-TEE setup until we receive an SMC call to load it\n");
123*91f16700Schasinglulu 	return 0;
124*91f16700Schasinglulu #else
125*91f16700Schasinglulu 	entry_point_info_t *optee_ep_info;
126*91f16700Schasinglulu 	uint32_t linear_id;
127*91f16700Schasinglulu 	uint64_t opteed_pageable_part;
128*91f16700Schasinglulu 	uint64_t opteed_mem_limit;
129*91f16700Schasinglulu 	uint64_t dt_addr;
130*91f16700Schasinglulu 
131*91f16700Schasinglulu 	linear_id = plat_my_core_pos();
132*91f16700Schasinglulu 
133*91f16700Schasinglulu 	/*
134*91f16700Schasinglulu 	 * Get information about the Secure Payload (BL32) image. Its
135*91f16700Schasinglulu 	 * absence is a critical failure.  TODO: Add support to
136*91f16700Schasinglulu 	 * conditionally include the SPD service
137*91f16700Schasinglulu 	 */
138*91f16700Schasinglulu 	optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
139*91f16700Schasinglulu 	if (!optee_ep_info) {
140*91f16700Schasinglulu 		WARN("No OPTEE provided by BL2 boot loader, Booting device"
141*91f16700Schasinglulu 			" without OPTEE initialization. SMC`s destined for OPTEE"
142*91f16700Schasinglulu 			" will return SMC_UNK\n");
143*91f16700Schasinglulu 		return 1;
144*91f16700Schasinglulu 	}
145*91f16700Schasinglulu 
146*91f16700Schasinglulu 	/*
147*91f16700Schasinglulu 	 * If there's no valid entry point for SP, we return a non-zero value
148*91f16700Schasinglulu 	 * signalling failure initializing the service. We bail out without
149*91f16700Schasinglulu 	 * registering any handlers
150*91f16700Schasinglulu 	 */
151*91f16700Schasinglulu 	if (!optee_ep_info->pc)
152*91f16700Schasinglulu 		return 1;
153*91f16700Schasinglulu 
154*91f16700Schasinglulu 	opteed_rw = optee_ep_info->args.arg0;
155*91f16700Schasinglulu 	opteed_pageable_part = optee_ep_info->args.arg1;
156*91f16700Schasinglulu 	opteed_mem_limit = optee_ep_info->args.arg2;
157*91f16700Schasinglulu 	dt_addr = optee_ep_info->args.arg3;
158*91f16700Schasinglulu 
159*91f16700Schasinglulu 	opteed_init_optee_ep_state(optee_ep_info,
160*91f16700Schasinglulu 				opteed_rw,
161*91f16700Schasinglulu 				optee_ep_info->pc,
162*91f16700Schasinglulu 				opteed_pageable_part,
163*91f16700Schasinglulu 				opteed_mem_limit,
164*91f16700Schasinglulu 				dt_addr,
165*91f16700Schasinglulu 				&opteed_sp_context[linear_id]);
166*91f16700Schasinglulu 
167*91f16700Schasinglulu 	/*
168*91f16700Schasinglulu 	 * All OPTEED initialization done. Now register our init function with
169*91f16700Schasinglulu 	 * BL31 for deferred invocation
170*91f16700Schasinglulu 	 */
171*91f16700Schasinglulu 	bl31_register_bl32_init(&opteed_init);
172*91f16700Schasinglulu 
173*91f16700Schasinglulu 	return 0;
174*91f16700Schasinglulu #endif  /* OPTEE_ALLOW_SMC_LOAD */
175*91f16700Schasinglulu }
176*91f16700Schasinglulu 
177*91f16700Schasinglulu /*******************************************************************************
178*91f16700Schasinglulu  * This function passes control to the OPTEE image (BL32) for the first time
179*91f16700Schasinglulu  * on the primary cpu after a cold boot. It assumes that a valid secure
180*91f16700Schasinglulu  * context has already been created by opteed_setup() which can be directly
181*91f16700Schasinglulu  * used.  It also assumes that a valid non-secure context has been
182*91f16700Schasinglulu  * initialised by PSCI so it does not need to save and restore any
183*91f16700Schasinglulu  * non-secure state. This function performs a synchronous entry into
184*91f16700Schasinglulu  * OPTEE. OPTEE passes control back to this routine through a SMC. This returns
185*91f16700Schasinglulu  * a non-zero value on success and zero on failure.
186*91f16700Schasinglulu  ******************************************************************************/
187*91f16700Schasinglulu static int32_t
188*91f16700Schasinglulu opteed_init_with_entry_point(entry_point_info_t *optee_entry_point)
189*91f16700Schasinglulu {
190*91f16700Schasinglulu 	uint32_t linear_id = plat_my_core_pos();
191*91f16700Schasinglulu 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
192*91f16700Schasinglulu 	uint64_t rc;
193*91f16700Schasinglulu 	assert(optee_entry_point);
194*91f16700Schasinglulu 
195*91f16700Schasinglulu 	cm_init_my_context(optee_entry_point);
196*91f16700Schasinglulu 
197*91f16700Schasinglulu 	/*
198*91f16700Schasinglulu 	 * Arrange for an entry into OPTEE. It will be returned via
199*91f16700Schasinglulu 	 * OPTEE_ENTRY_DONE case
200*91f16700Schasinglulu 	 */
201*91f16700Schasinglulu 	rc = opteed_synchronous_sp_entry(optee_ctx);
202*91f16700Schasinglulu 	assert(rc != 0);
203*91f16700Schasinglulu 
204*91f16700Schasinglulu 	return rc;
205*91f16700Schasinglulu }
206*91f16700Schasinglulu 
207*91f16700Schasinglulu #if !OPTEE_ALLOW_SMC_LOAD
208*91f16700Schasinglulu static int32_t opteed_init(void)
209*91f16700Schasinglulu {
210*91f16700Schasinglulu 	entry_point_info_t *optee_entry_point;
211*91f16700Schasinglulu 	/*
212*91f16700Schasinglulu 	 * Get information about the OP-TEE (BL32) image. Its
213*91f16700Schasinglulu 	 * absence is a critical failure.
214*91f16700Schasinglulu 	 */
215*91f16700Schasinglulu 	optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
216*91f16700Schasinglulu 	return opteed_init_with_entry_point(optee_entry_point);
217*91f16700Schasinglulu }
218*91f16700Schasinglulu #endif  /* !OPTEE_ALLOW_SMC_LOAD */
219*91f16700Schasinglulu 
220*91f16700Schasinglulu #if OPTEE_ALLOW_SMC_LOAD
221*91f16700Schasinglulu #if COREBOOT
222*91f16700Schasinglulu /*
223*91f16700Schasinglulu  * Adds a firmware/coreboot node with the coreboot table information to a device
224*91f16700Schasinglulu  * tree. Returns zero on success or if there is no coreboot table information;
225*91f16700Schasinglulu  * failure code otherwise.
226*91f16700Schasinglulu  */
227*91f16700Schasinglulu static int add_coreboot_node(void *fdt)
228*91f16700Schasinglulu {
229*91f16700Schasinglulu 	int ret;
230*91f16700Schasinglulu 	uint64_t coreboot_table_addr;
231*91f16700Schasinglulu 	uint32_t coreboot_table_size;
232*91f16700Schasinglulu 	struct {
233*91f16700Schasinglulu 		uint64_t addr;
234*91f16700Schasinglulu 		uint32_t size;
235*91f16700Schasinglulu 	} reg_node;
236*91f16700Schasinglulu 	coreboot_get_table_location(&coreboot_table_addr, &coreboot_table_size);
237*91f16700Schasinglulu 	if (!coreboot_table_addr || !coreboot_table_size) {
238*91f16700Schasinglulu 		WARN("Unable to get coreboot table location for device tree");
239*91f16700Schasinglulu 		return 0;
240*91f16700Schasinglulu 	}
241*91f16700Schasinglulu 	ret = fdt_begin_node(fdt, "firmware");
242*91f16700Schasinglulu 	if (ret)
243*91f16700Schasinglulu 		return ret;
244*91f16700Schasinglulu 
245*91f16700Schasinglulu 	ret = fdt_property(fdt, "ranges", NULL, 0);
246*91f16700Schasinglulu 	if (ret)
247*91f16700Schasinglulu 		return ret;
248*91f16700Schasinglulu 
249*91f16700Schasinglulu 	ret = fdt_begin_node(fdt, "coreboot");
250*91f16700Schasinglulu 	if (ret)
251*91f16700Schasinglulu 		return ret;
252*91f16700Schasinglulu 
253*91f16700Schasinglulu 	ret = fdt_property_string(fdt, "compatible", "coreboot");
254*91f16700Schasinglulu 	if (ret)
255*91f16700Schasinglulu 		return ret;
256*91f16700Schasinglulu 
257*91f16700Schasinglulu 	reg_node.addr = cpu_to_fdt64(coreboot_table_addr);
258*91f16700Schasinglulu 	reg_node.size = cpu_to_fdt32(coreboot_table_size);
259*91f16700Schasinglulu 	ret = fdt_property(fdt, "reg", &reg_node,
260*91f16700Schasinglulu 				sizeof(uint64_t) + sizeof(uint32_t));
261*91f16700Schasinglulu 	if (ret)
262*91f16700Schasinglulu 		return ret;
263*91f16700Schasinglulu 
264*91f16700Schasinglulu 	ret = fdt_end_node(fdt);
265*91f16700Schasinglulu 	if (ret)
266*91f16700Schasinglulu 		return ret;
267*91f16700Schasinglulu 
268*91f16700Schasinglulu 	return fdt_end_node(fdt);
269*91f16700Schasinglulu }
270*91f16700Schasinglulu #endif /* COREBOOT */
271*91f16700Schasinglulu 
272*91f16700Schasinglulu /*
273*91f16700Schasinglulu  * Creates a device tree for passing into OP-TEE. Currently is populated with
274*91f16700Schasinglulu  * the coreboot table address.
275*91f16700Schasinglulu  * Returns 0 on success, error code otherwise.
276*91f16700Schasinglulu  */
277*91f16700Schasinglulu static int create_opteed_dt(void)
278*91f16700Schasinglulu {
279*91f16700Schasinglulu 	int ret;
280*91f16700Schasinglulu 
281*91f16700Schasinglulu 	ret = fdt_create(fdt_buf, OPTEED_FDT_SIZE);
282*91f16700Schasinglulu 	if (ret)
283*91f16700Schasinglulu 		return ret;
284*91f16700Schasinglulu 
285*91f16700Schasinglulu 	ret = fdt_finish_reservemap(fdt_buf);
286*91f16700Schasinglulu 	if (ret)
287*91f16700Schasinglulu 		return ret;
288*91f16700Schasinglulu 
289*91f16700Schasinglulu 	ret = fdt_begin_node(fdt_buf, "");
290*91f16700Schasinglulu 	if (ret)
291*91f16700Schasinglulu 		return ret;
292*91f16700Schasinglulu 
293*91f16700Schasinglulu #if COREBOOT
294*91f16700Schasinglulu 	ret = add_coreboot_node(fdt_buf);
295*91f16700Schasinglulu 	if (ret)
296*91f16700Schasinglulu 		return ret;
297*91f16700Schasinglulu #endif /* COREBOOT */
298*91f16700Schasinglulu 
299*91f16700Schasinglulu 	ret = fdt_end_node(fdt_buf);
300*91f16700Schasinglulu 	if (ret)
301*91f16700Schasinglulu 		return ret;
302*91f16700Schasinglulu 
303*91f16700Schasinglulu 	return fdt_finish(fdt_buf);
304*91f16700Schasinglulu }
305*91f16700Schasinglulu 
306*91f16700Schasinglulu /*******************************************************************************
307*91f16700Schasinglulu  * This function is responsible for handling the SMC that loads the OP-TEE
308*91f16700Schasinglulu  * binary image via a non-secure SMC call. It takes the size and physical
309*91f16700Schasinglulu  * address of the payload as parameters.
310*91f16700Schasinglulu  ******************************************************************************/
311*91f16700Schasinglulu static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa)
312*91f16700Schasinglulu {
313*91f16700Schasinglulu 	uintptr_t data_va = data_pa;
314*91f16700Schasinglulu 	uint64_t mapped_data_pa;
315*91f16700Schasinglulu 	uintptr_t mapped_data_va;
316*91f16700Schasinglulu 	uint64_t data_map_size;
317*91f16700Schasinglulu 	int32_t rc;
318*91f16700Schasinglulu 	optee_header_t *image_header;
319*91f16700Schasinglulu 	uint8_t *image_ptr;
320*91f16700Schasinglulu 	uint64_t target_pa;
321*91f16700Schasinglulu 	uint64_t target_end_pa;
322*91f16700Schasinglulu 	uint64_t image_pa;
323*91f16700Schasinglulu 	uintptr_t image_va;
324*91f16700Schasinglulu 	optee_image_t *curr_image;
325*91f16700Schasinglulu 	uintptr_t target_va;
326*91f16700Schasinglulu 	uint64_t target_size;
327*91f16700Schasinglulu 	entry_point_info_t optee_ep_info;
328*91f16700Schasinglulu 	uint32_t linear_id = plat_my_core_pos();
329*91f16700Schasinglulu 	uint64_t dt_addr = 0;
330*91f16700Schasinglulu 
331*91f16700Schasinglulu 	mapped_data_pa = page_align(data_pa, DOWN);
332*91f16700Schasinglulu 	mapped_data_va = mapped_data_pa;
333*91f16700Schasinglulu 	data_map_size = page_align(data_size + (mapped_data_pa - data_pa), UP);
334*91f16700Schasinglulu 
335*91f16700Schasinglulu 	/*
336*91f16700Schasinglulu 	 * We do not validate the passed in address because we are trusting the
337*91f16700Schasinglulu 	 * non-secure world at this point still.
338*91f16700Schasinglulu 	 */
339*91f16700Schasinglulu 	rc = mmap_add_dynamic_region(mapped_data_pa, mapped_data_va,
340*91f16700Schasinglulu 				     data_map_size, MT_MEMORY | MT_RO | MT_NS);
341*91f16700Schasinglulu 	if (rc != 0) {
342*91f16700Schasinglulu 		return rc;
343*91f16700Schasinglulu 	}
344*91f16700Schasinglulu 
345*91f16700Schasinglulu 	image_header = (optee_header_t *)data_va;
346*91f16700Schasinglulu 	if (image_header->magic != TEE_MAGIC_NUM_OPTEE ||
347*91f16700Schasinglulu 	    image_header->version != 2 || image_header->nb_images != 1) {
348*91f16700Schasinglulu 		mmap_remove_dynamic_region(mapped_data_va, data_map_size);
349*91f16700Schasinglulu 		return -EINVAL;
350*91f16700Schasinglulu 	}
351*91f16700Schasinglulu 
352*91f16700Schasinglulu 	image_ptr = (uint8_t *)data_va + sizeof(optee_header_t) +
353*91f16700Schasinglulu 			sizeof(optee_image_t);
354*91f16700Schasinglulu 	if (image_header->arch == 1) {
355*91f16700Schasinglulu 		opteed_rw = OPTEE_AARCH64;
356*91f16700Schasinglulu 	} else {
357*91f16700Schasinglulu 		opteed_rw = OPTEE_AARCH32;
358*91f16700Schasinglulu 	}
359*91f16700Schasinglulu 
360*91f16700Schasinglulu 	curr_image = &image_header->optee_image_list[0];
361*91f16700Schasinglulu 	image_pa = dual32to64(curr_image->load_addr_hi,
362*91f16700Schasinglulu 			      curr_image->load_addr_lo);
363*91f16700Schasinglulu 	image_va = image_pa;
364*91f16700Schasinglulu 	target_end_pa = image_pa + curr_image->size;
365*91f16700Schasinglulu 
366*91f16700Schasinglulu 	/* Now also map the memory we want to copy it to. */
367*91f16700Schasinglulu 	target_pa = page_align(image_pa, DOWN);
368*91f16700Schasinglulu 	target_va = target_pa;
369*91f16700Schasinglulu 	target_size = page_align(target_end_pa, UP) - target_pa;
370*91f16700Schasinglulu 
371*91f16700Schasinglulu 	rc = mmap_add_dynamic_region(target_pa, target_va, target_size,
372*91f16700Schasinglulu 				     MT_MEMORY | MT_RW | MT_SECURE);
373*91f16700Schasinglulu 	if (rc != 0) {
374*91f16700Schasinglulu 		mmap_remove_dynamic_region(mapped_data_va, data_map_size);
375*91f16700Schasinglulu 		return rc;
376*91f16700Schasinglulu 	}
377*91f16700Schasinglulu 
378*91f16700Schasinglulu 	INFO("Loaded OP-TEE via SMC: size %d addr 0x%" PRIx64 "\n",
379*91f16700Schasinglulu 	     curr_image->size, image_va);
380*91f16700Schasinglulu 
381*91f16700Schasinglulu 	memcpy((void *)image_va, image_ptr, curr_image->size);
382*91f16700Schasinglulu 	flush_dcache_range(target_pa, target_size);
383*91f16700Schasinglulu 
384*91f16700Schasinglulu 	mmap_remove_dynamic_region(mapped_data_va, data_map_size);
385*91f16700Schasinglulu 	mmap_remove_dynamic_region(target_va, target_size);
386*91f16700Schasinglulu 
387*91f16700Schasinglulu 	/* Save the non-secure state */
388*91f16700Schasinglulu 	cm_el1_sysregs_context_save(NON_SECURE);
389*91f16700Schasinglulu 
390*91f16700Schasinglulu 	rc = create_opteed_dt();
391*91f16700Schasinglulu 	if (rc) {
392*91f16700Schasinglulu 		ERROR("Failed device tree creation %d\n", rc);
393*91f16700Schasinglulu 		return rc;
394*91f16700Schasinglulu 	}
395*91f16700Schasinglulu 	dt_addr = (uint64_t)fdt_buf;
396*91f16700Schasinglulu 	flush_dcache_range(dt_addr, OPTEED_FDT_SIZE);
397*91f16700Schasinglulu 
398*91f16700Schasinglulu 	opteed_init_optee_ep_state(&optee_ep_info,
399*91f16700Schasinglulu 				   opteed_rw,
400*91f16700Schasinglulu 				   image_pa,
401*91f16700Schasinglulu 				   0,
402*91f16700Schasinglulu 				   0,
403*91f16700Schasinglulu 				   dt_addr,
404*91f16700Schasinglulu 				   &opteed_sp_context[linear_id]);
405*91f16700Schasinglulu 	if (opteed_init_with_entry_point(&optee_ep_info) == 0) {
406*91f16700Schasinglulu 		rc = -EFAULT;
407*91f16700Schasinglulu 	}
408*91f16700Schasinglulu 
409*91f16700Schasinglulu 	/* Restore non-secure state */
410*91f16700Schasinglulu 	cm_el1_sysregs_context_restore(NON_SECURE);
411*91f16700Schasinglulu 	cm_set_next_eret_context(NON_SECURE);
412*91f16700Schasinglulu 
413*91f16700Schasinglulu 	return rc;
414*91f16700Schasinglulu }
415*91f16700Schasinglulu #endif  /* OPTEE_ALLOW_SMC_LOAD */
416*91f16700Schasinglulu 
417*91f16700Schasinglulu /*******************************************************************************
418*91f16700Schasinglulu  * This function is responsible for handling all SMCs in the Trusted OS/App
419*91f16700Schasinglulu  * range from the non-secure state as defined in the SMC Calling Convention
420*91f16700Schasinglulu  * Document. It is also responsible for communicating with the Secure
421*91f16700Schasinglulu  * payload to delegate work and return results back to the non-secure
422*91f16700Schasinglulu  * state. Lastly it will also return any information that OPTEE needs to do
423*91f16700Schasinglulu  * the work assigned to it.
424*91f16700Schasinglulu  ******************************************************************************/
425*91f16700Schasinglulu static uintptr_t opteed_smc_handler(uint32_t smc_fid,
426*91f16700Schasinglulu 			 u_register_t x1,
427*91f16700Schasinglulu 			 u_register_t x2,
428*91f16700Schasinglulu 			 u_register_t x3,
429*91f16700Schasinglulu 			 u_register_t x4,
430*91f16700Schasinglulu 			 void *cookie,
431*91f16700Schasinglulu 			 void *handle,
432*91f16700Schasinglulu 			 u_register_t flags)
433*91f16700Schasinglulu {
434*91f16700Schasinglulu 	cpu_context_t *ns_cpu_context;
435*91f16700Schasinglulu 	uint32_t linear_id = plat_my_core_pos();
436*91f16700Schasinglulu 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
437*91f16700Schasinglulu 	uint64_t __attribute__((__unused__)) rc;
438*91f16700Schasinglulu 
439*91f16700Schasinglulu 	/*
440*91f16700Schasinglulu 	 * Determine which security state this SMC originated from
441*91f16700Schasinglulu 	 */
442*91f16700Schasinglulu 
443*91f16700Schasinglulu 	if (is_caller_non_secure(flags)) {
444*91f16700Schasinglulu #if OPTEE_ALLOW_SMC_LOAD
445*91f16700Schasinglulu 		if (opteed_allow_load && smc_fid == NSSMC_OPTEED_CALL_UID) {
446*91f16700Schasinglulu 			/* Provide the UUID of the image loading service. */
447*91f16700Schasinglulu 			SMC_UUID_RET(handle, optee_image_load_uuid);
448*91f16700Schasinglulu 		}
449*91f16700Schasinglulu 		if (smc_fid == NSSMC_OPTEED_CALL_LOAD_IMAGE) {
450*91f16700Schasinglulu 			/*
451*91f16700Schasinglulu 			 * TODO: Consider wiping the code for SMC loading from
452*91f16700Schasinglulu 			 * memory after it has been invoked similar to what is
453*91f16700Schasinglulu 			 * done under RECLAIM_INIT, but extended to happen
454*91f16700Schasinglulu 			 * later.
455*91f16700Schasinglulu 			 */
456*91f16700Schasinglulu 			if (!opteed_allow_load) {
457*91f16700Schasinglulu 				SMC_RET1(handle, -EPERM);
458*91f16700Schasinglulu 			}
459*91f16700Schasinglulu 
460*91f16700Schasinglulu 			opteed_allow_load = false;
461*91f16700Schasinglulu 			uint64_t data_size = dual32to64(x1, x2);
462*91f16700Schasinglulu 			uint64_t data_pa = dual32to64(x3, x4);
463*91f16700Schasinglulu 			if (!data_size || !data_pa) {
464*91f16700Schasinglulu 				/*
465*91f16700Schasinglulu 				 * This is invoked when the OP-TEE image didn't
466*91f16700Schasinglulu 				 * load correctly in the kernel but we want to
467*91f16700Schasinglulu 				 * block off loading of it later for security
468*91f16700Schasinglulu 				 * reasons.
469*91f16700Schasinglulu 				 */
470*91f16700Schasinglulu 				SMC_RET1(handle, -EINVAL);
471*91f16700Schasinglulu 			}
472*91f16700Schasinglulu 			SMC_RET1(handle, opteed_handle_smc_load(
473*91f16700Schasinglulu 					data_size, data_pa));
474*91f16700Schasinglulu 		}
475*91f16700Schasinglulu #endif  /* OPTEE_ALLOW_SMC_LOAD */
476*91f16700Schasinglulu 		/*
477*91f16700Schasinglulu 		 * This is a fresh request from the non-secure client.
478*91f16700Schasinglulu 		 * The parameters are in x1 and x2. Figure out which
479*91f16700Schasinglulu 		 * registers need to be preserved, save the non-secure
480*91f16700Schasinglulu 		 * state and send the request to the secure payload.
481*91f16700Schasinglulu 		 */
482*91f16700Schasinglulu 		assert(handle == cm_get_context(NON_SECURE));
483*91f16700Schasinglulu 
484*91f16700Schasinglulu 		cm_el1_sysregs_context_save(NON_SECURE);
485*91f16700Schasinglulu 
486*91f16700Schasinglulu 		/*
487*91f16700Schasinglulu 		 * We are done stashing the non-secure context. Ask the
488*91f16700Schasinglulu 		 * OP-TEE to do the work now. If we are loading vi an SMC,
489*91f16700Schasinglulu 		 * then we also need to init this CPU context if not done
490*91f16700Schasinglulu 		 * already.
491*91f16700Schasinglulu 		 */
492*91f16700Schasinglulu 		if (optee_vector_table == NULL) {
493*91f16700Schasinglulu 			SMC_RET1(handle, -EINVAL);
494*91f16700Schasinglulu 		}
495*91f16700Schasinglulu 
496*91f16700Schasinglulu 		if (get_optee_pstate(optee_ctx->state) ==
497*91f16700Schasinglulu 		    OPTEE_PSTATE_UNKNOWN) {
498*91f16700Schasinglulu 			opteed_cpu_on_finish_handler(0);
499*91f16700Schasinglulu 		}
500*91f16700Schasinglulu 
501*91f16700Schasinglulu 		/*
502*91f16700Schasinglulu 		 * Verify if there is a valid context to use, copy the
503*91f16700Schasinglulu 		 * operation type and parameters to the secure context
504*91f16700Schasinglulu 		 * and jump to the fast smc entry point in the secure
505*91f16700Schasinglulu 		 * payload. Entry into S-EL1 will take place upon exit
506*91f16700Schasinglulu 		 * from this function.
507*91f16700Schasinglulu 		 */
508*91f16700Schasinglulu 		assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE));
509*91f16700Schasinglulu 
510*91f16700Schasinglulu 		/* Set appropriate entry for SMC.
511*91f16700Schasinglulu 		 * We expect OPTEE to manage the PSTATE.I and PSTATE.F
512*91f16700Schasinglulu 		 * flags as appropriate.
513*91f16700Schasinglulu 		 */
514*91f16700Schasinglulu 		if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) {
515*91f16700Schasinglulu 			cm_set_elr_el3(SECURE, (uint64_t)
516*91f16700Schasinglulu 					&optee_vector_table->fast_smc_entry);
517*91f16700Schasinglulu 		} else {
518*91f16700Schasinglulu 			cm_set_elr_el3(SECURE, (uint64_t)
519*91f16700Schasinglulu 					&optee_vector_table->yield_smc_entry);
520*91f16700Schasinglulu 		}
521*91f16700Schasinglulu 
522*91f16700Schasinglulu 		cm_el1_sysregs_context_restore(SECURE);
523*91f16700Schasinglulu 		cm_set_next_eret_context(SECURE);
524*91f16700Schasinglulu 
525*91f16700Schasinglulu 		write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
526*91f16700Schasinglulu 			      CTX_GPREG_X4,
527*91f16700Schasinglulu 			      read_ctx_reg(get_gpregs_ctx(handle),
528*91f16700Schasinglulu 					   CTX_GPREG_X4));
529*91f16700Schasinglulu 		write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
530*91f16700Schasinglulu 			      CTX_GPREG_X5,
531*91f16700Schasinglulu 			      read_ctx_reg(get_gpregs_ctx(handle),
532*91f16700Schasinglulu 					   CTX_GPREG_X5));
533*91f16700Schasinglulu 		write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
534*91f16700Schasinglulu 			      CTX_GPREG_X6,
535*91f16700Schasinglulu 			      read_ctx_reg(get_gpregs_ctx(handle),
536*91f16700Schasinglulu 					   CTX_GPREG_X6));
537*91f16700Schasinglulu 		/* Propagate hypervisor client ID */
538*91f16700Schasinglulu 		write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
539*91f16700Schasinglulu 			      CTX_GPREG_X7,
540*91f16700Schasinglulu 			      read_ctx_reg(get_gpregs_ctx(handle),
541*91f16700Schasinglulu 					   CTX_GPREG_X7));
542*91f16700Schasinglulu 
543*91f16700Schasinglulu 		SMC_RET4(&optee_ctx->cpu_ctx, smc_fid, x1, x2, x3);
544*91f16700Schasinglulu 	}
545*91f16700Schasinglulu 
546*91f16700Schasinglulu 	/*
547*91f16700Schasinglulu 	 * Returning from OPTEE
548*91f16700Schasinglulu 	 */
549*91f16700Schasinglulu 
550*91f16700Schasinglulu 	switch (smc_fid) {
551*91f16700Schasinglulu 	/*
552*91f16700Schasinglulu 	 * OPTEE has finished initialising itself after a cold boot
553*91f16700Schasinglulu 	 */
554*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_ENTRY_DONE:
555*91f16700Schasinglulu 		/*
556*91f16700Schasinglulu 		 * Stash the OPTEE entry points information. This is done
557*91f16700Schasinglulu 		 * only once on the primary cpu
558*91f16700Schasinglulu 		 */
559*91f16700Schasinglulu 		assert(optee_vector_table == NULL);
560*91f16700Schasinglulu 		optee_vector_table = (optee_vectors_t *) x1;
561*91f16700Schasinglulu 
562*91f16700Schasinglulu 		if (optee_vector_table) {
563*91f16700Schasinglulu 			set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
564*91f16700Schasinglulu 
565*91f16700Schasinglulu 			/*
566*91f16700Schasinglulu 			 * OPTEE has been successfully initialized.
567*91f16700Schasinglulu 			 * Register power management hooks with PSCI
568*91f16700Schasinglulu 			 */
569*91f16700Schasinglulu 			psci_register_spd_pm_hook(&opteed_pm);
570*91f16700Schasinglulu 
571*91f16700Schasinglulu 			/* On GICv2 systems, it's required that the build option
572*91f16700Schasinglulu 			 * GICV2_G0_FOR_EL3 is set to 1 so that Group 0 interrupts
573*91f16700Schasinglulu 			 * target EL3.
574*91f16700Schasinglulu 			 * This option determines which type Group0 interrupts maps to,
575*91f16700Schasinglulu 			 * (INTR_TYPE_S_EL1 or INTR_TYPE_EL3)
576*91f16700Schasinglulu 			 */
577*91f16700Schasinglulu #if (GICV2_G0_FOR_EL3 == 0)
578*91f16700Schasinglulu 			/*
579*91f16700Schasinglulu 			 * Register an interrupt handler for S-EL1 interrupts
580*91f16700Schasinglulu 			 * when generated during code executing in the
581*91f16700Schasinglulu 			 * non-secure state.
582*91f16700Schasinglulu 			 */
583*91f16700Schasinglulu 			flags = 0;
584*91f16700Schasinglulu 			set_interrupt_rm_flag(flags, NON_SECURE);
585*91f16700Schasinglulu 			rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
586*91f16700Schasinglulu 						opteed_sel1_interrupt_handler,
587*91f16700Schasinglulu 						flags);
588*91f16700Schasinglulu 			if (rc)
589*91f16700Schasinglulu 				panic();
590*91f16700Schasinglulu #endif
591*91f16700Schasinglulu 		}
592*91f16700Schasinglulu 
593*91f16700Schasinglulu 		/*
594*91f16700Schasinglulu 		 * OPTEE reports completion. The OPTEED must have initiated
595*91f16700Schasinglulu 		 * the original request through a synchronous entry into
596*91f16700Schasinglulu 		 * OPTEE. Jump back to the original C runtime context.
597*91f16700Schasinglulu 		 */
598*91f16700Schasinglulu 		opteed_synchronous_sp_exit(optee_ctx, x1);
599*91f16700Schasinglulu 		break;
600*91f16700Schasinglulu 
601*91f16700Schasinglulu 
602*91f16700Schasinglulu 	/*
603*91f16700Schasinglulu 	 * These function IDs is used only by OP-TEE to indicate it has
604*91f16700Schasinglulu 	 * finished:
605*91f16700Schasinglulu 	 * 1. turning itself on in response to an earlier psci
606*91f16700Schasinglulu 	 *    cpu_on request
607*91f16700Schasinglulu 	 * 2. resuming itself after an earlier psci cpu_suspend
608*91f16700Schasinglulu 	 *    request.
609*91f16700Schasinglulu 	 */
610*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_ON_DONE:
611*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_RESUME_DONE:
612*91f16700Schasinglulu 
613*91f16700Schasinglulu 
614*91f16700Schasinglulu 	/*
615*91f16700Schasinglulu 	 * These function IDs is used only by the SP to indicate it has
616*91f16700Schasinglulu 	 * finished:
617*91f16700Schasinglulu 	 * 1. suspending itself after an earlier psci cpu_suspend
618*91f16700Schasinglulu 	 *    request.
619*91f16700Schasinglulu 	 * 2. turning itself off in response to an earlier psci
620*91f16700Schasinglulu 	 *    cpu_off request.
621*91f16700Schasinglulu 	 */
622*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_OFF_DONE:
623*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_SUSPEND_DONE:
624*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE:
625*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE:
626*91f16700Schasinglulu 
627*91f16700Schasinglulu 		/*
628*91f16700Schasinglulu 		 * OPTEE reports completion. The OPTEED must have initiated the
629*91f16700Schasinglulu 		 * original request through a synchronous entry into OPTEE.
630*91f16700Schasinglulu 		 * Jump back to the original C runtime context, and pass x1 as
631*91f16700Schasinglulu 		 * return value to the caller
632*91f16700Schasinglulu 		 */
633*91f16700Schasinglulu 		opteed_synchronous_sp_exit(optee_ctx, x1);
634*91f16700Schasinglulu 		break;
635*91f16700Schasinglulu 
636*91f16700Schasinglulu 	/*
637*91f16700Schasinglulu 	 * OPTEE is returning from a call or being preempted from a call, in
638*91f16700Schasinglulu 	 * either case execution should resume in the normal world.
639*91f16700Schasinglulu 	 */
640*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_CALL_DONE:
641*91f16700Schasinglulu 		/*
642*91f16700Schasinglulu 		 * This is the result from the secure client of an
643*91f16700Schasinglulu 		 * earlier request. The results are in x0-x3. Copy it
644*91f16700Schasinglulu 		 * into the non-secure context, save the secure state
645*91f16700Schasinglulu 		 * and return to the non-secure state.
646*91f16700Schasinglulu 		 */
647*91f16700Schasinglulu 		assert(handle == cm_get_context(SECURE));
648*91f16700Schasinglulu 		cm_el1_sysregs_context_save(SECURE);
649*91f16700Schasinglulu 
650*91f16700Schasinglulu 		/* Get a reference to the non-secure context */
651*91f16700Schasinglulu 		ns_cpu_context = cm_get_context(NON_SECURE);
652*91f16700Schasinglulu 		assert(ns_cpu_context);
653*91f16700Schasinglulu 
654*91f16700Schasinglulu 		/* Restore non-secure state */
655*91f16700Schasinglulu 		cm_el1_sysregs_context_restore(NON_SECURE);
656*91f16700Schasinglulu 		cm_set_next_eret_context(NON_SECURE);
657*91f16700Schasinglulu 
658*91f16700Schasinglulu 		SMC_RET4(ns_cpu_context, x1, x2, x3, x4);
659*91f16700Schasinglulu 
660*91f16700Schasinglulu 	/*
661*91f16700Schasinglulu 	 * OPTEE has finished handling a S-EL1 FIQ interrupt. Execution
662*91f16700Schasinglulu 	 * should resume in the normal world.
663*91f16700Schasinglulu 	 */
664*91f16700Schasinglulu 	case TEESMC_OPTEED_RETURN_FIQ_DONE:
665*91f16700Schasinglulu 		/* Get a reference to the non-secure context */
666*91f16700Schasinglulu 		ns_cpu_context = cm_get_context(NON_SECURE);
667*91f16700Schasinglulu 		assert(ns_cpu_context);
668*91f16700Schasinglulu 
669*91f16700Schasinglulu 		/*
670*91f16700Schasinglulu 		 * Restore non-secure state. There is no need to save the
671*91f16700Schasinglulu 		 * secure system register context since OPTEE was supposed
672*91f16700Schasinglulu 		 * to preserve it during S-EL1 interrupt handling.
673*91f16700Schasinglulu 		 */
674*91f16700Schasinglulu 		cm_el1_sysregs_context_restore(NON_SECURE);
675*91f16700Schasinglulu 		cm_set_next_eret_context(NON_SECURE);
676*91f16700Schasinglulu 
677*91f16700Schasinglulu 		SMC_RET0((uint64_t) ns_cpu_context);
678*91f16700Schasinglulu 
679*91f16700Schasinglulu 	default:
680*91f16700Schasinglulu 		panic();
681*91f16700Schasinglulu 	}
682*91f16700Schasinglulu }
683*91f16700Schasinglulu 
684*91f16700Schasinglulu /* Define an OPTEED runtime service descriptor for fast SMC calls */
685*91f16700Schasinglulu DECLARE_RT_SVC(
686*91f16700Schasinglulu 	opteed_fast,
687*91f16700Schasinglulu 
688*91f16700Schasinglulu 	OEN_TOS_START,
689*91f16700Schasinglulu 	OEN_TOS_END,
690*91f16700Schasinglulu 	SMC_TYPE_FAST,
691*91f16700Schasinglulu 	opteed_setup,
692*91f16700Schasinglulu 	opteed_smc_handler
693*91f16700Schasinglulu );
694*91f16700Schasinglulu 
695*91f16700Schasinglulu /* Define an OPTEED runtime service descriptor for yielding SMC calls */
696*91f16700Schasinglulu DECLARE_RT_SVC(
697*91f16700Schasinglulu 	opteed_std,
698*91f16700Schasinglulu 
699*91f16700Schasinglulu 	OEN_TOS_START,
700*91f16700Schasinglulu 	OEN_TOS_END,
701*91f16700Schasinglulu 	SMC_TYPE_YIELD,
702*91f16700Schasinglulu 	NULL,
703*91f16700Schasinglulu 	opteed_smc_handler
704*91f16700Schasinglulu );
705