blob: 6de4858b0508630d8b4c832dc536e5cfd37ec4fb [file] [log] [blame]
Antonio Nino Diazc41f2062017-10-24 10:07:35 +01001/*
Antonio Nino Diaz35b37f02018-01-08 17:33:34 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <assert.h>
9#include <bl31.h>
10#include <context_mgmt.h>
11#include <debug.h>
Sughosh Ganue77f9e82018-11-14 11:06:24 +053012#include <ehf.h>
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010013#include <errno.h>
Antonio Nino Diaz35b37f02018-01-08 17:33:34 +000014#include <mm_svc.h>
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010015#include <platform.h>
16#include <runtime_svc.h>
Antonio Nino Diaz3c817f42018-03-21 10:49:27 +000017#include <smccc.h>
18#include <smccc_helpers.h>
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010019#include <spinlock.h>
20#include <spm_svc.h>
21#include <utils.h>
22#include <xlat_tables_v2.h>
23
24#include "spm_private.h"
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +010025
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010026/*******************************************************************************
27 * Secure Partition context information.
28 ******************************************************************************/
Antonio Nino Diaz28759312018-05-22 16:26:48 +010029static sp_context_t sp_ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010030
31/*******************************************************************************
Antonio Nino Diazc4f27522018-05-23 09:09:41 +010032 * Set state of a Secure Partition context.
33 ******************************************************************************/
34void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
35{
36 spin_lock(&(sp_ptr->state_lock));
37 sp_ptr->state = state;
38 spin_unlock(&(sp_ptr->state_lock));
39}
40
41/*******************************************************************************
42 * Wait until the state of a Secure Partition is the specified one and change it
43 * to the desired state.
44 ******************************************************************************/
45void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
46{
47 int success = 0;
48
49 while (success == 0) {
50 spin_lock(&(sp_ptr->state_lock));
51
52 if (sp_ptr->state == from) {
53 sp_ptr->state = to;
54
55 success = 1;
56 }
57
58 spin_unlock(&(sp_ptr->state_lock));
59 }
60}
61
62/*******************************************************************************
63 * Check if the state of a Secure Partition is the specified one and, if so,
64 * change it to the desired state. Returns 0 on success, -1 on error.
65 ******************************************************************************/
66int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
67{
68 int ret = -1;
69
70 spin_lock(&(sp_ptr->state_lock));
71
72 if (sp_ptr->state == from) {
73 sp_ptr->state = to;
74
75 ret = 0;
76 }
77
78 spin_unlock(&(sp_ptr->state_lock));
79
80 return ret;
81}
82
83/*******************************************************************************
Antonio Nino Diazda50cd02018-06-15 16:21:01 +010084 * This function takes an SP context pointer and performs a synchronous entry
85 * into it.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010086 ******************************************************************************/
Antonio Nino Diazda50cd02018-06-15 16:21:01 +010087static uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010088{
Antonio Nino Diazda50cd02018-06-15 16:21:01 +010089 uint64_t rc;
90
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +010091 assert(sp_ctx != NULL);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010092
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +010093 /* Assign the context of the SP to this CPU */
94 cm_set_context(&(sp_ctx->cpu_ctx), SECURE);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010095
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +010096 /* Restore the context assigned above */
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010097 cm_el1_sysregs_context_restore(SECURE);
98 cm_set_next_eret_context(SECURE);
99
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100100 /* Invalidate TLBs at EL1. */
101 tlbivmalle1();
102 dsbish();
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100103
104 /* Enter Secure Partition */
105 rc = spm_secure_partition_enter(&sp_ctx->c_rt_ctx);
106
107 /* Save secure state */
108 cm_el1_sysregs_context_save(SECURE);
109
110 return rc;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100111}
112
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100113/*******************************************************************************
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100114 * This function returns to the place where spm_sp_synchronous_entry() was
115 * called originally.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100116 ******************************************************************************/
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100117__dead2 static void spm_sp_synchronous_exit(uint64_t rc)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100118{
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100119 sp_context_t *ctx = &sp_ctx;
120
121 /*
122 * The SPM must have initiated the original request through a
123 * synchronous entry into the secure partition. Jump back to the
124 * original C runtime context with the value of rc in x0;
125 */
126 spm_secure_partition_exit(ctx->c_rt_ctx, rc);
127
128 panic();
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100129}
130
131/*******************************************************************************
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100132 * Jump to each Secure Partition for the first time.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100133 ******************************************************************************/
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100134static int32_t spm_init(void)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100135{
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100136 uint64_t rc;
Antonio Nino Diaz28759312018-05-22 16:26:48 +0100137 sp_context_t *ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100138
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100139 INFO("Secure Partition init...\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100140
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100141 ctx = &sp_ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100142
Antonio Nino Diazc4f27522018-05-23 09:09:41 +0100143 ctx->state = SP_STATE_RESET;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100144
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100145 rc = spm_sp_synchronous_entry(ctx);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100146 assert(rc == 0);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100147
Antonio Nino Diazc4f27522018-05-23 09:09:41 +0100148 ctx->state = SP_STATE_IDLE;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100149
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100150 INFO("Secure Partition initialized.\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100151
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100152 return rc;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100153}
154
155/*******************************************************************************
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100156 * Initialize contexts of all Secure Partitions.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100157 ******************************************************************************/
158int32_t spm_setup(void)
159{
Antonio Nino Diaz840627f2018-11-27 08:36:02 +0000160 int rc;
Antonio Nino Diaz28759312018-05-22 16:26:48 +0100161 sp_context_t *ctx;
Antonio Nino Diaz840627f2018-11-27 08:36:02 +0000162 void *sp_base, *rd_base;
163 size_t sp_size, rd_size;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100164
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100165 /* Disable MMU at EL1 (initialized by BL2) */
166 disable_mmu_icache_el1();
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100167
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100168 /* Initialize context of the SP */
169 INFO("Secure Partition context setup start...\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100170
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100171 ctx = &sp_ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100172
Antonio Nino Diaz840627f2018-11-27 08:36:02 +0000173 rc = plat_spm_sp_get_next_address(&sp_base, &sp_size,
174 &rd_base, &rd_size);
175 if (rc != 0) {
176 ERROR("No Secure Partition found.\n");
177 panic();
178 }
179
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100180 /* Assign translation tables context. */
181 ctx->xlat_ctx_handle = spm_get_sp_xlat_context();
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100182
Antonio Nino Diaz840627f2018-11-27 08:36:02 +0000183 /* Save location of the image in physical memory */
184 ctx->image_base = (uintptr_t)sp_base;
185 ctx->image_size = sp_size;
186
187 rc = plat_spm_sp_rd_load(&ctx->rd, rd_base, rd_size);
188 if (rc < 0) {
189 ERROR("Error while loading RD blob.\n");
190 panic();
191 }
192
Antonio Nino Diaz28759312018-05-22 16:26:48 +0100193 spm_sp_setup(ctx);
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100194
195 /* Register init function for deferred init. */
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100196 bl31_register_bl32_init(&spm_init);
197
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100198 INFO("Secure Partition setup done.\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100199
200 return 0;
201}
202
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100203/*******************************************************************************
Antonio Nino Diaz10c3e982018-06-20 12:05:02 +0100204 * Function to perform a call to a Secure Partition.
205 ******************************************************************************/
206uint64_t spm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3)
207{
208 uint64_t rc;
209 sp_context_t *sp_ptr = &sp_ctx;
210
211 /* Wait until the Secure Partition is idle and set it to busy. */
212 sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY);
213
214 /* Set values for registers on SP entry */
215 cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx);
216
217 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid);
218 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1);
219 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2);
220 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3);
221
222 /* Jump to the Secure Partition. */
223 rc = spm_sp_synchronous_entry(sp_ptr);
224
225 /* Flag Secure Partition as idle. */
226 assert(sp_ptr->state == SP_STATE_BUSY);
227 sp_state_set(sp_ptr, SP_STATE_IDLE);
228
229 return rc;
230}
231
232/*******************************************************************************
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100233 * MM_COMMUNICATE handler
234 ******************************************************************************/
235static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie,
236 uint64_t comm_buffer_address,
237 uint64_t comm_size_address, void *handle)
238{
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100239 uint64_t rc;
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100240
241 /* Cookie. Reserved for future use. It must be zero. */
242 if (mm_cookie != 0U) {
243 ERROR("MM_COMMUNICATE: cookie is not zero\n");
244 SMC_RET1(handle, SPM_INVALID_PARAMETER);
245 }
246
247 if (comm_buffer_address == 0U) {
248 ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
249 SMC_RET1(handle, SPM_INVALID_PARAMETER);
250 }
251
252 if (comm_size_address != 0U) {
253 VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
254 }
255
Sughosh Ganue77f9e82018-11-14 11:06:24 +0530256 /*
257 * The current secure partition design mandates
258 * - at any point, only a single core can be
259 * executing in the secure partiton.
260 * - a core cannot be preempted by an interrupt
261 * while executing in secure partition.
262 * Raise the running priority of the core to the
263 * interrupt level configured for secure partition
264 * so as to block any interrupt from preempting this
265 * core.
266 */
267 ehf_activate_priority(PLAT_SP_PRI);
268
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100269 /* Save the Normal world context */
270 cm_el1_sysregs_context_save(NON_SECURE);
271
Antonio Nino Diaz10c3e982018-06-20 12:05:02 +0100272 rc = spm_sp_call(smc_fid, comm_buffer_address, comm_size_address,
273 plat_my_core_pos());
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100274
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100275 /* Restore non-secure state */
276 cm_el1_sysregs_context_restore(NON_SECURE);
277 cm_set_next_eret_context(NON_SECURE);
278
Sughosh Ganue77f9e82018-11-14 11:06:24 +0530279 /*
280 * Exited from secure partition. This core can take
281 * interrupts now.
282 */
283 ehf_deactivate_priority(PLAT_SP_PRI);
284
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100285 SMC_RET1(handle, rc);
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100286}
287
288/*******************************************************************************
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100289 * Secure Partition Manager SMC handler.
290 ******************************************************************************/
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100291uint64_t spm_smc_handler(uint32_t smc_fid,
292 uint64_t x1,
293 uint64_t x2,
294 uint64_t x3,
295 uint64_t x4,
296 void *cookie,
297 void *handle,
298 uint64_t flags)
299{
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100300 unsigned int ns;
301
302 /* Determine which security state this SMC originated from */
303 ns = is_caller_non_secure(flags);
304
305 if (ns == SMC_FROM_SECURE) {
306
307 /* Handle SMCs from Secure world. */
308
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100309 assert(handle == cm_get_context(SECURE));
310
311 /* Make next ERET jump to S-EL0 instead of S-EL1. */
312 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1());
313
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100314 switch (smc_fid) {
315
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000316 case SPM_VERSION_AARCH32:
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100317 SMC_RET1(handle, SPM_VERSION_COMPILED);
318
319 case SP_EVENT_COMPLETE_AARCH64:
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100320 spm_sp_synchronous_exit(x1);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100321
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000322 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
323 INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100324
Antonio Nino Diazc4f27522018-05-23 09:09:41 +0100325 if (sp_ctx.state != SP_STATE_RESET) {
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000326 WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100327 SMC_RET1(handle, SPM_NOT_SUPPORTED);
328 }
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100329 SMC_RET1(handle,
330 spm_memory_attributes_get_smc_handler(
331 &sp_ctx, x1));
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100332
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000333 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
334 INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100335
Antonio Nino Diazc4f27522018-05-23 09:09:41 +0100336 if (sp_ctx.state != SP_STATE_RESET) {
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000337 WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100338 SMC_RET1(handle, SPM_NOT_SUPPORTED);
339 }
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100340 SMC_RET1(handle,
341 spm_memory_attributes_set_smc_handler(
342 &sp_ctx, x1, x2, x3));
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100343 default:
344 break;
345 }
346 } else {
347
348 /* Handle SMCs from Non-secure world. */
349
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100350 assert(handle == cm_get_context(NON_SECURE));
351
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100352 switch (smc_fid) {
353
Antonio Nino Diaz35b37f02018-01-08 17:33:34 +0000354 case MM_VERSION_AARCH32:
355 SMC_RET1(handle, MM_VERSION_COMPILED);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100356
Sandrine Bailleuxb31ee6b2017-12-01 09:44:21 +0000357 case MM_COMMUNICATE_AARCH32:
358 case MM_COMMUNICATE_AARCH64:
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100359 return mm_communicate(smc_fid, x1, x2, x3, handle);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100360
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000361 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
362 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100363 /* SMC interfaces reserved for secure callers. */
364 SMC_RET1(handle, SPM_NOT_SUPPORTED);
365
366 default:
367 break;
368 }
369 }
370
371 SMC_RET1(handle, SMC_UNK);
372}