1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2021, Arm Limited. All rights reserved. 4 */ 5 #include <assert.h> 6 #include <bitstring.h> 7 #include <ffa.h> 8 #include <kernel/spinlock.h> 9 #include <mm/fobj.h> 10 #include <mm/mobj.h> 11 #include <mm/sp_mem.h> 12 13 #define NUM_SHARES 64 14 15 static bitstr_t bit_decl(share_bits, NUM_SHARES); 16 static unsigned int sp_mem_lock = SPINLOCK_UNLOCK; 17 18 /* mem_shares stores all active FF-A shares. */ 19 SLIST_HEAD(sp_mem_head, sp_mem); 20 static struct sp_mem_head mem_shares = SLIST_HEAD_INITIALIZER(sp_mem_head); 21 22 struct sp_mem *sp_mem_new(void) 23 { 24 struct sp_mem *smem = NULL; 25 uint32_t exceptions = 0; 26 int i = 0; 27 28 smem = calloc(sizeof(*smem), 1); 29 if (!smem) 30 return NULL; 31 32 exceptions = cpu_spin_lock_xsave(&sp_mem_lock); 33 34 bit_ffc(share_bits, NUM_SHARES, &i); 35 if (i == -1) { 36 cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); 37 free(smem); 38 return NULL; 39 } 40 41 bit_set(share_bits, i); 42 /* 43 * OP-TEE SHAREs use bit 44 use bit 45 instead. 44 */ 45 smem->global_handle = i | FFA_MEMORY_HANDLE_SECURE_BIT; 46 SLIST_INIT(&smem->regions); 47 SLIST_INIT(&smem->receivers); 48 49 cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); 50 51 return smem; 52 } 53 54 void sp_mem_add(struct sp_mem *smem) 55 { 56 uint32_t exceptions = cpu_spin_lock_xsave(&sp_mem_lock); 57 58 SLIST_INSERT_HEAD(&mem_shares, smem, link); 59 60 cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); 61 } 62 63 void sp_mem_remove(struct sp_mem *smem) 64 { 65 uint32_t exceptions = 0; 66 int i = 0; 67 struct sp_mem *tsmem = NULL; 68 69 if (!smem) 70 return; 71 72 /* Remove all receivers */ 73 while (!SLIST_EMPTY(&smem->receivers)) { 74 struct sp_mem_receiver *receiver = NULL; 75 76 receiver = SLIST_FIRST(&smem->receivers); 77 SLIST_REMOVE_HEAD(&smem->receivers, link); 78 free(receiver); 79 } 80 /* Remove all regions */ 81 while (!SLIST_EMPTY(&smem->regions)) { 82 struct sp_mem_map_region *region = SLIST_FIRST(&smem->regions); 83 84 mobj_put(region->mobj); 85 86 SLIST_REMOVE_HEAD(&smem->regions, link); 87 free(region); 88 } 89 90 exceptions = cpu_spin_lock_xsave(&sp_mem_lock); 91 92 i = smem->global_handle & ~FFA_MEMORY_HANDLE_SECURE_BIT; 93 assert(i < NUM_SHARES); 94 95 bit_clear(share_bits, i); 96 97 SLIST_FOREACH(tsmem, &mem_shares, link) { 98 if (tsmem == smem) { 99 SLIST_REMOVE(&mem_shares, smem, sp_mem, link); 100 break; 101 } 102 } 103 104 cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); 105 106 free(smem); 107 } 108