xref: /rk3399_ARM-atf/services/std_svc/spm/el3_spmc/spmc_setup.c (revision 48db2b0120d1726208ff38a0edf6962f55a988bf)
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 
41 /*
42  * This function creates a initialization descriptor in the memory reserved
43  * for passing boot information to an SP. It then copies the partition manifest
44  * into this region and ensures that its reference in the initialization
45  * descriptor is updated.
46  */
47 static void spmc_create_boot_info(entry_point_info_t *ep_info,
48 				  struct secure_partition_desc *sp)
49 {
50 	struct ffa_boot_info_header *boot_header;
51 	struct ffa_boot_info_desc *boot_descriptor;
52 	uintptr_t manifest_addr;
53 
54 	/*
55 	 * Calculate the maximum size of the manifest that can be accommodated
56 	 * in the boot information memory region.
57 	 */
58 	const unsigned int
59 	max_manifest_sz = sizeof(ffa_boot_info_mem) -
60 			  (sizeof(struct ffa_boot_info_header) +
61 			   sizeof(struct ffa_boot_info_desc));
62 
63 	/*
64 	 * The current implementation only supports the FF-A v1.1
65 	 * implementation of the boot protocol, therefore check
66 	 * that a v1.0 SP has not requested use of the protocol.
67 	 */
68 	if (sp->ffa_version == MAKE_FFA_VERSION(1, 0)) {
69 		ERROR("FF-A boot protocol not supported for v1.0 clients\n");
70 		return;
71 	}
72 
73 	/*
74 	 * Check if the manifest will fit into the boot info memory region else
75 	 * bail.
76 	 */
77 	if (ep_info->args.arg1 > max_manifest_sz) {
78 		WARN("Unable to copy manifest into boot information. ");
79 		WARN("Max sz = %u bytes. Manifest sz = %lu bytes\n",
80 		     max_manifest_sz, ep_info->args.arg1);
81 		return;
82 	}
83 
84 	/* Zero the memory region before populating. */
85 	memset(ffa_boot_info_mem, 0, PAGE_SIZE);
86 
87 	/*
88 	 * Populate the ffa_boot_info_header at the start of the boot info
89 	 * region.
90 	 */
91 	boot_header = (struct ffa_boot_info_header *) ffa_boot_info_mem;
92 
93 	/* Position the ffa_boot_info_desc after the ffa_boot_info_header. */
94 	boot_header->offset_boot_info_desc =
95 					sizeof(struct ffa_boot_info_header);
96 	boot_descriptor = (struct ffa_boot_info_desc *)
97 			  (ffa_boot_info_mem +
98 			   boot_header->offset_boot_info_desc);
99 
100 	/*
101 	 * We must use the FF-A version corresponding to the version implemented
102 	 * by the SP. Currently this can only be v1.1.
103 	 */
104 	boot_header->version = sp->ffa_version;
105 
106 	/* Populate the boot information header. */
107 	boot_header->size_boot_info_desc = sizeof(struct ffa_boot_info_desc);
108 
109 	/* Set the signature "0xFFA". */
110 	boot_header->signature = FFA_INIT_DESC_SIGNATURE;
111 
112 	/* Set the count. Currently 1 since only the manifest is specified. */
113 	boot_header->count_boot_info_desc = 1;
114 
115 	/* Populate the boot information descriptor for the manifest. */
116 	boot_descriptor->type =
117 		FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
118 		FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_FDT);
119 
120 	boot_descriptor->flags =
121 		FFA_BOOT_INFO_FLAG_NAME(FFA_BOOT_INFO_FLAG_NAME_UUID) |
122 		FFA_BOOT_INFO_FLAG_CONTENT(FFA_BOOT_INFO_FLAG_CONTENT_ADR);
123 
124 	/*
125 	 * Copy the manifest into boot info region after the boot information
126 	 * descriptor.
127 	 */
128 	boot_descriptor->size_boot_info = (uint32_t) ep_info->args.arg1;
129 
130 	manifest_addr = (uintptr_t) (ffa_boot_info_mem +
131 				     boot_header->offset_boot_info_desc +
132 				     boot_header->size_boot_info_desc);
133 
134 	memcpy((void *) manifest_addr, (void *) ep_info->args.arg0,
135 	       boot_descriptor->size_boot_info);
136 
137 	boot_descriptor->content = manifest_addr;
138 
139 	/* Calculate the size of the total boot info blob. */
140 	boot_header->size_boot_info_blob = boot_header->offset_boot_info_desc +
141 					   boot_descriptor->size_boot_info +
142 					   (boot_header->count_boot_info_desc *
143 					    boot_header->size_boot_info_desc);
144 
145 	INFO("SP boot info @ 0x%lx, size: %u bytes.\n",
146 	     (uintptr_t) ffa_boot_info_mem,
147 	     boot_header->size_boot_info_blob);
148 	INFO("SP manifest @ 0x%lx, size: %u bytes.\n",
149 	     boot_descriptor->content,
150 	     boot_descriptor->size_boot_info);
151 }
152 
153 /*
154  * S-EL1 partitions can be assigned with multiple execution contexts, each
155  * pinned to the physical CPU. Each execution context index corresponds to the
156  * respective liner core position.
157  * S-EL0 partitions execute in a single execution context (index 0).
158  */
159 unsigned int get_ec_index(struct secure_partition_desc *sp)
160 {
161 	return (sp->runtime_el == S_EL0) ?
162 		SEL0_SP_EC_INDEX : plat_my_core_pos();
163 }
164 
165 #if SPMC_AT_EL3_SEL0_SP
166 /* Setup spsr in entry point info for common context management code to use. */
167 void spmc_el0_sp_spsr_setup(entry_point_info_t *ep_info)
168 {
169 	/* Setup Secure Partition SPSR for S-EL0 SP. */
170 	ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
171 }
172 
173 /* Setup context of an EL0 Secure Partition.  */
174 void spmc_el0_sp_setup(struct secure_partition_desc *sp,
175 		       int32_t boot_info_reg)
176 {
177 	mmap_region_t sel1_exception_vectors =
178 		MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
179 				SPM_SHIM_EXCEPTIONS_SIZE,
180 				MT_CODE | MT_SECURE | MT_PRIVILEGED);
181 	cpu_context_t *ctx;
182 
183 	ctx = &sp->ec[SEL0_SP_EC_INDEX].cpu_ctx;
184 
185 	sp->xlat_ctx_handle->xlat_regime = EL1_EL0_REGIME;
186 
187 	/* This region contains the exception vectors used at S-EL1. */
188 	mmap_add_region_ctx(sp->xlat_ctx_handle,
189 			    &sel1_exception_vectors);
190 
191 	/*
192 	 * If the SP manifest specified the register to pass the address of the
193 	 * boot information, then map the memory region to pass boot
194 	 * information.
195 	 */
196 	if (boot_info_reg >= 0) {
197 		mmap_region_t ffa_boot_info_region = MAP_REGION_FLAT(
198 			(uintptr_t) ffa_boot_info_mem,
199 			PAGE_SIZE,
200 			MT_RO_DATA | MT_SECURE | MT_USER);
201 		mmap_add_region_ctx(sp->xlat_ctx_handle, &ffa_boot_info_region);
202 	}
203 
204 	/* Setup SCTLR_EL1 */
205 	u_register_t sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
206 
207 	sctlr_el1 |=
208 		/*SCTLR_EL1_RES1 |*/
209 		/* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
210 		SCTLR_UCI_BIT							|
211 		/* RW regions at xlat regime EL1&0 are forced to be XN. */
212 		SCTLR_WXN_BIT							|
213 		/* Don't trap to EL1 execution of WFI or WFE at EL0. */
214 		SCTLR_NTWI_BIT | SCTLR_NTWE_BIT					|
215 		/* Don't trap to EL1 accesses to CTR_EL0 from EL0. */
216 		SCTLR_UCT_BIT							|
217 		/* Don't trap to EL1 execution of DZ ZVA at EL0. */
218 		SCTLR_DZE_BIT							|
219 		/* Enable SP Alignment check for EL0 */
220 		SCTLR_SA0_BIT							|
221 		/* Don't change PSTATE.PAN on taking an exception to EL1 */
222 		SCTLR_SPAN_BIT							|
223 		/* Allow cacheable data and instr. accesses to normal memory. */
224 		SCTLR_C_BIT | SCTLR_I_BIT					|
225 		/* Enable MMU. */
226 		SCTLR_M_BIT
227 	;
228 
229 	sctlr_el1 &= ~(
230 		/* Explicit data accesses at EL0 are little-endian. */
231 		SCTLR_E0E_BIT							|
232 		/*
233 		 * Alignment fault checking disabled when at EL1 and EL0 as
234 		 * the UEFI spec permits unaligned accesses.
235 		 */
236 		SCTLR_A_BIT							|
237 		/* Accesses to DAIF from EL0 are trapped to EL1. */
238 		SCTLR_UMA_BIT
239 	);
240 
241 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
242 
243 	/* Setup other system registers. */
244 
245 	/* Shim Exception Vector Base Address */
246 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
247 			SPM_SHIM_EXCEPTIONS_PTR);
248 #if NS_TIMER_SWITCH
249 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
250 		      EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
251 #endif
252 
253 	/*
254 	 * FPEN: Allow the Secure Partition to access FP/SIMD registers.
255 	 * Note that SPM will not do any saving/restoring of these registers on
256 	 * behalf of the SP. This falls under the SP's responsibility.
257 	 * TTA: Enable access to trace registers.
258 	 * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
259 	 */
260 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
261 			CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
262 }
263 #endif /* SPMC_AT_EL3_SEL0_SP */
264 
265 /* S-EL1 partition specific initialisation. */
266 void spmc_el1_sp_setup(struct secure_partition_desc *sp,
267 		       entry_point_info_t *ep_info)
268 {
269 	/* Sanity check input arguments. */
270 	assert(sp != NULL);
271 	assert(ep_info != NULL);
272 
273 	/* Initialise the SPSR for S-EL1 SPs. */
274 	ep_info->spsr =	SPSR_64(MODE_EL1, MODE_SP_ELX,
275 				DISABLE_ALL_EXCEPTIONS);
276 
277 	/*
278 	 * TF-A Implementation defined behaviour to provide the linear
279 	 * core ID in the x4 register.
280 	 */
281 	ep_info->args.arg4 = (uintptr_t) plat_my_core_pos();
282 
283 	/*
284 	 * Check whether setup is being performed for the primary or a secondary
285 	 * execution context. In the latter case, indicate to the SP that this
286 	 * is a warm boot.
287 	 * TODO: This check would need to be reworked if the same entry point is
288 	 * used for both primary and secondary initialisation.
289 	 */
290 	if (sp->secondary_ep != 0U) {
291 		/*
292 		 * Sanity check that the secondary entry point is still what was
293 		 * originally set.
294 		 */
295 		assert(sp->secondary_ep == ep_info->pc);
296 		ep_info->args.arg0 = FFA_WB_TYPE_S2RAM;
297 	}
298 }
299 
300 /* Common initialisation for all SPs. */
301 void spmc_sp_common_setup(struct secure_partition_desc *sp,
302 			  entry_point_info_t *ep_info,
303 			  int32_t boot_info_reg)
304 {
305 	uint16_t sp_id;
306 
307 	/* Assign FF-A Partition ID if not already assigned. */
308 	if (sp->sp_id == INV_SP_ID) {
309 		sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX;
310 		/*
311 		 * Ensure we don't clash with previously assigned partition
312 		 * IDs.
313 		 */
314 		while (!is_ffa_secure_id_valid(sp_id)) {
315 			sp_id++;
316 
317 			if (sp_id == FFA_SWD_ID_LIMIT) {
318 				ERROR("Unable to determine valid SP ID.\n");
319 				panic();
320 			}
321 		}
322 		sp->sp_id = sp_id;
323 	}
324 
325 	/* Check if the SP wants to use the FF-A boot protocol. */
326 	if (boot_info_reg >= 0) {
327 		/*
328 		 * Create a boot information descriptor and copy the partition
329 		 * manifest into the reserved memory region for consumption by
330 		 * the SP.
331 		 */
332 		spmc_create_boot_info(ep_info, sp);
333 
334 		/*
335 		 * We have consumed what we need from ep args so we can now
336 		 * zero them before we start populating with new information
337 		 * specifically for the SP.
338 		 */
339 		zeromem(&ep_info->args, sizeof(ep_info->args));
340 
341 		/*
342 		 * Pass the address of the boot information in the
343 		 * boot_info_reg.
344 		 */
345 		switch (boot_info_reg) {
346 		case 0:
347 			ep_info->args.arg0 = (uintptr_t) ffa_boot_info_mem;
348 			break;
349 		case 1:
350 			ep_info->args.arg1 = (uintptr_t) ffa_boot_info_mem;
351 			break;
352 		case 2:
353 			ep_info->args.arg2 = (uintptr_t) ffa_boot_info_mem;
354 			break;
355 		case 3:
356 			ep_info->args.arg3 = (uintptr_t) ffa_boot_info_mem;
357 			break;
358 		default:
359 			ERROR("Invalid value for \"gp-register-num\" %d.\n",
360 			      boot_info_reg);
361 		}
362 	} else {
363 		/*
364 		 * We don't need any of the information that was populated
365 		 * in ep_args so we can clear them.
366 		 */
367 		zeromem(&ep_info->args, sizeof(ep_info->args));
368 	}
369 }
370 
371 /*
372  * Initialise the SP context now we have populated the common and EL specific
373  * entrypoint information.
374  */
375 void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
376 			      entry_point_info_t *ep_info)
377 {
378 	cpu_context_t *cpu_ctx;
379 
380 	cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx);
381 	print_entry_point_info(ep_info);
382 	cm_setup_context(cpu_ctx, ep_info);
383 }
384