blob: c4cd8882871dd26b34459b1cfa38e5c3366e6995 [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>
Sughosh Ganu6e3bad32018-11-14 11:06:24 +053012#include <ehf.h>
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010013#include <errno.h>
14#include <platform.h>
15#include <runtime_svc.h>
Antonio Nino Diaz085e80e2018-03-21 10:49:27 +000016#include <smccc.h>
17#include <smccc_helpers.h>
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010018#include <spinlock.h>
19#include <spm_svc.h>
20#include <utils.h>
21#include <xlat_tables_v2.h>
22
23#include "spm_private.h"
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010024
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010025/*******************************************************************************
26 * Secure Partition context information.
27 ******************************************************************************/
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +010028static sp_context_t sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010029
30/*******************************************************************************
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +010031 * Set state of a Secure Partition context.
32 ******************************************************************************/
33void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
34{
35 spin_lock(&(sp_ptr->state_lock));
36 sp_ptr->state = state;
37 spin_unlock(&(sp_ptr->state_lock));
38}
39
40/*******************************************************************************
41 * Wait until the state of a Secure Partition is the specified one and change it
42 * to the desired state.
43 ******************************************************************************/
44void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
45{
46 int success = 0;
47
48 while (success == 0) {
49 spin_lock(&(sp_ptr->state_lock));
50
51 if (sp_ptr->state == from) {
52 sp_ptr->state = to;
53
54 success = 1;
55 }
56
57 spin_unlock(&(sp_ptr->state_lock));
58 }
59}
60
61/*******************************************************************************
62 * Check if the state of a Secure Partition is the specified one and, if so,
63 * change it to the desired state. Returns 0 on success, -1 on error.
64 ******************************************************************************/
65int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
66{
67 int ret = -1;
68
69 spin_lock(&(sp_ptr->state_lock));
70
71 if (sp_ptr->state == from) {
72 sp_ptr->state = to;
73
74 ret = 0;
75 }
76
77 spin_unlock(&(sp_ptr->state_lock));
78
79 return ret;
80}
81
82/*******************************************************************************
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +010083 * This function takes an SP context pointer and performs a synchronous entry
84 * into it.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010085 ******************************************************************************/
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +010086static uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010087{
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +010088 uint64_t rc;
89
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010090 assert(sp_ctx != NULL);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010091
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010092 /* Assign the context of the SP to this CPU */
93 cm_set_context(&(sp_ctx->cpu_ctx), SECURE);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010094
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010095 /* Restore the context assigned above */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010096 cm_el1_sysregs_context_restore(SECURE);
97 cm_set_next_eret_context(SECURE);
98
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010099 /* Invalidate TLBs at EL1. */
100 tlbivmalle1();
101 dsbish();
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +0100102
103 /* Enter Secure Partition */
104 rc = spm_secure_partition_enter(&sp_ctx->c_rt_ctx);
105
106 /* Save secure state */
107 cm_el1_sysregs_context_save(SECURE);
108
109 return rc;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100110}
111
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100112/*******************************************************************************
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +0100113 * This function returns to the place where spm_sp_synchronous_entry() was
114 * called originally.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100115 ******************************************************************************/
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +0100116__dead2 static void spm_sp_synchronous_exit(uint64_t rc)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100117{
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +0100118 sp_context_t *ctx = &sp_ctx;
119
120 /*
121 * The SPM must have initiated the original request through a
122 * synchronous entry into the secure partition. Jump back to the
123 * original C runtime context with the value of rc in x0;
124 */
125 spm_secure_partition_exit(ctx->c_rt_ctx, rc);
126
127 panic();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100128}
129
130/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100131 * Jump to each Secure Partition for the first time.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100132 ******************************************************************************/
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100133static int32_t spm_init(void)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100134{
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +0100135 uint64_t rc;
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +0100136 sp_context_t *ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100137
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100138 INFO("Secure Partition init...\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100139
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100140 ctx = &sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100141
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100142 ctx->state = SP_STATE_RESET;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100143
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +0100144 rc = spm_sp_synchronous_entry(ctx);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100145 assert(rc == 0);
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100146
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100147 ctx->state = SP_STATE_IDLE;
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100148
149 INFO("Secure Partition initialized.\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100150
151 return rc;
152}
153
154/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100155 * Initialize contexts of all Secure Partitions.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100156 ******************************************************************************/
157int32_t spm_setup(void)
158{
Antonio Nino Diaz680389a2018-11-27 08:36:02 +0000159 int rc;
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +0100160 sp_context_t *ctx;
Antonio Nino Diaz680389a2018-11-27 08:36:02 +0000161 void *sp_base, *rd_base;
162 size_t sp_size, rd_size;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100163
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100164 /* Disable MMU at EL1 (initialized by BL2) */
165 disable_mmu_icache_el1();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100166
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100167 /* Initialize context of the SP */
168 INFO("Secure Partition context setup start...\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100169
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100170 ctx = &sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100171
Antonio Nino Diaz680389a2018-11-27 08:36:02 +0000172 rc = plat_spm_sp_get_next_address(&sp_base, &sp_size,
173 &rd_base, &rd_size);
174 if (rc != 0) {
175 ERROR("No Secure Partition found.\n");
176 panic();
177 }
178
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100179 /* Assign translation tables context. */
180 ctx->xlat_ctx_handle = spm_get_sp_xlat_context();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100181
Antonio Nino Diaz680389a2018-11-27 08:36:02 +0000182 /* Save location of the image in physical memory */
183 ctx->image_base = (uintptr_t)sp_base;
184 ctx->image_size = sp_size;
185
186 rc = plat_spm_sp_rd_load(&ctx->rd, rd_base, rd_size);
187 if (rc < 0) {
188 ERROR("Error while loading RD blob.\n");
189 panic();
190 }
191
Antonio Nino Diaz07f3f632018-05-22 16:26:48 +0100192 spm_sp_setup(ctx);
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100193
194 /* Register init function for deferred init. */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100195 bl31_register_bl32_init(&spm_init);
196
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100197 INFO("Secure Partition setup done.\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100198
199 return 0;
200}
201
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100202/*******************************************************************************
203 * Secure Partition Manager SMC handler.
204 ******************************************************************************/
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100205uint64_t spm_smc_handler(uint32_t smc_fid,
206 uint64_t x1,
207 uint64_t x2,
208 uint64_t x3,
209 uint64_t x4,
210 void *cookie,
211 void *handle,
212 uint64_t flags)
213{
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100214 unsigned int ns;
215
216 /* Determine which security state this SMC originated from */
217 ns = is_caller_non_secure(flags);
218
219 if (ns == SMC_FROM_SECURE) {
220
221 /* Handle SMCs from Secure world. */
222
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100223 assert(handle == cm_get_context(SECURE));
224
225 /* Make next ERET jump to S-EL0 instead of S-EL1. */
226 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1());
227
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100228 switch (smc_fid) {
229
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000230 case SPM_VERSION_AARCH32:
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100231 SMC_RET1(handle, SPM_VERSION_COMPILED);
232
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000233 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
234 INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100235
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100236 if (sp_ctx.state != SP_STATE_RESET) {
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000237 WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100238 SMC_RET1(handle, SPM_NOT_SUPPORTED);
239 }
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100240 SMC_RET1(handle,
241 spm_memory_attributes_get_smc_handler(
242 &sp_ctx, x1));
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100243
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000244 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
245 INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100246
Antonio Nino Diaz46f996d2018-05-23 09:09:41 +0100247 if (sp_ctx.state != SP_STATE_RESET) {
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000248 WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100249 SMC_RET1(handle, SPM_NOT_SUPPORTED);
250 }
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100251 SMC_RET1(handle,
252 spm_memory_attributes_set_smc_handler(
253 &sp_ctx, x1, x2, x3));
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100254 default:
255 break;
256 }
257 } else {
258
259 /* Handle SMCs from Non-secure world. */
260
Antonio Nino Diaz14fcc6e2018-06-15 16:21:01 +0100261 assert(handle == cm_get_context(NON_SECURE));
262
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100263 switch (smc_fid) {
264
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000265 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
266 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100267 /* SMC interfaces reserved for secure callers. */
268 SMC_RET1(handle, SPM_NOT_SUPPORTED);
269
270 default:
271 break;
272 }
273 }
274
275 SMC_RET1(handle, SMC_UNK);
276}