xref: /rk3399_ARM-atf/services/std_svc/spm/el3_spmc/spmc_setup.c (revision 83c3da7711a246e04f4d0a64593fc0ab46f08bad)
1 /*
2  * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <string.h>
9 
10 #include <arch.h>
11 #include <arch_helpers.h>
12 #include <common/debug.h>
13 #include <common/fdt_wrappers.h>
14 #include <context.h>
15 #include <lib/el3_runtime/context_mgmt.h>
16 #include <lib/utils.h>
17 #include <lib/xlat_tables/xlat_tables_v2.h>
18 #include <libfdt.h>
19 #include <plat/common/common_def.h>
20 #include <plat/common/platform.h>
21 #include <services/ffa_svc.h>
22 #include "spm_common.h"
23 #include "spm_shim_private.h"
24 #include "spmc.h"
25 #include <tools_share/firmware_image_package.h>
26 
27 #include <platform_def.h>
28 
29 /*
30  * Statically allocate a page of memory for passing boot information to an SP.
31  */
32 static uint8_t ffa_boot_info_mem[PAGE_SIZE] __aligned(PAGE_SIZE);
33 
34 /*
35  * We need to choose one execution context from all those available for a S-EL0
36  * SP. This execution context will be used subsequently irrespective of which
37  * physical CPU the SP runs on.
38  */
39 #define SEL0_SP_EC_INDEX 0
40 #define SP_MEM_READ 0x1
41 #define SP_MEM_WRITE 0x2
42 #define SP_MEM_EXECUTE 0x4
43 #define SP_MEM_NON_SECURE 0x8
44 #define SP_MEM_READ_ONLY SP_MEM_READ
45 #define SP_MEM_READ_WRITE (SP_MEM_READ | SP_MEM_WRITE)
46 
47 /*
48  * This function creates a initialization descriptor in the memory reserved
49  * for passing boot information to an SP. It then copies the partition manifest
50  * into this region and ensures that its reference in the initialization
51  * descriptor is updated.
52  */
53 static void spmc_create_boot_info(entry_point_info_t *ep_info,
54 				  struct secure_partition_desc *sp)
55 {
56 	struct ffa_boot_info_header *boot_header;
57 	struct ffa_boot_info_desc *boot_descriptor;
58 	uintptr_t manifest_addr;
59 
60 	/*
61 	 * Calculate the maximum size of the manifest that can be accommodated
62 	 * in the boot information memory region.
63 	 */
64 	const unsigned int
65 	max_manifest_sz = sizeof(ffa_boot_info_mem) -
66 			  (sizeof(struct ffa_boot_info_header) +
67 			   sizeof(struct ffa_boot_info_desc));
68 
69 	/*
70 	 * The current implementation only supports the FF-A v1.1
71 	 * implementation of the boot protocol, therefore check
72 	 * that a v1.0 SP has not requested use of the protocol.
73 	 */
74 	if (sp->ffa_version == MAKE_FFA_VERSION(1, 0)) {
75 		ERROR("FF-A boot protocol not supported for v1.0 clients\n");
76 		return;
77 	}
78 
79 	/*
80 	 * Check if the manifest will fit into the boot info memory region else
81 	 * bail.
82 	 */
83 	if (ep_info->args.arg1 > max_manifest_sz) {
84 		WARN("Unable to copy manifest into boot information. ");
85 		WARN("Max sz = %u bytes. Manifest sz = %lu bytes\n",
86 		     max_manifest_sz, ep_info->args.arg1);
87 		return;
88 	}
89 
90 	/* Zero the memory region before populating. */
91 	memset(ffa_boot_info_mem, 0, PAGE_SIZE);
92 
93 	/*
94 	 * Populate the ffa_boot_info_header at the start of the boot info
95 	 * region.
96 	 */
97 	boot_header = (struct ffa_boot_info_header *) ffa_boot_info_mem;
98 
99 	/* Position the ffa_boot_info_desc after the ffa_boot_info_header. */
100 	boot_header->offset_boot_info_desc =
101 					sizeof(struct ffa_boot_info_header);
102 	boot_descriptor = (struct ffa_boot_info_desc *)
103 			  (ffa_boot_info_mem +
104 			   boot_header->offset_boot_info_desc);
105 
106 	/*
107 	 * We must use the FF-A version corresponding to the version implemented
108 	 * by the SP. Currently this can only be v1.1.
109 	 */
110 	boot_header->version = sp->ffa_version;
111 
112 	/* Populate the boot information header. */
113 	boot_header->size_boot_info_desc = sizeof(struct ffa_boot_info_desc);
114 
115 	/* Set the signature "0xFFA". */
116 	boot_header->signature = FFA_INIT_DESC_SIGNATURE;
117 
118 	/* Set the count. Currently 1 since only the manifest is specified. */
119 	boot_header->count_boot_info_desc = 1;
120 
121 	/* Populate the boot information descriptor for the manifest. */
122 	boot_descriptor->type =
123 		FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
124 		FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_FDT);
125 
126 	boot_descriptor->flags =
127 		FFA_BOOT_INFO_FLAG_NAME(FFA_BOOT_INFO_FLAG_NAME_UUID) |
128 		FFA_BOOT_INFO_FLAG_CONTENT(FFA_BOOT_INFO_FLAG_CONTENT_ADR);
129 
130 	/*
131 	 * Copy the manifest into boot info region after the boot information
132 	 * descriptor.
133 	 */
134 	boot_descriptor->size_boot_info = (uint32_t) ep_info->args.arg1;
135 
136 	manifest_addr = (uintptr_t) (ffa_boot_info_mem +
137 				     boot_header->offset_boot_info_desc +
138 				     boot_header->size_boot_info_desc);
139 
140 	memcpy((void *) manifest_addr, (void *) ep_info->args.arg0,
141 	       boot_descriptor->size_boot_info);
142 
143 	boot_descriptor->content = manifest_addr;
144 
145 	/* Calculate the size of the total boot info blob. */
146 	boot_header->size_boot_info_blob = boot_header->offset_boot_info_desc +
147 					   boot_descriptor->size_boot_info +
148 					   (boot_header->count_boot_info_desc *
149 					    boot_header->size_boot_info_desc);
150 
151 	INFO("SP boot info @ 0x%lx, size: %u bytes.\n",
152 	     (uintptr_t) ffa_boot_info_mem,
153 	     boot_header->size_boot_info_blob);
154 	INFO("SP manifest @ 0x%lx, size: %u bytes.\n",
155 	     boot_descriptor->content,
156 	     boot_descriptor->size_boot_info);
157 }
158 
159 /*
160  * S-EL1 partitions can be assigned with multiple execution contexts, each
161  * pinned to the physical CPU. Each execution context index corresponds to the
162  * respective liner core position.
163  * S-EL0 partitions execute in a single execution context (index 0).
164  */
165 unsigned int get_ec_index(struct secure_partition_desc *sp)
166 {
167 	return (sp->runtime_el == S_EL0) ?
168 		SEL0_SP_EC_INDEX : plat_my_core_pos();
169 }
170 
171 #if SPMC_AT_EL3_SEL0_SP
172 /* Setup spsr in entry point info for common context management code to use. */
173 void spmc_el0_sp_spsr_setup(entry_point_info_t *ep_info)
174 {
175 	/* Setup Secure Partition SPSR for S-EL0 SP. */
176 	ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
177 }
178 
179 static void read_optional_string(void *manifest, int32_t offset,
180 				 char *property, char *out, size_t len)
181 {
182 	const fdt32_t *prop;
183 	int lenp;
184 
185 	prop = fdt_getprop(manifest, offset, property, &lenp);
186 	if (prop == NULL) {
187 		out[0] = '\0';
188 	} else {
189 		memcpy(out, prop, MIN(lenp, (int)len));
190 	}
191 }
192 
193 /*******************************************************************************
194  * This function will parse the Secure Partition Manifest for fetching secure
195  * partition specific memory region details. It will find base address, size,
196  * memory attributes for each memory region and then add the respective region
197  * into secure parition's translation context.
198  ******************************************************************************/
199 static void populate_sp_mem_regions(struct secure_partition_desc *sp,
200 				    void *sp_manifest,
201 				    int node)
202 {
203 	uintptr_t base_address;
204 	uint32_t mem_attr, mem_region, size;
205 	struct mmap_region sp_mem_regions;
206 	int32_t offset, ret;
207 	char description[10];
208 	char *property;
209 
210 	if (fdt_node_check_compatible(sp_manifest, node,
211 				      "arm,ffa-manifest-memory-regions") != 0) {
212 		WARN("Incompatible memory region node in manifest\n");
213 		return;
214 	}
215 
216 	INFO("Mapping SP's memory regions\n");
217 
218 	for (offset = fdt_first_subnode(sp_manifest, node), mem_region = 0;
219 	     offset >= 0;
220 	     offset = fdt_next_subnode(sp_manifest, offset), mem_region++) {
221 		read_optional_string(sp_manifest, offset, "description",
222 				     description, sizeof(description));
223 
224 		INFO("Mapping: region: %d, %s\n", mem_region, description);
225 
226 		property = "base-address";
227 		ret = fdt_read_uint64(sp_manifest, offset, property,
228 					&base_address);
229 		if (ret < 0) {
230 			WARN("Missing:%s for %s.\n", property, description);
231 			continue;
232 		}
233 
234 		property = "pages-count";
235 		ret = fdt_read_uint32(sp_manifest, offset, property, &size);
236 		if (ret < 0) {
237 			WARN("Missing: %s for %s.\n", property, description);
238 			continue;
239 		}
240 		size *= PAGE_SIZE;
241 
242 		property = "attributes";
243 		ret = fdt_read_uint32(sp_manifest, offset, property, &mem_attr);
244 		if (ret < 0) {
245 			WARN("Missing: %s for %s.\n", property, description);
246 			continue;
247 		}
248 
249 		sp_mem_regions.attr = MT_USER;
250 		if ((mem_attr & SP_MEM_EXECUTE) == SP_MEM_EXECUTE) {
251 			sp_mem_regions.attr |= MT_CODE;
252 		} else if ((mem_attr & SP_MEM_READ_ONLY) == SP_MEM_READ_ONLY) {
253 			sp_mem_regions.attr |= MT_RO_DATA;
254 		} else if ((mem_attr & SP_MEM_READ_WRITE) ==
255 				SP_MEM_READ_WRITE) {
256 			sp_mem_regions.attr |= MT_RW_DATA;
257 		}
258 
259 		if ((mem_attr & SP_MEM_NON_SECURE) == SP_MEM_NON_SECURE) {
260 			sp_mem_regions.attr |= MT_NS;
261 		} else {
262 			sp_mem_regions.attr |= MT_SECURE;
263 		}
264 
265 		sp_mem_regions.base_pa = base_address;
266 		sp_mem_regions.base_va = base_address;
267 		sp_mem_regions.size = size;
268 		sp_mem_regions.granularity = XLAT_BLOCK_SIZE(3);
269 		mmap_add_region_ctx(sp->xlat_ctx_handle, &sp_mem_regions);
270 	}
271 }
272 
273 static void spmc_el0_sp_setup_mmu(struct secure_partition_desc *sp,
274 				  cpu_context_t *ctx)
275 {
276 	xlat_ctx_t *xlat_ctx;
277 	uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
278 
279 	xlat_ctx = sp->xlat_ctx_handle;
280 	init_xlat_tables_ctx(sp->xlat_ctx_handle);
281 	setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table,
282 		      xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
283 		      EL1_EL0_REGIME);
284 
285 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
286 		      mmu_cfg_params[MMU_CFG_MAIR]);
287 
288 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
289 		      mmu_cfg_params[MMU_CFG_TCR]);
290 
291 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
292 		      mmu_cfg_params[MMU_CFG_TTBR0]);
293 }
294 
295 static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
296 {
297 	u_register_t sctlr_el1;
298 
299 	/* Setup SCTLR_EL1 */
300 	sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
301 
302 	sctlr_el1 |=
303 		/*SCTLR_EL1_RES1 |*/
304 		/* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
305 		SCTLR_UCI_BIT |
306 		/* RW regions at xlat regime EL1&0 are forced to be XN. */
307 		SCTLR_WXN_BIT |
308 		/* Don't trap to EL1 execution of WFI or WFE at EL0. */
309 		SCTLR_NTWI_BIT | SCTLR_NTWE_BIT |
310 		/* Don't trap to EL1 accesses to CTR_EL0 from EL0. */
311 		SCTLR_UCT_BIT |
312 		/* Don't trap to EL1 execution of DZ ZVA at EL0. */
313 		SCTLR_DZE_BIT |
314 		/* Enable SP Alignment check for EL0 */
315 		SCTLR_SA0_BIT |
316 		/* Don't change PSTATE.PAN on taking an exception to EL1 */
317 		SCTLR_SPAN_BIT |
318 		/* Allow cacheable data and instr. accesses to normal memory. */
319 		SCTLR_C_BIT | SCTLR_I_BIT |
320 		/* Enable MMU. */
321 		SCTLR_M_BIT;
322 
323 	sctlr_el1 &= ~(
324 		/* Explicit data accesses at EL0 are little-endian. */
325 		SCTLR_E0E_BIT |
326 		/*
327 		 * Alignment fault checking disabled when at EL1 and EL0 as
328 		 * the UEFI spec permits unaligned accesses.
329 		 */
330 		SCTLR_A_BIT |
331 		/* Accesses to DAIF from EL0 are trapped to EL1. */
332 		SCTLR_UMA_BIT
333 	);
334 
335 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
336 }
337 
338 static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
339 					       cpu_context_t *ctx)
340 {
341 
342 	spmc_el0_sp_setup_mmu(sp, ctx);
343 
344 	spmc_el0_sp_setup_sctlr_el1(ctx);
345 
346 	/* Setup other system registers. */
347 
348 	/* Shim Exception Vector Base Address */
349 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
350 			SPM_SHIM_EXCEPTIONS_PTR);
351 #if NS_TIMER_SWITCH
352 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
353 		      EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
354 #endif
355 
356 	/*
357 	 * FPEN: Allow the Secure Partition to access FP/SIMD registers.
358 	 * Note that SPM will not do any saving/restoring of these registers on
359 	 * behalf of the SP. This falls under the SP's responsibility.
360 	 * TTA: Enable access to trace registers.
361 	 * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
362 	 */
363 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
364 			CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
365 }
366 
367 /* Setup context of an EL0 Secure Partition.  */
368 void spmc_el0_sp_setup(struct secure_partition_desc *sp,
369 		       int32_t boot_info_reg,
370 		       void *sp_manifest)
371 {
372 	mmap_region_t sel1_exception_vectors =
373 		MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
374 				SPM_SHIM_EXCEPTIONS_SIZE,
375 				MT_CODE | MT_SECURE | MT_PRIVILEGED);
376 	cpu_context_t *ctx;
377 	int node;
378 	int offset = 0;
379 
380 	ctx = &sp->ec[SEL0_SP_EC_INDEX].cpu_ctx;
381 
382 	sp->xlat_ctx_handle->xlat_regime = EL1_EL0_REGIME;
383 
384 	/* This region contains the exception vectors used at S-EL1. */
385 	mmap_add_region_ctx(sp->xlat_ctx_handle,
386 			    &sel1_exception_vectors);
387 
388 	/*
389 	 * If the SP manifest specified the register to pass the address of the
390 	 * boot information, then map the memory region to pass boot
391 	 * information.
392 	 */
393 	if (boot_info_reg >= 0) {
394 		mmap_region_t ffa_boot_info_region = MAP_REGION_FLAT(
395 			(uintptr_t) ffa_boot_info_mem,
396 			PAGE_SIZE,
397 			MT_RO_DATA | MT_SECURE | MT_USER);
398 		mmap_add_region_ctx(sp->xlat_ctx_handle, &ffa_boot_info_region);
399 	}
400 
401 	/*
402 	 * Parse the manifest for any memory regions that the SP wants to be
403 	 * mapped in its translation regime.
404 	 */
405 	node = fdt_subnode_offset_namelen(sp_manifest, offset,
406 					  "memory-regions",
407 					  sizeof("memory-regions") - 1);
408 	if (node < 0) {
409 		WARN("Not found memory-region configuration for SP.\n");
410 	} else {
411 		populate_sp_mem_regions(sp, sp_manifest, node);
412 	}
413 
414 	spmc_el0_sp_setup_system_registers(sp, ctx);
415 
416 }
417 #endif /* SPMC_AT_EL3_SEL0_SP */
418 
419 /* S-EL1 partition specific initialisation. */
420 void spmc_el1_sp_setup(struct secure_partition_desc *sp,
421 		       entry_point_info_t *ep_info)
422 {
423 	/* Sanity check input arguments. */
424 	assert(sp != NULL);
425 	assert(ep_info != NULL);
426 
427 	/* Initialise the SPSR for S-EL1 SPs. */
428 	ep_info->spsr =	SPSR_64(MODE_EL1, MODE_SP_ELX,
429 				DISABLE_ALL_EXCEPTIONS);
430 
431 	/*
432 	 * TF-A Implementation defined behaviour to provide the linear
433 	 * core ID in the x4 register.
434 	 */
435 	ep_info->args.arg4 = (uintptr_t) plat_my_core_pos();
436 
437 	/*
438 	 * Check whether setup is being performed for the primary or a secondary
439 	 * execution context. In the latter case, indicate to the SP that this
440 	 * is a warm boot.
441 	 * TODO: This check would need to be reworked if the same entry point is
442 	 * used for both primary and secondary initialisation.
443 	 */
444 	if (sp->secondary_ep != 0U) {
445 		/*
446 		 * Sanity check that the secondary entry point is still what was
447 		 * originally set.
448 		 */
449 		assert(sp->secondary_ep == ep_info->pc);
450 		ep_info->args.arg0 = FFA_WB_TYPE_S2RAM;
451 	}
452 }
453 
454 /* Common initialisation for all SPs. */
455 void spmc_sp_common_setup(struct secure_partition_desc *sp,
456 			  entry_point_info_t *ep_info,
457 			  int32_t boot_info_reg)
458 {
459 	uint16_t sp_id;
460 
461 	/* Assign FF-A Partition ID if not already assigned. */
462 	if (sp->sp_id == INV_SP_ID) {
463 		sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX;
464 		/*
465 		 * Ensure we don't clash with previously assigned partition
466 		 * IDs.
467 		 */
468 		while (!is_ffa_secure_id_valid(sp_id)) {
469 			sp_id++;
470 
471 			if (sp_id == FFA_SWD_ID_LIMIT) {
472 				ERROR("Unable to determine valid SP ID.\n");
473 				panic();
474 			}
475 		}
476 		sp->sp_id = sp_id;
477 	}
478 
479 	/* Check if the SP wants to use the FF-A boot protocol. */
480 	if (boot_info_reg >= 0) {
481 		/*
482 		 * Create a boot information descriptor and copy the partition
483 		 * manifest into the reserved memory region for consumption by
484 		 * the SP.
485 		 */
486 		spmc_create_boot_info(ep_info, sp);
487 
488 		/*
489 		 * We have consumed what we need from ep args so we can now
490 		 * zero them before we start populating with new information
491 		 * specifically for the SP.
492 		 */
493 		zeromem(&ep_info->args, sizeof(ep_info->args));
494 
495 		/*
496 		 * Pass the address of the boot information in the
497 		 * boot_info_reg.
498 		 */
499 		switch (boot_info_reg) {
500 		case 0:
501 			ep_info->args.arg0 = (uintptr_t) ffa_boot_info_mem;
502 			break;
503 		case 1:
504 			ep_info->args.arg1 = (uintptr_t) ffa_boot_info_mem;
505 			break;
506 		case 2:
507 			ep_info->args.arg2 = (uintptr_t) ffa_boot_info_mem;
508 			break;
509 		case 3:
510 			ep_info->args.arg3 = (uintptr_t) ffa_boot_info_mem;
511 			break;
512 		default:
513 			ERROR("Invalid value for \"gp-register-num\" %d.\n",
514 			      boot_info_reg);
515 		}
516 	} else {
517 		/*
518 		 * We don't need any of the information that was populated
519 		 * in ep_args so we can clear them.
520 		 */
521 		zeromem(&ep_info->args, sizeof(ep_info->args));
522 	}
523 }
524 
525 /*
526  * Initialise the SP context now we have populated the common and EL specific
527  * entrypoint information.
528  */
529 void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
530 			      entry_point_info_t *ep_info)
531 {
532 	cpu_context_t *cpu_ctx;
533 
534 	cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx);
535 	print_entry_point_info(ep_info);
536 	cm_setup_context(cpu_ctx, ep_info);
537 }
538