blob: ac58e047c987f71e1dd4afeb3d6bb582b179263a [file] [log] [blame]
Jens Wiklanderc2888862014-08-04 15:39:58 +02001/*
David Cunadoc8833ea2017-04-16 17:15:08 +01002 * Copyright (c) 2013-2017, 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 ******************************************************************************/
17#include <arch_helpers.h>
18#include <assert.h>
Jens Wiklanderc2888862014-08-04 15:39:58 +020019#include <bl31.h>
Isla Mitchell99305012017-07-11 14:54:08 +010020#include <bl_common.h>
Jens Wiklanderc2888862014-08-04 15:39:58 +020021#include <context_mgmt.h>
22#include <debug.h>
23#include <errno.h>
24#include <platform.h>
25#include <runtime_svc.h>
26#include <stddef.h>
27#include <uuid.h>
28#include "opteed_private.h"
Jens Wiklanderc2888862014-08-04 15:39:58 +020029#include "teesmc_opteed.h"
Isla Mitchell99305012017-07-11 14:54:08 +010030#include "teesmc_opteed_macros.h"
31
Jens Wiklanderc2888862014-08-04 15:39:58 +020032
33/*******************************************************************************
34 * Address of the entrypoint vector table in OPTEE. It is
35 * initialised once on the primary core after a cold boot.
36 ******************************************************************************/
37optee_vectors_t *optee_vectors;
38
39/*******************************************************************************
40 * Array to keep track of per-cpu OPTEE state
41 ******************************************************************************/
42optee_context_t opteed_sp_context[OPTEED_CORE_COUNT];
43uint32_t opteed_rw;
44
Jens Wiklanderc2888862014-08-04 15:39:58 +020045static int32_t opteed_init(void);
46
47/*******************************************************************************
48 * This function is the handler registered for S-EL1 interrupts by the
49 * OPTEED. It validates the interrupt and upon success arranges entry into
50 * the OPTEE at 'optee_fiq_entry()' for handling the interrupt.
51 ******************************************************************************/
52static uint64_t opteed_sel1_interrupt_handler(uint32_t id,
53 uint32_t flags,
54 void *handle,
55 void *cookie)
56{
57 uint32_t linear_id;
Jens Wiklanderc2888862014-08-04 15:39:58 +020058 optee_context_t *optee_ctx;
59
60 /* Check the security state when the exception was generated */
61 assert(get_interrupt_src_ss(flags) == NON_SECURE);
62
Jens Wiklanderc2888862014-08-04 15:39:58 +020063 /* Sanity check the pointer to this cpu's context */
Jens Wiklanderc2888862014-08-04 15:39:58 +020064 assert(handle == cm_get_context(NON_SECURE));
65
66 /* Save the non-secure context before entering the OPTEE */
67 cm_el1_sysregs_context_save(NON_SECURE);
68
69 /* Get a reference to this cpu's OPTEE context */
Soby Mathewda43b662015-07-08 21:45:46 +010070 linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020071 optee_ctx = &opteed_sp_context[linear_id];
72 assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE));
73
74 cm_set_elr_el3(SECURE, (uint64_t)&optee_vectors->fiq_entry);
75 cm_el1_sysregs_context_restore(SECURE);
76 cm_set_next_eret_context(SECURE);
77
78 /*
79 * Tell the OPTEE that it has to handle an FIQ (synchronously).
80 * Also the instruction in normal world where the interrupt was
81 * generated is passed for debugging purposes. It is safe to
82 * retrieve this address from ELR_EL3 as the secure context will
83 * not take effect until el3_exit().
84 */
85 SMC_RET1(&optee_ctx->cpu_ctx, read_elr_el3());
86}
87
88/*******************************************************************************
89 * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type
90 * (aarch32/aarch64) if not already known and initialises the context for entry
91 * into OPTEE for its initialization.
92 ******************************************************************************/
Masahiro Yamada56212752018-04-19 01:14:42 +090093static int32_t opteed_setup(void)
Jens Wiklanderc2888862014-08-04 15:39:58 +020094{
95 entry_point_info_t *optee_ep_info;
Jens Wiklanderc2888862014-08-04 15:39:58 +020096 uint32_t linear_id;
Edison Ai5d685d32017-07-18 16:52:26 +080097 uint64_t opteed_pageable_part;
98 uint64_t opteed_mem_limit;
Jens Wiklanderce6cd162017-08-24 13:16:22 +020099 uint64_t dt_addr;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200100
Soby Mathewda43b662015-07-08 21:45:46 +0100101 linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200102
103 /*
104 * Get information about the Secure Payload (BL32) image. Its
105 * absence is a critical failure. TODO: Add support to
106 * conditionally include the SPD service
107 */
108 optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
109 if (!optee_ep_info) {
110 WARN("No OPTEE provided by BL2 boot loader, Booting device"
111 " without OPTEE initialization. SMC`s destined for OPTEE"
112 " will return SMC_UNK\n");
113 return 1;
114 }
115
116 /*
117 * If there's no valid entry point for SP, we return a non-zero value
118 * signalling failure initializing the service. We bail out without
119 * registering any handlers
120 */
121 if (!optee_ep_info->pc)
122 return 1;
123
Edison Ai5d685d32017-07-18 16:52:26 +0800124 opteed_rw = optee_ep_info->args.arg0;
125 opteed_pageable_part = optee_ep_info->args.arg1;
126 opteed_mem_limit = optee_ep_info->args.arg2;
Jens Wiklanderce6cd162017-08-24 13:16:22 +0200127 dt_addr = optee_ep_info->args.arg3;
Edison Ai5d685d32017-07-18 16:52:26 +0800128
Jens Wiklanderc2888862014-08-04 15:39:58 +0200129 opteed_init_optee_ep_state(optee_ep_info,
130 opteed_rw,
131 optee_ep_info->pc,
Edison Ai5d685d32017-07-18 16:52:26 +0800132 opteed_pageable_part,
133 opteed_mem_limit,
Jens Wiklanderce6cd162017-08-24 13:16:22 +0200134 dt_addr,
Jens Wiklanderc2888862014-08-04 15:39:58 +0200135 &opteed_sp_context[linear_id]);
136
137 /*
138 * All OPTEED initialization done. Now register our init function with
139 * BL31 for deferred invocation
140 */
141 bl31_register_bl32_init(&opteed_init);
142
143 return 0;
144}
145
146/*******************************************************************************
147 * This function passes control to the OPTEE image (BL32) for the first time
148 * on the primary cpu after a cold boot. It assumes that a valid secure
149 * context has already been created by opteed_setup() which can be directly
150 * used. It also assumes that a valid non-secure context has been
151 * initialised by PSCI so it does not need to save and restore any
152 * non-secure state. This function performs a synchronous entry into
153 * OPTEE. OPTEE passes control back to this routine through a SMC.
154 ******************************************************************************/
155static int32_t opteed_init(void)
156{
Soby Mathewda43b662015-07-08 21:45:46 +0100157 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200158 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
159 entry_point_info_t *optee_entry_point;
160 uint64_t rc;
161
162 /*
163 * Get information about the OPTEE (BL32) image. Its
164 * absence is a critical failure.
165 */
166 optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
167 assert(optee_entry_point);
168
Soby Mathewda43b662015-07-08 21:45:46 +0100169 cm_init_my_context(optee_entry_point);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200170
171 /*
172 * Arrange for an entry into OPTEE. It will be returned via
173 * OPTEE_ENTRY_DONE case
174 */
175 rc = opteed_synchronous_sp_entry(optee_ctx);
176 assert(rc != 0);
177
178 return rc;
179}
180
181
182/*******************************************************************************
183 * This function is responsible for handling all SMCs in the Trusted OS/App
184 * range from the non-secure state as defined in the SMC Calling Convention
185 * Document. It is also responsible for communicating with the Secure
186 * payload to delegate work and return results back to the non-secure
187 * state. Lastly it will also return any information that OPTEE needs to do
188 * the work assigned to it.
189 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900190static uintptr_t opteed_smc_handler(uint32_t smc_fid,
191 u_register_t x1,
192 u_register_t x2,
193 u_register_t x3,
194 u_register_t x4,
Jens Wiklanderc2888862014-08-04 15:39:58 +0200195 void *cookie,
196 void *handle,
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900197 u_register_t flags)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200198{
199 cpu_context_t *ns_cpu_context;
Soby Mathewda43b662015-07-08 21:45:46 +0100200 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200201 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
202 uint64_t rc;
203
204 /*
205 * Determine which security state this SMC originated from
206 */
207
208 if (is_caller_non_secure(flags)) {
209 /*
210 * This is a fresh request from the non-secure client.
211 * The parameters are in x1 and x2. Figure out which
212 * registers need to be preserved, save the non-secure
213 * state and send the request to the secure payload.
214 */
215 assert(handle == cm_get_context(NON_SECURE));
216
217 cm_el1_sysregs_context_save(NON_SECURE);
218
219 /*
220 * We are done stashing the non-secure context. Ask the
221 * OPTEE to do the work now.
222 */
223
224 /*
225 * Verify if there is a valid context to use, copy the
226 * operation type and parameters to the secure context
227 * and jump to the fast smc entry point in the secure
228 * payload. Entry into S-EL1 will take place upon exit
229 * from this function.
230 */
231 assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE));
232
233 /* Set appropriate entry for SMC.
234 * We expect OPTEE to manage the PSTATE.I and PSTATE.F
235 * flags as appropriate.
236 */
237 if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) {
238 cm_set_elr_el3(SECURE, (uint64_t)
239 &optee_vectors->fast_smc_entry);
240 } else {
241 cm_set_elr_el3(SECURE, (uint64_t)
David Cunadoc8833ea2017-04-16 17:15:08 +0100242 &optee_vectors->yield_smc_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200243 }
244
245 cm_el1_sysregs_context_restore(SECURE);
246 cm_set_next_eret_context(SECURE);
247
Ashutosh Singh3270b842016-03-31 17:18:34 +0100248 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
249 CTX_GPREG_X4,
250 read_ctx_reg(get_gpregs_ctx(handle),
251 CTX_GPREG_X4));
252 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
253 CTX_GPREG_X5,
254 read_ctx_reg(get_gpregs_ctx(handle),
255 CTX_GPREG_X5));
256 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
257 CTX_GPREG_X6,
258 read_ctx_reg(get_gpregs_ctx(handle),
259 CTX_GPREG_X6));
Jens Wiklanderc2888862014-08-04 15:39:58 +0200260 /* Propagate hypervisor client ID */
261 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
262 CTX_GPREG_X7,
263 read_ctx_reg(get_gpregs_ctx(handle),
264 CTX_GPREG_X7));
265
266 SMC_RET4(&optee_ctx->cpu_ctx, smc_fid, x1, x2, x3);
267 }
268
269 /*
270 * Returning from OPTEE
271 */
272
273 switch (smc_fid) {
274 /*
275 * OPTEE has finished initialising itself after a cold boot
276 */
277 case TEESMC_OPTEED_RETURN_ENTRY_DONE:
278 /*
279 * Stash the OPTEE entry points information. This is done
280 * only once on the primary cpu
281 */
282 assert(optee_vectors == NULL);
283 optee_vectors = (optee_vectors_t *) x1;
284
285 if (optee_vectors) {
286 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
287
288 /*
289 * OPTEE has been successfully initialized.
290 * Register power management hooks with PSCI
291 */
292 psci_register_spd_pm_hook(&opteed_pm);
293
294 /*
295 * Register an interrupt handler for S-EL1 interrupts
296 * when generated during code executing in the
297 * non-secure state.
298 */
299 flags = 0;
300 set_interrupt_rm_flag(flags, NON_SECURE);
301 rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
302 opteed_sel1_interrupt_handler,
303 flags);
304 if (rc)
305 panic();
306 }
307
308 /*
309 * OPTEE reports completion. The OPTEED must have initiated
310 * the original request through a synchronous entry into
311 * OPTEE. Jump back to the original C runtime context.
312 */
313 opteed_synchronous_sp_exit(optee_ctx, x1);
Jonathan Wright75a5d8b2018-03-14 15:56:21 +0000314 break;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200315
316
317 /*
318 * These function IDs is used only by OP-TEE to indicate it has
319 * finished:
320 * 1. turning itself on in response to an earlier psci
321 * cpu_on request
322 * 2. resuming itself after an earlier psci cpu_suspend
323 * request.
324 */
325 case TEESMC_OPTEED_RETURN_ON_DONE:
326 case TEESMC_OPTEED_RETURN_RESUME_DONE:
327
328
329 /*
330 * These function IDs is used only by the SP to indicate it has
331 * finished:
332 * 1. suspending itself after an earlier psci cpu_suspend
333 * request.
334 * 2. turning itself off in response to an earlier psci
335 * cpu_off request.
336 */
337 case TEESMC_OPTEED_RETURN_OFF_DONE:
338 case TEESMC_OPTEED_RETURN_SUSPEND_DONE:
339 case TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE:
340 case TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE:
341
342 /*
343 * OPTEE reports completion. The OPTEED must have initiated the
344 * original request through a synchronous entry into OPTEE.
345 * Jump back to the original C runtime context, and pass x1 as
346 * return value to the caller
347 */
348 opteed_synchronous_sp_exit(optee_ctx, x1);
Jonathan Wright75a5d8b2018-03-14 15:56:21 +0000349 break;
Jens Wiklanderc2888862014-08-04 15:39:58 +0200350
351 /*
352 * OPTEE is returning from a call or being preempted from a call, in
353 * either case execution should resume in the normal world.
354 */
355 case TEESMC_OPTEED_RETURN_CALL_DONE:
356 /*
357 * This is the result from the secure client of an
358 * earlier request. The results are in x0-x3. Copy it
359 * into the non-secure context, save the secure state
360 * and return to the non-secure state.
361 */
362 assert(handle == cm_get_context(SECURE));
363 cm_el1_sysregs_context_save(SECURE);
364
365 /* Get a reference to the non-secure context */
366 ns_cpu_context = cm_get_context(NON_SECURE);
367 assert(ns_cpu_context);
368
369 /* Restore non-secure state */
370 cm_el1_sysregs_context_restore(NON_SECURE);
371 cm_set_next_eret_context(NON_SECURE);
372
373 SMC_RET4(ns_cpu_context, x1, x2, x3, x4);
374
375 /*
376 * OPTEE has finished handling a S-EL1 FIQ interrupt. Execution
377 * should resume in the normal world.
378 */
379 case TEESMC_OPTEED_RETURN_FIQ_DONE:
380 /* Get a reference to the non-secure context */
381 ns_cpu_context = cm_get_context(NON_SECURE);
382 assert(ns_cpu_context);
383
384 /*
385 * Restore non-secure state. There is no need to save the
386 * secure system register context since OPTEE was supposed
387 * to preserve it during S-EL1 interrupt handling.
388 */
389 cm_el1_sysregs_context_restore(NON_SECURE);
390 cm_set_next_eret_context(NON_SECURE);
391
392 SMC_RET0((uint64_t) ns_cpu_context);
393
394 default:
395 panic();
396 }
397}
398
399/* Define an OPTEED runtime service descriptor for fast SMC calls */
400DECLARE_RT_SVC(
401 opteed_fast,
402
403 OEN_TOS_START,
404 OEN_TOS_END,
405 SMC_TYPE_FAST,
406 opteed_setup,
407 opteed_smc_handler
408);
409
David Cunadoc8833ea2017-04-16 17:15:08 +0100410/* Define an OPTEED runtime service descriptor for yielding SMC calls */
Jens Wiklanderc2888862014-08-04 15:39:58 +0200411DECLARE_RT_SVC(
412 opteed_std,
413
414 OEN_TOS_START,
415 OEN_TOS_END,
David Cunadoc8833ea2017-04-16 17:15:08 +0100416 SMC_TYPE_YIELD,
Jens Wiklanderc2888862014-08-04 15:39:58 +0200417 NULL,
418 opteed_smc_handler
419);