blob: ff2aee0c512fe757b17cabb4ebf0e91ec402f469 [file] [log] [blame]
Jens Wiklanderc2888862014-08-04 15:39:58 +02001/*
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -07002 * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
Jens Wiklanderc2888862014-08-04 15:39:58 +02003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Jens Wiklanderc2888862014-08-04 15:39:58 +02005 */
6
7
8/*******************************************************************************
9 * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a
10 * plug-in component to the Secure Monitor, registered as a runtime service. The
11 * SPD is expected to be a functional extension of the Secure Payload (SP) that
12 * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting
13 * the Trusted OS/Applications range to the dispatcher. The SPD will either
14 * handle the request locally or delegate it to the Secure Payload. It is also
15 * responsible for initialising and maintaining communication with the SP.
16 ******************************************************************************/
Jens Wiklanderc2888862014-08-04 15:39:58 +020017#include <assert.h>
Jens Wiklanderc2888862014-08-04 15:39:58 +020018#include <errno.h>
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -070019#include <inttypes.h>
Jens Wiklanderc2888862014-08-04 15:39:58 +020020#include <stddef.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000021
22#include <arch_helpers.h>
23#include <bl31/bl31.h>
24#include <common/bl_common.h>
25#include <common/debug.h>
26#include <common/runtime_svc.h>
27#include <lib/el3_runtime/context_mgmt.h>
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -070028#include <lib/optee_utils.h>
29#include <lib/xlat_tables/xlat_tables_v2.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000030#include <plat/common/platform.h>
31#include <tools_share/uuid.h>
32
Jens Wiklanderc2888862014-08-04 15:39:58 +020033#include "opteed_private.h"
Jens Wiklanderc2888862014-08-04 15:39:58 +020034#include "teesmc_opteed.h"
Isla Mitchell99305012017-07-11 14:54:08 +010035
Jens Wiklanderc2888862014-08-04 15:39:58 +020036/*******************************************************************************
37 * Address of the entrypoint vector table in OPTEE. It is
38 * initialised once on the primary core after a cold boot.
39 ******************************************************************************/
Sandrine Bailleuxb3b6e222018-07-11 12:44:22 +020040struct optee_vectors *optee_vector_table;
Jens Wiklanderc2888862014-08-04 15:39:58 +020041
42/*******************************************************************************
43 * Array to keep track of per-cpu OPTEE state
44 ******************************************************************************/
45optee_context_t opteed_sp_context[OPTEED_CORE_COUNT];
46uint32_t opteed_rw;
47
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -070048#if OPTEE_ALLOW_SMC_LOAD
49static bool opteed_allow_load;
50#else
Jens Wiklanderc2888862014-08-04 15:39:58 +020051static int32_t opteed_init(void);
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -070052#endif
53
54uint64_t dual32to64(uint32_t high, uint32_t low)
55{
56 return ((uint64_t)high << 32) | low;
57}
Jens Wiklanderc2888862014-08-04 15:39:58 +020058
59/*******************************************************************************
60 * This function is the handler registered for S-EL1 interrupts by the
61 * OPTEED. It validates the interrupt and upon success arranges entry into
62 * the OPTEE at 'optee_fiq_entry()' for handling the interrupt.
63 ******************************************************************************/
64static uint64_t opteed_sel1_interrupt_handler(uint32_t id,
65 uint32_t flags,
66 void *handle,
67 void *cookie)
68{
69 uint32_t linear_id;
Jens Wiklanderc2888862014-08-04 15:39:58 +020070 optee_context_t *optee_ctx;
71
72 /* Check the security state when the exception was generated */
73 assert(get_interrupt_src_ss(flags) == NON_SECURE);
74
Jens Wiklanderc2888862014-08-04 15:39:58 +020075 /* Sanity check the pointer to this cpu's context */
Jens Wiklanderc2888862014-08-04 15:39:58 +020076 assert(handle == cm_get_context(NON_SECURE));
77
78 /* Save the non-secure context before entering the OPTEE */
79 cm_el1_sysregs_context_save(NON_SECURE);
80
81 /* Get a reference to this cpu's OPTEE context */
Soby Mathewda43b662015-07-08 21:45:46 +010082 linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020083 optee_ctx = &opteed_sp_context[linear_id];
84 assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE));
85
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010086 cm_set_elr_el3(SECURE, (uint64_t)&optee_vector_table->fiq_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +020087 cm_el1_sysregs_context_restore(SECURE);
88 cm_set_next_eret_context(SECURE);
89
90 /*
91 * Tell the OPTEE that it has to handle an FIQ (synchronously).
92 * Also the instruction in normal world where the interrupt was
93 * generated is passed for debugging purposes. It is safe to
94 * retrieve this address from ELR_EL3 as the secure context will
95 * not take effect until el3_exit().
96 */
97 SMC_RET1(&optee_ctx->cpu_ctx, read_elr_el3());
98}
99
100/*******************************************************************************
101 * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type
102 * (aarch32/aarch64) if not already known and initialises the context for entry
103 * into OPTEE for its initialization.
104 ******************************************************************************/
Masahiro Yamada56212752018-04-19 01:14:42 +0900105static int32_t opteed_setup(void)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200106{
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700107#if OPTEE_ALLOW_SMC_LOAD
108 opteed_allow_load = true;
109 INFO("Delaying OP-TEE setup until we receive an SMC call to load it\n");
110 return 0;
111#else
Jens Wiklanderc2888862014-08-04 15:39:58 +0200112 entry_point_info_t *optee_ep_info;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200113 uint32_t linear_id;
Edison Ai5d685d32017-07-18 16:52:26 +0800114 uint64_t opteed_pageable_part;
115 uint64_t opteed_mem_limit;
Jens Wiklanderce6cd162017-08-24 13:16:22 +0200116 uint64_t dt_addr;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200117
Soby Mathewda43b662015-07-08 21:45:46 +0100118 linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200119
120 /*
121 * Get information about the Secure Payload (BL32) image. Its
122 * absence is a critical failure. TODO: Add support to
123 * conditionally include the SPD service
124 */
125 optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
126 if (!optee_ep_info) {
127 WARN("No OPTEE provided by BL2 boot loader, Booting device"
128 " without OPTEE initialization. SMC`s destined for OPTEE"
129 " will return SMC_UNK\n");
130 return 1;
131 }
132
133 /*
134 * If there's no valid entry point for SP, we return a non-zero value
135 * signalling failure initializing the service. We bail out without
136 * registering any handlers
137 */
138 if (!optee_ep_info->pc)
139 return 1;
140
Edison Ai5d685d32017-07-18 16:52:26 +0800141 opteed_rw = optee_ep_info->args.arg0;
142 opteed_pageable_part = optee_ep_info->args.arg1;
143 opteed_mem_limit = optee_ep_info->args.arg2;
Jens Wiklanderce6cd162017-08-24 13:16:22 +0200144 dt_addr = optee_ep_info->args.arg3;
Edison Ai5d685d32017-07-18 16:52:26 +0800145
Jens Wiklanderc2888862014-08-04 15:39:58 +0200146 opteed_init_optee_ep_state(optee_ep_info,
147 opteed_rw,
148 optee_ep_info->pc,
Edison Ai5d685d32017-07-18 16:52:26 +0800149 opteed_pageable_part,
150 opteed_mem_limit,
Jens Wiklanderce6cd162017-08-24 13:16:22 +0200151 dt_addr,
Jens Wiklanderc2888862014-08-04 15:39:58 +0200152 &opteed_sp_context[linear_id]);
153
154 /*
155 * All OPTEED initialization done. Now register our init function with
156 * BL31 for deferred invocation
157 */
158 bl31_register_bl32_init(&opteed_init);
159
160 return 0;
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700161#endif /* OPTEE_ALLOW_SMC_LOAD */
Jens Wiklanderc2888862014-08-04 15:39:58 +0200162}
163
164/*******************************************************************************
165 * This function passes control to the OPTEE image (BL32) for the first time
166 * on the primary cpu after a cold boot. It assumes that a valid secure
167 * context has already been created by opteed_setup() which can be directly
168 * used. It also assumes that a valid non-secure context has been
169 * initialised by PSCI so it does not need to save and restore any
170 * non-secure state. This function performs a synchronous entry into
171 * OPTEE. OPTEE passes control back to this routine through a SMC.
172 ******************************************************************************/
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700173static int32_t
174opteed_init_with_entry_point(entry_point_info_t *optee_entry_point)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200175{
Soby Mathewda43b662015-07-08 21:45:46 +0100176 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200177 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
Jens Wiklanderc2888862014-08-04 15:39:58 +0200178 uint64_t rc;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200179 assert(optee_entry_point);
180
Soby Mathewda43b662015-07-08 21:45:46 +0100181 cm_init_my_context(optee_entry_point);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200182
183 /*
184 * Arrange for an entry into OPTEE. It will be returned via
185 * OPTEE_ENTRY_DONE case
186 */
187 rc = opteed_synchronous_sp_entry(optee_ctx);
188 assert(rc != 0);
189
190 return rc;
191}
192
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700193#if !OPTEE_ALLOW_SMC_LOAD
194static int32_t opteed_init(void)
195{
196 entry_point_info_t *optee_entry_point;
197 /*
198 * Get information about the OP-TEE (BL32) image. Its
199 * absence is a critical failure.
200 */
201 optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
202 return opteed_init_with_entry_point(optee_entry_point);
203}
204#endif /* !OPTEE_ALLOW_SMC_LOAD */
Jens Wiklanderc2888862014-08-04 15:39:58 +0200205
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700206#if OPTEE_ALLOW_SMC_LOAD
207/*******************************************************************************
208 * This function is responsible for handling the SMC that loads the OP-TEE
209 * binary image via a non-secure SMC call. It takes the size and physical
210 * address of the payload as parameters.
211 ******************************************************************************/
212static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa)
213{
214 uintptr_t data_va = data_pa;
215 uint64_t mapped_data_pa;
216 uintptr_t mapped_data_va;
217 uint64_t data_map_size;
218 int32_t rc;
219 optee_header_t *image_header;
220 uint8_t *image_ptr;
221 uint64_t target_pa;
222 uint64_t target_end_pa;
223 uint64_t image_pa;
224 uintptr_t image_va;
225 optee_image_t *curr_image;
226 uintptr_t target_va;
227 uint64_t target_size;
228 entry_point_info_t optee_ep_info;
229 uint32_t linear_id = plat_my_core_pos();
230
231 mapped_data_pa = page_align(data_pa, DOWN);
232 mapped_data_va = mapped_data_pa;
233 data_map_size = page_align(data_size + (mapped_data_pa - data_pa), UP);
234
235 rc = mmap_add_dynamic_region(mapped_data_pa, mapped_data_va,
236 data_map_size, MT_MEMORY | MT_RO | MT_NS);
237 if (rc != 0) {
238 return rc;
239 }
240
241 image_header = (optee_header_t *)data_va;
242 if (image_header->magic != TEE_MAGIC_NUM_OPTEE ||
243 image_header->version != 2 || image_header->nb_images != 1) {
244 mmap_remove_dynamic_region(mapped_data_va, data_map_size);
245 return -EINVAL;
246 }
247
248 image_ptr = (uint8_t *)data_va + sizeof(optee_header_t) +
249 sizeof(optee_image_t);
250 if (image_header->arch == 1) {
251 opteed_rw = OPTEE_AARCH64;
252 } else {
253 opteed_rw = OPTEE_AARCH32;
254 }
255
256 curr_image = &image_header->optee_image_list[0];
257 image_pa = dual32to64(curr_image->load_addr_hi,
258 curr_image->load_addr_lo);
259 image_va = image_pa;
260 target_end_pa = image_pa + curr_image->size;
261
262 /* Now also map the memory we want to copy it to. */
263 target_pa = page_align(image_pa, DOWN);
264 target_va = target_pa;
265 target_size = page_align(target_end_pa, UP) - target_pa;
266
267 rc = mmap_add_dynamic_region(target_pa, target_va, target_size,
268 MT_MEMORY | MT_RW | MT_SECURE);
269 if (rc != 0) {
270 mmap_remove_dynamic_region(mapped_data_va, data_map_size);
271 return rc;
272 }
273
274 INFO("Loaded OP-TEE via SMC: size %d addr 0x%" PRIx64 "\n",
275 curr_image->size, image_va);
276
277 memcpy((void *)image_va, image_ptr, curr_image->size);
278 flush_dcache_range(target_pa, target_size);
279
280 mmap_remove_dynamic_region(mapped_data_va, data_map_size);
281 mmap_remove_dynamic_region(target_va, target_size);
282
283 /* Save the non-secure state */
284 cm_el1_sysregs_context_save(NON_SECURE);
285
286 opteed_init_optee_ep_state(&optee_ep_info,
287 opteed_rw,
288 image_pa,
289 0,
290 0,
291 0,
292 &opteed_sp_context[linear_id]);
293 rc = opteed_init_with_entry_point(&optee_ep_info);
294
295 /* Restore non-secure state */
296 cm_el1_sysregs_context_restore(NON_SECURE);
297 cm_set_next_eret_context(NON_SECURE);
298
299 return rc;
300}
301#endif /* OPTEE_ALLOW_SMC_LOAD */
302
Jens Wiklanderc2888862014-08-04 15:39:58 +0200303/*******************************************************************************
304 * This function is responsible for handling all SMCs in the Trusted OS/App
305 * range from the non-secure state as defined in the SMC Calling Convention
306 * Document. It is also responsible for communicating with the Secure
307 * payload to delegate work and return results back to the non-secure
308 * state. Lastly it will also return any information that OPTEE needs to do
309 * the work assigned to it.
310 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900311static uintptr_t opteed_smc_handler(uint32_t smc_fid,
312 u_register_t x1,
313 u_register_t x2,
314 u_register_t x3,
315 u_register_t x4,
Jens Wiklanderc2888862014-08-04 15:39:58 +0200316 void *cookie,
317 void *handle,
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900318 u_register_t flags)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200319{
320 cpu_context_t *ns_cpu_context;
Soby Mathewda43b662015-07-08 21:45:46 +0100321 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200322 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
323 uint64_t rc;
324
325 /*
326 * Determine which security state this SMC originated from
327 */
328
329 if (is_caller_non_secure(flags)) {
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700330#if OPTEE_ALLOW_SMC_LOAD
331 if (smc_fid == NSSMC_OPTEED_CALL_LOAD_IMAGE) {
332 /*
333 * TODO: Consider wiping the code for SMC loading from
334 * memory after it has been invoked similar to what is
335 * done under RECLAIM_INIT, but extended to happen
336 * later.
337 */
338 if (!opteed_allow_load) {
339 SMC_RET1(handle, -EPERM);
340 }
341
342 opteed_allow_load = false;
343 uint64_t data_size = dual32to64(x1, x2);
344 uint64_t data_pa = dual32to64(x3, x4);
345 if (!data_size || !data_pa) {
346 /*
347 * This is invoked when the OP-TEE image didn't
348 * load correctly in the kernel but we want to
349 * block off loading of it later for security
350 * reasons.
351 */
352 SMC_RET1(handle, -EINVAL);
353 }
354 SMC_RET1(handle, opteed_handle_smc_load(
355 data_size, data_pa));
356 }
357#endif /* OPTEE_ALLOW_SMC_LOAD */
Jens Wiklanderc2888862014-08-04 15:39:58 +0200358 /*
359 * This is a fresh request from the non-secure client.
360 * The parameters are in x1 and x2. Figure out which
361 * registers need to be preserved, save the non-secure
362 * state and send the request to the secure payload.
363 */
364 assert(handle == cm_get_context(NON_SECURE));
365
366 cm_el1_sysregs_context_save(NON_SECURE);
367
368 /*
369 * We are done stashing the non-secure context. Ask the
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700370 * OP-TEE to do the work now. If we are loading vi an SMC,
371 * then we also need to init this CPU context if not done
372 * already.
Jens Wiklanderc2888862014-08-04 15:39:58 +0200373 */
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700374 if (optee_vector_table == NULL) {
375 SMC_RET1(handle, -EINVAL);
376 }
377
378 if (get_optee_pstate(optee_ctx->state) ==
379 OPTEE_PSTATE_UNKNOWN) {
380 opteed_cpu_on_finish_handler(0);
381 }
Jens Wiklanderc2888862014-08-04 15:39:58 +0200382
383 /*
384 * Verify if there is a valid context to use, copy the
385 * operation type and parameters to the secure context
386 * and jump to the fast smc entry point in the secure
387 * payload. Entry into S-EL1 will take place upon exit
388 * from this function.
389 */
390 assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE));
391
392 /* Set appropriate entry for SMC.
393 * We expect OPTEE to manage the PSTATE.I and PSTATE.F
394 * flags as appropriate.
395 */
396 if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) {
397 cm_set_elr_el3(SECURE, (uint64_t)
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100398 &optee_vector_table->fast_smc_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200399 } else {
400 cm_set_elr_el3(SECURE, (uint64_t)
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100401 &optee_vector_table->yield_smc_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200402 }
403
404 cm_el1_sysregs_context_restore(SECURE);
405 cm_set_next_eret_context(SECURE);
406
Ashutosh Singh3270b842016-03-31 17:18:34 +0100407 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
408 CTX_GPREG_X4,
409 read_ctx_reg(get_gpregs_ctx(handle),
410 CTX_GPREG_X4));
411 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
412 CTX_GPREG_X5,
413 read_ctx_reg(get_gpregs_ctx(handle),
414 CTX_GPREG_X5));
415 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
416 CTX_GPREG_X6,
417 read_ctx_reg(get_gpregs_ctx(handle),
418 CTX_GPREG_X6));
Jens Wiklanderc2888862014-08-04 15:39:58 +0200419 /* Propagate hypervisor client ID */
420 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
421 CTX_GPREG_X7,
422 read_ctx_reg(get_gpregs_ctx(handle),
423 CTX_GPREG_X7));
424
425 SMC_RET4(&optee_ctx->cpu_ctx, smc_fid, x1, x2, x3);
426 }
427
428 /*
429 * Returning from OPTEE
430 */
431
432 switch (smc_fid) {
433 /*
434 * OPTEE has finished initialising itself after a cold boot
435 */
436 case TEESMC_OPTEED_RETURN_ENTRY_DONE:
437 /*
438 * Stash the OPTEE entry points information. This is done
439 * only once on the primary cpu
440 */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100441 assert(optee_vector_table == NULL);
442 optee_vector_table = (optee_vectors_t *) x1;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200443
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100444 if (optee_vector_table) {
Jens Wiklanderc2888862014-08-04 15:39:58 +0200445 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
446
447 /*
448 * OPTEE has been successfully initialized.
449 * Register power management hooks with PSCI
450 */
451 psci_register_spd_pm_hook(&opteed_pm);
452
453 /*
454 * Register an interrupt handler for S-EL1 interrupts
455 * when generated during code executing in the
456 * non-secure state.
457 */
458 flags = 0;
459 set_interrupt_rm_flag(flags, NON_SECURE);
460 rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
461 opteed_sel1_interrupt_handler,
462 flags);
463 if (rc)
464 panic();
465 }
466
467 /*
468 * OPTEE reports completion. The OPTEED must have initiated
469 * the original request through a synchronous entry into
470 * OPTEE. Jump back to the original C runtime context.
471 */
472 opteed_synchronous_sp_exit(optee_ctx, x1);
Jonathan Wright75a5d8b2018-03-14 15:56:21 +0000473 break;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200474
475
476 /*
477 * These function IDs is used only by OP-TEE to indicate it has
478 * finished:
479 * 1. turning itself on in response to an earlier psci
480 * cpu_on request
481 * 2. resuming itself after an earlier psci cpu_suspend
482 * request.
483 */
484 case TEESMC_OPTEED_RETURN_ON_DONE:
485 case TEESMC_OPTEED_RETURN_RESUME_DONE:
486
487
488 /*
489 * These function IDs is used only by the SP to indicate it has
490 * finished:
491 * 1. suspending itself after an earlier psci cpu_suspend
492 * request.
493 * 2. turning itself off in response to an earlier psci
494 * cpu_off request.
495 */
496 case TEESMC_OPTEED_RETURN_OFF_DONE:
497 case TEESMC_OPTEED_RETURN_SUSPEND_DONE:
498 case TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE:
499 case TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE:
500
501 /*
502 * OPTEE reports completion. The OPTEED must have initiated the
503 * original request through a synchronous entry into OPTEE.
504 * Jump back to the original C runtime context, and pass x1 as
505 * return value to the caller
506 */
507 opteed_synchronous_sp_exit(optee_ctx, x1);
Jonathan Wright75a5d8b2018-03-14 15:56:21 +0000508 break;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200509
510 /*
511 * OPTEE is returning from a call or being preempted from a call, in
512 * either case execution should resume in the normal world.
513 */
514 case TEESMC_OPTEED_RETURN_CALL_DONE:
515 /*
516 * This is the result from the secure client of an
517 * earlier request. The results are in x0-x3. Copy it
518 * into the non-secure context, save the secure state
519 * and return to the non-secure state.
520 */
521 assert(handle == cm_get_context(SECURE));
522 cm_el1_sysregs_context_save(SECURE);
523
524 /* Get a reference to the non-secure context */
525 ns_cpu_context = cm_get_context(NON_SECURE);
526 assert(ns_cpu_context);
527
528 /* Restore non-secure state */
529 cm_el1_sysregs_context_restore(NON_SECURE);
530 cm_set_next_eret_context(NON_SECURE);
531
532 SMC_RET4(ns_cpu_context, x1, x2, x3, x4);
533
534 /*
535 * OPTEE has finished handling a S-EL1 FIQ interrupt. Execution
536 * should resume in the normal world.
537 */
538 case TEESMC_OPTEED_RETURN_FIQ_DONE:
539 /* Get a reference to the non-secure context */
540 ns_cpu_context = cm_get_context(NON_SECURE);
541 assert(ns_cpu_context);
542
543 /*
544 * Restore non-secure state. There is no need to save the
545 * secure system register context since OPTEE was supposed
546 * to preserve it during S-EL1 interrupt handling.
547 */
548 cm_el1_sysregs_context_restore(NON_SECURE);
549 cm_set_next_eret_context(NON_SECURE);
550
551 SMC_RET0((uint64_t) ns_cpu_context);
552
553 default:
554 panic();
555 }
556}
557
558/* Define an OPTEED runtime service descriptor for fast SMC calls */
559DECLARE_RT_SVC(
560 opteed_fast,
561
562 OEN_TOS_START,
563 OEN_TOS_END,
564 SMC_TYPE_FAST,
565 opteed_setup,
566 opteed_smc_handler
567);
568
David Cunadoc8833ea2017-04-16 17:15:08 +0100569/* Define an OPTEED runtime service descriptor for yielding SMC calls */
Jens Wiklanderc2888862014-08-04 15:39:58 +0200570DECLARE_RT_SVC(
571 opteed_std,
572
573 OEN_TOS_START,
574 OEN_TOS_END,
David Cunadoc8833ea2017-04-16 17:15:08 +0100575 SMC_TYPE_YIELD,
Jens Wiklanderc2888862014-08-04 15:39:58 +0200576 NULL,
577 opteed_smc_handler
578);