1 /*
2 * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <arch_helpers.h>
8 #include <assert.h>
9 #include <errno.h>
10
11 #include <bl31/bl31.h>
12 #include <bl31/ehf.h>
13 #include <common/debug.h>
14 #include <common/runtime_svc.h>
15 #include <lib/el3_runtime/context_mgmt.h>
16 #include <lib/smccc.h>
17 #include <lib/spinlock.h>
18 #include <lib/utils.h>
19 #include <lib/xlat_tables/xlat_tables_v2.h>
20 #include <plat/common/platform.h>
21 #include <services/spm_mm_svc.h>
22 #include <smccc_helpers.h>
23
24 #include "spm_common.h"
25 #include "spm_partition.h"
26 #include "spm_shim_private.h"
27
28 /*******************************************************************************
29 * Secure Partition context information.
30 ******************************************************************************/
31 static sp_context_t sp_ctx;
32
33 /*******************************************************************************
34 * Jump to each MM Secure Partition for the first time.
35 ******************************************************************************/
spm_init(void)36 static int32_t spm_init(void)
37 {
38 uint64_t rc;
39 sp_context_t *ctx;
40
41 INFO("Secure Partition init...\n");
42
43 ctx = &sp_ctx;
44
45 ctx->state = SP_STATE_RESET;
46
47 rc = spm_sp_synchronous_entry(ctx);
48 assert(rc == 0);
49
50 ctx->state = SP_STATE_IDLE;
51
52 INFO("Secure Partition initialized.\n");
53
54 return !rc;
55 }
56
57 /*******************************************************************************
58 * Initialize contexts of all MM Secure Partitions.
59 ******************************************************************************/
spm_mm_setup(void)60 int32_t spm_mm_setup(void)
61 {
62 sp_context_t *ctx;
63 cpu_context_t *cpu_ctx;
64
65 /* Disable MMU at EL1 (initialized by BL2) */
66 disable_mmu_icache_el1();
67
68 /* Initialize context of the SP */
69 INFO("Secure Partition context setup start...\n");
70
71 ctx = &sp_ctx;
72 cpu_ctx = &(ctx->cpu_ctx);
73
74 /* Assign translation tables context. */
75 ctx->xlat_ctx_handle = spm_get_sp_xlat_context();
76
77 /* Pointer to the MP information from the platform port. */
78 const spm_boot_info_t *sp_boot_info =
79 plat_get_secure_partition_boot_info(NULL);
80
81 /*
82 * Initialize CPU context
83 * ----------------------
84 */
85
86 entry_point_info_t ep_info = {0};
87
88 SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE);
89
90 /* Setup entrypoint and SPSR */
91 ep_info.pc = sp_boot_info->sp_image_base;
92 ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
93
94 /*
95 * X0: Virtual address of a buffer shared between EL3 and Secure EL0.
96 * The buffer will be mapped in the Secure EL1 translation regime
97 * with Normal IS WBWA attributes and RO data and Execute Never
98 * instruction access permissions.
99 *
100 * X1: Size of the buffer in bytes
101 *
102 * X2: cookie value (Implementation Defined)
103 *
104 * X3: cookie value (Implementation Defined)
105 *
106 * X4 to X7 = 0
107 */
108 ep_info.args.arg0 = sp_boot_info->sp_shared_buf_base;
109 ep_info.args.arg1 = sp_boot_info->sp_shared_buf_size;
110 ep_info.args.arg2 = PLAT_SPM_COOKIE_0;
111 ep_info.args.arg3 = PLAT_SPM_COOKIE_1;
112
113 cm_setup_context(cpu_ctx, &ep_info);
114
115 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_SP_EL0,
116 sp_boot_info->sp_stack_base + sp_boot_info->sp_pcpu_stack_size);
117
118 #if ENABLE_ASSERTIONS
119
120 /* Get max granularity supported by the platform. */
121 unsigned int max_granule = xlat_arch_get_max_supported_granule_size();
122
123 VERBOSE("Max translation granule size supported: %u KiB\n",
124 max_granule / 1024U);
125
126 unsigned int max_granule_mask = max_granule - 1U;
127
128 /* Base must be aligned to the max granularity */
129 assert((sp_boot_info->sp_ns_comm_buf_base & max_granule_mask) == 0);
130
131 /* Size must be a multiple of the max granularity */
132 assert((sp_boot_info->sp_ns_comm_buf_size & max_granule_mask) == 0);
133
134 #endif /* ENABLE_ASSERTIONS */
135
136 /* This region contains the exception vectors used at S-EL1. */
137 const mmap_region_t sel1_exception_vectors =
138 MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
139 SPM_SHIM_EXCEPTIONS_SIZE,
140 MT_CODE | MT_SECURE | MT_PRIVILEGED);
141 mmap_add_region_ctx(ctx->xlat_ctx_handle,
142 &sel1_exception_vectors);
143
144 mmap_add_ctx(ctx->xlat_ctx_handle,
145 plat_get_secure_partition_mmap(NULL));
146
147 spm_el0_sp_setup(ctx);
148
149 /*
150 * Prepare information in buffer shared between EL3 and S-EL0
151 * ----------------------------------------------------------
152 */
153
154 void *shared_buf_ptr = (void *) sp_boot_info->sp_shared_buf_base;
155
156 /* Copy the boot information into the shared buffer with the SP. */
157 assert((uintptr_t)shared_buf_ptr + sizeof(spm_boot_info_t)
158 <= (sp_boot_info->sp_shared_buf_base + sp_boot_info->sp_shared_buf_size));
159
160 assert(sp_boot_info->sp_shared_buf_base <=
161 (UINTPTR_MAX - sp_boot_info->sp_shared_buf_size + 1));
162
163 assert(sp_boot_info != NULL);
164
165 memcpy((void *) shared_buf_ptr, (const void *) sp_boot_info,
166 sizeof(spm_boot_info_t));
167
168 /* Pointer to the MP information from the platform port. */
169 spm_mp_info_t *sp_mp_info =
170 ((spm_boot_info_t *) shared_buf_ptr)->mp_info;
171
172 assert(sp_mp_info != NULL);
173
174 /*
175 * Point the shared buffer MP information pointer to where the info will
176 * be populated, just after the boot info.
177 */
178 ((spm_boot_info_t *) shared_buf_ptr)->mp_info =
179 (spm_mp_info_t *) ((uintptr_t)shared_buf_ptr
180 + sizeof(spm_boot_info_t));
181
182 /*
183 * Update the shared buffer pointer to where the MP information for the
184 * payload will be populated
185 */
186 shared_buf_ptr = ((spm_boot_info_t *) shared_buf_ptr)->mp_info;
187
188 /*
189 * Copy the cpu information into the shared buffer area after the boot
190 * information.
191 */
192 assert(sp_boot_info->num_cpus <= PLATFORM_CORE_COUNT);
193
194 assert((uintptr_t)shared_buf_ptr
195 <= (sp_boot_info->sp_shared_buf_base + sp_boot_info->sp_shared_buf_size -
196 (sp_boot_info->num_cpus * sizeof(*sp_mp_info))));
197
198 memcpy(shared_buf_ptr, (const void *) sp_mp_info,
199 sp_boot_info->num_cpus * sizeof(*sp_mp_info));
200
201 /*
202 * Calculate the linear indices of cores in boot information for the
203 * secure partition and flag the primary CPU
204 */
205 sp_mp_info = (spm_mp_info_t *) shared_buf_ptr;
206
207 for (unsigned int index = 0; index < sp_boot_info->num_cpus; index++) {
208 u_register_t mpidr = sp_mp_info[index].mpidr;
209
210 sp_mp_info[index].linear_id = plat_core_pos_by_mpidr(mpidr);
211 if (plat_my_core_pos() == sp_mp_info[index].linear_id)
212 sp_mp_info[index].flags |= MP_INFO_FLAG_PRIMARY_CPU;
213 }
214
215 /* Register init function for deferred init. */
216 bl31_register_bl32_init(&spm_init);
217
218 INFO("Secure Partition setup done.\n");
219
220 return 0;
221 }
222
223 /*******************************************************************************
224 * Function to perform a call to a MM Secure Partition.
225 ******************************************************************************/
spm_mm_sp_call(uint32_t smc_fid,uint64_t x1,uint64_t x2,uint64_t x3)226 uint64_t spm_mm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3)
227 {
228 uint64_t rc;
229 sp_context_t *sp_ptr = &sp_ctx;
230
231 /* Wait until the Secure Partition is idle and set it to busy. */
232 sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY);
233
234 /* Set values for registers on SP entry */
235 cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx);
236
237 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid);
238 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1);
239 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2);
240 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3);
241
242 /* Jump to the Secure Partition. */
243 rc = spm_sp_synchronous_entry(sp_ptr);
244
245 /* Flag Secure Partition as idle. */
246 assert(sp_ptr->state == SP_STATE_BUSY);
247 sp_state_set(sp_ptr, SP_STATE_IDLE);
248
249 return rc;
250 }
251
252 /*******************************************************************************
253 * MM_COMMUNICATE handler
254 ******************************************************************************/
mm_communicate(uint32_t smc_fid,uint64_t mm_cookie,uint64_t comm_buffer_address,uint64_t comm_size_address,void * handle)255 static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie,
256 uint64_t comm_buffer_address,
257 uint64_t comm_size_address, void *handle)
258 {
259 uint64_t rc;
260
261 /* Cookie. Reserved for future use. It must be zero. */
262 if (mm_cookie != 0U) {
263 ERROR("MM_COMMUNICATE: cookie is not zero\n");
264 SMC_RET1(handle, SPM_INVALID_PARAMETER);
265 }
266
267 if (comm_buffer_address == 0U) {
268 ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
269 SMC_RET1(handle, SPM_INVALID_PARAMETER);
270 }
271
272 if (comm_size_address != 0U) {
273 VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
274 }
275
276 /*
277 * The current secure partition design mandates
278 * - at any point, only a single core can be
279 * executing in the secure partiton.
280 * - a core cannot be preempted by an interrupt
281 * while executing in secure partition.
282 * Raise the running priority of the core to the
283 * interrupt level configured for secure partition
284 * so as to block any interrupt from preempting this
285 * core.
286 */
287 ehf_activate_priority(PLAT_SP_PRI);
288
289 /* Save the Normal world context */
290 cm_el1_sysregs_context_save(NON_SECURE);
291
292 rc = spm_mm_sp_call(smc_fid, comm_buffer_address, comm_size_address,
293 plat_my_core_pos());
294
295 /* Restore non-secure state */
296 cm_el1_sysregs_context_restore(NON_SECURE);
297 cm_set_next_eret_context(NON_SECURE);
298
299 /*
300 * Exited from secure partition. This core can take
301 * interrupts now.
302 */
303 ehf_deactivate_priority(PLAT_SP_PRI);
304
305 SMC_RET1(handle, rc);
306 }
307
308 /*******************************************************************************
309 * MM Secure Partition Manager SMC handler.
310 ******************************************************************************/
spm_mm_smc_handler(uint32_t smc_fid,uint64_t x1,uint64_t x2,uint64_t x3,uint64_t x4,void * cookie,void * handle,uint64_t flags)311 uint64_t spm_mm_smc_handler(uint32_t smc_fid,
312 uint64_t x1,
313 uint64_t x2,
314 uint64_t x3,
315 uint64_t x4,
316 void *cookie,
317 void *handle,
318 uint64_t flags)
319 {
320 unsigned int ns;
321
322 /* Determine which security state this SMC originated from */
323 ns = is_caller_non_secure(flags);
324
325 if (ns == SMC_FROM_SECURE) {
326
327 /* Handle SMCs from Secure world. */
328
329 assert(handle == cm_get_context(SECURE));
330
331 /* Make next ERET jump to S-EL0 instead of S-EL1. */
332 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1());
333
334 switch (smc_fid) {
335
336 case SPM_MM_VERSION_AARCH32:
337 SMC_RET1(handle, SPM_MM_VERSION_COMPILED);
338
339 case MM_SP_EVENT_COMPLETE_AARCH64:
340 spm_sp_synchronous_exit(&sp_ctx, x1);
341
342 case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64:
343 INFO("Received MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
344
345 if (sp_ctx.state != SP_STATE_RESET) {
346 WARN("MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
347 SMC_RET1(handle, SPM_NOT_SUPPORTED);
348 }
349 SMC_RET1(handle,
350 spm_memory_attributes_get_smc_handler(
351 &sp_ctx, x1));
352
353 case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64:
354 INFO("Received MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
355
356 if (sp_ctx.state != SP_STATE_RESET) {
357 WARN("MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
358 SMC_RET1(handle, SPM_NOT_SUPPORTED);
359 }
360 SMC_RET1(handle,
361 spm_memory_attributes_set_smc_handler(
362 &sp_ctx, x1, x2, x3));
363 default:
364 break;
365 }
366 } else {
367
368 /* Handle SMCs from Non-secure world. */
369
370 assert(handle == cm_get_context(NON_SECURE));
371
372 switch (smc_fid) {
373
374 case MM_VERSION_AARCH32:
375 SMC_RET1(handle, MM_VERSION_COMPILED);
376
377 case MM_COMMUNICATE_AARCH32:
378 case MM_COMMUNICATE_AARCH64:
379 return mm_communicate(smc_fid, x1, x2, x3, handle);
380
381 case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64:
382 case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64:
383 /* SMC interfaces reserved for secure callers. */
384 SMC_RET1(handle, SPM_NOT_SUPPORTED);
385
386 default:
387 break;
388 }
389 }
390
391 SMC_RET1(handle, SMC_UNK);
392 }
393