1 /*
2 * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10
11 #include <arch.h>
12 #include <arch_helpers.h>
13 #include <common/debug.h>
14 #include <common/fdt_wrappers.h>
15
16 #include <context.h>
17 #include <lib/el3_runtime/context_mgmt.h>
18 #if HOB_LIST
19 #include <lib/hob/hob.h>
20 #include <lib/hob/hob_guid.h>
21 #include <lib/hob/mmram.h>
22 #include <lib/hob/mpinfo.h>
23 #endif
24 #include <lib/utils.h>
25 #include <lib/xlat_tables/xlat_tables_v2.h>
26 #include <libfdt.h>
27 #include <plat/common/common_def.h>
28 #include <plat/common/platform.h>
29 #include <services/ffa_svc.h>
30 #include "spm_common.h"
31 #include "spm_shim_private.h"
32 #include "spmc.h"
33 #if TRANSFER_LIST
34 #include <transfer_list.h>
35 #include <tpm_event_log.h>
36 #endif
37 #include <tools_share/firmware_image_package.h>
38
39 #include <platform_def.h>
40
41 #define FFA_BOOT_INFO_SIZE (PAGE_SIZE * 2)
42
43 /*
44 * Statically allocate a page of memory for passing boot information to an SP.
45 */
46 static uint8_t ffa_boot_info_mem[FFA_BOOT_INFO_SIZE] __aligned(PAGE_SIZE);
47
48 #if HOB_LIST
49 static void *tpm_evtlog_addr;
50 static size_t tpm_evtlog_size;
51 #endif
52
53 /*
54 * We need to choose one execution context from all those available for a S-EL0
55 * SP. This execution context will be used subsequently irrespective of which
56 * physical CPU the SP runs on.
57 */
58 #define SEL0_SP_EC_INDEX 0
59 #define SP_MEM_READ 0x1
60 #define SP_MEM_WRITE 0x2
61 #define SP_MEM_EXECUTE 0x4
62 #define SP_MEM_NON_SECURE 0x8
63 #define SP_MEM_READ_ONLY SP_MEM_READ
64 #define SP_MEM_READ_WRITE (SP_MEM_READ | SP_MEM_WRITE)
65
66 /* Type of the memory region in SP's manifest. */
67 enum sp_memory_region_type {
68 SP_MEM_REGION_DEVICE,
69 SP_MEM_REGION_MEMORY,
70 SP_MEM_REGION_NOT_SPECIFIED
71 };
72
73 #if HOB_LIST
74 #if TRANSFER_LIST
get_tpm_event_log(void * secure_tl)75 static void get_tpm_event_log(void *secure_tl)
76 {
77 struct transfer_list_entry *te;
78 void *evlog;
79
80 if (secure_tl == NULL) {
81 tpm_evtlog_addr = NULL;
82 tpm_evtlog_size = 0;
83 return;
84 }
85
86 te = transfer_list_find((struct transfer_list_header *)secure_tl,
87 TL_TAG_TPM_EVLOG);
88 if (te == NULL) {
89 tpm_evtlog_addr = NULL;
90 tpm_evtlog_size = 0;
91 return;
92 }
93
94 evlog = transfer_list_entry_data(te);
95 assert(evlog != NULL);
96
97 tpm_evtlog_addr = evlog + EVENT_LOG_RESERVED_BYTES;
98 tpm_evtlog_size = te->data_size - EVENT_LOG_RESERVED_BYTES;
99 }
100 #else
get_tpm_event_log(void * secure_tl)101 static void get_tpm_event_log(void *secure_tl)
102 {
103 tpm_evtlog_addr = NULL;
104 tpm_evtlog_size = 0;
105 }
106 #endif
107
get_memory_region_info(void * sp_manifest,int mem_region_node,const char * name,uint32_t granularity,uint64_t * base_address,uint32_t * size)108 static int get_memory_region_info(void *sp_manifest, int mem_region_node,
109 const char *name, uint32_t granularity,
110 uint64_t *base_address, uint32_t *size)
111 {
112 char *property;
113 int node, ret;
114
115 if (name != NULL) {
116 node = fdt_subnode_offset_namelen(sp_manifest, mem_region_node,
117 name, strlen(name));
118 if (node < 0) {
119 ERROR("Not found '%s' region in memory regions configuration for SP.\n",
120 name);
121 return -ENOENT;
122 }
123 } else {
124 node = mem_region_node;
125 }
126
127 property = "base-address";
128 ret = fdt_read_uint64(sp_manifest, node, property, base_address);
129 if (ret < 0) {
130 ERROR("Not found property(%s) in memory region(%s).\n",
131 property, name);
132 return -ENOENT;
133 }
134
135 property = "pages-count";
136 ret = fdt_read_uint32(sp_manifest, node, property, size);
137 if (ret < 0) {
138 ERROR("Not found property(%s) in memory region(%s).\n",
139 property, name);
140 return -ENOENT;
141 }
142
143 *size = ((*size) << (PAGE_SIZE_SHIFT + (granularity << 1)));
144
145 return 0;
146 }
147
build_sp_boot_hob_list(void * secure_tl,void * sp_manifest,uintptr_t hob_table_start,size_t * hob_table_size)148 static struct efi_hob_handoff_info_table *build_sp_boot_hob_list(
149 void *secure_tl, void *sp_manifest,
150 uintptr_t hob_table_start, size_t *hob_table_size)
151 {
152 struct efi_hob_handoff_info_table *hob_table;
153 uintptr_t base_address;
154 int mem_region_node;
155 int32_t node, ret;
156 const char *name;
157 uint32_t granularity, size;
158 uint32_t mem_region_num;
159 struct efi_guid ns_buf_guid = MM_NS_BUFFER_GUID;
160 struct efi_guid mmram_resv_guid = MM_PEI_MMRAM_MEMORY_RESERVE_GUID;
161 struct efi_guid tpm_evtlog_guid = MM_TPM_EVENT_LOG_GUID;
162 struct efi_mmram_descriptor *mmram_desc_data;
163 struct efi_mmram_hob_descriptor_block *mmram_hob_desc_data;
164
165 if (sp_manifest == NULL || hob_table_size == NULL || *hob_table_size == 0) {
166 return NULL;
167 }
168
169 node = fdt_path_offset(sp_manifest, "/");
170 if (node < 0) {
171 ERROR("Failed to get root in sp_manifest.\n");
172 return NULL;
173 }
174
175 ret = fdt_read_uint32(sp_manifest, node, "xlat-granule", &granularity);
176 if (ret < 0) {
177 ERROR("Not found property(xlat-granule) in sp_manifest.\n");
178 return NULL;
179 }
180
181 if (granularity > 0x02) {
182 ERROR("Invalid granularity value: 0x%x\n", granularity);
183 return NULL;
184 }
185
186 mem_region_node = fdt_subnode_offset_namelen(sp_manifest, 0, "memory-regions",
187 sizeof("memory-regions") - 1);
188 if (node < 0) {
189 ERROR("Not found memory-region configuration for SP.\n");
190 return NULL;
191 }
192
193 INFO("Generating PHIT_HOB...\n");
194
195 hob_table = create_hob_list(BL32_BASE, BL32_LIMIT,
196 hob_table_start, *hob_table_size);
197 if (hob_table == NULL) {
198 ERROR("Failed to create Hob Table.\n");
199 return NULL;
200 }
201
202 /*
203 * Create fv hob.
204 */
205 ret = get_memory_region_info(sp_manifest, mem_region_node,
206 "stmm_region", granularity, &base_address, &size);
207 if (ret < 0) {
208 return NULL;
209 }
210
211 if (base_address != BL32_BASE &&
212 base_address + size > BL32_LIMIT) {
213 ERROR("Image is ouf of bound(0x%lx/0x%x), should be in (0x%llx/0x%llx)\n",
214 base_address, size, BL32_BASE, BL32_LIMIT - BL32_BASE);
215 return NULL;
216 }
217
218 ret = create_fv_hob(hob_table, base_address, size);
219 if (ret < 0) {
220 ERROR("Failed to create fv hob... ret:%d\n", ret);
221 return NULL;
222 }
223
224 INFO("Success to create FV hob(0x%lx/0x%x).\n", base_address, size);
225
226 /*
227 * Create Ns Buffer hob.
228 */
229 ret = get_memory_region_info(sp_manifest, mem_region_node,
230 "ns_comm_buffer", granularity, &base_address, &size);
231 if (ret < 0) {
232 return NULL;
233 }
234
235 ret = create_guid_hob(hob_table, &ns_buf_guid,
236 sizeof(struct efi_mmram_descriptor), (void **) &mmram_desc_data);
237 if (ret < 0) {
238 ERROR("Failed to create ns buffer hob\n");
239 return NULL;
240 }
241
242 mmram_desc_data->physical_start = base_address;
243 mmram_desc_data->physical_size = size;
244 mmram_desc_data->cpu_start = base_address;
245 mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
246
247 /*
248 * Create mmram_resv hob.
249 */
250 for (node = fdt_first_subnode(sp_manifest, mem_region_node), mem_region_num = 0;
251 node >= 0;
252 node = fdt_next_subnode(sp_manifest, node), mem_region_num++) {
253 ret = get_memory_region_info(sp_manifest, node, NULL, granularity,
254 &base_address, &size);
255 if (ret < 0) {
256 name = fdt_get_name(sp_manifest, node, NULL);
257 ERROR("Invalid memory region(%s) found!\n", name);
258 return NULL;
259 }
260 }
261
262 ret = create_guid_hob(hob_table, &mmram_resv_guid,
263 (sizeof(struct efi_mmram_hob_descriptor_block) +
264 (sizeof(struct efi_mmram_descriptor) * (mem_region_num))),
265 (void **) &mmram_hob_desc_data);
266 if (ret < 0) {
267 ERROR("Failed to create mmram_resv hob. ret: %d\n", ret);
268 return NULL;
269 }
270
271 mmram_hob_desc_data->number_of_mm_reserved_regions = mem_region_num;
272
273 for (node = fdt_first_subnode(sp_manifest, mem_region_node), mem_region_num = 0;
274 node >= 0;
275 node = fdt_next_subnode(sp_manifest, node), mem_region_num++) {
276 get_memory_region_info(sp_manifest, node, NULL, granularity,
277 &base_address, &size);
278 name = fdt_get_name(sp_manifest, node, NULL);
279
280 mmram_desc_data = &mmram_hob_desc_data->descriptor[mem_region_num];
281 mmram_desc_data->physical_start = base_address;
282 mmram_desc_data->physical_size = size;
283 mmram_desc_data->cpu_start = base_address;
284
285 if (!strcmp(name, "heap")) {
286 mmram_desc_data->region_state = EFI_CACHEABLE;
287 } else {
288 mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
289 }
290 }
291
292 /*
293 * Add tpm mmram descriptor.
294 */
295 get_tpm_event_log(secure_tl);
296
297 if (tpm_evtlog_addr != NULL && tpm_evtlog_size != 0) {
298 ret = create_guid_hob(hob_table, &tpm_evtlog_guid,
299 sizeof(struct efi_mmram_descriptor), (void **) &mmram_desc_data);
300 if (ret < 0) {
301 ERROR("Failed to create tpm_event_log hob\n");
302 return NULL;
303 }
304
305 mmram_desc_data->physical_start = (uintptr_t)tpm_evtlog_addr;
306 mmram_desc_data->physical_size = tpm_evtlog_size;
307 mmram_desc_data->cpu_start = (uintptr_t)tpm_evtlog_addr;
308 mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
309 }
310
311 *hob_table_size = hob_table->efi_free_memory_bottom -
312 (efi_physical_address_t) hob_table;
313
314 return hob_table;
315 }
316 #endif
317
318 /*
319 * This function creates a initialization descriptor in the memory reserved
320 * for passing boot information to an SP. It then copies the partition manifest
321 * into this region and ensures that its reference in the initialization
322 * descriptor is updated.
323 */
spmc_create_boot_info(entry_point_info_t * ep_info,struct secure_partition_desc * sp)324 static void spmc_create_boot_info(entry_point_info_t *ep_info,
325 struct secure_partition_desc *sp)
326 {
327 struct ffa_boot_info_header *boot_header;
328 struct ffa_boot_info_desc *boot_descriptor;
329 uintptr_t content_addr;
330 void *sp_manifest;
331 void *tl __maybe_unused;
332 #if TRANSFER_LIST && !RESET_TO_BL31
333 struct transfer_list_entry *te;
334
335 tl = (void *)((uintptr_t)ep_info->args.arg3);
336 te = transfer_list_find((struct transfer_list_header *)tl,
337 TL_TAG_DT_FFA_MANIFEST);
338 assert(te != NULL);
339
340 sp_manifest = (void *)transfer_list_entry_data(te);
341 #else
342 tl = NULL;
343 sp_manifest = (void *)ep_info->args.arg0;
344 #endif
345
346 /*
347 * Calculate the maximum size of the manifest that can be accommodated
348 * in the boot information memory region.
349 */
350 size_t max_sz = sizeof(ffa_boot_info_mem) -
351 (sizeof(struct ffa_boot_info_header) +
352 sizeof(struct ffa_boot_info_desc));
353
354 /*
355 * The current implementation only supports the FF-A v1.1
356 * implementation of the boot protocol, therefore check
357 * that a v1.0 SP has not requested use of the protocol.
358 */
359 if (sp->ffa_version == MAKE_FFA_VERSION(1, 0)) {
360 ERROR("FF-A boot protocol not supported for v1.0 clients\n");
361 return;
362 }
363
364 /* Zero the memory region before populating. */
365 memset(ffa_boot_info_mem, 0, FFA_BOOT_INFO_SIZE);
366
367 /*
368 * Populate the ffa_boot_info_header at the start of the boot info
369 * region.
370 */
371 boot_header = (struct ffa_boot_info_header *) ffa_boot_info_mem;
372
373 /* Position the ffa_boot_info_desc after the ffa_boot_info_header. */
374 boot_header->offset_boot_info_desc =
375 sizeof(struct ffa_boot_info_header);
376 boot_descriptor = (struct ffa_boot_info_desc *)
377 (ffa_boot_info_mem +
378 boot_header->offset_boot_info_desc);
379
380 /*
381 * We must use the FF-A version corresponding to the version implemented
382 * by the SP. Currently this can only be v1.1.
383 */
384 boot_header->version = sp->ffa_version;
385
386 /* Populate the boot information header. */
387 boot_header->size_boot_info_desc = sizeof(struct ffa_boot_info_desc);
388
389 /* Set the signature "0xFFA". */
390 boot_header->signature = FFA_INIT_DESC_SIGNATURE;
391
392 /* Set the count. Currently 1 since only the manifest is specified. */
393 boot_header->count_boot_info_desc = 1;
394
395 boot_descriptor->flags =
396 FFA_BOOT_INFO_FLAG_NAME(FFA_BOOT_INFO_FLAG_NAME_UUID) |
397 FFA_BOOT_INFO_FLAG_CONTENT(FFA_BOOT_INFO_FLAG_CONTENT_ADR);
398
399 content_addr = (uintptr_t) (ffa_boot_info_mem +
400 boot_header->offset_boot_info_desc +
401 boot_header->size_boot_info_desc);
402
403 #if HOB_LIST
404 /* Populate the boot information descriptor for the hob_list. */
405 boot_descriptor->type =
406 FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
407 FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_HOB);
408
409 content_addr = (uintptr_t) build_sp_boot_hob_list(
410 tl, sp_manifest, content_addr, &max_sz);
411 if (content_addr == (uintptr_t) NULL) {
412 WARN("Unable to create phit hob properly.");
413 return;
414 }
415
416 boot_descriptor->size_boot_info = max_sz;
417 boot_descriptor->content = content_addr;
418 #else
419 /*
420 * Check if the manifest will fit into the boot info memory region else
421 * bail.
422 */
423 if (ep_info->args.arg1 > max_sz) {
424 WARN("Unable to copy manifest into boot information. ");
425 WARN("Max sz = %lu bytes. Manifest sz = %lu bytes\n",
426 max_sz, ep_info->args.arg1);
427 return;
428 }
429
430 /* Populate the boot information descriptor for the manifest. */
431 boot_descriptor->type =
432 FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
433 FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_FDT);
434
435 /*
436 * Copy the manifest into boot info region after the boot information
437 * descriptor.
438 */
439 boot_descriptor->size_boot_info = (uint32_t) ep_info->args.arg1;
440
441 memcpy((void *) content_addr, sp_manifest, boot_descriptor->size_boot_info);
442
443 boot_descriptor->content = content_addr;
444 #endif
445
446 /* Calculate the size of the total boot info blob. */
447 boot_header->size_boot_info_blob = boot_header->offset_boot_info_desc +
448 boot_descriptor->size_boot_info +
449 (boot_header->count_boot_info_desc *
450 boot_header->size_boot_info_desc);
451
452 INFO("SP boot info @ 0x%lx, size: %u bytes.\n",
453 (uintptr_t) ffa_boot_info_mem,
454 boot_header->size_boot_info_blob);
455 INFO("SP content @ 0x%lx, size: %u bytes.\n",
456 boot_descriptor->content,
457 boot_descriptor->size_boot_info);
458 }
459
460 /*
461 * S-EL1 partitions can be assigned with multiple execution contexts, each
462 * pinned to the physical CPU. Each execution context index corresponds to the
463 * respective liner core position.
464 * S-EL0 partitions execute in a single execution context (index 0).
465 */
get_ec_index(struct secure_partition_desc * sp)466 unsigned int get_ec_index(struct secure_partition_desc *sp)
467 {
468 return (sp->runtime_el == S_EL0) ?
469 SEL0_SP_EC_INDEX : plat_my_core_pos();
470 }
471
472 #if SPMC_AT_EL3_SEL0_SP
473 /* Setup spsr in entry point info for common context management code to use. */
spmc_el0_sp_spsr_setup(entry_point_info_t * ep_info)474 void spmc_el0_sp_spsr_setup(entry_point_info_t *ep_info)
475 {
476 /* Setup Secure Partition SPSR for S-EL0 SP. */
477 ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
478 }
479
read_optional_string(void * manifest,int32_t offset,char * property,char * out,size_t len)480 static void read_optional_string(void *manifest, int32_t offset,
481 char *property, char *out, size_t len)
482 {
483 const fdt32_t *prop;
484 int lenp;
485
486 prop = fdt_getprop(manifest, offset, property, &lenp);
487 if (prop == NULL) {
488 out[0] = '\0';
489 } else {
490 memcpy(out, prop, MIN(lenp, (int)len));
491 out[MIN(lenp, (int)len) - 1] = '\0';
492 }
493 }
494
495 /*******************************************************************************
496 * This function will parse the Secure Partition Manifest for fetching secure
497 * partition specific memory/device region details. It will find base address,
498 * size, memory attributes for each region and then add the respective region
499 * into secure parition's translation context.
500 ******************************************************************************/
populate_sp_regions(struct secure_partition_desc * sp,void * sp_manifest,int node,enum sp_memory_region_type type)501 static void populate_sp_regions(struct secure_partition_desc *sp,
502 void *sp_manifest, int node,
503 enum sp_memory_region_type type)
504 {
505 uintptr_t base_address;
506 uint32_t mem_attr, mem_region, size;
507 struct mmap_region sp_mem_regions = {0};
508 int32_t offset, ret;
509 char *compatibility[SP_MEM_REGION_NOT_SPECIFIED] = {
510 "arm,ffa-manifest-device-regions",
511 "arm,ffa-manifest-memory-regions"
512 };
513 char description[10];
514 char *property;
515 char *region[SP_MEM_REGION_NOT_SPECIFIED] = {
516 "device regions",
517 "memory regions"
518 };
519
520 if (type >= SP_MEM_REGION_NOT_SPECIFIED) {
521 WARN("Invalid region type\n");
522 return;
523 }
524
525 INFO("Mapping SP's %s\n", region[type]);
526
527 if (fdt_node_check_compatible(sp_manifest, node,
528 compatibility[type]) != 0) {
529 WARN("Incompatible region node in manifest\n");
530 return;
531 }
532
533 for (offset = fdt_first_subnode(sp_manifest, node), mem_region = 0;
534 offset >= 0;
535 offset = fdt_next_subnode(sp_manifest, offset), mem_region++) {
536 read_optional_string(sp_manifest, offset, "description",
537 description, sizeof(description));
538
539 INFO("Mapping: region: %d, %s\n", mem_region, description);
540
541 property = "base-address";
542 ret = fdt_read_uint64(sp_manifest, offset, property,
543 &base_address);
544 if (ret < 0) {
545 WARN("Missing:%s for %s.\n", property, description);
546 continue;
547 }
548
549 property = "pages-count";
550 ret = fdt_read_uint32(sp_manifest, offset, property, &size);
551 if (ret < 0) {
552 WARN("Missing: %s for %s.\n", property, description);
553 continue;
554 }
555 size *= PAGE_SIZE;
556
557 property = "attributes";
558 ret = fdt_read_uint32(sp_manifest, offset, property, &mem_attr);
559 if (ret < 0) {
560 WARN("Missing: %s for %s.\n", property, description);
561 continue;
562 }
563
564 sp_mem_regions.attr = MT_USER;
565 if (type == SP_MEM_REGION_DEVICE) {
566 sp_mem_regions.attr |= MT_EXECUTE_NEVER;
567 } else {
568 sp_mem_regions.attr |= MT_MEMORY;
569 if ((mem_attr & SP_MEM_EXECUTE) == SP_MEM_EXECUTE) {
570 sp_mem_regions.attr &= ~MT_EXECUTE_NEVER;
571 } else {
572 sp_mem_regions.attr |= MT_EXECUTE_NEVER;
573 }
574 }
575
576 if ((mem_attr & SP_MEM_READ_WRITE) == SP_MEM_READ_WRITE) {
577 sp_mem_regions.attr |= MT_RW;
578 }
579
580 if ((mem_attr & SP_MEM_NON_SECURE) == SP_MEM_NON_SECURE) {
581 sp_mem_regions.attr |= MT_NS;
582 } else {
583 sp_mem_regions.attr |= MT_SECURE;
584 }
585
586 sp_mem_regions.base_pa = base_address;
587 sp_mem_regions.base_va = base_address;
588 sp_mem_regions.size = size;
589
590 INFO("Adding PA: 0x%llx VA: 0x%lx Size: 0x%lx mem_attr: 0x%x, attr:0x%x\n",
591 sp_mem_regions.base_pa,
592 sp_mem_regions.base_va,
593 sp_mem_regions.size,
594 mem_attr,
595 sp_mem_regions.attr);
596
597 if (type == SP_MEM_REGION_DEVICE) {
598 sp_mem_regions.granularity = XLAT_BLOCK_SIZE(1);
599 } else {
600 sp_mem_regions.granularity = XLAT_BLOCK_SIZE(3);
601 }
602 mmap_add_region_ctx(sp->xlat_ctx_handle, &sp_mem_regions);
603 }
604 }
605
spmc_el0_sp_setup_mmu(struct secure_partition_desc * sp,cpu_context_t * ctx)606 static void spmc_el0_sp_setup_mmu(struct secure_partition_desc *sp,
607 cpu_context_t *ctx)
608 {
609 xlat_ctx_t *xlat_ctx;
610 uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
611
612 xlat_ctx = sp->xlat_ctx_handle;
613 init_xlat_tables_ctx(sp->xlat_ctx_handle);
614 setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table,
615 xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
616 EL1_EL0_REGIME);
617
618 write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
619 mmu_cfg_params[MMU_CFG_MAIR]);
620
621 write_ctx_tcr_el1_reg_errata(ctx, mmu_cfg_params[MMU_CFG_TCR]);
622
623 write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
624 mmu_cfg_params[MMU_CFG_TTBR0]);
625 }
626
spmc_el0_sp_setup_sctlr_el1(cpu_context_t * ctx)627 static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
628 {
629 u_register_t sctlr_el1_val;
630
631 /* Setup SCTLR_EL1 */
632 sctlr_el1_val = read_ctx_sctlr_el1_reg_errata(ctx);
633
634 sctlr_el1_val |=
635 /*SCTLR_EL1_RES1 |*/
636 /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
637 SCTLR_UCI_BIT |
638 /* RW regions at xlat regime EL1&0 are forced to be XN. */
639 SCTLR_WXN_BIT |
640 /* Don't trap to EL1 execution of WFI or WFE at EL0. */
641 SCTLR_NTWI_BIT | SCTLR_NTWE_BIT |
642 /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */
643 SCTLR_UCT_BIT |
644 /* Don't trap to EL1 execution of DZ ZVA at EL0. */
645 SCTLR_DZE_BIT |
646 /* Enable SP Alignment check for EL0 */
647 SCTLR_SA0_BIT |
648 /* Don't change PSTATE.PAN on taking an exception to EL1 */
649 SCTLR_SPAN_BIT |
650 /* Allow cacheable data and instr. accesses to normal memory. */
651 SCTLR_C_BIT | SCTLR_I_BIT |
652 /* Enable MMU. */
653 SCTLR_M_BIT;
654
655 sctlr_el1_val &= ~(
656 /* Explicit data accesses at EL0 are little-endian. */
657 SCTLR_E0E_BIT |
658 /*
659 * Alignment fault checking disabled when at EL1 and EL0 as
660 * the UEFI spec permits unaligned accesses.
661 */
662 SCTLR_A_BIT |
663 /* Accesses to DAIF from EL0 are trapped to EL1. */
664 SCTLR_UMA_BIT
665 );
666
667 /* Store the initialised SCTLR_EL1 value in the cpu_context */
668 write_ctx_sctlr_el1_reg_errata(ctx, sctlr_el1_val);
669 }
670
spmc_el0_sp_setup_system_registers(struct secure_partition_desc * sp,cpu_context_t * ctx)671 static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
672 cpu_context_t *ctx)
673 {
674
675 spmc_el0_sp_setup_mmu(sp, ctx);
676
677 spmc_el0_sp_setup_sctlr_el1(ctx);
678
679 /* Setup other system registers. */
680
681 /* Shim Exception Vector Base Address */
682 write_el1_ctx_common(get_el1_sysregs_ctx(ctx), vbar_el1,
683 SPM_SHIM_EXCEPTIONS_PTR);
684 write_el1_ctx_arch_timer(get_el1_sysregs_ctx(ctx), cntkctl_el1,
685 EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
686
687 /*
688 * FPEN: Allow the Secure Partition to access FP/SIMD registers.
689 * Note that SPM will not do any saving/restoring of these registers on
690 * behalf of the SP. This falls under the SP's responsibility.
691 * TTA: Enable access to trace registers.
692 * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
693 */
694 write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cpacr_el1,
695 CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
696 }
697
698 /* Setup context of an EL0 Secure Partition. */
spmc_el0_sp_setup(struct secure_partition_desc * sp,int32_t boot_info_reg,void * sp_manifest)699 void spmc_el0_sp_setup(struct secure_partition_desc *sp,
700 int32_t boot_info_reg,
701 void *sp_manifest)
702 {
703 mmap_region_t sel1_exception_vectors =
704 MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
705 SPM_SHIM_EXCEPTIONS_SIZE,
706 MT_CODE | MT_SECURE | MT_PRIVILEGED);
707 cpu_context_t *ctx;
708 int node;
709 int offset = 0;
710 struct mmap_region sp_mem_regions __unused = {0};
711
712 ctx = &sp->ec[SEL0_SP_EC_INDEX].cpu_ctx;
713
714 sp->xlat_ctx_handle->xlat_regime = EL1_EL0_REGIME;
715
716 /* This region contains the exception vectors used at S-EL1. */
717 mmap_add_region_ctx(sp->xlat_ctx_handle,
718 &sel1_exception_vectors);
719
720 /*
721 * If the SP manifest specified the register to pass the address of the
722 * boot information, then map the memory region to pass boot
723 * information.
724 */
725 if (boot_info_reg >= 0) {
726 mmap_region_t ffa_boot_info_region = MAP_REGION_FLAT(
727 (uintptr_t) ffa_boot_info_mem,
728 FFA_BOOT_INFO_SIZE,
729 MT_RO_DATA | MT_SECURE | MT_USER);
730 mmap_add_region_ctx(sp->xlat_ctx_handle, &ffa_boot_info_region);
731 }
732
733 /*
734 * Parse the manifest for any device regions that the SP wants to be
735 * mapped in its translation regime.
736 */
737 node = fdt_subnode_offset_namelen(sp_manifest, offset,
738 "device-regions",
739 sizeof("device-regions") - 1);
740 if (node < 0) {
741 WARN("Not found device-region configuration for SP.\n");
742 } else {
743 populate_sp_regions(sp, sp_manifest, node,
744 SP_MEM_REGION_DEVICE);
745 }
746
747 /*
748 * Parse the manifest for any memory regions that the SP wants to be
749 * mapped in its translation regime.
750 */
751 node = fdt_subnode_offset_namelen(sp_manifest, offset,
752 "memory-regions",
753 sizeof("memory-regions") - 1);
754 if (node < 0) {
755 WARN("Not found memory-region configuration for SP.\n");
756 } else {
757 populate_sp_regions(sp, sp_manifest, node,
758 SP_MEM_REGION_MEMORY);
759 }
760
761 #if HOB_LIST
762 /*
763 * Add tpm event log region with RO permission.
764 */
765 if (tpm_evtlog_addr != NULL && tpm_evtlog_size != 0) {
766 INFO("Mapping SP's TPM event log\n");
767 INFO("TPM event log addr(0x%lx), size(0x%lx)\n",
768 (uintptr_t)tpm_evtlog_addr, tpm_evtlog_size);
769 sp_mem_regions.base_pa = (uintptr_t)
770 ((unsigned long)tpm_evtlog_addr & ~(PAGE_SIZE_MASK));
771 sp_mem_regions.base_va = sp_mem_regions.base_pa;
772 sp_mem_regions.size = (tpm_evtlog_size & ~(PAGE_SIZE_MASK)) + PAGE_SIZE;
773 sp_mem_regions.attr = MT_USER | MT_SECURE | MT_RO_DATA;
774 sp_mem_regions.granularity = XLAT_BLOCK_SIZE(3);
775
776 INFO("Adding PA: 0x%llx VA: 0x%lx Size: 0x%lx attr:0x%x\n",
777 sp_mem_regions.base_pa,
778 sp_mem_regions.base_va,
779 sp_mem_regions.size,
780 sp_mem_regions.attr);
781
782 mmap_add_region_ctx(sp->xlat_ctx_handle, &sp_mem_regions);
783 }
784 #endif
785
786 spmc_el0_sp_setup_system_registers(sp, ctx);
787 }
788 #endif /* SPMC_AT_EL3_SEL0_SP */
789
790 /* S-EL1 partition specific initialisation. */
spmc_el1_sp_setup(struct secure_partition_desc * sp,entry_point_info_t * ep_info)791 void spmc_el1_sp_setup(struct secure_partition_desc *sp,
792 entry_point_info_t *ep_info)
793 {
794 /* Sanity check input arguments. */
795 assert(sp != NULL);
796 assert(ep_info != NULL);
797
798 /* Initialise the SPSR for S-EL1 SPs. */
799 ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
800 DISABLE_ALL_EXCEPTIONS);
801
802 /*
803 * TF-A Implementation defined behaviour to provide the linear
804 * core ID in the x4 register.
805 */
806 ep_info->args.arg4 = (uintptr_t) plat_my_core_pos();
807
808 /*
809 * Check whether setup is being performed for the primary or a secondary
810 * execution context. In the latter case, indicate to the SP that this
811 * is a warm boot.
812 * TODO: This check would need to be reworked if the same entry point is
813 * used for both primary and secondary initialisation.
814 */
815 if (sp->secondary_ep != 0U) {
816 /*
817 * Sanity check that the secondary entry point is still what was
818 * originally set.
819 */
820 assert(sp->secondary_ep == ep_info->pc);
821 ep_info->args.arg0 = FFA_WB_TYPE_S2RAM;
822 }
823 }
824
825 /* Common initialisation for all SPs. */
spmc_sp_common_setup(struct secure_partition_desc * sp,entry_point_info_t * ep_info,int32_t boot_info_reg)826 void spmc_sp_common_setup(struct secure_partition_desc *sp,
827 entry_point_info_t *ep_info,
828 int32_t boot_info_reg)
829 {
830 uint16_t sp_id;
831
832 /* Assign FF-A Partition ID if not already assigned. */
833 if (sp->sp_id == INV_SP_ID) {
834 sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX;
835 /*
836 * Ensure we don't clash with previously assigned partition
837 * IDs.
838 */
839 while (!is_ffa_secure_id_valid(sp_id)) {
840 sp_id++;
841
842 if (sp_id == FFA_SWD_ID_LIMIT) {
843 ERROR("Unable to determine valid SP ID.\n");
844 panic();
845 }
846 }
847 sp->sp_id = sp_id;
848 }
849
850 /* Check if the SP wants to use the FF-A boot protocol. */
851 if (boot_info_reg >= 0) {
852 /*
853 * Create a boot information descriptor and copy the partition
854 * manifest into the reserved memory region for consumption by
855 * the SP.
856 */
857 spmc_create_boot_info(ep_info, sp);
858
859 /*
860 * We have consumed what we need from ep args so we can now
861 * zero them before we start populating with new information
862 * specifically for the SP.
863 */
864 zeromem(&ep_info->args, sizeof(ep_info->args));
865
866 /*
867 * Pass the address of the boot information in the
868 * boot_info_reg.
869 */
870 switch (boot_info_reg) {
871 case 0:
872 ep_info->args.arg0 = (uintptr_t) ffa_boot_info_mem;
873 break;
874 case 1:
875 ep_info->args.arg1 = (uintptr_t) ffa_boot_info_mem;
876 break;
877 case 2:
878 ep_info->args.arg2 = (uintptr_t) ffa_boot_info_mem;
879 break;
880 case 3:
881 ep_info->args.arg3 = (uintptr_t) ffa_boot_info_mem;
882 break;
883 default:
884 ERROR("Invalid value for \"gp-register-num\" %d.\n",
885 boot_info_reg);
886 }
887 } else {
888 /*
889 * We don't need any of the information that was populated
890 * in ep_args so we can clear them.
891 */
892 zeromem(&ep_info->args, sizeof(ep_info->args));
893 }
894 }
895
896 /*
897 * Initialise the SP context now we have populated the common and EL specific
898 * entrypoint information.
899 */
spmc_sp_common_ep_commit(struct secure_partition_desc * sp,entry_point_info_t * ep_info)900 void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
901 entry_point_info_t *ep_info)
902 {
903 cpu_context_t *cpu_ctx;
904
905 cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx);
906 print_entry_point_info(ep_info);
907 cm_setup_context(cpu_ctx, ep_info);
908 }
909