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