blob: 609d968b96e5bd60ba352bd8c8036be914fc8bc8 [file] [log] [blame]
Marc Bonnici8e1a7552021-12-01 17:57:04 +00001/*
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>
Achin Guptaeaf17162021-10-19 12:21:16 +010013#include <common/fdt_wrappers.h>
Marc Bonnici8e1a7552021-12-01 17:57:04 +000014#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>
Achin Guptaeaf17162021-10-19 12:21:16 +010018#include <libfdt.h>
Marc Bonnici8e1a7552021-12-01 17:57:04 +000019#include <plat/common/common_def.h>
20#include <plat/common/platform.h>
21#include <services/ffa_svc.h>
22#include "spm_common.h"
Nishant Sharma9dc905b2022-04-28 10:58:24 +010023#include "spm_shim_private.h"
Marc Bonnici8e1a7552021-12-01 17:57:04 +000024#include "spmc.h"
Achin Guptaeaf17162021-10-19 12:21:16 +010025#include <tools_share/firmware_image_package.h>
Marc Bonnici8e1a7552021-12-01 17:57:04 +000026
27#include <platform_def.h>
28
29/*
Achin Guptaeaf17162021-10-19 12:21:16 +010030 * Statically allocate a page of memory for passing boot information to an SP.
31 */
32static uint8_t ffa_boot_info_mem[PAGE_SIZE] __aligned(PAGE_SIZE);
33
34/*
Nishant Sharma9dc905b2022-04-28 10:58:24 +010035 * 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
Nishant Sharma6817bdb2022-04-28 11:52:07 +010040#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)
Nishant Sharma9dc905b2022-04-28 10:58:24 +010046
Nishant Sharma85579412022-08-14 01:31:06 +010047/* Type of the memory region in SP's manifest. */
48enum sp_memory_region_type {
49 SP_MEM_REGION_DEVICE,
50 SP_MEM_REGION_MEMORY,
51 SP_MEM_REGION_NOT_SPECIFIED
52};
53
Nishant Sharma9dc905b2022-04-28 10:58:24 +010054/*
Achin Guptaeaf17162021-10-19 12:21:16 +010055 * This function creates a initialization descriptor in the memory reserved
56 * for passing boot information to an SP. It then copies the partition manifest
57 * into this region and ensures that its reference in the initialization
58 * descriptor is updated.
59 */
60static void spmc_create_boot_info(entry_point_info_t *ep_info,
61 struct secure_partition_desc *sp)
62{
63 struct ffa_boot_info_header *boot_header;
64 struct ffa_boot_info_desc *boot_descriptor;
65 uintptr_t manifest_addr;
66
67 /*
68 * Calculate the maximum size of the manifest that can be accommodated
69 * in the boot information memory region.
70 */
71 const unsigned int
72 max_manifest_sz = sizeof(ffa_boot_info_mem) -
73 (sizeof(struct ffa_boot_info_header) +
74 sizeof(struct ffa_boot_info_desc));
75
76 /*
77 * The current implementation only supports the FF-A v1.1
78 * implementation of the boot protocol, therefore check
79 * that a v1.0 SP has not requested use of the protocol.
80 */
81 if (sp->ffa_version == MAKE_FFA_VERSION(1, 0)) {
82 ERROR("FF-A boot protocol not supported for v1.0 clients\n");
83 return;
84 }
85
86 /*
87 * Check if the manifest will fit into the boot info memory region else
88 * bail.
89 */
90 if (ep_info->args.arg1 > max_manifest_sz) {
91 WARN("Unable to copy manifest into boot information. ");
92 WARN("Max sz = %u bytes. Manifest sz = %lu bytes\n",
93 max_manifest_sz, ep_info->args.arg1);
94 return;
95 }
96
97 /* Zero the memory region before populating. */
98 memset(ffa_boot_info_mem, 0, PAGE_SIZE);
99
100 /*
101 * Populate the ffa_boot_info_header at the start of the boot info
102 * region.
103 */
104 boot_header = (struct ffa_boot_info_header *) ffa_boot_info_mem;
105
106 /* Position the ffa_boot_info_desc after the ffa_boot_info_header. */
107 boot_header->offset_boot_info_desc =
108 sizeof(struct ffa_boot_info_header);
109 boot_descriptor = (struct ffa_boot_info_desc *)
110 (ffa_boot_info_mem +
111 boot_header->offset_boot_info_desc);
112
113 /*
Elyes Haouas2be03c02023-02-13 09:14:48 +0100114 * We must use the FF-A version corresponding to the version implemented
Achin Guptaeaf17162021-10-19 12:21:16 +0100115 * by the SP. Currently this can only be v1.1.
116 */
117 boot_header->version = sp->ffa_version;
118
119 /* Populate the boot information header. */
120 boot_header->size_boot_info_desc = sizeof(struct ffa_boot_info_desc);
121
122 /* Set the signature "0xFFA". */
123 boot_header->signature = FFA_INIT_DESC_SIGNATURE;
124
125 /* Set the count. Currently 1 since only the manifest is specified. */
126 boot_header->count_boot_info_desc = 1;
127
128 /* Populate the boot information descriptor for the manifest. */
129 boot_descriptor->type =
130 FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
131 FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_FDT);
132
133 boot_descriptor->flags =
134 FFA_BOOT_INFO_FLAG_NAME(FFA_BOOT_INFO_FLAG_NAME_UUID) |
135 FFA_BOOT_INFO_FLAG_CONTENT(FFA_BOOT_INFO_FLAG_CONTENT_ADR);
136
137 /*
138 * Copy the manifest into boot info region after the boot information
139 * descriptor.
140 */
141 boot_descriptor->size_boot_info = (uint32_t) ep_info->args.arg1;
142
143 manifest_addr = (uintptr_t) (ffa_boot_info_mem +
144 boot_header->offset_boot_info_desc +
145 boot_header->size_boot_info_desc);
146
147 memcpy((void *) manifest_addr, (void *) ep_info->args.arg0,
148 boot_descriptor->size_boot_info);
149
150 boot_descriptor->content = manifest_addr;
151
152 /* Calculate the size of the total boot info blob. */
153 boot_header->size_boot_info_blob = boot_header->offset_boot_info_desc +
154 boot_descriptor->size_boot_info +
155 (boot_header->count_boot_info_desc *
156 boot_header->size_boot_info_desc);
157
158 INFO("SP boot info @ 0x%lx, size: %u bytes.\n",
159 (uintptr_t) ffa_boot_info_mem,
160 boot_header->size_boot_info_blob);
161 INFO("SP manifest @ 0x%lx, size: %u bytes.\n",
162 boot_descriptor->content,
163 boot_descriptor->size_boot_info);
164}
165
166/*
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100167 * S-EL1 partitions can be assigned with multiple execution contexts, each
168 * pinned to the physical CPU. Each execution context index corresponds to the
169 * respective liner core position.
170 * S-EL0 partitions execute in a single execution context (index 0).
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000171 */
172unsigned int get_ec_index(struct secure_partition_desc *sp)
173{
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100174 return (sp->runtime_el == S_EL0) ?
175 SEL0_SP_EC_INDEX : plat_my_core_pos();
176}
177
178#if SPMC_AT_EL3_SEL0_SP
179/* Setup spsr in entry point info for common context management code to use. */
180void spmc_el0_sp_spsr_setup(entry_point_info_t *ep_info)
181{
182 /* Setup Secure Partition SPSR for S-EL0 SP. */
183 ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
184}
185
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100186static void read_optional_string(void *manifest, int32_t offset,
187 char *property, char *out, size_t len)
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100188{
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100189 const fdt32_t *prop;
190 int lenp;
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100191
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100192 prop = fdt_getprop(manifest, offset, property, &lenp);
193 if (prop == NULL) {
194 out[0] = '\0';
195 } else {
196 memcpy(out, prop, MIN(lenp, (int)len));
197 }
198}
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100199
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100200/*******************************************************************************
201 * This function will parse the Secure Partition Manifest for fetching secure
Nishant Sharma85579412022-08-14 01:31:06 +0100202 * partition specific memory/device region details. It will find base address,
203 * size, memory attributes for each region and then add the respective region
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100204 * into secure parition's translation context.
205 ******************************************************************************/
Nishant Sharma85579412022-08-14 01:31:06 +0100206static void populate_sp_regions(struct secure_partition_desc *sp,
207 void *sp_manifest, int node,
208 enum sp_memory_region_type type)
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100209{
210 uintptr_t base_address;
211 uint32_t mem_attr, mem_region, size;
Nishant Sharma85579412022-08-14 01:31:06 +0100212 struct mmap_region sp_mem_regions = {0};
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100213 int32_t offset, ret;
Nishant Sharma85579412022-08-14 01:31:06 +0100214 char *compatibility[SP_MEM_REGION_NOT_SPECIFIED] = {
215 "arm,ffa-manifest-device-regions",
216 "arm,ffa-manifest-memory-regions"
217 };
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100218 char description[10];
219 char *property;
Nishant Sharma85579412022-08-14 01:31:06 +0100220 char *region[SP_MEM_REGION_NOT_SPECIFIED] = {
221 "device regions",
222 "memory regions"
223 };
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100224
Nishant Sharma85579412022-08-14 01:31:06 +0100225 if (type >= SP_MEM_REGION_NOT_SPECIFIED) {
226 WARN("Invalid region type\n");
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100227 return;
228 }
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100229
Nishant Sharma85579412022-08-14 01:31:06 +0100230 INFO("Mapping SP's %s\n", region[type]);
231
232 if (fdt_node_check_compatible(sp_manifest, node,
233 compatibility[type]) != 0) {
234 WARN("Incompatible region node in manifest\n");
235 return;
236 }
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100237
238 for (offset = fdt_first_subnode(sp_manifest, node), mem_region = 0;
239 offset >= 0;
240 offset = fdt_next_subnode(sp_manifest, offset), mem_region++) {
241 read_optional_string(sp_manifest, offset, "description",
242 description, sizeof(description));
243
244 INFO("Mapping: region: %d, %s\n", mem_region, description);
245
246 property = "base-address";
247 ret = fdt_read_uint64(sp_manifest, offset, property,
248 &base_address);
249 if (ret < 0) {
250 WARN("Missing:%s for %s.\n", property, description);
251 continue;
252 }
253
254 property = "pages-count";
255 ret = fdt_read_uint32(sp_manifest, offset, property, &size);
256 if (ret < 0) {
257 WARN("Missing: %s for %s.\n", property, description);
258 continue;
259 }
260 size *= PAGE_SIZE;
261
262 property = "attributes";
263 ret = fdt_read_uint32(sp_manifest, offset, property, &mem_attr);
264 if (ret < 0) {
265 WARN("Missing: %s for %s.\n", property, description);
266 continue;
267 }
268
269 sp_mem_regions.attr = MT_USER;
Nishant Sharma85579412022-08-14 01:31:06 +0100270 if (type == SP_MEM_REGION_DEVICE) {
271 sp_mem_regions.attr |= MT_EXECUTE_NEVER;
272 } else {
273 sp_mem_regions.attr |= MT_MEMORY;
274 if ((mem_attr & SP_MEM_EXECUTE) == SP_MEM_EXECUTE) {
275 sp_mem_regions.attr &= ~MT_EXECUTE_NEVER;
276 } else {
277 sp_mem_regions.attr |= MT_EXECUTE_NEVER;
278 }
279 }
280
281 if ((mem_attr & SP_MEM_READ_WRITE) == SP_MEM_READ_WRITE) {
282 sp_mem_regions.attr |= MT_RW;
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100283 }
284
285 if ((mem_attr & SP_MEM_NON_SECURE) == SP_MEM_NON_SECURE) {
286 sp_mem_regions.attr |= MT_NS;
287 } else {
288 sp_mem_regions.attr |= MT_SECURE;
289 }
290
291 sp_mem_regions.base_pa = base_address;
292 sp_mem_regions.base_va = base_address;
293 sp_mem_regions.size = size;
Nishant Sharma85579412022-08-14 01:31:06 +0100294
295 INFO("Adding PA: 0x%llx VA: 0x%lx Size: 0x%lx attr:0x%x\n",
296 sp_mem_regions.base_pa,
297 sp_mem_regions.base_va,
298 sp_mem_regions.size,
299 sp_mem_regions.attr);
300
301 if (type == SP_MEM_REGION_DEVICE) {
302 sp_mem_regions.granularity = XLAT_BLOCK_SIZE(1);
303 } else {
304 sp_mem_regions.granularity = XLAT_BLOCK_SIZE(3);
305 }
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100306 mmap_add_region_ctx(sp->xlat_ctx_handle, &sp_mem_regions);
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100307 }
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100308}
309
310static void spmc_el0_sp_setup_mmu(struct secure_partition_desc *sp,
311 cpu_context_t *ctx)
312{
313 xlat_ctx_t *xlat_ctx;
314 uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
315
316 xlat_ctx = sp->xlat_ctx_handle;
317 init_xlat_tables_ctx(sp->xlat_ctx_handle);
318 setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table,
319 xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
320 EL1_EL0_REGIME);
321
322 write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
323 mmu_cfg_params[MMU_CFG_MAIR]);
324
325 write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
326 mmu_cfg_params[MMU_CFG_TCR]);
327
328 write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
329 mmu_cfg_params[MMU_CFG_TTBR0]);
330}
331
332static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
333{
334 u_register_t sctlr_el1;
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100335
336 /* Setup SCTLR_EL1 */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100337 sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100338
339 sctlr_el1 |=
340 /*SCTLR_EL1_RES1 |*/
341 /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100342 SCTLR_UCI_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100343 /* RW regions at xlat regime EL1&0 are forced to be XN. */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100344 SCTLR_WXN_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100345 /* Don't trap to EL1 execution of WFI or WFE at EL0. */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100346 SCTLR_NTWI_BIT | SCTLR_NTWE_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100347 /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100348 SCTLR_UCT_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100349 /* Don't trap to EL1 execution of DZ ZVA at EL0. */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100350 SCTLR_DZE_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100351 /* Enable SP Alignment check for EL0 */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100352 SCTLR_SA0_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100353 /* Don't change PSTATE.PAN on taking an exception to EL1 */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100354 SCTLR_SPAN_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100355 /* Allow cacheable data and instr. accesses to normal memory. */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100356 SCTLR_C_BIT | SCTLR_I_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100357 /* Enable MMU. */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100358 SCTLR_M_BIT;
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100359
360 sctlr_el1 &= ~(
361 /* Explicit data accesses at EL0 are little-endian. */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100362 SCTLR_E0E_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100363 /*
364 * Alignment fault checking disabled when at EL1 and EL0 as
365 * the UEFI spec permits unaligned accesses.
366 */
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100367 SCTLR_A_BIT |
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100368 /* Accesses to DAIF from EL0 are trapped to EL1. */
369 SCTLR_UMA_BIT
370 );
371
372 write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100373}
374
375static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
376 cpu_context_t *ctx)
377{
378
379 spmc_el0_sp_setup_mmu(sp, ctx);
380
381 spmc_el0_sp_setup_sctlr_el1(ctx);
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100382
383 /* Setup other system registers. */
384
385 /* Shim Exception Vector Base Address */
386 write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
387 SPM_SHIM_EXCEPTIONS_PTR);
388#if NS_TIMER_SWITCH
389 write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
390 EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
391#endif
392
393 /*
394 * FPEN: Allow the Secure Partition to access FP/SIMD registers.
395 * Note that SPM will not do any saving/restoring of these registers on
396 * behalf of the SP. This falls under the SP's responsibility.
397 * TTA: Enable access to trace registers.
398 * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
399 */
400 write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
401 CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000402}
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100403
404/* Setup context of an EL0 Secure Partition. */
405void spmc_el0_sp_setup(struct secure_partition_desc *sp,
406 int32_t boot_info_reg,
407 void *sp_manifest)
408{
409 mmap_region_t sel1_exception_vectors =
410 MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
411 SPM_SHIM_EXCEPTIONS_SIZE,
412 MT_CODE | MT_SECURE | MT_PRIVILEGED);
413 cpu_context_t *ctx;
414 int node;
415 int offset = 0;
416
417 ctx = &sp->ec[SEL0_SP_EC_INDEX].cpu_ctx;
418
419 sp->xlat_ctx_handle->xlat_regime = EL1_EL0_REGIME;
420
421 /* This region contains the exception vectors used at S-EL1. */
422 mmap_add_region_ctx(sp->xlat_ctx_handle,
423 &sel1_exception_vectors);
424
425 /*
426 * If the SP manifest specified the register to pass the address of the
427 * boot information, then map the memory region to pass boot
428 * information.
429 */
430 if (boot_info_reg >= 0) {
431 mmap_region_t ffa_boot_info_region = MAP_REGION_FLAT(
432 (uintptr_t) ffa_boot_info_mem,
433 PAGE_SIZE,
434 MT_RO_DATA | MT_SECURE | MT_USER);
435 mmap_add_region_ctx(sp->xlat_ctx_handle, &ffa_boot_info_region);
436 }
437
438 /*
Nishant Sharma85579412022-08-14 01:31:06 +0100439 * Parse the manifest for any device regions that the SP wants to be
440 * mapped in its translation regime.
441 */
442 node = fdt_subnode_offset_namelen(sp_manifest, offset,
443 "device-regions",
444 sizeof("device-regions") - 1);
445 if (node < 0) {
446 WARN("Not found device-region configuration for SP.\n");
447 } else {
448 populate_sp_regions(sp, sp_manifest, node,
449 SP_MEM_REGION_DEVICE);
450 }
451
452 /*
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100453 * Parse the manifest for any memory regions that the SP wants to be
454 * mapped in its translation regime.
455 */
456 node = fdt_subnode_offset_namelen(sp_manifest, offset,
457 "memory-regions",
458 sizeof("memory-regions") - 1);
459 if (node < 0) {
460 WARN("Not found memory-region configuration for SP.\n");
461 } else {
Nishant Sharma85579412022-08-14 01:31:06 +0100462 populate_sp_regions(sp, sp_manifest, node,
463 SP_MEM_REGION_MEMORY);
Nishant Sharma6817bdb2022-04-28 11:52:07 +0100464 }
465
466 spmc_el0_sp_setup_system_registers(sp, ctx);
467
468}
Nishant Sharma9dc905b2022-04-28 10:58:24 +0100469#endif /* SPMC_AT_EL3_SEL0_SP */
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000470
471/* S-EL1 partition specific initialisation. */
472void spmc_el1_sp_setup(struct secure_partition_desc *sp,
473 entry_point_info_t *ep_info)
474{
475 /* Sanity check input arguments. */
476 assert(sp != NULL);
477 assert(ep_info != NULL);
478
479 /* Initialise the SPSR for S-EL1 SPs. */
480 ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
481 DISABLE_ALL_EXCEPTIONS);
482
483 /*
Marc Bonnici6fbed8c2021-12-15 18:00:50 +0000484 * TF-A Implementation defined behaviour to provide the linear
485 * core ID in the x4 register.
486 */
487 ep_info->args.arg4 = (uintptr_t) plat_my_core_pos();
488
489 /*
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000490 * Check whether setup is being performed for the primary or a secondary
491 * execution context. In the latter case, indicate to the SP that this
492 * is a warm boot.
493 * TODO: This check would need to be reworked if the same entry point is
494 * used for both primary and secondary initialisation.
495 */
496 if (sp->secondary_ep != 0U) {
497 /*
498 * Sanity check that the secondary entry point is still what was
499 * originally set.
500 */
501 assert(sp->secondary_ep == ep_info->pc);
502 ep_info->args.arg0 = FFA_WB_TYPE_S2RAM;
503 }
504}
505
506/* Common initialisation for all SPs. */
507void spmc_sp_common_setup(struct secure_partition_desc *sp,
Achin Guptaeaf17162021-10-19 12:21:16 +0100508 entry_point_info_t *ep_info,
509 int32_t boot_info_reg)
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000510{
511 uint16_t sp_id;
512
513 /* Assign FF-A Partition ID if not already assigned. */
514 if (sp->sp_id == INV_SP_ID) {
515 sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX;
516 /*
517 * Ensure we don't clash with previously assigned partition
518 * IDs.
519 */
520 while (!is_ffa_secure_id_valid(sp_id)) {
521 sp_id++;
522
523 if (sp_id == FFA_SWD_ID_LIMIT) {
524 ERROR("Unable to determine valid SP ID.\n");
525 panic();
526 }
527 }
528 sp->sp_id = sp_id;
529 }
530
Achin Guptaeaf17162021-10-19 12:21:16 +0100531 /* Check if the SP wants to use the FF-A boot protocol. */
532 if (boot_info_reg >= 0) {
533 /*
534 * Create a boot information descriptor and copy the partition
535 * manifest into the reserved memory region for consumption by
536 * the SP.
537 */
538 spmc_create_boot_info(ep_info, sp);
539
540 /*
541 * We have consumed what we need from ep args so we can now
542 * zero them before we start populating with new information
543 * specifically for the SP.
544 */
545 zeromem(&ep_info->args, sizeof(ep_info->args));
546
547 /*
548 * Pass the address of the boot information in the
549 * boot_info_reg.
550 */
551 switch (boot_info_reg) {
552 case 0:
553 ep_info->args.arg0 = (uintptr_t) ffa_boot_info_mem;
554 break;
555 case 1:
556 ep_info->args.arg1 = (uintptr_t) ffa_boot_info_mem;
557 break;
558 case 2:
559 ep_info->args.arg2 = (uintptr_t) ffa_boot_info_mem;
560 break;
561 case 3:
562 ep_info->args.arg3 = (uintptr_t) ffa_boot_info_mem;
563 break;
564 default:
565 ERROR("Invalid value for \"gp-register-num\" %d.\n",
566 boot_info_reg);
567 }
568 } else {
569 /*
570 * We don't need any of the information that was populated
571 * in ep_args so we can clear them.
572 */
573 zeromem(&ep_info->args, sizeof(ep_info->args));
574 }
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000575}
576
577/*
578 * Initialise the SP context now we have populated the common and EL specific
579 * entrypoint information.
580 */
581void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
582 entry_point_info_t *ep_info)
583{
584 cpu_context_t *cpu_ctx;
585
586 cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx);
587 print_entry_point_info(ep_info);
588 cm_setup_context(cpu_ctx, ep_info);
589}