1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2018, EPAM Systems. All rights reserved. 4 * Copyright (c) 2023-2024, Linaro Limited 5 */ 6 7 #include <bitstring.h> 8 #include <compiler.h> 9 #include <kernel/boot.h> 10 #include <kernel/linker.h> 11 #include <kernel/misc.h> 12 #include <kernel/mutex.h> 13 #include <kernel/notif.h> 14 #include <kernel/panic.h> 15 #include <kernel/refcount.h> 16 #include <kernel/spinlock.h> 17 #include <kernel/thread_spmc.h> 18 #include <kernel/virtualization.h> 19 #include <mm/core_memprot.h> 20 #include <mm/core_mmu.h> 21 #include <mm/phys_mem.h> 22 #include <mm/tee_mm.h> 23 #include <platform_config.h> 24 #include <sm/optee_smc.h> 25 #include <string.h> 26 #include <string_ext.h> 27 #include <util.h> 28 29 LIST_HEAD(prtn_list_head, guest_partition); 30 31 static unsigned int prtn_list_lock __nex_data = SPINLOCK_UNLOCK; 32 33 static struct prtn_list_head prtn_list __nex_data = 34 LIST_HEAD_INITIALIZER(prtn_list); 35 static struct prtn_list_head prtn_destroy_list __nex_data = 36 LIST_HEAD_INITIALIZER(prtn_destroy_list); 37 38 /* Memory used by OP-TEE core */ 39 struct memory_map *kmem_map __nex_bss; 40 41 struct guest_spec_data { 42 size_t size; 43 void (*destroy)(void *data); 44 }; 45 46 static bool add_disabled __nex_bss; 47 static unsigned gsd_count __nex_bss; 48 static struct guest_spec_data *gsd_array __nex_bss; 49 50 struct guest_partition { 51 LIST_ENTRY(guest_partition) link; 52 struct mmu_partition *mmu_prtn; 53 struct memory_map mem_map; 54 struct mutex mutex; 55 void *tables_va; 56 tee_mm_entry_t *tee_ram; 57 tee_mm_entry_t *ta_ram; 58 tee_mm_entry_t *tables; 59 bool runtime_initialized; 60 bool got_guest_destroyed; 61 bool shutting_down; 62 uint16_t id; 63 struct refcount refc; 64 #ifdef CFG_CORE_SEL1_SPMC 65 uint64_t cookies[SPMC_CORE_SEL1_MAX_SHM_COUNT]; 66 uint8_t cookie_count; 67 bitstr_t bit_decl(shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT); 68 #endif 69 void **data_array; 70 }; 71 72 struct guest_partition *current_partition[CFG_TEE_CORE_NB_CORE] __nex_bss; 73 74 static struct guest_partition *get_current_prtn(void) 75 { 76 struct guest_partition *ret; 77 uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); 78 79 ret = current_partition[get_core_pos()]; 80 81 thread_unmask_exceptions(exceptions); 82 83 return ret; 84 } 85 86 uint16_t virt_get_current_guest_id(void) 87 { 88 struct guest_partition *prtn = get_current_prtn(); 89 90 if (!prtn) 91 return 0; 92 return prtn->id; 93 } 94 95 static void set_current_prtn(struct guest_partition *prtn) 96 { 97 uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); 98 99 current_partition[get_core_pos()] = prtn; 100 101 thread_unmask_exceptions(exceptions); 102 } 103 104 static size_t get_ta_ram_size(void) 105 { 106 size_t ta_size = nex_phys_mem_get_ta_size(); 107 108 return ROUNDDOWN(ta_size / CFG_VIRT_GUEST_COUNT - VCORE_UNPG_RW_SZ - 109 core_mmu_get_total_pages_size(), SMALL_PAGE_SIZE); 110 } 111 112 static TEE_Result prepare_memory_map(struct memory_map *mem_map, 113 paddr_t tee_data) 114 { 115 struct tee_mmap_region *map = NULL; 116 vaddr_t max_va = 0; 117 size_t n = 0; 118 /* 119 * This function assumes that at time of operation, 120 * kmemory_map (aka static_memory_map from core_mmu.c) 121 * will not be altered. This is true, because all 122 * changes to static_memory_map are done during 123 * OP-TEE initialization, while this function will 124 * called when hypervisor creates a guest. 125 */ 126 127 /* Allocate entries for virtual guest map */ 128 mem_map->map = nex_calloc(kmem_map->count + 1, sizeof(*mem_map->map)); 129 if (!mem_map->map) 130 return TEE_ERROR_OUT_OF_MEMORY; 131 mem_map->count = kmem_map->count; 132 mem_map->alloc_count = kmem_map->count + 1; 133 134 memcpy(mem_map->map, kmem_map->map, 135 sizeof(*mem_map->map) * mem_map->count); 136 137 /* Map TEE .data and .bss sections */ 138 for (n = 0; n < mem_map->count; n++) { 139 map = mem_map->map + n; 140 if (map->va == (vaddr_t)(VCORE_UNPG_RW_PA)) { 141 map->type = MEM_AREA_TEE_RAM_RW; 142 map->attr = core_mmu_type_to_attr(map->type); 143 map->pa = tee_data; 144 } 145 if (map->va + map->size > max_va) 146 max_va = map->va + map->size; 147 } 148 149 DMSG("New map (%08lx):", (vaddr_t)(VCORE_UNPG_RW_PA)); 150 151 for (n = 0; n < mem_map->count; n++) 152 DMSG("T: %-16s rsz: %08x, pa: %08lx, va: %08lx, sz: %08lx attr: %x", 153 teecore_memtype_name(mem_map->map[n].type), 154 mem_map->map[n].region_size, mem_map->map[n].pa, 155 mem_map->map[n].va, mem_map->map[n].size, 156 mem_map->map[n].attr); 157 return TEE_SUCCESS; 158 } 159 160 void virt_init_memory(struct memory_map *mem_map, paddr_t secmem0_base, 161 paddr_size_t secmem0_size, paddr_t secmem1_base, 162 paddr_size_t secmem1_size) 163 { 164 size_t n = 0; 165 166 /* Init page pool that covers all secure RAM */ 167 nex_phys_mem_init(secmem0_base, secmem0_size, secmem1_base, 168 secmem1_size); 169 170 /* Carve out areas that are used by OP-TEE core */ 171 for (n = 0; n < mem_map->count; n++) { 172 struct tee_mmap_region *map = mem_map->map + n; 173 174 switch (map->type) { 175 case MEM_AREA_TEE_RAM_RX: 176 case MEM_AREA_TEE_RAM_RO: 177 case MEM_AREA_NEX_RAM_RO: 178 case MEM_AREA_NEX_RAM_RW: 179 DMSG("Carving out area of type %d (0x%08lx-0x%08lx)", 180 map->type, map->pa, map->pa + map->size); 181 if (!nex_phys_mem_alloc2(map->pa, map->size)) 182 panic("Can't carve out used area"); 183 break; 184 default: 185 continue; 186 } 187 } 188 189 kmem_map = mem_map; 190 } 191 192 193 static TEE_Result configure_guest_prtn_mem(struct guest_partition *prtn) 194 { 195 TEE_Result res = TEE_SUCCESS; 196 paddr_t original_data_pa = 0; 197 198 prtn->tee_ram = nex_phys_mem_core_alloc(VCORE_UNPG_RW_SZ); 199 if (!prtn->tee_ram) { 200 EMSG("Can't allocate memory for TEE runtime context"); 201 res = TEE_ERROR_OUT_OF_MEMORY; 202 goto err; 203 } 204 DMSG("TEE RAM: %08" PRIxPA, tee_mm_get_smem(prtn->tee_ram)); 205 206 prtn->ta_ram = nex_phys_mem_ta_alloc(get_ta_ram_size()); 207 if (!prtn->ta_ram) { 208 EMSG("Can't allocate memory for TA data"); 209 res = TEE_ERROR_OUT_OF_MEMORY; 210 goto err; 211 } 212 DMSG("TA RAM: %08" PRIxPA, tee_mm_get_smem(prtn->ta_ram)); 213 214 prtn->tables = nex_phys_mem_core_alloc(core_mmu_get_total_pages_size()); 215 if (!prtn->tables) { 216 EMSG("Can't allocate memory for page tables"); 217 res = TEE_ERROR_OUT_OF_MEMORY; 218 goto err; 219 } 220 221 prtn->tables_va = phys_to_virt(tee_mm_get_smem(prtn->tables), 222 MEM_AREA_SEC_RAM_OVERALL, 223 core_mmu_get_total_pages_size()); 224 assert(prtn->tables_va); 225 226 prtn->mmu_prtn = core_alloc_mmu_prtn(prtn->tables_va); 227 if (!prtn->mmu_prtn) { 228 res = TEE_ERROR_OUT_OF_MEMORY; 229 goto err; 230 } 231 232 res = prepare_memory_map(&prtn->mem_map, 233 tee_mm_get_smem(prtn->tee_ram)); 234 if (res) 235 goto err; 236 237 core_init_mmu_prtn(prtn->mmu_prtn, &prtn->mem_map); 238 239 original_data_pa = virt_to_phys(__data_start); 240 /* Switch to guest's mappings */ 241 core_mmu_set_prtn(prtn->mmu_prtn); 242 243 /* clear .bss */ 244 memset((void *)(VCORE_UNPG_RW_PA), 0, VCORE_UNPG_RW_SZ); 245 246 /* copy .data section from R/O original */ 247 memcpy(__data_start, 248 phys_to_virt(original_data_pa, MEM_AREA_SEC_RAM_OVERALL, 249 __data_end - __data_start), 250 __data_end - __data_start); 251 252 return TEE_SUCCESS; 253 254 err: 255 if (prtn->tee_ram) 256 tee_mm_free(prtn->tee_ram); 257 if (prtn->ta_ram) 258 tee_mm_free(prtn->ta_ram); 259 if (prtn->tables) 260 tee_mm_free(prtn->tables); 261 nex_free(prtn->mmu_prtn); 262 nex_free(prtn->mem_map.map); 263 264 return res; 265 } 266 267 static void destroy_gsd(struct guest_partition *prtn, bool free_only) 268 { 269 size_t n = 0; 270 271 for (n = 0; n < gsd_count; n++) { 272 if (!free_only && prtn->data_array[n] && gsd_array[n].destroy) 273 gsd_array[n].destroy(prtn->data_array[n]); 274 nex_free(prtn->data_array[n]); 275 } 276 nex_free(prtn->data_array); 277 prtn->data_array = NULL; 278 } 279 280 static TEE_Result alloc_gsd(struct guest_partition *prtn) 281 { 282 unsigned int n = 0; 283 284 if (!gsd_count) 285 return TEE_SUCCESS; 286 287 prtn->data_array = nex_calloc(gsd_count, sizeof(void *)); 288 if (!prtn->data_array) 289 return TEE_ERROR_OUT_OF_MEMORY; 290 291 for (n = 0; n < gsd_count; n++) { 292 prtn->data_array[n] = nex_calloc(1, gsd_array[n].size); 293 if (!prtn->data_array[n]) { 294 destroy_gsd(prtn, true /*free_only*/); 295 return TEE_ERROR_OUT_OF_MEMORY; 296 } 297 } 298 299 return TEE_SUCCESS; 300 } 301 TEE_Result virt_guest_created(uint16_t guest_id) 302 { 303 struct guest_partition *prtn = NULL; 304 TEE_Result res = TEE_SUCCESS; 305 uint32_t exceptions = 0; 306 307 if (guest_id == HYP_CLNT_ID) 308 return TEE_ERROR_BAD_PARAMETERS; 309 310 prtn = nex_calloc(1, sizeof(*prtn)); 311 if (!prtn) 312 return TEE_ERROR_OUT_OF_MEMORY; 313 314 res = alloc_gsd(prtn); 315 if (res) 316 goto err_free_prtn; 317 318 prtn->id = guest_id; 319 mutex_init(&prtn->mutex); 320 refcount_set(&prtn->refc, 1); 321 res = configure_guest_prtn_mem(prtn); 322 if (res) 323 goto err_free_gsd; 324 325 set_current_prtn(prtn); 326 327 malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); 328 phys_mem_init(0, 0, tee_mm_get_smem(prtn->ta_ram), 329 tee_mm_get_bytes(prtn->ta_ram)); 330 /* Initialize threads */ 331 thread_init_threads(); 332 /* Do the preinitcalls */ 333 call_preinitcalls(); 334 335 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 336 LIST_INSERT_HEAD(&prtn_list, prtn, link); 337 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 338 339 IMSG("Added guest %d", guest_id); 340 341 set_current_prtn(NULL); 342 core_mmu_set_default_prtn(); 343 344 return TEE_SUCCESS; 345 346 err_free_gsd: 347 destroy_gsd(prtn, true /*free_only*/); 348 err_free_prtn: 349 nex_free(prtn); 350 return res; 351 } 352 353 static bool 354 prtn_have_remaining_resources(struct guest_partition *prtn __maybe_unused) 355 { 356 #ifdef CFG_CORE_SEL1_SPMC 357 int i = 0; 358 359 if (prtn->cookie_count) 360 return true; 361 bit_ffs(prtn->shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT, &i); 362 return i >= 0; 363 #else 364 return false; 365 #endif 366 } 367 368 static void get_prtn(struct guest_partition *prtn) 369 { 370 if (!refcount_inc(&prtn->refc)) 371 panic(); 372 } 373 374 uint16_t virt_get_guest_id(struct guest_partition *prtn) 375 { 376 if (!prtn) 377 return 0; 378 return prtn->id; 379 } 380 381 static struct guest_partition *find_guest_by_id_unlocked(uint16_t guest_id) 382 { 383 struct guest_partition *prtn = NULL; 384 385 LIST_FOREACH(prtn, &prtn_list, link) 386 if (!prtn->shutting_down && prtn->id == guest_id) 387 return prtn; 388 389 return NULL; 390 } 391 392 struct guest_partition *virt_next_guest(struct guest_partition *prtn) 393 { 394 struct guest_partition *ret = NULL; 395 uint32_t exceptions = 0; 396 397 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 398 if (prtn) 399 ret = LIST_NEXT(prtn, link); 400 else 401 ret = LIST_FIRST(&prtn_list); 402 403 while (ret && ret->shutting_down) 404 ret = LIST_NEXT(prtn, link); 405 if (ret) 406 get_prtn(ret); 407 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 408 409 virt_put_guest(prtn); 410 411 return ret; 412 } 413 414 struct guest_partition *virt_get_current_guest(void) 415 { 416 struct guest_partition *prtn = get_current_prtn(); 417 418 if (prtn) 419 get_prtn(prtn); 420 return prtn; 421 } 422 423 struct guest_partition *virt_get_guest(uint16_t guest_id) 424 { 425 struct guest_partition *prtn = NULL; 426 uint32_t exceptions = 0; 427 428 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 429 prtn = find_guest_by_id_unlocked(guest_id); 430 if (prtn) 431 get_prtn(prtn); 432 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 433 434 return prtn; 435 } 436 437 void virt_put_guest(struct guest_partition *prtn) 438 { 439 if (prtn && refcount_dec(&prtn->refc)) { 440 uint32_t exceptions = 0; 441 bool do_free = true; 442 443 assert(prtn->shutting_down); 444 445 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 446 LIST_REMOVE(prtn, link); 447 if (prtn_have_remaining_resources(prtn)) { 448 LIST_INSERT_HEAD(&prtn_destroy_list, prtn, link); 449 /* 450 * Delay the nex_free() until 451 * virt_reclaim_cookie_from_destroyed_guest() 452 * is done with this partition. 453 */ 454 do_free = false; 455 } 456 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 457 458 destroy_gsd(prtn, false /*!free_only*/); 459 tee_mm_free(prtn->tee_ram); 460 prtn->tee_ram = NULL; 461 tee_mm_free(prtn->ta_ram); 462 prtn->ta_ram = NULL; 463 tee_mm_free(prtn->tables); 464 prtn->tables = NULL; 465 core_free_mmu_prtn(prtn->mmu_prtn); 466 prtn->mmu_prtn = NULL; 467 nex_free(prtn->mem_map.map); 468 prtn->mem_map.map = NULL; 469 if (do_free) 470 nex_free(prtn); 471 } 472 } 473 474 TEE_Result virt_guest_destroyed(uint16_t guest_id) 475 { 476 struct guest_partition *prtn = NULL; 477 uint32_t exceptions = 0; 478 479 IMSG("Removing guest %"PRId16, guest_id); 480 481 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 482 483 prtn = find_guest_by_id_unlocked(guest_id); 484 if (prtn && !prtn->got_guest_destroyed) 485 prtn->got_guest_destroyed = true; 486 else 487 prtn = NULL; 488 489 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 490 491 if (prtn) { 492 notif_deliver_atomic_event(NOTIF_EVENT_SHUTDOWN, prtn->id); 493 494 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 495 prtn->shutting_down = true; 496 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 497 498 virt_put_guest(prtn); 499 } else { 500 EMSG("Client with id %d is not found", guest_id); 501 } 502 503 return TEE_SUCCESS; 504 } 505 506 TEE_Result virt_set_guest(uint16_t guest_id) 507 { 508 struct guest_partition *prtn = get_current_prtn(); 509 510 /* This can be true only if we return from IRQ RPC */ 511 if (prtn && prtn->id == guest_id) 512 return TEE_SUCCESS; 513 514 if (prtn) 515 panic("Virtual guest partition is already set"); 516 517 prtn = virt_get_guest(guest_id); 518 if (!prtn) 519 return TEE_ERROR_ITEM_NOT_FOUND; 520 521 set_current_prtn(prtn); 522 core_mmu_set_prtn(prtn->mmu_prtn); 523 524 return TEE_SUCCESS; 525 } 526 527 void virt_unset_guest(void) 528 { 529 struct guest_partition *prtn = get_current_prtn(); 530 531 if (!prtn) 532 return; 533 534 set_current_prtn(NULL); 535 core_mmu_set_default_prtn(); 536 virt_put_guest(prtn); 537 } 538 539 void virt_on_stdcall(void) 540 { 541 struct guest_partition *prtn = get_current_prtn(); 542 543 /* Initialize runtime on first std call */ 544 if (!prtn->runtime_initialized) { 545 mutex_lock(&prtn->mutex); 546 if (!prtn->runtime_initialized) { 547 init_tee_runtime(); 548 call_driver_initcalls(); 549 prtn->runtime_initialized = true; 550 } 551 mutex_unlock(&prtn->mutex); 552 } 553 } 554 555 struct memory_map *virt_get_memory_map(void) 556 { 557 struct guest_partition *prtn; 558 559 prtn = get_current_prtn(); 560 561 if (!prtn) 562 return NULL; 563 564 return &prtn->mem_map; 565 } 566 567 #ifdef CFG_CORE_SEL1_SPMC 568 static int find_cookie(struct guest_partition *prtn, uint64_t cookie) 569 { 570 int i = 0; 571 572 for (i = 0; i < prtn->cookie_count; i++) 573 if (prtn->cookies[i] == cookie) 574 return i; 575 return -1; 576 } 577 578 static struct guest_partition *find_prtn_cookie(uint64_t cookie, int *idx) 579 { 580 struct guest_partition *prtn = NULL; 581 int i = 0; 582 583 LIST_FOREACH(prtn, &prtn_list, link) { 584 i = find_cookie(prtn, cookie); 585 if (i >= 0) { 586 if (idx) 587 *idx = i; 588 return prtn; 589 } 590 } 591 592 return NULL; 593 } 594 595 TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie) 596 { 597 TEE_Result res = TEE_ERROR_ACCESS_DENIED; 598 struct guest_partition *prtn = NULL; 599 uint32_t exceptions = 0; 600 601 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 602 if (find_prtn_cookie(cookie, NULL)) 603 goto out; 604 605 prtn = current_partition[get_core_pos()]; 606 if (prtn->cookie_count < ARRAY_SIZE(prtn->cookies)) { 607 prtn->cookies[prtn->cookie_count] = cookie; 608 prtn->cookie_count++; 609 res = TEE_SUCCESS; 610 } 611 out: 612 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 613 614 return res; 615 } 616 617 void virt_remove_cookie(uint64_t cookie) 618 { 619 struct guest_partition *prtn = NULL; 620 uint32_t exceptions = 0; 621 int i = 0; 622 623 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 624 prtn = find_prtn_cookie(cookie, &i); 625 if (prtn) { 626 memmove(prtn->cookies + i, prtn->cookies + i + 1, 627 sizeof(uint64_t) * (prtn->cookie_count - i - 1)); 628 prtn->cookie_count--; 629 } 630 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 631 } 632 633 uint16_t virt_find_guest_by_cookie(uint64_t cookie) 634 { 635 struct guest_partition *prtn = NULL; 636 uint32_t exceptions = 0; 637 uint16_t ret = 0; 638 639 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 640 prtn = find_prtn_cookie(cookie, NULL); 641 if (prtn) 642 ret = prtn->id; 643 644 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 645 646 return ret; 647 } 648 649 bitstr_t *virt_get_shm_bits(void) 650 { 651 return get_current_prtn()->shm_bits; 652 } 653 654 static TEE_Result reclaim_cookie(struct guest_partition *prtn, uint64_t cookie) 655 { 656 if (cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT) { 657 size_t n = 0; 658 659 for (n = 0; n < prtn->cookie_count; n++) { 660 if (prtn->cookies[n] == cookie) { 661 memmove(prtn->cookies + n, 662 prtn->cookies + n + 1, 663 sizeof(uint64_t) * 664 (prtn->cookie_count - n - 1)); 665 prtn->cookie_count--; 666 return TEE_SUCCESS; 667 } 668 } 669 } else { 670 uint64_t mask = FFA_MEMORY_HANDLE_NON_SECURE_BIT | 671 SHIFT_U64(FFA_MEMORY_HANDLE_PRTN_MASK, 672 FFA_MEMORY_HANDLE_PRTN_SHIFT); 673 int64_t i = cookie & ~mask; 674 675 if (i >= 0 && i < SPMC_CORE_SEL1_MAX_SHM_COUNT && 676 bit_test(prtn->shm_bits, i)) { 677 bit_clear(prtn->shm_bits, i); 678 return TEE_SUCCESS; 679 } 680 } 681 682 return TEE_ERROR_ITEM_NOT_FOUND; 683 } 684 685 TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id, 686 uint64_t cookie) 687 688 { 689 struct guest_partition *prtn = NULL; 690 TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; 691 uint32_t exceptions = 0; 692 693 exceptions = cpu_spin_lock_xsave(&prtn_list_lock); 694 LIST_FOREACH(prtn, &prtn_destroy_list, link) { 695 if (prtn->id == guest_id) { 696 res = reclaim_cookie(prtn, cookie); 697 if (prtn_have_remaining_resources(prtn)) 698 prtn = NULL; 699 else 700 LIST_REMOVE(prtn, link); 701 break; 702 } 703 } 704 cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); 705 706 nex_free(prtn); 707 708 return res; 709 } 710 #endif /*CFG_CORE_SEL1_SPMC*/ 711 712 TEE_Result virt_add_guest_spec_data(unsigned int *data_id, size_t data_size, 713 void (*data_destroy)(void *data)) 714 { 715 void *p = NULL; 716 717 /* 718 * This function only executes successfully in a single threaded 719 * environment before exiting to the normal world the first time. 720 * If add_disabled is true, it means we're not in this environment 721 * any longer. 722 */ 723 724 if (add_disabled) 725 return TEE_ERROR_BAD_PARAMETERS; 726 727 p = nex_realloc(gsd_array, sizeof(*gsd_array) * (gsd_count + 1)); 728 if (!p) 729 return TEE_ERROR_OUT_OF_MEMORY; 730 gsd_array = p; 731 732 gsd_array[gsd_count] = (struct guest_spec_data){ 733 .size = data_size, 734 .destroy = data_destroy, 735 }; 736 *data_id = gsd_count + 1; 737 gsd_count++; 738 return TEE_SUCCESS; 739 } 740 741 void *virt_get_guest_spec_data(struct guest_partition *prtn, 742 unsigned int data_id) 743 { 744 assert(data_id); 745 if (!data_id || !prtn || data_id > gsd_count) 746 return NULL; 747 return prtn->data_array[data_id - 1]; 748 } 749 750 static TEE_Result virt_disable_add(void) 751 { 752 add_disabled = true; 753 754 return TEE_SUCCESS; 755 } 756 nex_release_init_resource(virt_disable_add); 757