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