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