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 * @mem_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 memory_map *mem_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 memory_map *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 /** 163 * virt_add_guest_spec_data() - add guest specific data 164 * @data_id: assigned id for the guest specific data 165 * @data_size: size of the guest specific data 166 * @data_destroy: function to destroy the guest specific data when the 167 * guest is destroyed, does not free the data itself 168 * 169 * Assigns a new data ID returned in @data_id and records the associated 170 * @data_size size and destructor function @data_destroy. 171 * 172 * To keep things simple, this function is only to be called before exiting 173 * to the normal world for the first time, that is, while we're single 174 * threaded and only have one partition. 175 */ 176 TEE_Result virt_add_guest_spec_data(unsigned int *data_id, size_t data_size, 177 void (*data_destroy)(void *data)); 178 179 /* 180 * virt_get_guest_spec_data() - get guest specific data 181 * @prtn: guest partition 182 * @data_id: previously assigned ID for the data 183 * 184 * Returns the preallocated guest specific data of the partition with the 185 * ID of @guest_id, will only return NULL for an unrecognized @data_id or 186 * NULL @prtn. 187 */ 188 void *virt_get_guest_spec_data(struct guest_partition *prtn, 189 unsigned int data_id); 190 191 #else 192 static inline TEE_Result virt_guest_created(uint16_t guest_id __unused) 193 { return TEE_ERROR_NOT_SUPPORTED; } 194 195 static inline TEE_Result virt_guest_destroyed(uint16_t guest_id __unused) 196 { return TEE_ERROR_NOT_SUPPORTED; } 197 198 static inline TEE_Result virt_set_guest(uint16_t guest_id __unused) 199 { return TEE_ERROR_NOT_SUPPORTED; } 200 201 static inline void virt_unset_guest(void) { } 202 static inline void virt_on_stdcall(void) { } 203 static inline struct memory_map *virt_get_memory_map(void) { return NULL; } 204 static inline void 205 virt_get_ta_ram(vaddr_t *start __unused, vaddr_t *end __unused) { } 206 static inline void virt_init_memory(struct memory_map *mem_map __unused, 207 paddr_t secmem0_base __unused, 208 paddr_size_t secmem0_size __unused, 209 paddr_t secmem1_base __unused, 210 paddr_size_t secmem1_size __unused) { } 211 static inline uint16_t virt_get_current_guest_id(void) { return 0; } 212 static inline uint16_t virt_get_guest_id(struct guest_partition *prtn __unused) 213 { 214 return 0; 215 } 216 static inline struct guest_partition *virt_get_current_guest(void) 217 { 218 return NULL; 219 } 220 static inline struct guest_partition *virt_get_guest(uint16_t guest_id __unused) 221 { 222 return NULL; 223 } 224 static inline struct guest_partition * 225 virt_next_guest(struct guest_partition *prtn __unused) 226 { 227 return NULL; 228 } 229 static inline void virt_put_guest(struct guest_partition *prtn __unused) { } 230 static inline TEE_Result 231 virt_add_guest_spec_data(unsigned int *data_id __unused, 232 size_t data_size __unused, 233 void (*data_destroy)(void *data) __unused) 234 { 235 return TEE_ERROR_NOT_SUPPORTED; 236 } 237 238 static inline void * 239 virt_get_guest_spec_data(struct guest_partition *prtn __unused, 240 unsigned int data_id __unused) 241 { 242 return NULL; 243 } 244 245 #endif /*CFG_NS_VIRTUALIZATION*/ 246 247 #if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_NS_VIRTUALIZATION) 248 TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie); 249 void virt_remove_cookie(uint64_t cookie); 250 uint16_t virt_find_guest_by_cookie(uint64_t cookie); 251 bitstr_t *virt_get_shm_bits(void); 252 253 TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id, 254 uint64_t cookie); 255 #else 256 static inline TEE_Result 257 virt_add_cookie_to_current_guest(uint64_t cookie __unused) 258 { return TEE_ERROR_NOT_SUPPORTED; } 259 static inline void virt_remove_cookie(uint64_t cookie __unused) { } 260 static inline uint16_t virt_find_guest_by_cookie(uint64_t cookie __unused) 261 { return 0; } 262 static inline bitstr_t *virt_get_shm_bits(void) { return NULL; } 263 static inline TEE_Result 264 virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id __unused, 265 uint64_t cookie __unused) 266 { return TEE_ERROR_NOT_SUPPORTED; } 267 #endif 268 269 #endif /* __KERNEL_VIRTUALIZATION_H */ 270