1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2018, EPAM Systems. All rights reserved. 4 * Copyright (c) 2024, Linaro Limited 5 */ 6 7 #ifndef __KERNEL_VIRTUALIZATION_H 8 #define __KERNEL_VIRTUALIZATION_H 9 10 #include <bitstring.h> 11 #include <mm/core_mmu.h> 12 #include <stdbool.h> 13 #include <stdint.h> 14 #include <tee_api_types.h> 15 16 #define HYP_CLNT_ID 0 17 18 struct guest_partition; 19 20 #if defined(CFG_NS_VIRTUALIZATION) 21 /** 22 * virt_guest_created() - create new VM partition 23 * @guest_id: VM id provided by hypervisor 24 * 25 * This function is called by hypervisor (via fast SMC) 26 * when hypervisor creates new guest VM, so OP-TEE 27 * can prepare partition for that VM 28 */ 29 TEE_Result virt_guest_created(uint16_t guest_id); 30 31 /** 32 * virt_guest_destroyed() - destroy existing VM partition 33 * @guest_id: VM id provided by hypervisor 34 * 35 * This function is called by hypervisor (via fast SMC) 36 * when hypervisor is ready to destroy guest VM. Hypervisor 37 * must ensure that there are no ongoing calls from this 38 * VM right now. 39 */ 40 TEE_Result virt_guest_destroyed(uint16_t guest_id); 41 42 /** 43 * virt_set_guest() - set guest VM context for current core 44 * @guest_id: VM id provided by hypervisor 45 * 46 * This function switches memory partitions, so TEE part of 47 * OP-TEE will see memory associated with current guest. 48 * It should be called on entry to OP-TEE 49 */ 50 TEE_Result virt_set_guest(uint16_t guest_id); 51 52 /** 53 * virt_unset_guest() - set default memory partition 54 * 55 * This function should be called upon leaving OP-TEE, 56 * to switch to default memory partition, so all TEE-specific 57 * memory will be unmapped. This is safety measure to ensure 58 * that TEE memory is untouched when there is no active VM. 59 */ 60 void virt_unset_guest(void); 61 62 /** 63 * virt_on_stdcall() - std call hook 64 * 65 * This hook is called on every std call, but really is needed 66 * only once: to initialize TEE runtime for current guest VM 67 */ 68 void virt_on_stdcall(void); 69 70 /* 71 * Next function are needed because virtualization subsystem manages 72 * memory in own way. There is no one static memory map, instead 73 * every guest gets own memory map. 74 */ 75 76 /** 77 * virt_init_memory() - initialize memory for virtualization subsystem 78 * @memory_map: current OP-TEE memory map 79 * @secmem0_base: base of first secure memory range 80 * @secmem0_size: size of first secure memory range 81 * @secmem1_base: base of an eventual second secure memory range, 0 if unused 82 * @secmem1_size: size of an eventual second secure memory range, 0 if unused 83 */ 84 void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base, 85 paddr_size_t secmem0_size, paddr_t secmem1_base, 86 paddr_size_t secmem1_size); 87 88 /** 89 * virt_get_memory_map() - get current memory map 90 */ 91 struct tee_mmap_region *virt_get_memory_map(void); 92 93 /** 94 * virt_get_ta_ram() - get TA RAM mapping for current VM 95 * @start: beginning of TA RAM returned here 96 * @end: end of TA RAM returned here 97 */ 98 void virt_get_ta_ram(vaddr_t *start, vaddr_t *end); 99 100 /** 101 * virt_get_current_guest_id() - return current guest ID 102 * 103 * Returns current guest ID or 0 if none is set. 104 */ 105 uint16_t virt_get_current_guest_id(void); 106 107 /** 108 * virt_get_guest_id() - return guest ID of a guest partition 109 * @prtn: Guest partition 110 * 111 * Returns guest ID or 0 if @prtn is NULL 112 */ 113 uint16_t virt_get_guest_id(struct guest_partition *prtn); 114 115 /* 116 * virt_next_guest() - iterate over guest partitions 117 * @prtn: Guest partition to start from 118 * 119 * Iterates of the guest partitions, if @prtn is NULL the first partition 120 * is returned. If there are none or no next partition NULL is returned. 121 * 122 * The supplied @prtn has its reference counter decreased with 123 * virt_put_guest() before returning the next partition. A returned 124 * partition has its reference counter increased before being returned. 125 * 126 * If virt_next_guest() is called in sequence until it returns NULL, all 127 * reference counters are restored, but if the sequence is stopped earlier 128 * it's the callers responsibility to call virt_put_guest() on the last 129 * returned partition. 130 */ 131 struct guest_partition *virt_next_guest(struct guest_partition *prtn); 132 133 /** 134 * virt_get_current_guest() - increase reference to current guest partition 135 * 136 * Each successful call to this function must be matched by a call to 137 * virt_put_guest() in order to decrease the reference counter again. 138 * 139 * Return a pointer to the guest partition on success or NULL on failure 140 */ 141 struct guest_partition *virt_get_current_guest(void); 142 143 /** 144 * virt_get_guest() - increase reference to a guest partition 145 * @guest_id: ID of the guest partition to find 146 * 147 * Each successful call to this function must be matched by a call to 148 * virt_put_guest() in order to decrease the reference counter again. 149 * 150 * Return a pointer to the guest partition on success or NULL on failure 151 */ 152 struct guest_partition *virt_get_guest(uint16_t guest_id); 153 154 /** 155 * virt_put_guest() - decrease reference to a guest partition 156 * @prtn: Guest partition 157 * 158 * Does nothing if @prtn is NULL. 159 */ 160 void virt_put_guest(struct guest_partition *prtn); 161 162 #else 163 static inline TEE_Result virt_guest_created(uint16_t guest_id __unused) 164 { return TEE_ERROR_NOT_SUPPORTED; } 165 166 static inline TEE_Result virt_guest_destroyed(uint16_t guest_id __unused) 167 { return TEE_ERROR_NOT_SUPPORTED; } 168 169 static inline TEE_Result virt_set_guest(uint16_t guest_id __unused) 170 { return TEE_ERROR_NOT_SUPPORTED; } 171 172 static inline void virt_unset_guest(void) { } 173 static inline void virt_on_stdcall(void) { } 174 static inline struct tee_mmap_region *virt_get_memory_map(void) { return NULL; } 175 static inline void 176 virt_get_ta_ram(vaddr_t *start __unused, vaddr_t *end __unused) { } 177 static inline void virt_init_memory(struct tee_mmap_region *memory_map __unused, 178 paddr_t secmem0_base __unused, 179 paddr_size_t secmem0_size __unused, 180 paddr_t secmem1_base __unused, 181 paddr_size_t secmem1_size __unused) { } 182 static inline uint16_t virt_get_current_guest_id(void) { return 0; } 183 static inline uint16_t virt_get_guest_id(struct guest_partition *prtn __unused) 184 { 185 return 0; 186 } 187 static inline struct guest_partition *virt_get_current_guest(void) 188 { 189 return NULL; 190 } 191 static inline struct guest_partition *virt_get_guest(uint16_t guest_id __unused) 192 { 193 return NULL; 194 } 195 static inline struct guest_partition * 196 virt_next_guest(struct guest_partition *prtn __unused) 197 { 198 return NULL; 199 } 200 static inline void virt_put_guest(struct guest_partition *prtn __unused) { } 201 #endif /*CFG_NS_VIRTUALIZATION*/ 202 203 #if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_NS_VIRTUALIZATION) 204 TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie); 205 void virt_remove_cookie(uint64_t cookie); 206 uint16_t virt_find_guest_by_cookie(uint64_t cookie); 207 bitstr_t *virt_get_shm_bits(void); 208 209 TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id, 210 uint64_t cookie); 211 #else 212 static inline TEE_Result 213 virt_add_cookie_to_current_guest(uint64_t cookie __unused) 214 { return TEE_ERROR_NOT_SUPPORTED; } 215 static inline void virt_remove_cookie(uint64_t cookie __unused) { } 216 static inline uint16_t virt_find_guest_by_cookie(uint64_t cookie __unused) 217 { return 0; } 218 static inline bitstr_t *virt_get_shm_bits(void) { return NULL; } 219 static inline TEE_Result 220 virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id __unused, 221 uint64_t cookie __unused) 222 { return TEE_ERROR_NOT_SUPPORTED; } 223 #endif 224 225 #endif /* __KERNEL_VIRTUALIZATION_H */ 226