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