1 /* 2 * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <string.h> 10 11 #include <arch.h> 12 #include <arch_helpers.h> 13 #include <common/debug.h> 14 #include <common/fdt_wrappers.h> 15 16 #include <context.h> 17 #include <lib/el3_runtime/context_mgmt.h> 18 #if HOB_LIST 19 #include <lib/hob/hob.h> 20 #include <lib/hob/hob_guid.h> 21 #include <lib/hob/mmram.h> 22 #include <lib/hob/mpinfo.h> 23 #endif 24 #include <lib/utils.h> 25 #include <lib/xlat_tables/xlat_tables_v2.h> 26 #include <libfdt.h> 27 #include <plat/common/common_def.h> 28 #include <plat/common/platform.h> 29 #include <services/ffa_svc.h> 30 #include "spm_common.h" 31 #include "spm_shim_private.h" 32 #include "spmc.h" 33 #if TRANSFER_LIST 34 #include <transfer_list.h> 35 #endif 36 #include <tools_share/firmware_image_package.h> 37 38 #include <platform_def.h> 39 40 /* 41 * Statically allocate a page of memory for passing boot information to an SP. 42 */ 43 static uint8_t ffa_boot_info_mem[PAGE_SIZE] __aligned(PAGE_SIZE); 44 45 /* 46 * We need to choose one execution context from all those available for a S-EL0 47 * SP. This execution context will be used subsequently irrespective of which 48 * physical CPU the SP runs on. 49 */ 50 #define SEL0_SP_EC_INDEX 0 51 #define SP_MEM_READ 0x1 52 #define SP_MEM_WRITE 0x2 53 #define SP_MEM_EXECUTE 0x4 54 #define SP_MEM_NON_SECURE 0x8 55 #define SP_MEM_READ_ONLY SP_MEM_READ 56 #define SP_MEM_READ_WRITE (SP_MEM_READ | SP_MEM_WRITE) 57 58 /* Type of the memory region in SP's manifest. */ 59 enum sp_memory_region_type { 60 SP_MEM_REGION_DEVICE, 61 SP_MEM_REGION_MEMORY, 62 SP_MEM_REGION_NOT_SPECIFIED 63 }; 64 65 66 #if HOB_LIST 67 static int get_memory_region_info(void *sp_manifest, int mem_region_node, 68 const char *name, uint32_t granularity, 69 uint64_t *base_address, uint32_t *size) 70 { 71 char *property; 72 int node, ret; 73 74 if (name != NULL) { 75 node = fdt_subnode_offset_namelen(sp_manifest, mem_region_node, 76 name, strlen(name)); 77 if (node < 0) { 78 ERROR("Not found '%s' region in memory regions configuration for SP.\n", 79 name); 80 return -ENOENT; 81 } 82 } else { 83 node = mem_region_node; 84 } 85 86 property = "base-address"; 87 ret = fdt_read_uint64(sp_manifest, node, property, base_address); 88 if (ret < 0) { 89 ERROR("Not found property(%s) in memory region(%s).\n", 90 property, name); 91 return -ENOENT; 92 } 93 94 property = "pages-count"; 95 ret = fdt_read_uint32(sp_manifest, node, property, size); 96 if (ret < 0) { 97 ERROR("Not found property(%s) in memory region(%s).\n", 98 property, name); 99 return -ENOENT; 100 } 101 102 *size = ((*size) << (PAGE_SIZE_SHIFT + (granularity << 1))); 103 104 return 0; 105 } 106 107 static struct efi_hob_handoff_info_table *build_sp_boot_hob_list( 108 void *sp_manifest, uintptr_t hob_table_start, size_t *hob_table_size) 109 { 110 struct efi_hob_handoff_info_table *hob_table; 111 uintptr_t base_address; 112 int mem_region_node; 113 int32_t node, ret; 114 const char *name; 115 uint32_t granularity, size; 116 uint32_t mem_region_num; 117 struct efi_guid ns_buf_guid = MM_NS_BUFFER_GUID; 118 struct efi_guid mmram_resv_guid = MM_PEI_MMRAM_MEMORY_RESERVE_GUID; 119 struct efi_mmram_descriptor *mmram_desc_data; 120 struct efi_mmram_hob_descriptor_block *mmram_hob_desc_data; 121 122 if (sp_manifest == NULL || hob_table_size == NULL || *hob_table_size == 0) { 123 return NULL; 124 } 125 126 node = fdt_path_offset(sp_manifest, "/"); 127 if (node < 0) { 128 ERROR("Failed to get root in sp_manifest.\n"); 129 return NULL; 130 } 131 132 ret = fdt_read_uint32(sp_manifest, node, "xlat-granule", &granularity); 133 if (ret < 0) { 134 ERROR("Not found property(xlat-granule) in sp_manifest.\n"); 135 return NULL; 136 } 137 138 if (granularity > 0x02) { 139 ERROR("Invalid granularity value: 0x%x\n", granularity); 140 return NULL; 141 } 142 143 mem_region_node = fdt_subnode_offset_namelen(sp_manifest, 0, "memory-regions", 144 sizeof("memory-regions") - 1); 145 if (node < 0) { 146 ERROR("Not found memory-region configuration for SP.\n"); 147 return NULL; 148 } 149 150 INFO("Generating PHIT_HOB...\n"); 151 152 hob_table = create_hob_list(BL32_BASE, BL32_LIMIT, 153 hob_table_start, *hob_table_size); 154 if (hob_table == NULL) { 155 ERROR("Failed to create Hob Table.\n"); 156 return NULL; 157 } 158 159 /* 160 * Create fv hob. 161 */ 162 ret = get_memory_region_info(sp_manifest, mem_region_node, 163 "stmm_region", granularity, &base_address, &size); 164 if (ret < 0) { 165 return NULL; 166 } 167 168 if (base_address != BL32_BASE && 169 base_address + size > BL32_LIMIT) { 170 ERROR("Image is ouf of bound(0x%lx/0x%x), should be in (0x%llx/0x%llx)\n", 171 base_address, size, BL32_BASE, BL32_LIMIT - BL32_BASE); 172 return NULL; 173 } 174 175 ret = create_fv_hob(hob_table, base_address, size); 176 if (ret < 0) { 177 ERROR("Failed to create fv hob... ret:%d\n", ret); 178 return NULL; 179 } 180 181 INFO("Success to create FV hob(0x%lx/0x%x).\n", base_address, size); 182 183 /* 184 * Create Ns Buffer hob. 185 */ 186 ret = get_memory_region_info(sp_manifest, mem_region_node, 187 "ns_comm_buffer", granularity, &base_address, &size); 188 if (ret < 0) { 189 return NULL; 190 } 191 192 ret = create_guid_hob(hob_table, &ns_buf_guid, 193 sizeof(struct efi_mmram_descriptor), (void **) &mmram_desc_data); 194 if (ret < 0) { 195 ERROR("Failed to create ns buffer hob\n"); 196 return NULL; 197 } 198 199 mmram_desc_data->physical_start = base_address; 200 mmram_desc_data->physical_size = size; 201 mmram_desc_data->cpu_start = base_address; 202 mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED; 203 204 /* 205 * Create mmram_resv hob. 206 */ 207 for (node = fdt_first_subnode(sp_manifest, mem_region_node), mem_region_num = 0; 208 node >= 0; 209 node = fdt_next_subnode(sp_manifest, node), mem_region_num++) { 210 ret = get_memory_region_info(sp_manifest, node, NULL, granularity, 211 &base_address, &size); 212 if (ret < 0) { 213 name = fdt_get_name(sp_manifest, node, NULL); 214 ERROR("Invalid memory region(%s) found!\n", name); 215 return NULL; 216 } 217 } 218 219 ret = create_guid_hob(hob_table, &mmram_resv_guid, 220 (sizeof(struct efi_mmram_hob_descriptor_block) + 221 (sizeof(struct efi_mmram_descriptor) * mem_region_num)), 222 (void **) &mmram_hob_desc_data); 223 if (ret < 0) { 224 ERROR("Failed to create mmram_resv hob. ret: %d\n", ret); 225 return NULL; 226 } 227 228 mmram_hob_desc_data->number_of_mm_reserved_regions = mem_region_num; 229 230 for (node = fdt_first_subnode(sp_manifest, mem_region_node), mem_region_num = 0; 231 node >= 0; 232 node = fdt_next_subnode(sp_manifest, node), mem_region_num++) { 233 get_memory_region_info(sp_manifest, node, NULL, granularity, 234 &base_address, &size); 235 name = fdt_get_name(sp_manifest, node, NULL); 236 237 mmram_desc_data = &mmram_hob_desc_data->descriptor[mem_region_num]; 238 mmram_desc_data->physical_start = base_address; 239 mmram_desc_data->physical_size = size; 240 mmram_desc_data->cpu_start = base_address; 241 242 if (!strcmp(name, "heap")) { 243 mmram_desc_data->region_state = EFI_CACHEABLE; 244 } else { 245 mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED; 246 } 247 } 248 249 *hob_table_size = hob_table->efi_free_memory_bottom - 250 (efi_physical_address_t) hob_table; 251 252 return hob_table; 253 } 254 #endif 255 256 257 258 /* 259 * This function creates a initialization descriptor in the memory reserved 260 * for passing boot information to an SP. It then copies the partition manifest 261 * into this region and ensures that its reference in the initialization 262 * descriptor is updated. 263 */ 264 static void spmc_create_boot_info(entry_point_info_t *ep_info, 265 struct secure_partition_desc *sp) 266 { 267 struct ffa_boot_info_header *boot_header; 268 struct ffa_boot_info_desc *boot_descriptor; 269 uintptr_t content_addr; 270 void *sp_manifest; 271 void *tl __maybe_unused; 272 #if TRANSFER_LIST && !RESET_TO_BL31 273 struct transfer_list_entry *te; 274 275 tl = (void *)((uintptr_t)ep_info->args.arg3); 276 te = transfer_list_find((struct transfer_list_header *)tl, 277 TL_TAG_DT_FFA_MANIFEST); 278 assert(te != NULL); 279 280 sp_manifest = (void *)transfer_list_entry_data(te); 281 #else 282 sp_manifest = (void *)ep_info->args.arg0; 283 #endif 284 285 /* 286 * Calculate the maximum size of the manifest that can be accommodated 287 * in the boot information memory region. 288 */ 289 size_t max_sz = sizeof(ffa_boot_info_mem) - 290 (sizeof(struct ffa_boot_info_header) + 291 sizeof(struct ffa_boot_info_desc)); 292 293 /* 294 * The current implementation only supports the FF-A v1.1 295 * implementation of the boot protocol, therefore check 296 * that a v1.0 SP has not requested use of the protocol. 297 */ 298 if (sp->ffa_version == MAKE_FFA_VERSION(1, 0)) { 299 ERROR("FF-A boot protocol not supported for v1.0 clients\n"); 300 return; 301 } 302 303 /* Zero the memory region before populating. */ 304 memset(ffa_boot_info_mem, 0, PAGE_SIZE); 305 306 /* 307 * Populate the ffa_boot_info_header at the start of the boot info 308 * region. 309 */ 310 boot_header = (struct ffa_boot_info_header *) ffa_boot_info_mem; 311 312 /* Position the ffa_boot_info_desc after the ffa_boot_info_header. */ 313 boot_header->offset_boot_info_desc = 314 sizeof(struct ffa_boot_info_header); 315 boot_descriptor = (struct ffa_boot_info_desc *) 316 (ffa_boot_info_mem + 317 boot_header->offset_boot_info_desc); 318 319 /* 320 * We must use the FF-A version corresponding to the version implemented 321 * by the SP. Currently this can only be v1.1. 322 */ 323 boot_header->version = sp->ffa_version; 324 325 /* Populate the boot information header. */ 326 boot_header->size_boot_info_desc = sizeof(struct ffa_boot_info_desc); 327 328 /* Set the signature "0xFFA". */ 329 boot_header->signature = FFA_INIT_DESC_SIGNATURE; 330 331 /* Set the count. Currently 1 since only the manifest is specified. */ 332 boot_header->count_boot_info_desc = 1; 333 334 boot_descriptor->flags = 335 FFA_BOOT_INFO_FLAG_NAME(FFA_BOOT_INFO_FLAG_NAME_UUID) | 336 FFA_BOOT_INFO_FLAG_CONTENT(FFA_BOOT_INFO_FLAG_CONTENT_ADR); 337 338 content_addr = (uintptr_t) (ffa_boot_info_mem + 339 boot_header->offset_boot_info_desc + 340 boot_header->size_boot_info_desc); 341 342 #if HOB_LIST 343 /* Populate the boot information descriptor for the hob_list. */ 344 boot_descriptor->type = 345 FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) | 346 FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_HOB); 347 348 content_addr = (uintptr_t) build_sp_boot_hob_list( 349 sp_manifest, content_addr, &max_sz); 350 if (content_addr == (uintptr_t) NULL) { 351 WARN("Unable to create phit hob properly."); 352 return; 353 } 354 355 boot_descriptor->size_boot_info = max_sz; 356 boot_descriptor->content = content_addr; 357 #else 358 /* 359 * Check if the manifest will fit into the boot info memory region else 360 * bail. 361 */ 362 if (ep_info->args.arg1 > max_sz) { 363 WARN("Unable to copy manifest into boot information. "); 364 WARN("Max sz = %lu bytes. Manifest sz = %lu bytes\n", 365 max_sz, ep_info->args.arg1); 366 return; 367 } 368 369 /* Populate the boot information descriptor for the manifest. */ 370 boot_descriptor->type = 371 FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) | 372 FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_FDT); 373 374 /* 375 * Copy the manifest into boot info region after the boot information 376 * descriptor. 377 */ 378 boot_descriptor->size_boot_info = (uint32_t) ep_info->args.arg1; 379 380 memcpy((void *) content_addr, sp_manifest, boot_descriptor->size_boot_info); 381 382 boot_descriptor->content = content_addr; 383 #endif 384 385 /* Calculate the size of the total boot info blob. */ 386 boot_header->size_boot_info_blob = boot_header->offset_boot_info_desc + 387 boot_descriptor->size_boot_info + 388 (boot_header->count_boot_info_desc * 389 boot_header->size_boot_info_desc); 390 391 INFO("SP boot info @ 0x%lx, size: %u bytes.\n", 392 (uintptr_t) ffa_boot_info_mem, 393 boot_header->size_boot_info_blob); 394 INFO("SP content @ 0x%lx, size: %u bytes.\n", 395 boot_descriptor->content, 396 boot_descriptor->size_boot_info); 397 } 398 399 /* 400 * S-EL1 partitions can be assigned with multiple execution contexts, each 401 * pinned to the physical CPU. Each execution context index corresponds to the 402 * respective liner core position. 403 * S-EL0 partitions execute in a single execution context (index 0). 404 */ 405 unsigned int get_ec_index(struct secure_partition_desc *sp) 406 { 407 return (sp->runtime_el == S_EL0) ? 408 SEL0_SP_EC_INDEX : plat_my_core_pos(); 409 } 410 411 #if SPMC_AT_EL3_SEL0_SP 412 /* Setup spsr in entry point info for common context management code to use. */ 413 void spmc_el0_sp_spsr_setup(entry_point_info_t *ep_info) 414 { 415 /* Setup Secure Partition SPSR for S-EL0 SP. */ 416 ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS); 417 } 418 419 static void read_optional_string(void *manifest, int32_t offset, 420 char *property, char *out, size_t len) 421 { 422 const fdt32_t *prop; 423 int lenp; 424 425 prop = fdt_getprop(manifest, offset, property, &lenp); 426 if (prop == NULL) { 427 out[0] = '\0'; 428 } else { 429 memcpy(out, prop, MIN(lenp, (int)len)); 430 out[MIN(lenp, (int)len) - 1] = '\0'; 431 } 432 } 433 434 /******************************************************************************* 435 * This function will parse the Secure Partition Manifest for fetching secure 436 * partition specific memory/device region details. It will find base address, 437 * size, memory attributes for each region and then add the respective region 438 * into secure parition's translation context. 439 ******************************************************************************/ 440 static void populate_sp_regions(struct secure_partition_desc *sp, 441 void *sp_manifest, int node, 442 enum sp_memory_region_type type) 443 { 444 uintptr_t base_address; 445 uint32_t mem_attr, mem_region, size; 446 struct mmap_region sp_mem_regions = {0}; 447 int32_t offset, ret; 448 char *compatibility[SP_MEM_REGION_NOT_SPECIFIED] = { 449 "arm,ffa-manifest-device-regions", 450 "arm,ffa-manifest-memory-regions" 451 }; 452 char description[10]; 453 char *property; 454 char *region[SP_MEM_REGION_NOT_SPECIFIED] = { 455 "device regions", 456 "memory regions" 457 }; 458 459 if (type >= SP_MEM_REGION_NOT_SPECIFIED) { 460 WARN("Invalid region type\n"); 461 return; 462 } 463 464 INFO("Mapping SP's %s\n", region[type]); 465 466 if (fdt_node_check_compatible(sp_manifest, node, 467 compatibility[type]) != 0) { 468 WARN("Incompatible region node in manifest\n"); 469 return; 470 } 471 472 for (offset = fdt_first_subnode(sp_manifest, node), mem_region = 0; 473 offset >= 0; 474 offset = fdt_next_subnode(sp_manifest, offset), mem_region++) { 475 read_optional_string(sp_manifest, offset, "description", 476 description, sizeof(description)); 477 478 INFO("Mapping: region: %d, %s\n", mem_region, description); 479 480 property = "base-address"; 481 ret = fdt_read_uint64(sp_manifest, offset, property, 482 &base_address); 483 if (ret < 0) { 484 WARN("Missing:%s for %s.\n", property, description); 485 continue; 486 } 487 488 property = "pages-count"; 489 ret = fdt_read_uint32(sp_manifest, offset, property, &size); 490 if (ret < 0) { 491 WARN("Missing: %s for %s.\n", property, description); 492 continue; 493 } 494 size *= PAGE_SIZE; 495 496 property = "attributes"; 497 ret = fdt_read_uint32(sp_manifest, offset, property, &mem_attr); 498 if (ret < 0) { 499 WARN("Missing: %s for %s.\n", property, description); 500 continue; 501 } 502 503 sp_mem_regions.attr = MT_USER; 504 if (type == SP_MEM_REGION_DEVICE) { 505 sp_mem_regions.attr |= MT_EXECUTE_NEVER; 506 } else { 507 sp_mem_regions.attr |= MT_MEMORY; 508 if ((mem_attr & SP_MEM_EXECUTE) == SP_MEM_EXECUTE) { 509 sp_mem_regions.attr &= ~MT_EXECUTE_NEVER; 510 } else { 511 sp_mem_regions.attr |= MT_EXECUTE_NEVER; 512 } 513 } 514 515 if ((mem_attr & SP_MEM_READ_WRITE) == SP_MEM_READ_WRITE) { 516 sp_mem_regions.attr |= MT_RW; 517 } 518 519 if ((mem_attr & SP_MEM_NON_SECURE) == SP_MEM_NON_SECURE) { 520 sp_mem_regions.attr |= MT_NS; 521 } else { 522 sp_mem_regions.attr |= MT_SECURE; 523 } 524 525 sp_mem_regions.base_pa = base_address; 526 sp_mem_regions.base_va = base_address; 527 sp_mem_regions.size = size; 528 529 INFO("Adding PA: 0x%llx VA: 0x%lx Size: 0x%lx mem_attr: 0x%x, attr:0x%x\n", 530 sp_mem_regions.base_pa, 531 sp_mem_regions.base_va, 532 sp_mem_regions.size, 533 mem_attr, 534 sp_mem_regions.attr); 535 536 if (type == SP_MEM_REGION_DEVICE) { 537 sp_mem_regions.granularity = XLAT_BLOCK_SIZE(1); 538 } else { 539 sp_mem_regions.granularity = XLAT_BLOCK_SIZE(3); 540 } 541 mmap_add_region_ctx(sp->xlat_ctx_handle, &sp_mem_regions); 542 } 543 } 544 545 static void spmc_el0_sp_setup_mmu(struct secure_partition_desc *sp, 546 cpu_context_t *ctx) 547 { 548 xlat_ctx_t *xlat_ctx; 549 uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; 550 551 xlat_ctx = sp->xlat_ctx_handle; 552 init_xlat_tables_ctx(sp->xlat_ctx_handle); 553 setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table, 554 xlat_ctx->pa_max_address, xlat_ctx->va_max_address, 555 EL1_EL0_REGIME); 556 557 write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1, 558 mmu_cfg_params[MMU_CFG_MAIR]); 559 560 write_ctx_tcr_el1_reg_errata(ctx, mmu_cfg_params[MMU_CFG_TCR]); 561 562 write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1, 563 mmu_cfg_params[MMU_CFG_TTBR0]); 564 } 565 566 static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx) 567 { 568 u_register_t sctlr_el1_val; 569 570 /* Setup SCTLR_EL1 */ 571 sctlr_el1_val = read_ctx_sctlr_el1_reg_errata(ctx); 572 573 sctlr_el1_val |= 574 /*SCTLR_EL1_RES1 |*/ 575 /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */ 576 SCTLR_UCI_BIT | 577 /* RW regions at xlat regime EL1&0 are forced to be XN. */ 578 SCTLR_WXN_BIT | 579 /* Don't trap to EL1 execution of WFI or WFE at EL0. */ 580 SCTLR_NTWI_BIT | SCTLR_NTWE_BIT | 581 /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */ 582 SCTLR_UCT_BIT | 583 /* Don't trap to EL1 execution of DZ ZVA at EL0. */ 584 SCTLR_DZE_BIT | 585 /* Enable SP Alignment check for EL0 */ 586 SCTLR_SA0_BIT | 587 /* Don't change PSTATE.PAN on taking an exception to EL1 */ 588 SCTLR_SPAN_BIT | 589 /* Allow cacheable data and instr. accesses to normal memory. */ 590 SCTLR_C_BIT | SCTLR_I_BIT | 591 /* Enable MMU. */ 592 SCTLR_M_BIT; 593 594 sctlr_el1_val &= ~( 595 /* Explicit data accesses at EL0 are little-endian. */ 596 SCTLR_E0E_BIT | 597 /* 598 * Alignment fault checking disabled when at EL1 and EL0 as 599 * the UEFI spec permits unaligned accesses. 600 */ 601 SCTLR_A_BIT | 602 /* Accesses to DAIF from EL0 are trapped to EL1. */ 603 SCTLR_UMA_BIT 604 ); 605 606 /* Store the initialised SCTLR_EL1 value in the cpu_context */ 607 write_ctx_sctlr_el1_reg_errata(ctx, sctlr_el1_val); 608 } 609 610 static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp, 611 cpu_context_t *ctx) 612 { 613 614 spmc_el0_sp_setup_mmu(sp, ctx); 615 616 spmc_el0_sp_setup_sctlr_el1(ctx); 617 618 /* Setup other system registers. */ 619 620 /* Shim Exception Vector Base Address */ 621 write_el1_ctx_common(get_el1_sysregs_ctx(ctx), vbar_el1, 622 SPM_SHIM_EXCEPTIONS_PTR); 623 #if NS_TIMER_SWITCH 624 write_el1_ctx_arch_timer(get_el1_sysregs_ctx(ctx), cntkctl_el1, 625 EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT); 626 #endif 627 628 /* 629 * FPEN: Allow the Secure Partition to access FP/SIMD registers. 630 * Note that SPM will not do any saving/restoring of these registers on 631 * behalf of the SP. This falls under the SP's responsibility. 632 * TTA: Enable access to trace registers. 633 * ZEN (v8.2): Trap SVE instructions and access to SVE registers. 634 */ 635 write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cpacr_el1, 636 CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); 637 } 638 639 /* Setup context of an EL0 Secure Partition. */ 640 void spmc_el0_sp_setup(struct secure_partition_desc *sp, 641 int32_t boot_info_reg, 642 void *sp_manifest) 643 { 644 mmap_region_t sel1_exception_vectors = 645 MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START, 646 SPM_SHIM_EXCEPTIONS_SIZE, 647 MT_CODE | MT_SECURE | MT_PRIVILEGED); 648 cpu_context_t *ctx; 649 int node; 650 int offset = 0; 651 652 ctx = &sp->ec[SEL0_SP_EC_INDEX].cpu_ctx; 653 654 sp->xlat_ctx_handle->xlat_regime = EL1_EL0_REGIME; 655 656 /* This region contains the exception vectors used at S-EL1. */ 657 mmap_add_region_ctx(sp->xlat_ctx_handle, 658 &sel1_exception_vectors); 659 660 /* 661 * If the SP manifest specified the register to pass the address of the 662 * boot information, then map the memory region to pass boot 663 * information. 664 */ 665 if (boot_info_reg >= 0) { 666 mmap_region_t ffa_boot_info_region = MAP_REGION_FLAT( 667 (uintptr_t) ffa_boot_info_mem, 668 PAGE_SIZE, 669 MT_RO_DATA | MT_SECURE | MT_USER); 670 mmap_add_region_ctx(sp->xlat_ctx_handle, &ffa_boot_info_region); 671 } 672 673 /* 674 * Parse the manifest for any device regions that the SP wants to be 675 * mapped in its translation regime. 676 */ 677 node = fdt_subnode_offset_namelen(sp_manifest, offset, 678 "device-regions", 679 sizeof("device-regions") - 1); 680 if (node < 0) { 681 WARN("Not found device-region configuration for SP.\n"); 682 } else { 683 populate_sp_regions(sp, sp_manifest, node, 684 SP_MEM_REGION_DEVICE); 685 } 686 687 /* 688 * Parse the manifest for any memory regions that the SP wants to be 689 * mapped in its translation regime. 690 */ 691 node = fdt_subnode_offset_namelen(sp_manifest, offset, 692 "memory-regions", 693 sizeof("memory-regions") - 1); 694 if (node < 0) { 695 WARN("Not found memory-region configuration for SP.\n"); 696 } else { 697 populate_sp_regions(sp, sp_manifest, node, 698 SP_MEM_REGION_MEMORY); 699 } 700 701 spmc_el0_sp_setup_system_registers(sp, ctx); 702 } 703 #endif /* SPMC_AT_EL3_SEL0_SP */ 704 705 /* S-EL1 partition specific initialisation. */ 706 void spmc_el1_sp_setup(struct secure_partition_desc *sp, 707 entry_point_info_t *ep_info) 708 { 709 /* Sanity check input arguments. */ 710 assert(sp != NULL); 711 assert(ep_info != NULL); 712 713 /* Initialise the SPSR for S-EL1 SPs. */ 714 ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 715 DISABLE_ALL_EXCEPTIONS); 716 717 /* 718 * TF-A Implementation defined behaviour to provide the linear 719 * core ID in the x4 register. 720 */ 721 ep_info->args.arg4 = (uintptr_t) plat_my_core_pos(); 722 723 /* 724 * Check whether setup is being performed for the primary or a secondary 725 * execution context. In the latter case, indicate to the SP that this 726 * is a warm boot. 727 * TODO: This check would need to be reworked if the same entry point is 728 * used for both primary and secondary initialisation. 729 */ 730 if (sp->secondary_ep != 0U) { 731 /* 732 * Sanity check that the secondary entry point is still what was 733 * originally set. 734 */ 735 assert(sp->secondary_ep == ep_info->pc); 736 ep_info->args.arg0 = FFA_WB_TYPE_S2RAM; 737 } 738 } 739 740 /* Common initialisation for all SPs. */ 741 void spmc_sp_common_setup(struct secure_partition_desc *sp, 742 entry_point_info_t *ep_info, 743 int32_t boot_info_reg) 744 { 745 uint16_t sp_id; 746 747 /* Assign FF-A Partition ID if not already assigned. */ 748 if (sp->sp_id == INV_SP_ID) { 749 sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX; 750 /* 751 * Ensure we don't clash with previously assigned partition 752 * IDs. 753 */ 754 while (!is_ffa_secure_id_valid(sp_id)) { 755 sp_id++; 756 757 if (sp_id == FFA_SWD_ID_LIMIT) { 758 ERROR("Unable to determine valid SP ID.\n"); 759 panic(); 760 } 761 } 762 sp->sp_id = sp_id; 763 } 764 765 /* Check if the SP wants to use the FF-A boot protocol. */ 766 if (boot_info_reg >= 0) { 767 /* 768 * Create a boot information descriptor and copy the partition 769 * manifest into the reserved memory region for consumption by 770 * the SP. 771 */ 772 spmc_create_boot_info(ep_info, sp); 773 774 /* 775 * We have consumed what we need from ep args so we can now 776 * zero them before we start populating with new information 777 * specifically for the SP. 778 */ 779 zeromem(&ep_info->args, sizeof(ep_info->args)); 780 781 /* 782 * Pass the address of the boot information in the 783 * boot_info_reg. 784 */ 785 switch (boot_info_reg) { 786 case 0: 787 ep_info->args.arg0 = (uintptr_t) ffa_boot_info_mem; 788 break; 789 case 1: 790 ep_info->args.arg1 = (uintptr_t) ffa_boot_info_mem; 791 break; 792 case 2: 793 ep_info->args.arg2 = (uintptr_t) ffa_boot_info_mem; 794 break; 795 case 3: 796 ep_info->args.arg3 = (uintptr_t) ffa_boot_info_mem; 797 break; 798 default: 799 ERROR("Invalid value for \"gp-register-num\" %d.\n", 800 boot_info_reg); 801 } 802 } else { 803 /* 804 * We don't need any of the information that was populated 805 * in ep_args so we can clear them. 806 */ 807 zeromem(&ep_info->args, sizeof(ep_info->args)); 808 } 809 } 810 811 /* 812 * Initialise the SP context now we have populated the common and EL specific 813 * entrypoint information. 814 */ 815 void spmc_sp_common_ep_commit(struct secure_partition_desc *sp, 816 entry_point_info_t *ep_info) 817 { 818 cpu_context_t *cpu_ctx; 819 820 cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx); 821 print_entry_point_info(ep_info); 822 cm_setup_context(cpu_ctx, ep_info); 823 } 824