blob: 880e86e49603c23666ddafcb1b07ab7035c85826 [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>
17#include <secure_partition.h>
Antonio Nino Diaz3c817f42018-03-21 10:49:27 +000018#include <smccc.h>
19#include <smccc_helpers.h>
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010020#include <spinlock.h>
21#include <spm_svc.h>
22#include <utils.h>
23#include <xlat_tables_v2.h>
24
25#include "spm_private.h"
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +010026
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010027/*******************************************************************************
28 * Secure Partition context information.
29 ******************************************************************************/
Antonio Nino Diaz28759312018-05-22 16:26:48 +010030static sp_context_t sp_ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010031
32/*******************************************************************************
Antonio Nino Diazc4f27522018-05-23 09:09:41 +010033 * Set state of a Secure Partition context.
34 ******************************************************************************/
35void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
36{
37 spin_lock(&(sp_ptr->state_lock));
38 sp_ptr->state = state;
39 spin_unlock(&(sp_ptr->state_lock));
40}
41
42/*******************************************************************************
43 * Wait until the state of a Secure Partition is the specified one and change it
44 * to the desired state.
45 ******************************************************************************/
46void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
47{
48 int success = 0;
49
50 while (success == 0) {
51 spin_lock(&(sp_ptr->state_lock));
52
53 if (sp_ptr->state == from) {
54 sp_ptr->state = to;
55
56 success = 1;
57 }
58
59 spin_unlock(&(sp_ptr->state_lock));
60 }
61}
62
63/*******************************************************************************
64 * Check if the state of a Secure Partition is the specified one and, if so,
65 * change it to the desired state. Returns 0 on success, -1 on error.
66 ******************************************************************************/
67int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
68{
69 int ret = -1;
70
71 spin_lock(&(sp_ptr->state_lock));
72
73 if (sp_ptr->state == from) {
74 sp_ptr->state = to;
75
76 ret = 0;
77 }
78
79 spin_unlock(&(sp_ptr->state_lock));
80
81 return ret;
82}
83
84/*******************************************************************************
Antonio Nino Diazda50cd02018-06-15 16:21:01 +010085 * This function takes an SP context pointer and performs a synchronous entry
86 * into it.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010087 ******************************************************************************/
Antonio Nino Diazda50cd02018-06-15 16:21:01 +010088static uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010089{
Antonio Nino Diazda50cd02018-06-15 16:21:01 +010090 uint64_t rc;
91
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +010092 assert(sp_ctx != NULL);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010093
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +010094 /* Assign the context of the SP to this CPU */
95 cm_set_context(&(sp_ctx->cpu_ctx), SECURE);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010096
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +010097 /* Restore the context assigned above */
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010098 cm_el1_sysregs_context_restore(SECURE);
99 cm_set_next_eret_context(SECURE);
100
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100101 /* Invalidate TLBs at EL1. */
102 tlbivmalle1();
103 dsbish();
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100104
105 /* Enter Secure Partition */
106 rc = spm_secure_partition_enter(&sp_ctx->c_rt_ctx);
107
108 /* Save secure state */
109 cm_el1_sysregs_context_save(SECURE);
110
111 return rc;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100112}
113
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100114/*******************************************************************************
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100115 * This function returns to the place where spm_sp_synchronous_entry() was
116 * called originally.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100117 ******************************************************************************/
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100118__dead2 static void spm_sp_synchronous_exit(uint64_t rc)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100119{
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100120 sp_context_t *ctx = &sp_ctx;
121
122 /*
123 * The SPM must have initiated the original request through a
124 * synchronous entry into the secure partition. Jump back to the
125 * original C runtime context with the value of rc in x0;
126 */
127 spm_secure_partition_exit(ctx->c_rt_ctx, rc);
128
129 panic();
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100130}
131
132/*******************************************************************************
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100133 * Jump to each Secure Partition for the first time.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100134 ******************************************************************************/
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100135static int32_t spm_init(void)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100136{
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100137 uint64_t rc;
Antonio Nino Diaz28759312018-05-22 16:26:48 +0100138 sp_context_t *ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100139
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100140 INFO("Secure Partition init...\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100141
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100142 ctx = &sp_ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100143
Antonio Nino Diazc4f27522018-05-23 09:09:41 +0100144 ctx->state = SP_STATE_RESET;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100145
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100146 rc = spm_sp_synchronous_entry(ctx);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100147 assert(rc == 0);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100148
Antonio Nino Diazc4f27522018-05-23 09:09:41 +0100149 ctx->state = SP_STATE_IDLE;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100150
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100151 INFO("Secure Partition initialized.\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100152
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100153 return rc;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100154}
155
156/*******************************************************************************
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100157 * Initialize contexts of all Secure Partitions.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100158 ******************************************************************************/
159int32_t spm_setup(void)
160{
Antonio Nino Diaz28759312018-05-22 16:26:48 +0100161 sp_context_t *ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100162
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100163 /* Disable MMU at EL1 (initialized by BL2) */
164 disable_mmu_icache_el1();
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100165
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100166 /* Initialize context of the SP */
167 INFO("Secure Partition context setup start...\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100168
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100169 ctx = &sp_ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100170
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100171 /* Assign translation tables context. */
172 ctx->xlat_ctx_handle = spm_get_sp_xlat_context();
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100173
Antonio Nino Diaz28759312018-05-22 16:26:48 +0100174 spm_sp_setup(ctx);
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100175
176 /* Register init function for deferred init. */
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100177 bl31_register_bl32_init(&spm_init);
178
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100179 INFO("Secure Partition setup done.\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100180
181 return 0;
182}
183
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100184/*******************************************************************************
Antonio Nino Diaz10c3e982018-06-20 12:05:02 +0100185 * Function to perform a call to a Secure Partition.
186 ******************************************************************************/
187uint64_t spm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3)
188{
189 uint64_t rc;
190 sp_context_t *sp_ptr = &sp_ctx;
191
192 /* Wait until the Secure Partition is idle and set it to busy. */
193 sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY);
194
195 /* Set values for registers on SP entry */
196 cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx);
197
198 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid);
199 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1);
200 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2);
201 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3);
202
203 /* Jump to the Secure Partition. */
204 rc = spm_sp_synchronous_entry(sp_ptr);
205
206 /* Flag Secure Partition as idle. */
207 assert(sp_ptr->state == SP_STATE_BUSY);
208 sp_state_set(sp_ptr, SP_STATE_IDLE);
209
210 return rc;
211}
212
213/*******************************************************************************
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100214 * MM_COMMUNICATE handler
215 ******************************************************************************/
216static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie,
217 uint64_t comm_buffer_address,
218 uint64_t comm_size_address, void *handle)
219{
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100220 uint64_t rc;
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100221
222 /* Cookie. Reserved for future use. It must be zero. */
223 if (mm_cookie != 0U) {
224 ERROR("MM_COMMUNICATE: cookie is not zero\n");
225 SMC_RET1(handle, SPM_INVALID_PARAMETER);
226 }
227
228 if (comm_buffer_address == 0U) {
229 ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
230 SMC_RET1(handle, SPM_INVALID_PARAMETER);
231 }
232
233 if (comm_size_address != 0U) {
234 VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
235 }
236
Sughosh Ganue77f9e82018-11-14 11:06:24 +0530237 /*
238 * The current secure partition design mandates
239 * - at any point, only a single core can be
240 * executing in the secure partiton.
241 * - a core cannot be preempted by an interrupt
242 * while executing in secure partition.
243 * Raise the running priority of the core to the
244 * interrupt level configured for secure partition
245 * so as to block any interrupt from preempting this
246 * core.
247 */
248 ehf_activate_priority(PLAT_SP_PRI);
249
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100250 /* Save the Normal world context */
251 cm_el1_sysregs_context_save(NON_SECURE);
252
Antonio Nino Diaz10c3e982018-06-20 12:05:02 +0100253 rc = spm_sp_call(smc_fid, comm_buffer_address, comm_size_address,
254 plat_my_core_pos());
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100255
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100256 /* Restore non-secure state */
257 cm_el1_sysregs_context_restore(NON_SECURE);
258 cm_set_next_eret_context(NON_SECURE);
259
Sughosh Ganue77f9e82018-11-14 11:06:24 +0530260 /*
261 * Exited from secure partition. This core can take
262 * interrupts now.
263 */
264 ehf_deactivate_priority(PLAT_SP_PRI);
265
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100266 SMC_RET1(handle, rc);
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100267}
268
269/*******************************************************************************
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100270 * Secure Partition Manager SMC handler.
271 ******************************************************************************/
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100272uint64_t spm_smc_handler(uint32_t smc_fid,
273 uint64_t x1,
274 uint64_t x2,
275 uint64_t x3,
276 uint64_t x4,
277 void *cookie,
278 void *handle,
279 uint64_t flags)
280{
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100281 unsigned int ns;
282
283 /* Determine which security state this SMC originated from */
284 ns = is_caller_non_secure(flags);
285
286 if (ns == SMC_FROM_SECURE) {
287
288 /* Handle SMCs from Secure world. */
289
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100290 assert(handle == cm_get_context(SECURE));
291
292 /* Make next ERET jump to S-EL0 instead of S-EL1. */
293 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1());
294
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100295 switch (smc_fid) {
296
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000297 case SPM_VERSION_AARCH32:
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100298 SMC_RET1(handle, SPM_VERSION_COMPILED);
299
300 case SP_EVENT_COMPLETE_AARCH64:
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100301 spm_sp_synchronous_exit(x1);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100302
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000303 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
304 INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100305
Antonio Nino Diazc4f27522018-05-23 09:09:41 +0100306 if (sp_ctx.state != SP_STATE_RESET) {
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000307 WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100308 SMC_RET1(handle, SPM_NOT_SUPPORTED);
309 }
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100310 SMC_RET1(handle,
311 spm_memory_attributes_get_smc_handler(
312 &sp_ctx, x1));
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100313
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000314 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
315 INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100316
Antonio Nino Diazc4f27522018-05-23 09:09:41 +0100317 if (sp_ctx.state != SP_STATE_RESET) {
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000318 WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100319 SMC_RET1(handle, SPM_NOT_SUPPORTED);
320 }
Antonio Nino Diaz2ac9a442018-05-23 11:40:46 +0100321 SMC_RET1(handle,
322 spm_memory_attributes_set_smc_handler(
323 &sp_ctx, x1, x2, x3));
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100324 default:
325 break;
326 }
327 } else {
328
329 /* Handle SMCs from Non-secure world. */
330
Antonio Nino Diazda50cd02018-06-15 16:21:01 +0100331 assert(handle == cm_get_context(NON_SECURE));
332
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100333 switch (smc_fid) {
334
Antonio Nino Diaz35b37f02018-01-08 17:33:34 +0000335 case MM_VERSION_AARCH32:
336 SMC_RET1(handle, MM_VERSION_COMPILED);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100337
Sandrine Bailleuxb31ee6b2017-12-01 09:44:21 +0000338 case MM_COMMUNICATE_AARCH32:
339 case MM_COMMUNICATE_AARCH64:
Antonio Nino Diazfbd7f502018-05-23 11:49:16 +0100340 return mm_communicate(smc_fid, x1, x2, x3, handle);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100341
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000342 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
343 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100344 /* SMC interfaces reserved for secure callers. */
345 SMC_RET1(handle, SPM_NOT_SUPPORTED);
346
347 default:
348 break;
349 }
350 }
351
352 SMC_RET1(handle, SMC_UNK);
353}