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