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