blob: 1971516b861a0f16d1d62d4dfefc7c6057ed4e41 [file] [log] [blame]
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +01001/*
Antonio Nino Diaza5b4c402018-01-08 17:33:34 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Antonio Nino Diaz2fccb222017-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>
12#include <errno.h>
Antonio Nino Diaza5b4c402018-01-08 17:33:34 +000013#include <mm_svc.h>
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010014#include <platform.h>
15#include <runtime_svc.h>
16#include <secure_partition.h>
Antonio Nino Diaz085e80e2018-03-21 10:49:27 +000017#include <smccc.h>
18#include <smccc_helpers.h>
Antonio Nino Diaz2fccb222017-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 Diaz22282bb2018-05-23 11:40:46 +010025
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010026/*******************************************************************************
27 * Secure Partition context information.
28 ******************************************************************************/
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +010029static sp_context_t sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010030
31/*******************************************************************************
Antonio Nino Diaz46f996d2018-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 Diaz22282bb2018-05-23 11:40:46 +010084 * This function takes an SP context pointer and prepares the CPU to enter.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010085 ******************************************************************************/
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +010086static void spm_sp_prepare_enter(sp_context_t *sp_ctx)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010087{
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010088 assert(sp_ctx != NULL);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010089
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010090 /* Assign the context of the SP to this CPU */
91 cm_set_context(&(sp_ctx->cpu_ctx), SECURE);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010092
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010093 /* Restore the context assigned above */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010094 cm_el1_sysregs_context_restore(SECURE);
95 cm_set_next_eret_context(SECURE);
96
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010097 /* Invalidate TLBs at EL1. */
98 tlbivmalle1();
99 dsbish();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100100}
101
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100102/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100103 * Enter SP after preparing it with spm_sp_prepare_enter().
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100104 ******************************************************************************/
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +0100105static uint64_t spm_sp_enter(sp_context_t *sp_ctx)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100106{
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100107 /* Enter Secure Partition */
108 return spm_secure_partition_enter(&sp_ctx->c_rt_ctx);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100109}
110
111/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100112 * Jump to each Secure Partition for the first time.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100113 ******************************************************************************/
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100114static int32_t spm_init(void)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100115{
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100116 uint64_t rc = 0;
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +0100117 sp_context_t *ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100118
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100119 INFO("Secure Partition init...\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100120
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100121 ctx = &sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100122
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100123 ctx->state = SP_STATE_RESET;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100124
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100125 spm_sp_prepare_enter(ctx);
126 rc |= spm_sp_enter(ctx);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100127 assert(rc == 0);
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100128
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100129 ctx->state = SP_STATE_IDLE;
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100130
131 INFO("Secure Partition initialized.\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100132
133 return rc;
134}
135
136/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100137 * Initialize contexts of all Secure Partitions.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100138 ******************************************************************************/
139int32_t spm_setup(void)
140{
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +0100141 sp_context_t *ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100142
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100143 /* Disable MMU at EL1 (initialized by BL2) */
144 disable_mmu_icache_el1();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100145
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100146 /* Initialize context of the SP */
147 INFO("Secure Partition context setup start...\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100148
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100149 ctx = &sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100150
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100151 /* Assign translation tables context. */
152 ctx->xlat_ctx_handle = spm_get_sp_xlat_context();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100153
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +0100154 spm_sp_setup(ctx);
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100155
156 /* Register init function for deferred init. */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100157 bl31_register_bl32_init(&spm_init);
158
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100159 INFO("Secure Partition setup done.\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100160
161 return 0;
162}
163
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100164/*******************************************************************************
165 * Secure Partition Manager SMC handler.
166 ******************************************************************************/
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100167uint64_t spm_smc_handler(uint32_t smc_fid,
168 uint64_t x1,
169 uint64_t x2,
170 uint64_t x3,
171 uint64_t x4,
172 void *cookie,
173 void *handle,
174 uint64_t flags)
175{
176 cpu_context_t *ns_cpu_context;
177 unsigned int ns;
178
179 /* Determine which security state this SMC originated from */
180 ns = is_caller_non_secure(flags);
181
182 if (ns == SMC_FROM_SECURE) {
183
184 /* Handle SMCs from Secure world. */
185
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100186 assert(handle == cm_get_context(SECURE));
187
188 /* Make next ERET jump to S-EL0 instead of S-EL1. */
189 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1());
190
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100191 switch (smc_fid) {
192
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000193 case SPM_VERSION_AARCH32:
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100194 SMC_RET1(handle, SPM_VERSION_COMPILED);
195
196 case SP_EVENT_COMPLETE_AARCH64:
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100197 /* Save secure state */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100198 cm_el1_sysregs_context_save(SECURE);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100199
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100200 if (sp_ctx.state == SP_STATE_RESET) {
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100201 /*
202 * SPM reports completion. The SPM must have
203 * initiated the original request through a
204 * synchronous entry into the secure
205 * partition. Jump back to the original C
206 * runtime context.
207 */
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100208 spm_secure_partition_exit(sp_ctx.c_rt_ctx, x1);
209
210 /* spm_secure_partition_exit doesn't return */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100211 }
212
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100213 /* Mark Secure Partition as idle */
214 assert(sp_ctx.state == SP_STATE_BUSY);
215
216 sp_state_set(&sp_ctx, SP_STATE_IDLE);
Antonio Nino Diaza43c85d2018-01-08 09:59:33 +0000217
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100218 /*
219 * This is the result from the Secure partition of an
220 * earlier request. Copy the result into the non-secure
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100221 * context and return to the non-secure state.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100222 */
223
224 /* Get a reference to the non-secure context */
225 ns_cpu_context = cm_get_context(NON_SECURE);
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100226 assert(ns_cpu_context != NULL);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100227
228 /* Restore non-secure state */
229 cm_el1_sysregs_context_restore(NON_SECURE);
230 cm_set_next_eret_context(NON_SECURE);
231
232 /* Return to normal world */
233 SMC_RET1(ns_cpu_context, x1);
234
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000235 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
236 INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100237
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100238 if (sp_ctx.state != SP_STATE_RESET) {
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000239 WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100240 SMC_RET1(handle, SPM_NOT_SUPPORTED);
241 }
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100242 SMC_RET1(handle,
243 spm_memory_attributes_get_smc_handler(
244 &sp_ctx, x1));
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100245
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000246 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
247 INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100248
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100249 if (sp_ctx.state != SP_STATE_RESET) {
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000250 WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100251 SMC_RET1(handle, SPM_NOT_SUPPORTED);
252 }
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100253 SMC_RET1(handle,
254 spm_memory_attributes_set_smc_handler(
255 &sp_ctx, x1, x2, x3));
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100256 default:
257 break;
258 }
259 } else {
260
261 /* Handle SMCs from Non-secure world. */
262
263 switch (smc_fid) {
264
Antonio Nino Diaza5b4c402018-01-08 17:33:34 +0000265 case MM_VERSION_AARCH32:
266 SMC_RET1(handle, MM_VERSION_COMPILED);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100267
Sandrine Bailleux756a2a02017-12-01 09:44:21 +0000268 case MM_COMMUNICATE_AARCH32:
269 case MM_COMMUNICATE_AARCH64:
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000270 {
271 uint64_t mm_cookie = x1;
272 uint64_t comm_buffer_address = x2;
273 uint64_t comm_size_address = x3;
274
275 /* Cookie. Reserved for future use. It must be zero. */
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100276 if (mm_cookie != 0U) {
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000277 ERROR("MM_COMMUNICATE: cookie is not zero\n");
278 SMC_RET1(handle, SPM_INVALID_PARAMETER);
279 }
280
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100281 if (comm_buffer_address == 0U) {
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000282 ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
283 SMC_RET1(handle, SPM_INVALID_PARAMETER);
284 }
285
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100286 if (comm_size_address != 0U) {
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000287 VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
288 }
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100289
290 /* Save the Normal world context */
291 cm_el1_sysregs_context_save(NON_SECURE);
292
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100293 /*
294 * Wait until the state of the Secure Partition is IDLE
295 * and set it to BUSY
296 */
297 sp_state_wait_switch(&sp_ctx,
298 SP_STATE_IDLE, SP_STATE_BUSY);
Antonio Nino Diaza43c85d2018-01-08 09:59:33 +0000299
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100300 /* Jump to the Secure Partition. */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100301
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100302 spm_sp_prepare_enter(&sp_ctx);
303
304 SMC_RET4(&(sp_ctx.cpu_ctx), smc_fid,
305 comm_buffer_address, comm_size_address,
306 plat_my_core_pos());
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000307 }
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100308
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000309 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
310 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100311 /* SMC interfaces reserved for secure callers. */
312 SMC_RET1(handle, SPM_NOT_SUPPORTED);
313
314 default:
315 break;
316 }
317 }
318
319 SMC_RET1(handle, SMC_UNK);
320}