blob: 1a064594f961e96c4b87fa21fccf3cf055d66ab3 [file] [log] [blame]
Achin Gupta375f5382014-02-18 18:12:48 +00001/*
Soby Mathewda43b662015-07-08 21:45:46 +01002 * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
Achin Gupta375f5382014-02-18 18:12:48 +00003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32/*******************************************************************************
33 * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a
34 * plug-in component to the Secure Monitor, registered as a runtime service. The
35 * SPD is expected to be a functional extension of the Secure Payload (SP) that
36 * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting
37 * the Trusted OS/Applications range to the dispatcher. The SPD will either
38 * handle the request locally or delegate it to the Secure Payload. It is also
39 * responsible for initialising and maintaining communication with the SP.
40 ******************************************************************************/
Achin Gupta375f5382014-02-18 18:12:48 +000041#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010042#include <assert.h>
43#include <bl_common.h>
44#include <bl31.h>
Achin Gupta375f5382014-02-18 18:12:48 +000045#include <context_mgmt.h>
Achin Guptaaeaab682014-05-09 13:21:31 +010046#include <debug.h>
47#include <errno.h>
48#include <platform.h>
Achin Gupta375f5382014-02-18 18:12:48 +000049#include <runtime_svc.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010050#include <stddef.h>
Soby Mathew47903c02015-01-13 15:48:26 +000051#include <string.h>
Achin Gupta375f5382014-02-18 18:12:48 +000052#include <tsp.h>
Jeenu Viswambharandf1ddb52014-02-28 11:23:35 +000053#include <uuid.h>
Dan Handley714a0d22014-04-09 13:13:04 +010054#include "tspd_private.h"
Achin Gupta375f5382014-02-18 18:12:48 +000055
56/*******************************************************************************
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010057 * Address of the entrypoint vector table in the Secure Payload. It is
58 * initialised once on the primary core after a cold boot.
Achin Gupta375f5382014-02-18 18:12:48 +000059 ******************************************************************************/
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010060tsp_vectors_t *tsp_vectors;
Achin Gupta375f5382014-02-18 18:12:48 +000061
62/*******************************************************************************
63 * Array to keep track of per-cpu Secure Payload state
64 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +010065tsp_context_t tspd_sp_context[TSPD_CORE_COUNT];
Achin Gupta375f5382014-02-18 18:12:48 +000066
Jeenu Viswambharan7f366602014-02-20 17:11:00 +000067
Jeenu Viswambharandf1ddb52014-02-28 11:23:35 +000068/* TSP UID */
69DEFINE_SVC_UUID(tsp_uuid,
70 0x5b3056a0, 0x3291, 0x427b, 0x98, 0x11,
71 0x71, 0x68, 0xca, 0x50, 0xf3, 0xfa);
72
Vikram Kanigirid8c9d262014-05-16 18:48:12 +010073int32_t tspd_init(void);
Jeenu Viswambharan7f366602014-02-20 17:11:00 +000074
Soby Mathewbc912822015-09-22 12:01:18 +010075/*
76 * This helper function handles Secure EL1 preemption. The preemption could be
77 * due Non Secure interrupts or EL3 interrupts. In both the cases we context
78 * switch to the normal world and in case of EL3 interrupts, it will again be
79 * routed to EL3 which will get handled at the exception vectors.
80 */
Soby Mathew47903c02015-01-13 15:48:26 +000081uint64_t tspd_handle_sp_preemption(void *handle)
82{
83 cpu_context_t *ns_cpu_context;
Soby Mathewbc912822015-09-22 12:01:18 +010084
Soby Mathew47903c02015-01-13 15:48:26 +000085 assert(handle == cm_get_context(SECURE));
86 cm_el1_sysregs_context_save(SECURE);
87 /* Get a reference to the non-secure context */
88 ns_cpu_context = cm_get_context(NON_SECURE);
89 assert(ns_cpu_context);
90
91 /*
Soby Mathew78664242015-11-13 02:08:43 +000092 * To allow Secure EL1 interrupt handler to re-enter TSP while TSP
93 * is preempted, the secure system register context which will get
94 * overwritten must be additionally saved. This is currently done
95 * by the TSPD S-EL1 interrupt handler.
96 */
97
98 /*
99 * Restore non-secure state.
Soby Mathew47903c02015-01-13 15:48:26 +0000100 */
101 cm_el1_sysregs_context_restore(NON_SECURE);
102 cm_set_next_eret_context(NON_SECURE);
103
Soby Mathewbc912822015-09-22 12:01:18 +0100104 /*
Soby Mathew78664242015-11-13 02:08:43 +0000105 * The TSP was preempted during STD SMC execution.
106 * Return back to the normal world with SMC_PREEMPTED as error
107 * code in x0.
Soby Mathewbc912822015-09-22 12:01:18 +0100108 */
Soby Mathew47903c02015-01-13 15:48:26 +0000109 SMC_RET1(ns_cpu_context, SMC_PREEMPTED);
110}
Soby Mathewbc912822015-09-22 12:01:18 +0100111
Achin Guptaaeaab682014-05-09 13:21:31 +0100112/*******************************************************************************
113 * This function is the handler registered for S-EL1 interrupts by the TSPD. It
114 * validates the interrupt and upon success arranges entry into the TSP at
Soby Mathewbec98512015-09-03 18:29:38 +0100115 * 'tsp_sel1_intr_entry()' for handling the interrupt.
Achin Guptaaeaab682014-05-09 13:21:31 +0100116 ******************************************************************************/
117static uint64_t tspd_sel1_interrupt_handler(uint32_t id,
118 uint32_t flags,
119 void *handle,
120 void *cookie)
121{
122 uint32_t linear_id;
Achin Guptaaeaab682014-05-09 13:21:31 +0100123 tsp_context_t *tsp_ctx;
124
125 /* Check the security state when the exception was generated */
126 assert(get_interrupt_src_ss(flags) == NON_SECURE);
127
Achin Guptaaeaab682014-05-09 13:21:31 +0100128 /* Sanity check the pointer to this cpu's context */
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100129 assert(handle == cm_get_context(NON_SECURE));
Achin Guptaaeaab682014-05-09 13:21:31 +0100130
131 /* Save the non-secure context before entering the TSP */
132 cm_el1_sysregs_context_save(NON_SECURE);
133
134 /* Get a reference to this cpu's TSP context */
Soby Mathewda43b662015-07-08 21:45:46 +0100135 linear_id = plat_my_core_pos();
Achin Guptaaeaab682014-05-09 13:21:31 +0100136 tsp_ctx = &tspd_sp_context[linear_id];
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100137 assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE));
Achin Guptaaeaab682014-05-09 13:21:31 +0100138
139 /*
140 * Determine if the TSP was previously preempted. Its last known
141 * context has to be preserved in this case.
142 * The TSP should return control to the TSPD after handling this
Soby Mathewbec98512015-09-03 18:29:38 +0100143 * S-EL1 interrupt. Preserve essential EL3 context to allow entry into
144 * the TSP at the S-EL1 interrupt entry point using the 'cpu_context'
145 * structure. There is no need to save the secure system register
146 * context since the TSP is supposed to preserve it during S-EL1
147 * interrupt handling.
Achin Guptaaeaab682014-05-09 13:21:31 +0100148 */
149 if (get_std_smc_active_flag(tsp_ctx->state)) {
150 tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
151 CTX_SPSR_EL3);
152 tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
153 CTX_ELR_EL3);
Soby Mathewbec98512015-09-03 18:29:38 +0100154#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000155 /*Need to save the previously interrupted secure context */
156 memcpy(&tsp_ctx->sp_ctx, &tsp_ctx->cpu_ctx, TSPD_SP_CTX_SIZE);
157#endif
Achin Guptaaeaab682014-05-09 13:21:31 +0100158 }
159
Achin Guptaaeaab682014-05-09 13:21:31 +0100160 cm_el1_sysregs_context_restore(SECURE);
Soby Mathewbec98512015-09-03 18:29:38 +0100161 cm_set_elr_spsr_el3(SECURE, (uint64_t) &tsp_vectors->sel1_intr_entry,
Andrew Thoelke4e126072014-06-04 21:10:52 +0100162 SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS));
Soby Mathew47903c02015-01-13 15:48:26 +0000163
Achin Guptaaeaab682014-05-09 13:21:31 +0100164 cm_set_next_eret_context(SECURE);
165
166 /*
Soby Mathewbec98512015-09-03 18:29:38 +0100167 * Tell the TSP that it has to handle a S-EL1 interrupt synchronously.
168 * Also the instruction in normal world where the interrupt was
169 * generated is passed for debugging purposes. It is safe to retrieve
170 * this address from ELR_EL3 as the secure context will not take effect
171 * until el3_exit().
Achin Guptaaeaab682014-05-09 13:21:31 +0100172 */
Soby Mathewbec98512015-09-03 18:29:38 +0100173 SMC_RET2(&tsp_ctx->cpu_ctx, TSP_HANDLE_SEL1_INTR_AND_RETURN, read_elr_el3());
Achin Guptaaeaab682014-05-09 13:21:31 +0100174}
Soby Mathew47903c02015-01-13 15:48:26 +0000175
Soby Mathewbec98512015-09-03 18:29:38 +0100176#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000177/*******************************************************************************
Soby Mathewbec98512015-09-03 18:29:38 +0100178 * This function is the handler registered for Non secure interrupts by the
179 * TSPD. It validates the interrupt and upon success arranges entry into the
180 * normal world for handling the interrupt.
Soby Mathew47903c02015-01-13 15:48:26 +0000181 ******************************************************************************/
182static uint64_t tspd_ns_interrupt_handler(uint32_t id,
183 uint32_t flags,
184 void *handle,
185 void *cookie)
186{
187 /* Check the security state when the exception was generated */
188 assert(get_interrupt_src_ss(flags) == SECURE);
189
Soby Mathew47903c02015-01-13 15:48:26 +0000190 /*
191 * Disable the routing of NS interrupts from secure world to EL3 while
192 * interrupted on this core.
193 */
194 disable_intr_rm_local(INTR_TYPE_NS, SECURE);
195
196 return tspd_handle_sp_preemption(handle);
197}
198#endif
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000199
Achin Gupta375f5382014-02-18 18:12:48 +0000200/*******************************************************************************
201 * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type
202 * (aarch32/aarch64) if not already known and initialises the context for entry
203 * into the SP for its initialisation.
204 ******************************************************************************/
205int32_t tspd_setup(void)
206{
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100207 entry_point_info_t *tsp_ep_info;
Achin Gupta375f5382014-02-18 18:12:48 +0000208 uint32_t linear_id;
209
Soby Mathewda43b662015-07-08 21:45:46 +0100210 linear_id = plat_my_core_pos();
Achin Gupta375f5382014-02-18 18:12:48 +0000211
212 /*
213 * Get information about the Secure Payload (BL32) image. Its
214 * absence is a critical failure. TODO: Add support to
215 * conditionally include the SPD service
216 */
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100217 tsp_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
218 if (!tsp_ep_info) {
219 WARN("No TSP provided by BL2 boot loader, Booting device"
220 " without TSP initialization. SMC`s destined for TSP"
221 " will return SMC_UNK\n");
222 return 1;
223 }
Achin Gupta375f5382014-02-18 18:12:48 +0000224
225 /*
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000226 * If there's no valid entry point for SP, we return a non-zero value
227 * signalling failure initializing the service. We bail out without
228 * registering any handlers
229 */
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100230 if (!tsp_ep_info->pc)
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000231 return 1;
232
233 /*
Sandrine Bailleuxf4119ec2015-12-17 13:58:58 +0000234 * We could inspect the SP image and determine its execution
Achin Gupta375f5382014-02-18 18:12:48 +0000235 * state i.e whether AArch32 or AArch64. Assuming it's AArch64
236 * for the time being.
237 */
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100238 tspd_init_tsp_ep_state(tsp_ep_info,
239 TSP_AARCH64,
240 tsp_ep_info->pc,
241 &tspd_sp_context[linear_id]);
Achin Gupta375f5382014-02-18 18:12:48 +0000242
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100243#if TSP_INIT_ASYNC
244 bl31_set_next_image_type(SECURE);
245#else
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000246 /*
247 * All TSPD initialization done. Now register our init function with
248 * BL31 for deferred invocation
249 */
250 bl31_register_bl32_init(&tspd_init);
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100251#endif
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100252 return 0;
Achin Gupta375f5382014-02-18 18:12:48 +0000253}
254
255/*******************************************************************************
256 * This function passes control to the Secure Payload image (BL32) for the first
257 * time on the primary cpu after a cold boot. It assumes that a valid secure
258 * context has already been created by tspd_setup() which can be directly used.
259 * It also assumes that a valid non-secure context has been initialised by PSCI
260 * so it does not need to save and restore any non-secure state. This function
261 * performs a synchronous entry into the Secure payload. The SP passes control
Vikram Kanigirid8c9d262014-05-16 18:48:12 +0100262 * back to this routine through a SMC.
Achin Gupta375f5382014-02-18 18:12:48 +0000263 ******************************************************************************/
Vikram Kanigirid8c9d262014-05-16 18:48:12 +0100264int32_t tspd_init(void)
Achin Gupta375f5382014-02-18 18:12:48 +0000265{
Soby Mathewda43b662015-07-08 21:45:46 +0100266 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +0100267 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100268 entry_point_info_t *tsp_entry_point;
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100269 uint64_t rc;
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100270
271 /*
272 * Get information about the Secure Payload (BL32) image. Its
273 * absence is a critical failure.
274 */
275 tsp_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
276 assert(tsp_entry_point);
277
Soby Mathewda43b662015-07-08 21:45:46 +0100278 cm_init_my_context(tsp_entry_point);
Achin Gupta375f5382014-02-18 18:12:48 +0000279
280 /*
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100281 * Arrange for an entry into the test secure payload. It will be
282 * returned via TSP_ENTRY_DONE case
Achin Gupta607084e2014-02-09 18:24:19 +0000283 */
Achin Gupta375f5382014-02-18 18:12:48 +0000284 rc = tspd_synchronous_sp_entry(tsp_ctx);
285 assert(rc != 0);
Achin Guptaaeaab682014-05-09 13:21:31 +0100286
Achin Gupta375f5382014-02-18 18:12:48 +0000287 return rc;
288}
289
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000290
Achin Gupta375f5382014-02-18 18:12:48 +0000291/*******************************************************************************
292 * This function is responsible for handling all SMCs in the Trusted OS/App
293 * range from the non-secure state as defined in the SMC Calling Convention
294 * Document. It is also responsible for communicating with the Secure payload
295 * to delegate work and return results back to the non-secure state. Lastly it
296 * will also return any information that the secure payload needs to do the
297 * work assigned to it.
298 ******************************************************************************/
299uint64_t tspd_smc_handler(uint32_t smc_fid,
300 uint64_t x1,
301 uint64_t x2,
302 uint64_t x3,
303 uint64_t x4,
304 void *cookie,
305 void *handle,
306 uint64_t flags)
307{
Dan Handleye2712bc2014-04-10 15:37:22 +0100308 cpu_context_t *ns_cpu_context;
Soby Mathewda43b662015-07-08 21:45:46 +0100309 uint32_t linear_id = plat_my_core_pos(), ns;
Dan Handleye2712bc2014-04-10 15:37:22 +0100310 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100311 uint64_t rc;
312#if TSP_INIT_ASYNC
313 entry_point_info_t *next_image_info;
314#endif
Achin Gupta375f5382014-02-18 18:12:48 +0000315
316 /* Determine which security state this SMC originated from */
317 ns = is_caller_non_secure(flags);
318
319 switch (smc_fid) {
320
321 /*
Soby Mathew9f71f702014-05-09 20:49:17 +0100322 * This function ID is used by TSP to indicate that it was
323 * preempted by a normal world IRQ.
324 *
325 */
326 case TSP_PREEMPTED:
327 if (ns)
328 SMC_RET1(handle, SMC_UNK);
329
Soby Mathew47903c02015-01-13 15:48:26 +0000330 return tspd_handle_sp_preemption(handle);
Soby Mathew9f71f702014-05-09 20:49:17 +0100331
332 /*
Achin Guptaaeaab682014-05-09 13:21:31 +0100333 * This function ID is used only by the TSP to indicate that it has
Soby Mathew78664242015-11-13 02:08:43 +0000334 * finished handling a S-EL1 interrupt or was preempted by a higher
335 * priority pending EL3 interrupt. Execution should resume
Achin Guptaaeaab682014-05-09 13:21:31 +0100336 * in the normal world.
337 */
Soby Mathewbec98512015-09-03 18:29:38 +0100338 case TSP_HANDLED_S_EL1_INTR:
Achin Guptaaeaab682014-05-09 13:21:31 +0100339 if (ns)
340 SMC_RET1(handle, SMC_UNK);
341
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100342 assert(handle == cm_get_context(SECURE));
Achin Guptaaeaab682014-05-09 13:21:31 +0100343
344 /*
345 * Restore the relevant EL3 state which saved to service
346 * this SMC.
347 */
348 if (get_std_smc_active_flag(tsp_ctx->state)) {
349 SMC_SET_EL3(&tsp_ctx->cpu_ctx,
350 CTX_SPSR_EL3,
351 tsp_ctx->saved_spsr_el3);
352 SMC_SET_EL3(&tsp_ctx->cpu_ctx,
353 CTX_ELR_EL3,
354 tsp_ctx->saved_elr_el3);
Soby Mathewbec98512015-09-03 18:29:38 +0100355#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000356 /*
357 * Need to restore the previously interrupted
358 * secure context.
359 */
360 memcpy(&tsp_ctx->cpu_ctx, &tsp_ctx->sp_ctx,
361 TSPD_SP_CTX_SIZE);
362#endif
Achin Guptaaeaab682014-05-09 13:21:31 +0100363 }
364
365 /* Get a reference to the non-secure context */
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100366 ns_cpu_context = cm_get_context(NON_SECURE);
Achin Guptaaeaab682014-05-09 13:21:31 +0100367 assert(ns_cpu_context);
368
369 /*
370 * Restore non-secure state. There is no need to save the
371 * secure system register context since the TSP was supposed
372 * to preserve it during S-EL1 interrupt handling.
373 */
374 cm_el1_sysregs_context_restore(NON_SECURE);
375 cm_set_next_eret_context(NON_SECURE);
376
377 SMC_RET0((uint64_t) ns_cpu_context);
378
Achin Guptaaeaab682014-05-09 13:21:31 +0100379 /*
Achin Gupta375f5382014-02-18 18:12:48 +0000380 * This function ID is used only by the SP to indicate it has
381 * finished initialising itself after a cold boot
382 */
383 case TSP_ENTRY_DONE:
384 if (ns)
385 SMC_RET1(handle, SMC_UNK);
386
387 /*
388 * Stash the SP entry points information. This is done
389 * only once on the primary cpu
390 */
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100391 assert(tsp_vectors == NULL);
392 tsp_vectors = (tsp_vectors_t *) x1;
Achin Gupta375f5382014-02-18 18:12:48 +0000393
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100394 if (tsp_vectors) {
395 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
396
397 /*
398 * TSP has been successfully initialized. Register power
399 * managemnt hooks with PSCI
400 */
401 psci_register_spd_pm_hook(&tspd_pm);
402
403 /*
404 * Register an interrupt handler for S-EL1 interrupts
405 * when generated during code executing in the
406 * non-secure state.
407 */
408 flags = 0;
409 set_interrupt_rm_flag(flags, NON_SECURE);
410 rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
411 tspd_sel1_interrupt_handler,
412 flags);
413 if (rc)
414 panic();
Soby Mathew47903c02015-01-13 15:48:26 +0000415
Soby Mathewbec98512015-09-03 18:29:38 +0100416#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000417 /*
418 * Register an interrupt handler for NS interrupts when
419 * generated during code executing in secure state are
420 * routed to EL3.
421 */
422 flags = 0;
423 set_interrupt_rm_flag(flags, SECURE);
424
425 rc = register_interrupt_type_handler(INTR_TYPE_NS,
426 tspd_ns_interrupt_handler,
427 flags);
428 if (rc)
429 panic();
430
431 /*
Soby Mathewbc912822015-09-22 12:01:18 +0100432 * Disable the NS interrupt locally.
Soby Mathew47903c02015-01-13 15:48:26 +0000433 */
434 disable_intr_rm_local(INTR_TYPE_NS, SECURE);
435#endif
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100436 }
437
438
439#if TSP_INIT_ASYNC
440 /* Save the Secure EL1 system register context */
441 assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx);
442 cm_el1_sysregs_context_save(SECURE);
443
444 /* Program EL3 registers to enable entry into the next EL */
445 next_image_info = bl31_plat_get_next_image_ep_info(NON_SECURE);
446 assert(next_image_info);
447 assert(NON_SECURE ==
448 GET_SECURITY_STATE(next_image_info->h.attr));
449
Soby Mathewda43b662015-07-08 21:45:46 +0100450 cm_init_my_context(next_image_info);
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100451 cm_prepare_el3_exit(NON_SECURE);
452 SMC_RET0(cm_get_context(NON_SECURE));
453#else
Achin Gupta375f5382014-02-18 18:12:48 +0000454 /*
455 * SP reports completion. The SPD must have initiated
456 * the original request through a synchronous entry
457 * into the SP. Jump back to the original C runtime
458 * context.
459 */
Achin Gupta916a2c12014-02-09 23:11:46 +0000460 tspd_synchronous_sp_exit(tsp_ctx, x1);
Vikram Kanigiri4e813412014-07-15 16:49:22 +0100461#endif
Achin Gupta375f5382014-02-18 18:12:48 +0000462
Achin Gupta607084e2014-02-09 18:24:19 +0000463 /*
Sandrine Bailleuxf4119ec2015-12-17 13:58:58 +0000464 * These function IDs are used only by the SP to indicate it has
Achin Gupta607084e2014-02-09 18:24:19 +0000465 * finished:
466 * 1. turning itself on in response to an earlier psci
467 * cpu_on request
468 * 2. resuming itself after an earlier psci cpu_suspend
469 * request.
470 */
471 case TSP_ON_DONE:
472 case TSP_RESUME_DONE:
473
474 /*
Sandrine Bailleuxf4119ec2015-12-17 13:58:58 +0000475 * These function IDs are used only by the SP to indicate it has
Achin Gupta607084e2014-02-09 18:24:19 +0000476 * finished:
477 * 1. suspending itself after an earlier psci cpu_suspend
478 * request.
479 * 2. turning itself off in response to an earlier psci
480 * cpu_off request.
481 */
482 case TSP_OFF_DONE:
483 case TSP_SUSPEND_DONE:
Juan Castillo4dc4a472014-08-12 11:17:06 +0100484 case TSP_SYSTEM_OFF_DONE:
485 case TSP_SYSTEM_RESET_DONE:
Achin Gupta607084e2014-02-09 18:24:19 +0000486 if (ns)
487 SMC_RET1(handle, SMC_UNK);
488
489 /*
490 * SP reports completion. The SPD must have initiated the
491 * original request through a synchronous entry into the SP.
492 * Jump back to the original C runtime context, and pass x1 as
493 * return value to the caller
494 */
Achin Gupta916a2c12014-02-09 23:11:46 +0000495 tspd_synchronous_sp_exit(tsp_ctx, x1);
Achin Gupta607084e2014-02-09 18:24:19 +0000496
Achin Gupta916a2c12014-02-09 23:11:46 +0000497 /*
498 * Request from non-secure client to perform an
499 * arithmetic operation or response from secure
500 * payload to an earlier request.
501 */
Soby Mathew9f71f702014-05-09 20:49:17 +0100502 case TSP_FAST_FID(TSP_ADD):
503 case TSP_FAST_FID(TSP_SUB):
504 case TSP_FAST_FID(TSP_MUL):
505 case TSP_FAST_FID(TSP_DIV):
506
507 case TSP_STD_FID(TSP_ADD):
508 case TSP_STD_FID(TSP_SUB):
509 case TSP_STD_FID(TSP_MUL):
510 case TSP_STD_FID(TSP_DIV):
Achin Gupta916a2c12014-02-09 23:11:46 +0000511 if (ns) {
512 /*
513 * This is a fresh request from the non-secure client.
514 * The parameters are in x1 and x2. Figure out which
515 * registers need to be preserved, save the non-secure
516 * state and send the request to the secure payload.
517 */
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100518 assert(handle == cm_get_context(NON_SECURE));
Soby Mathew9f71f702014-05-09 20:49:17 +0100519
520 /* Check if we are already preempted */
521 if (get_std_smc_active_flag(tsp_ctx->state))
522 SMC_RET1(handle, SMC_UNK);
523
Achin Gupta916a2c12014-02-09 23:11:46 +0000524 cm_el1_sysregs_context_save(NON_SECURE);
525
526 /* Save x1 and x2 for use by TSP_GET_ARGS call below */
Soby Mathew9f71f702014-05-09 20:49:17 +0100527 store_tsp_args(tsp_ctx, x1, x2);
Achin Gupta916a2c12014-02-09 23:11:46 +0000528
529 /*
530 * We are done stashing the non-secure context. Ask the
531 * secure payload to do the work now.
532 */
533
534 /*
535 * Verify if there is a valid context to use, copy the
536 * operation type and parameters to the secure context
537 * and jump to the fast smc entry point in the secure
538 * payload. Entry into S-EL1 will take place upon exit
539 * from this function.
540 */
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100541 assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE));
Soby Mathew9f71f702014-05-09 20:49:17 +0100542
543 /* Set appropriate entry for SMC.
544 * We expect the TSP to manage the PSTATE.I and PSTATE.F
545 * flags as appropriate.
546 */
547 if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) {
548 cm_set_elr_el3(SECURE, (uint64_t)
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100549 &tsp_vectors->fast_smc_entry);
Soby Mathew9f71f702014-05-09 20:49:17 +0100550 } else {
551 set_std_smc_active_flag(tsp_ctx->state);
552 cm_set_elr_el3(SECURE, (uint64_t)
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100553 &tsp_vectors->std_smc_entry);
Soby Mathewbec98512015-09-03 18:29:38 +0100554#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000555 /*
556 * Enable the routing of NS interrupts to EL3
557 * during STD SMC processing on this core.
558 */
559 enable_intr_rm_local(INTR_TYPE_NS, SECURE);
560#endif
Soby Mathew9f71f702014-05-09 20:49:17 +0100561 }
562
Achin Gupta916a2c12014-02-09 23:11:46 +0000563 cm_el1_sysregs_context_restore(SECURE);
564 cm_set_next_eret_context(SECURE);
Soby Mathew9f71f702014-05-09 20:49:17 +0100565 SMC_RET3(&tsp_ctx->cpu_ctx, smc_fid, x1, x2);
Achin Gupta916a2c12014-02-09 23:11:46 +0000566 } else {
567 /*
568 * This is the result from the secure client of an
Soby Mathew9f71f702014-05-09 20:49:17 +0100569 * earlier request. The results are in x1-x3. Copy it
Achin Gupta916a2c12014-02-09 23:11:46 +0000570 * into the non-secure context, save the secure state
571 * and return to the non-secure state.
572 */
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100573 assert(handle == cm_get_context(SECURE));
Achin Gupta916a2c12014-02-09 23:11:46 +0000574 cm_el1_sysregs_context_save(SECURE);
575
576 /* Get a reference to the non-secure context */
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100577 ns_cpu_context = cm_get_context(NON_SECURE);
Achin Gupta916a2c12014-02-09 23:11:46 +0000578 assert(ns_cpu_context);
Achin Gupta916a2c12014-02-09 23:11:46 +0000579
580 /* Restore non-secure state */
581 cm_el1_sysregs_context_restore(NON_SECURE);
582 cm_set_next_eret_context(NON_SECURE);
Soby Mathew47903c02015-01-13 15:48:26 +0000583 if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_STD) {
Soby Mathew9f71f702014-05-09 20:49:17 +0100584 clr_std_smc_active_flag(tsp_ctx->state);
Soby Mathewbec98512015-09-03 18:29:38 +0100585#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000586 /*
587 * Disable the routing of NS interrupts to EL3
588 * after STD SMC processing is finished on this
589 * core.
590 */
591 disable_intr_rm_local(INTR_TYPE_NS, SECURE);
592#endif
593 }
594
Soby Mathew9f71f702014-05-09 20:49:17 +0100595 SMC_RET3(ns_cpu_context, x1, x2, x3);
Achin Gupta916a2c12014-02-09 23:11:46 +0000596 }
597
598 break;
599
600 /*
Soby Mathew9f71f702014-05-09 20:49:17 +0100601 * Request from non secure world to resume the preempted
602 * Standard SMC call.
603 */
604 case TSP_FID_RESUME:
Soby Mathew3d578512014-05-27 10:20:01 +0100605 /* RESUME should be invoked only by normal world */
606 if (!ns) {
607 assert(0);
608 break;
609 }
Soby Mathew9f71f702014-05-09 20:49:17 +0100610
Soby Mathew3d578512014-05-27 10:20:01 +0100611 /*
612 * This is a resume request from the non-secure client.
613 * save the non-secure state and send the request to
614 * the secure payload.
615 */
Andrew Thoelkea2f65532014-05-14 17:09:32 +0100616 assert(handle == cm_get_context(NON_SECURE));
Soby Mathew9f71f702014-05-09 20:49:17 +0100617
Soby Mathew3d578512014-05-27 10:20:01 +0100618 /* Check if we are already preempted before resume */
619 if (!get_std_smc_active_flag(tsp_ctx->state))
620 SMC_RET1(handle, SMC_UNK);
Soby Mathew9f71f702014-05-09 20:49:17 +0100621
Soby Mathew3d578512014-05-27 10:20:01 +0100622 cm_el1_sysregs_context_save(NON_SECURE);
Soby Mathew9f71f702014-05-09 20:49:17 +0100623
Soby Mathew3d578512014-05-27 10:20:01 +0100624 /*
625 * We are done stashing the non-secure context. Ask the
626 * secure payload to do the work now.
627 */
Soby Mathewbec98512015-09-03 18:29:38 +0100628#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000629 /*
630 * Enable the routing of NS interrupts to EL3 during resumption
631 * of STD SMC call on this core.
632 */
633 enable_intr_rm_local(INTR_TYPE_NS, SECURE);
634#endif
635
636
Soby Mathew9f71f702014-05-09 20:49:17 +0100637
Soby Mathew3d578512014-05-27 10:20:01 +0100638 /* We just need to return to the preempted point in
639 * TSP and the execution will resume as normal.
640 */
641 cm_el1_sysregs_context_restore(SECURE);
642 cm_set_next_eret_context(SECURE);
643 SMC_RET0(&tsp_ctx->cpu_ctx);
Soby Mathew9f71f702014-05-09 20:49:17 +0100644
645 /*
Achin Gupta916a2c12014-02-09 23:11:46 +0000646 * This is a request from the secure payload for more arguments
647 * for an ongoing arithmetic operation requested by the
648 * non-secure world. Simply return the arguments from the non-
649 * secure client in the original call.
650 */
651 case TSP_GET_ARGS:
652 if (ns)
653 SMC_RET1(handle, SMC_UNK);
654
Soby Mathew9f71f702014-05-09 20:49:17 +0100655 get_tsp_args(tsp_ctx, x1, x2);
656 SMC_RET2(handle, x1, x2);
Achin Gupta916a2c12014-02-09 23:11:46 +0000657
Jeenu Viswambharandf1ddb52014-02-28 11:23:35 +0000658 case TOS_CALL_COUNT:
659 /*
660 * Return the number of service function IDs implemented to
661 * provide service to non-secure
662 */
663 SMC_RET1(handle, TSP_NUM_FID);
664
665 case TOS_UID:
666 /* Return TSP UID to the caller */
667 SMC_UUID_RET(handle, tsp_uuid);
668
669 case TOS_CALL_VERSION:
670 /* Return the version of current implementation */
671 SMC_RET2(handle, TSP_VERSION_MAJOR, TSP_VERSION_MINOR);
672
Achin Gupta375f5382014-02-18 18:12:48 +0000673 default:
Achin Gupta607084e2014-02-09 18:24:19 +0000674 break;
Achin Gupta375f5382014-02-18 18:12:48 +0000675 }
676
Achin Gupta607084e2014-02-09 18:24:19 +0000677 SMC_RET1(handle, SMC_UNK);
Achin Gupta375f5382014-02-18 18:12:48 +0000678}
679
Soby Mathew9f71f702014-05-09 20:49:17 +0100680/* Define a SPD runtime service descriptor for fast SMC calls */
Achin Gupta375f5382014-02-18 18:12:48 +0000681DECLARE_RT_SVC(
Soby Mathew9f71f702014-05-09 20:49:17 +0100682 tspd_fast,
Achin Gupta375f5382014-02-18 18:12:48 +0000683
684 OEN_TOS_START,
685 OEN_TOS_END,
686 SMC_TYPE_FAST,
687 tspd_setup,
688 tspd_smc_handler
689);
Soby Mathew9f71f702014-05-09 20:49:17 +0100690
691/* Define a SPD runtime service descriptor for standard SMC calls */
692DECLARE_RT_SVC(
693 tspd_std,
694
695 OEN_TOS_START,
696 OEN_TOS_END,
697 SMC_TYPE_STD,
698 NULL,
699 tspd_smc_handler
700);