blob: ec287731a2965a5152fa87d32a873285d6b93cbb [file] [log] [blame]
Achin Gupta375f5382014-02-18 18:12:48 +00001/*
2 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
3 *
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 ******************************************************************************/
41#include <stdio.h>
42#include <string.h>
43#include <assert.h>
44#include <arch_helpers.h>
45#include <console.h>
46#include <platform.h>
Achin Gupta375f5382014-02-18 18:12:48 +000047#include <context_mgmt.h>
48#include <runtime_svc.h>
49#include <bl31.h>
50#include <tsp.h>
51#include <psci.h>
52#include <tspd_private.h>
53#include <debug.h>
54
55/*******************************************************************************
56 * Single structure to hold information about the various entry points into the
57 * Secure Payload. It is initialised once on the primary core after a cold boot.
58 ******************************************************************************/
59entry_info *tsp_entry_info;
60
61/*******************************************************************************
62 * Array to keep track of per-cpu Secure Payload state
63 ******************************************************************************/
64tsp_context tspd_sp_context[TSPD_CORE_COUNT];
65
Jeenu Viswambharan7f366602014-02-20 17:11:00 +000066
67int32_t tspd_init(meminfo *bl32_meminfo);
68
69
Achin Gupta375f5382014-02-18 18:12:48 +000070/*******************************************************************************
71 * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type
72 * (aarch32/aarch64) if not already known and initialises the context for entry
73 * into the SP for its initialisation.
74 ******************************************************************************/
75int32_t tspd_setup(void)
76{
77 el_change_info *image_info;
78 int32_t rc;
79 uint64_t mpidr = read_mpidr();
80 uint32_t linear_id;
81
82 linear_id = platform_get_core_pos(mpidr);
83
84 /*
85 * Get information about the Secure Payload (BL32) image. Its
86 * absence is a critical failure. TODO: Add support to
87 * conditionally include the SPD service
88 */
89 image_info = bl31_get_next_image_info(SECURE);
90 assert(image_info);
91
92 /*
Jeenu Viswambharan7f366602014-02-20 17:11:00 +000093 * If there's no valid entry point for SP, we return a non-zero value
94 * signalling failure initializing the service. We bail out without
95 * registering any handlers
96 */
97 if (!image_info->entrypoint)
98 return 1;
99
100 /*
Achin Gupta375f5382014-02-18 18:12:48 +0000101 * We could inspect the SP image and determine it's execution
102 * state i.e whether AArch32 or AArch64. Assuming it's AArch64
103 * for the time being.
104 */
105 rc = tspd_init_secure_context(image_info->entrypoint,
106 TSP_AARCH64,
107 mpidr,
108 &tspd_sp_context[linear_id]);
109 assert(rc == 0);
110
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000111 /*
112 * All TSPD initialization done. Now register our init function with
113 * BL31 for deferred invocation
114 */
115 bl31_register_bl32_init(&tspd_init);
116
Achin Gupta375f5382014-02-18 18:12:48 +0000117 return rc;
118}
119
120/*******************************************************************************
121 * This function passes control to the Secure Payload image (BL32) for the first
122 * time on the primary cpu after a cold boot. It assumes that a valid secure
123 * context has already been created by tspd_setup() which can be directly used.
124 * It also assumes that a valid non-secure context has been initialised by PSCI
125 * so it does not need to save and restore any non-secure state. This function
126 * performs a synchronous entry into the Secure payload. The SP passes control
127 * back to this routine through a SMC. It also passes the extents of memory made
128 * available to BL32 by BL31.
129 ******************************************************************************/
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000130int32_t tspd_init(meminfo *bl32_meminfo)
Achin Gupta375f5382014-02-18 18:12:48 +0000131{
132 uint64_t mpidr = read_mpidr();
133 uint32_t linear_id = platform_get_core_pos(mpidr);
134 uint64_t rc;
135 tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
136
137 /*
138 * Arrange for passing a pointer to the meminfo structure
139 * describing the memory extents available to the secure
140 * payload.
141 * TODO: We are passing a pointer to BL31 internal memory
142 * whereas this structure should be copied to a communication
143 * buffer between the SP and SPD.
144 */
145 write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
146 CTX_GPREG_X0,
147 (uint64_t) bl32_meminfo);
148
Achin Gupta607084e2014-02-09 18:24:19 +0000149 /*
150 * Arrange for an entry into the test secure payload. We expect an array
151 * of vectors in return
152 */
Achin Gupta375f5382014-02-18 18:12:48 +0000153 rc = tspd_synchronous_sp_entry(tsp_ctx);
154 assert(rc != 0);
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000155 if (rc) {
Achin Gupta375f5382014-02-18 18:12:48 +0000156 tsp_ctx->state = TSP_STATE_ON;
157
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000158 /*
159 * TSP has been successfully initialized. Register power
160 * managemnt hooks with PSCI
161 */
162 psci_register_spd_pm_hook(&tspd_pm);
163 }
164
Achin Gupta375f5382014-02-18 18:12:48 +0000165 return rc;
166}
167
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000168
Achin Gupta375f5382014-02-18 18:12:48 +0000169/*******************************************************************************
170 * This function is responsible for handling all SMCs in the Trusted OS/App
171 * range from the non-secure state as defined in the SMC Calling Convention
172 * Document. It is also responsible for communicating with the Secure payload
173 * to delegate work and return results back to the non-secure state. Lastly it
174 * will also return any information that the secure payload needs to do the
175 * work assigned to it.
176 ******************************************************************************/
177uint64_t tspd_smc_handler(uint32_t smc_fid,
178 uint64_t x1,
179 uint64_t x2,
180 uint64_t x3,
181 uint64_t x4,
182 void *cookie,
183 void *handle,
184 uint64_t flags)
185{
Achin Gupta916a2c12014-02-09 23:11:46 +0000186 cpu_context *ns_cpu_context;
187 gp_regs *ns_gp_regs;
Achin Gupta375f5382014-02-18 18:12:48 +0000188 unsigned long mpidr = read_mpidr();
189 uint32_t linear_id = platform_get_core_pos(mpidr), ns;
Achin Gupta916a2c12014-02-09 23:11:46 +0000190 tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta375f5382014-02-18 18:12:48 +0000191
192 /* Determine which security state this SMC originated from */
193 ns = is_caller_non_secure(flags);
194
195 switch (smc_fid) {
196
197 /*
198 * This function ID is used only by the SP to indicate it has
199 * finished initialising itself after a cold boot
200 */
201 case TSP_ENTRY_DONE:
202 if (ns)
203 SMC_RET1(handle, SMC_UNK);
204
205 /*
206 * Stash the SP entry points information. This is done
207 * only once on the primary cpu
208 */
209 assert(tsp_entry_info == NULL);
210 tsp_entry_info = (entry_info *) x1;
211
212 /*
213 * SP reports completion. The SPD must have initiated
214 * the original request through a synchronous entry
215 * into the SP. Jump back to the original C runtime
216 * context.
217 */
Achin Gupta916a2c12014-02-09 23:11:46 +0000218 tspd_synchronous_sp_exit(tsp_ctx, x1);
Achin Gupta375f5382014-02-18 18:12:48 +0000219
220 /* Should never reach here */
221 assert(0);
222
Achin Gupta607084e2014-02-09 18:24:19 +0000223 /*
224 * These function IDs is used only by the SP to indicate it has
225 * finished:
226 * 1. turning itself on in response to an earlier psci
227 * cpu_on request
228 * 2. resuming itself after an earlier psci cpu_suspend
229 * request.
230 */
231 case TSP_ON_DONE:
232 case TSP_RESUME_DONE:
233
234 /*
235 * These function IDs is used only by the SP to indicate it has
236 * finished:
237 * 1. suspending itself after an earlier psci cpu_suspend
238 * request.
239 * 2. turning itself off in response to an earlier psci
240 * cpu_off request.
241 */
242 case TSP_OFF_DONE:
243 case TSP_SUSPEND_DONE:
244 if (ns)
245 SMC_RET1(handle, SMC_UNK);
246
247 /*
248 * SP reports completion. The SPD must have initiated the
249 * original request through a synchronous entry into the SP.
250 * Jump back to the original C runtime context, and pass x1 as
251 * return value to the caller
252 */
Achin Gupta916a2c12014-02-09 23:11:46 +0000253 tspd_synchronous_sp_exit(tsp_ctx, x1);
Achin Gupta607084e2014-02-09 18:24:19 +0000254
255 /* Should never reach here */
256 assert(0);
257
Achin Gupta916a2c12014-02-09 23:11:46 +0000258 /*
259 * Request from non-secure client to perform an
260 * arithmetic operation or response from secure
261 * payload to an earlier request.
262 */
263 case TSP_FID_ADD:
264 case TSP_FID_SUB:
265 case TSP_FID_MUL:
266 case TSP_FID_DIV:
267 if (ns) {
268 /*
269 * This is a fresh request from the non-secure client.
270 * The parameters are in x1 and x2. Figure out which
271 * registers need to be preserved, save the non-secure
272 * state and send the request to the secure payload.
273 */
274 assert(handle == cm_get_context(mpidr, NON_SECURE));
275 cm_el1_sysregs_context_save(NON_SECURE);
276
277 /* Save x1 and x2 for use by TSP_GET_ARGS call below */
278 SMC_SET_GP(handle, CTX_GPREG_X1, x1);
279 SMC_SET_GP(handle, CTX_GPREG_X2, x2);
280
281 /*
282 * We are done stashing the non-secure context. Ask the
283 * secure payload to do the work now.
284 */
285
286 /*
287 * Verify if there is a valid context to use, copy the
288 * operation type and parameters to the secure context
289 * and jump to the fast smc entry point in the secure
290 * payload. Entry into S-EL1 will take place upon exit
291 * from this function.
292 */
293 assert(&tsp_ctx->cpu_ctx == cm_get_context(mpidr, SECURE));
294 set_aapcs_args7(&tsp_ctx->cpu_ctx, smc_fid, x1, x2, 0, 0,
295 0, 0, 0);
296 cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->fast_smc_entry);
297 cm_el1_sysregs_context_restore(SECURE);
298 cm_set_next_eret_context(SECURE);
299
300 return smc_fid;
301 } else {
302 /*
303 * This is the result from the secure client of an
304 * earlier request. The results are in x1-x2. Copy it
305 * into the non-secure context, save the secure state
306 * and return to the non-secure state.
307 */
308 assert(handle == cm_get_context(mpidr, SECURE));
309 cm_el1_sysregs_context_save(SECURE);
310
311 /* Get a reference to the non-secure context */
312 ns_cpu_context = cm_get_context(mpidr, NON_SECURE);
313 assert(ns_cpu_context);
314 ns_gp_regs = get_gpregs_ctx(ns_cpu_context);
315
316 /* Restore non-secure state */
317 cm_el1_sysregs_context_restore(NON_SECURE);
318 cm_set_next_eret_context(NON_SECURE);
319
320 SMC_RET2(ns_gp_regs, x1, x2);
321 }
322
323 break;
324
325 /*
326 * This is a request from the secure payload for more arguments
327 * for an ongoing arithmetic operation requested by the
328 * non-secure world. Simply return the arguments from the non-
329 * secure client in the original call.
330 */
331 case TSP_GET_ARGS:
332 if (ns)
333 SMC_RET1(handle, SMC_UNK);
334
335 /* Get a reference to the non-secure context */
336 ns_cpu_context = cm_get_context(mpidr, NON_SECURE);
337 assert(ns_cpu_context);
338 ns_gp_regs = get_gpregs_ctx(ns_cpu_context);
339
340 SMC_RET2(handle, read_ctx_reg(ns_gp_regs, CTX_GPREG_X1),
341 read_ctx_reg(ns_gp_regs, CTX_GPREG_X2));
342
Achin Gupta375f5382014-02-18 18:12:48 +0000343 default:
Achin Gupta607084e2014-02-09 18:24:19 +0000344 break;
Achin Gupta375f5382014-02-18 18:12:48 +0000345 }
346
Achin Gupta607084e2014-02-09 18:24:19 +0000347 SMC_RET1(handle, SMC_UNK);
Achin Gupta375f5382014-02-18 18:12:48 +0000348}
349
350/* Define a SPD runtime service descriptor */
351DECLARE_RT_SVC(
352 spd,
353
354 OEN_TOS_START,
355 OEN_TOS_END,
356 SMC_TYPE_FAST,
357 tspd_setup,
358 tspd_smc_handler
359);