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_current_guest_id() - return current guest ID 95 * 96 * Returns current guest ID or 0 if none is set. 97 */ 98 uint16_t virt_get_current_guest_id(void); 99 100 /** 101 * virt_get_guest_id() - return guest ID of a guest partition 102 * @prtn: Guest partition 103 * 104 * Returns guest ID or 0 if @prtn is NULL 105 */ 106 uint16_t virt_get_guest_id(struct guest_partition *prtn); 107 108 /* 109 * virt_next_guest() - iterate over guest partitions 110 * @prtn: Guest partition to start from 111 * 112 * Iterates of the guest partitions, if @prtn is NULL the first partition 113 * is returned. If there are none or no next partition NULL is returned. 114 * 115 * The supplied @prtn has its reference counter decreased with 116 * virt_put_guest() before returning the next partition. A returned 117 * partition has its reference counter increased before being returned. 118 * 119 * If virt_next_guest() is called in sequence until it returns NULL, all 120 * reference counters are restored, but if the sequence is stopped earlier 121 * it's the callers responsibility to call virt_put_guest() on the last 122 * returned partition. 123 */ 124 struct guest_partition *virt_next_guest(struct guest_partition *prtn); 125 126 /** 127 * virt_get_current_guest() - increase reference to current guest partition 128 * 129 * Each successful call to this function must be matched by a call to 130 * virt_put_guest() in order to decrease the reference counter again. 131 * 132 * Return a pointer to the guest partition on success or NULL on failure 133 */ 134 struct guest_partition *virt_get_current_guest(void); 135 136 /** 137 * virt_get_guest() - increase reference to a guest partition 138 * @guest_id: ID of the guest partition to find 139 * 140 * Each successful call to this function must be matched by a call to 141 * virt_put_guest() in order to decrease the reference counter again. 142 * 143 * Return a pointer to the guest partition on success or NULL on failure 144 */ 145 struct guest_partition *virt_get_guest(uint16_t guest_id); 146 147 /** 148 * virt_put_guest() - decrease reference to a guest partition 149 * @prtn: Guest partition 150 * 151 * Does nothing if @prtn is NULL. 152 */ 153 void virt_put_guest(struct guest_partition *prtn); 154 155 /** 156 * virt_add_guest_spec_data() - add guest specific data 157 * @data_id: assigned id for the guest specific data 158 * @data_size: size of the guest specific data 159 * @data_destroy: function to destroy the guest specific data when the 160 * guest is destroyed, does not free the data itself 161 * 162 * Assigns a new data ID returned in @data_id and records the associated 163 * @data_size size and destructor function @data_destroy. 164 * 165 * To keep things simple, this function is only to be called before exiting 166 * to the normal world for the first time, that is, while we're single 167 * threaded and only have one partition. 168 */ 169 TEE_Result virt_add_guest_spec_data(unsigned int *data_id, size_t data_size, 170 void (*data_destroy)(void *data)); 171 172 /* 173 * virt_get_guest_spec_data() - get guest specific data 174 * @prtn: guest partition 175 * @data_id: previously assigned ID for the data 176 * 177 * Returns the preallocated guest specific data of the partition with the 178 * ID of @guest_id, will only return NULL for an unrecognized @data_id or 179 * NULL @prtn. 180 */ 181 void *virt_get_guest_spec_data(struct guest_partition *prtn, 182 unsigned int data_id); 183 184 #else 185 static inline TEE_Result virt_guest_created(uint16_t guest_id __unused) 186 { return TEE_ERROR_NOT_SUPPORTED; } 187 188 static inline TEE_Result virt_guest_destroyed(uint16_t guest_id __unused) 189 { return TEE_ERROR_NOT_SUPPORTED; } 190 191 static inline TEE_Result virt_set_guest(uint16_t guest_id __unused) 192 { return TEE_ERROR_NOT_SUPPORTED; } 193 194 static inline void virt_unset_guest(void) { } 195 static inline void virt_on_stdcall(void) { } 196 static inline struct memory_map *virt_get_memory_map(void) { return NULL; } 197 static inline void virt_init_memory(struct memory_map *mem_map __unused, 198 paddr_t secmem0_base __unused, 199 paddr_size_t secmem0_size __unused, 200 paddr_t secmem1_base __unused, 201 paddr_size_t secmem1_size __unused) { } 202 static inline uint16_t virt_get_current_guest_id(void) { return 0; } 203 static inline uint16_t virt_get_guest_id(struct guest_partition *prtn __unused) 204 { 205 return 0; 206 } 207 static inline struct guest_partition *virt_get_current_guest(void) 208 { 209 return NULL; 210 } 211 static inline struct guest_partition *virt_get_guest(uint16_t guest_id __unused) 212 { 213 return NULL; 214 } 215 static inline struct guest_partition * 216 virt_next_guest(struct guest_partition *prtn __unused) 217 { 218 return NULL; 219 } 220 static inline void virt_put_guest(struct guest_partition *prtn __unused) { } 221 static inline TEE_Result 222 virt_add_guest_spec_data(unsigned int *data_id __unused, 223 size_t data_size __unused, 224 void (*data_destroy)(void *data) __unused) 225 { 226 return TEE_ERROR_NOT_SUPPORTED; 227 } 228 229 static inline void * 230 virt_get_guest_spec_data(struct guest_partition *prtn __unused, 231 unsigned int data_id __unused) 232 { 233 return NULL; 234 } 235 236 #endif /*CFG_NS_VIRTUALIZATION*/ 237 238 #if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_NS_VIRTUALIZATION) 239 TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie); 240 void virt_remove_cookie(uint64_t cookie); 241 uint16_t virt_find_guest_by_cookie(uint64_t cookie); 242 bitstr_t *virt_get_shm_bits(void); 243 244 TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id, 245 uint64_t cookie); 246 #else 247 static inline TEE_Result 248 virt_add_cookie_to_current_guest(uint64_t cookie __unused) 249 { return TEE_ERROR_NOT_SUPPORTED; } 250 static inline void virt_remove_cookie(uint64_t cookie __unused) { } 251 static inline uint16_t virt_find_guest_by_cookie(uint64_t cookie __unused) 252 { return 0; } 253 static inline bitstr_t *virt_get_shm_bits(void) { return NULL; } 254 static inline TEE_Result 255 virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id __unused, 256 uint64_t cookie __unused) 257 { return TEE_ERROR_NOT_SUPPORTED; } 258 #endif 259 260 #endif /* __KERNEL_VIRTUALIZATION_H */ 261