1 /* 2 * Copyright (C) 2019-2022 Intel Corporation. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef IOREQ_H 8 #define IOREQ_H 9 10 #include <types.h> 11 #include <acrn_common.h> 12 #include <list.h> 13 14 /** 15 * @brief I/O Emulation 16 * 17 * @defgroup ioemul ACRN I/O Emulation 18 * @{ 19 */ 20 21 /** 22 * @brief Internal representation of a I/O request. 23 */ 24 struct io_request { 25 /** 26 * @brief Type of the request (PIO, MMIO, etc). 27 * 28 * Refer to acrn_io_request for detailed description of I/O request types. 29 */ 30 uint32_t io_type; 31 32 /** 33 * @brief Details of this request in the same format as acrn_io_request. 34 */ 35 union { 36 struct acrn_pio_request pio_request; 37 struct acrn_pci_request pci_request; 38 struct acrn_mmio_request mmio_request; 39 uint64_t data[8]; 40 } reqs; 41 }; 42 43 struct asyncio_desc { 44 struct acrn_asyncio_info asyncio_info; 45 struct list_head list; 46 }; 47 48 /** 49 * @brief Definition of a IO port range 50 */ 51 struct vm_io_range { 52 uint16_t base; /**< IO port base */ 53 uint16_t len; /**< IO port range */ 54 }; 55 56 struct vm_io_handler_desc; 57 struct acrn_vm; 58 struct acrn_vcpu; 59 60 typedef 61 bool (*io_read_fn_t)(struct acrn_vcpu *vcpu, uint16_t port, size_t size); 62 63 typedef 64 bool (*io_write_fn_t)(struct acrn_vcpu *vcpu, uint16_t port, size_t size, uint32_t val); 65 66 /** 67 * @brief Describes a single IO handler description entry. 68 */ 69 struct vm_io_handler_desc { 70 71 /** 72 * @brief The base port number of the IO range for this description. 73 */ 74 uint16_t port_start; 75 76 /** 77 * @brief The last port number of the IO range for this description (non-inclusive). 78 */ 79 uint16_t port_end; 80 81 /** 82 * @brief A pointer to the "read" function. 83 * 84 * The read function is called from the hypervisor whenever 85 * a read access to a range described in "ranges" occur. 86 * The arguments to the callback are: 87 * 88 * - The address of the port to read from. 89 * - The width of the read operation (1,2 or 4). 90 * 91 * The implementation must return the ports content as 92 * byte, word or doubleword (depending on the width). 93 * 94 * If the pointer is null, a read of 1's is assumed. 95 */ 96 io_read_fn_t io_read; 97 98 /** 99 * @brief A pointer to the "write" function. 100 * 101 * The write function is called from the hypervisor code 102 * whenever a write access to a range described in "ranges" 103 * occur. The arguments to the callback are: 104 * 105 * - The address of the port to write to. 106 * - The width of the write operation (1,2 or 4). 107 * - The value to write as byte, word or doubleword 108 * (depending on the width) 109 * 110 * The implementation must write the value to the port. 111 * 112 * If the pointer is null, the write access is ignored. 113 */ 114 io_write_fn_t io_write; 115 }; 116 117 /* Typedef for MMIO handler and range check routine */ 118 typedef int32_t (*hv_mem_io_handler_t)(struct io_request *io_req, void *handler_private_data); 119 120 /** 121 * @brief Structure for MMIO handler node 122 */ 123 struct mem_io_node { 124 125 /** 126 * @brief Whether the lock needs to hold when handle the MMIO access 127 */ 128 bool hold_lock; 129 130 131 /** 132 * @brief A pointer to the handler 133 * 134 * The function for handling MMIO accesses to the specified range. 135 */ 136 hv_mem_io_handler_t read_write; 137 138 /** 139 * @brief Private data used by the handler 140 * 141 * The pointer to any data specified at registration. This pointer is 142 * passed to the handler whenever the handler is called. 143 */ 144 void *handler_private_data; 145 146 /** 147 * @brief The struct to make a bi-directional linked list 148 */ 149 struct list_head list; 150 151 /** 152 * @brief The starting address 153 * 154 * This member is used in pair with \p range_end. See the documentation 155 * of \p range_end for details. 156 */ 157 uint64_t range_start; 158 159 /** 160 * @brief The ending address 161 * 162 * \p range_start (inclusive) and \p range_end (exclusive) together 163 * specify the address range that this handler is expected to 164 * emulate. Note that the bytes to be accessed shall completely fall in 165 * the range before the handler is called to emulate that access, or 166 * more specifically 167 * 168 * \p range_start <= address < address + size <= \p end 169 * 170 * where address and size are the starting address of the MMIO access 171 * and the number of bytes to be accessed, respectively. Otherwise the 172 * behavior is undefined. 173 */ 174 uint64_t range_end; 175 }; 176 177 /* External Interfaces */ 178 179 /** 180 * @brief Deliver \p io_req to Service VM and suspend \p vcpu till its completion 181 * 182 * @param vcpu The virtual CPU that triggers the MMIO access 183 * @param io_req The I/O request holding the details of the MMIO access 184 * 185 * @pre vcpu != NULL && io_req != NULL 186 */ 187 int32_t acrn_insert_request(struct acrn_vcpu *vcpu, const struct io_request *io_req); 188 189 /** 190 * @brief Reset all IO requests status of the VM 191 * 192 * @param vm The VM whose IO requests to be reset 193 */ 194 void reset_vm_ioreqs(struct acrn_vm *vm); 195 196 /** 197 * @brief Get the state of an IO request 198 * 199 * @param vm Target VM context 200 * @param vcpu_id VCPU ID of the IO request 201 * 202 * @return State of the IO Request. 203 */ 204 uint32_t get_io_req_state(struct acrn_vm *vm, uint16_t vcpu_id); 205 206 /** 207 * @brief Set the state of IO request 208 * 209 * @param vm Target VM context 210 * @param vcpu_id VCPU ID of the IO request 211 * @param state State to be set 212 */ 213 void set_io_req_state(struct acrn_vm *vm, uint16_t vcpu_id, uint32_t state); 214 215 /** 216 * @brief Set the vector for HV callback HSM 217 * 218 * @param vector vector for HV callback HSM 219 */ 220 void set_hsm_notification_vector(uint32_t vector); 221 222 /** 223 * @brief Get the vector for HV callback HSM 224 * 225 * @return vector for HV callbakc HSM 226 */ 227 uint32_t get_hsm_notification_vector(void); 228 229 /** 230 * @brief Emulate \p io_req for \p vcpu 231 * 232 * Handle an I/O request by either invoking a hypervisor-internal handler or 233 * deliver to HSM. 234 * 235 * @pre vcpu != NULL 236 * @pre vcpu->vm != NULL 237 * @pre vcpu->vm->vm_id < CONFIG_MAX_VM_NUM 238 * 239 * @param vcpu The virtual CPU that triggers the MMIO access 240 * @param io_req The I/O request holding the details of the MMIO access 241 * 242 * @retval 0 Successfully emulated by registered handlers. 243 * @retval IOREQ_PENDING The I/O request is delivered to HSM. 244 * @retval -EIO The request spans multiple devices and cannot be emulated. 245 * @retval -EINVAL \p io_req has an invalid type. 246 * @retval <0 on other errors during emulation. 247 */ 248 int32_t emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req); 249 250 /** 251 * @brief Register a port I/O handler 252 * 253 * @param vm The VM to which the port I/O handlers are registered 254 * @param pio_idx The emulated port io index 255 * @param range The emulated port io range 256 * @param io_read_fn_ptr The handler for emulating reads from the given range 257 * @param io_write_fn_ptr The handler for emulating writes to the given range 258 * @pre pio_idx < EMUL_PIO_IDX_MAX 259 */ 260 void register_pio_emulation_handler(struct acrn_vm *vm, uint32_t pio_idx, 261 const struct vm_io_range *range, io_read_fn_t io_read_fn_ptr, io_write_fn_t io_write_fn_ptr); 262 263 /** 264 * @brief Register a MMIO handler 265 * 266 * This API registers a MMIO handler to \p vm. 267 * 268 * @param vm The VM to which the MMIO handler is registered 269 * @param read_write The handler for emulating accesses to the given range 270 * @param start The base address of the range \p read_write can emulate 271 * @param end The end of the range (exclusive) \p read_write can emulate 272 * @param handler_private_data Handler-specific data which will be passed to \p read_write when called 273 * @param hold_lock Whether hold the lock to handle the MMIO access 274 */ 275 void register_mmio_emulation_handler(struct acrn_vm *vm, 276 hv_mem_io_handler_t read_write, uint64_t start, 277 uint64_t end, void *handler_private_data, bool hold_lock); 278 279 /** 280 * @brief Unregister a MMIO handler 281 * 282 * This API unregisters a MMIO handler to \p vm 283 * 284 * @param vm The VM to which the MMIO handler is unregistered 285 * @param start The base address of the range which wants to unregister 286 * @param end The end of the range (exclusive) which wants to unregister 287 */ 288 void unregister_mmio_emulation_handler(struct acrn_vm *vm, 289 uint64_t start, uint64_t end); 290 void deinit_emul_io(struct acrn_vm *vm); 291 292 int init_asyncio(struct acrn_vm *vm, uint64_t *hva); 293 294 int add_asyncio(struct acrn_vm *vm, const struct acrn_asyncio_info *async_info); 295 296 int remove_asyncio(struct acrn_vm *vm, const struct acrn_asyncio_info *async_info); 297 /** 298 * @} 299 */ 300 301 #endif /* IOREQ_H */ 302