blob: 133eea295cca2e840fbbf6ca83a516ed3a4f80f3 [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 ******************************************************************************/
29static secure_partition_context_t sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010030
31/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010032 * This function takes an SP context pointer and prepares the CPU to enter.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010033 ******************************************************************************/
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010034static void spm_sp_prepare_enter(secure_partition_context_t *sp_ctx)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010035{
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010036 assert(sp_ctx != NULL);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010037
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010038 /* Assign the context of the SP to this CPU */
39 cm_set_context(&(sp_ctx->cpu_ctx), SECURE);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010040
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010041 /* Restore the context assigned above */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010042 cm_el1_sysregs_context_restore(SECURE);
43 cm_set_next_eret_context(SECURE);
44
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010045 /* Invalidate TLBs at EL1. */
46 tlbivmalle1();
47 dsbish();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010048}
49
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010050/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010051 * Enter SP after preparing it with spm_sp_prepare_enter().
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010052 ******************************************************************************/
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010053static uint64_t spm_sp_enter(secure_partition_context_t *sp_ctx)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010054{
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010055 /* Enter Secure Partition */
56 return spm_secure_partition_enter(&sp_ctx->c_rt_ctx);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010057}
58
59/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010060 * Jump to each Secure Partition for the first time.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010061 ******************************************************************************/
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +010062static int32_t spm_init(void)
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010063{
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010064 uint64_t rc = 0;
65 secure_partition_context_t *ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010066
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010067 INFO("Secure Partition init...\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010068
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010069 ctx = &sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010070
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010071 ctx->sp_init_in_progress = 1;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010072
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010073 spm_sp_prepare_enter(ctx);
74 rc |= spm_sp_enter(ctx);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010075 assert(rc == 0);
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010076
77 ctx->sp_init_in_progress = 0;
78
79 INFO("Secure Partition initialized.\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010080
81 return rc;
82}
83
84/*******************************************************************************
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010085 * Initialize contexts of all Secure Partitions.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010086 ******************************************************************************/
87int32_t spm_setup(void)
88{
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010089 secure_partition_context_t *ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010090
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010091 /* Disable MMU at EL1 (initialized by BL2) */
92 disable_mmu_icache_el1();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010093
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010094 /* Initialize context of the SP */
95 INFO("Secure Partition context setup start...\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010096
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010097 ctx = &sp_ctx;
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +010098
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +010099 /* Assign translation tables context. */
100 ctx->xlat_ctx_handle = spm_get_sp_xlat_context();
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100101
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100102 secure_partition_setup(ctx);
103
104 /* Register init function for deferred init. */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100105 bl31_register_bl32_init(&spm_init);
106
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100107 INFO("Secure Partition setup done.\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100108
109 return 0;
110}
111
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100112/*******************************************************************************
113 * Secure Partition Manager SMC handler.
114 ******************************************************************************/
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100115uint64_t spm_smc_handler(uint32_t smc_fid,
116 uint64_t x1,
117 uint64_t x2,
118 uint64_t x3,
119 uint64_t x4,
120 void *cookie,
121 void *handle,
122 uint64_t flags)
123{
124 cpu_context_t *ns_cpu_context;
125 unsigned int ns;
126
127 /* Determine which security state this SMC originated from */
128 ns = is_caller_non_secure(flags);
129
130 if (ns == SMC_FROM_SECURE) {
131
132 /* Handle SMCs from Secure world. */
133
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100134 assert(handle == cm_get_context(SECURE));
135
136 /* Make next ERET jump to S-EL0 instead of S-EL1. */
137 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1());
138
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100139 switch (smc_fid) {
140
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000141 case SPM_VERSION_AARCH32:
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100142 SMC_RET1(handle, SPM_VERSION_COMPILED);
143
144 case SP_EVENT_COMPLETE_AARCH64:
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100145 /* Save secure state */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100146 cm_el1_sysregs_context_save(SECURE);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100147
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100148 if (sp_ctx.sp_init_in_progress == 1) {
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100149 /*
150 * SPM reports completion. The SPM must have
151 * initiated the original request through a
152 * synchronous entry into the secure
153 * partition. Jump back to the original C
154 * runtime context.
155 */
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100156 spm_secure_partition_exit(sp_ctx.c_rt_ctx, x1);
157
158 /* spm_secure_partition_exit doesn't return */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100159 }
160
Antonio Nino Diaza43c85d2018-01-08 09:59:33 +0000161 /* Release the Secure Partition context */
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100162 spin_unlock(&(sp_ctx.lock));
Antonio Nino Diaza43c85d2018-01-08 09:59:33 +0000163
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100164 /*
165 * This is the result from the Secure partition of an
166 * earlier request. Copy the result into the non-secure
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100167 * context and return to the non-secure state.
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100168 */
169
170 /* Get a reference to the non-secure context */
171 ns_cpu_context = cm_get_context(NON_SECURE);
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100172 assert(ns_cpu_context != NULL);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100173
174 /* Restore non-secure state */
175 cm_el1_sysregs_context_restore(NON_SECURE);
176 cm_set_next_eret_context(NON_SECURE);
177
178 /* Return to normal world */
179 SMC_RET1(ns_cpu_context, x1);
180
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000181 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
182 INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100183
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100184 if (sp_ctx.sp_init_in_progress == 0) {
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000185 WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100186 SMC_RET1(handle, SPM_NOT_SUPPORTED);
187 }
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100188 SMC_RET1(handle,
189 spm_memory_attributes_get_smc_handler(
190 &sp_ctx, x1));
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100191
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000192 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
193 INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100194
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100195 if (sp_ctx.sp_init_in_progress == 0) {
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000196 WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100197 SMC_RET1(handle, SPM_NOT_SUPPORTED);
198 }
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100199 SMC_RET1(handle,
200 spm_memory_attributes_set_smc_handler(
201 &sp_ctx, x1, x2, x3));
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100202 default:
203 break;
204 }
205 } else {
206
207 /* Handle SMCs from Non-secure world. */
208
209 switch (smc_fid) {
210
Antonio Nino Diaza5b4c402018-01-08 17:33:34 +0000211 case MM_VERSION_AARCH32:
212 SMC_RET1(handle, MM_VERSION_COMPILED);
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100213
Sandrine Bailleux756a2a02017-12-01 09:44:21 +0000214 case MM_COMMUNICATE_AARCH32:
215 case MM_COMMUNICATE_AARCH64:
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000216 {
217 uint64_t mm_cookie = x1;
218 uint64_t comm_buffer_address = x2;
219 uint64_t comm_size_address = x3;
220
221 /* Cookie. Reserved for future use. It must be zero. */
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100222 if (mm_cookie != 0U) {
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000223 ERROR("MM_COMMUNICATE: cookie is not zero\n");
224 SMC_RET1(handle, SPM_INVALID_PARAMETER);
225 }
226
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100227 if (comm_buffer_address == 0U) {
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000228 ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
229 SMC_RET1(handle, SPM_INVALID_PARAMETER);
230 }
231
Antonio Nino Diazb3323cd2018-04-17 15:10:18 +0100232 if (comm_size_address != 0U) {
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000233 VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
234 }
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100235
236 /* Save the Normal world context */
237 cm_el1_sysregs_context_save(NON_SECURE);
238
Antonio Nino Diaza43c85d2018-01-08 09:59:33 +0000239 /* Lock the Secure Partition context. */
240 spin_lock(&sp_ctx.lock);
241
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100242 /* Jump to the Secure Partition. */
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100243
Antonio Nino Diaz22282bb2018-05-23 11:40:46 +0100244 spm_sp_prepare_enter(&sp_ctx);
245
246 SMC_RET4(&(sp_ctx.cpu_ctx), smc_fid,
247 comm_buffer_address, comm_size_address,
248 plat_my_core_pos());
Sandrine Bailleux4d2787c2017-12-07 09:48:56 +0000249 }
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100250
Antonio Nino Diazfa0ed2b2017-12-01 14:12:43 +0000251 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
252 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
Antonio Nino Diaz2fccb222017-10-24 10:07:35 +0100253 /* SMC interfaces reserved for secure callers. */
254 SMC_RET1(handle, SPM_NOT_SUPPORTED);
255
256 default:
257 break;
258 }
259 }
260
261 SMC_RET1(handle, SMC_UNK);
262}