1 /* $OpenBSD: virtio.h,v 1.38 2021/04/21 18:27:36 dv Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <dev/pv/virtioreg.h> 20 21 #define VIRTQUEUE_ALIGN(n) (((n)+(VIRTIO_PAGE_SIZE-1))& \ 22 ~(VIRTIO_PAGE_SIZE-1)) 23 #define ALIGNSZ(sz, align) ((sz + align - 1) & ~(align - 1)) 24 #define MIN(a,b) (((a)<(b))?(a):(b)) 25 26 /* Queue sizes must be power of two */ 27 #define VIORND_QUEUE_SIZE 64 28 #define VIORND_QUEUE_MASK (VIORND_QUEUE_SIZE - 1) 29 30 #define VIOBLK_QUEUE_SIZE 128 31 #define VIOBLK_QUEUE_MASK (VIOBLK_QUEUE_SIZE - 1) 32 33 #define VIOSCSI_QUEUE_SIZE 128 34 #define VIOSCSI_QUEUE_MASK (VIOSCSI_QUEUE_SIZE - 1) 35 36 #define VIONET_QUEUE_SIZE 256 37 #define VIONET_QUEUE_MASK (VIONET_QUEUE_SIZE - 1) 38 39 /* VMM Control Interface shutdown timeout (in seconds) */ 40 #define VMMCI_TIMEOUT 3 41 #define VMMCI_SHUTDOWN_TIMEOUT 120 42 43 /* All the devices we support have either 1, 2 or 3 queues */ 44 /* viornd - 1 queue 45 * vioblk - 1 queue 46 * vionet - 2 queues 47 * vioscsi - 3 queues 48 */ 49 #define VIRTIO_MAX_QUEUES 3 50 51 /* 52 * This struct stores notifications from a virtio driver. There is 53 * one such struct per virtio device. 54 */ 55 struct virtio_io_cfg { 56 uint32_t device_feature; 57 uint32_t guest_feature; 58 uint32_t queue_address; 59 uint16_t queue_size; 60 uint16_t queue_select; 61 uint16_t queue_notify; 62 uint8_t device_status; 63 uint8_t isr_status; 64 }; 65 66 struct virtio_backing { 67 void *p; 68 ssize_t (*pread)(void *p, char *buf, size_t len, off_t off); 69 ssize_t (*pwrite)(void *p, char *buf, size_t len, off_t off); 70 void (*close)(void *p, int); 71 }; 72 73 /* 74 * A virtio device can have several virtqs. For example, vionet has one virtq 75 * each for transmitting and receiving packets. This struct describes the state 76 * of one virtq, such as their address in memory, size, offsets of rings, etc. 77 * There is one virtio_vq_info per virtq. 78 */ 79 struct virtio_vq_info { 80 /* Guest physical address of virtq */ 81 uint32_t qa; 82 83 /* Queue size: number of queue entries in virtq */ 84 uint32_t qs; 85 86 /* 87 * The offset of the 'available' ring within the virtq located at 88 * guest physical address qa above 89 */ 90 uint32_t vq_availoffset; 91 92 /* 93 * The offset of the 'used' ring within the virtq located at guest 94 * physical address qa above 95 */ 96 uint32_t vq_usedoffset; 97 98 /* 99 * The index into a slot of the 'available' ring that a virtio device 100 * can consume next 101 */ 102 uint16_t last_avail; 103 104 /* 105 * The most recent index into the 'available' ring that a virtio 106 * driver notified to the host. 107 */ 108 uint16_t notified_avail; 109 }; 110 111 /* 112 * Each virtio driver has a notifyq method where one or more messages 113 * are ready to be processed on a given virtq. As such, various 114 * pieces of information are needed to provide ring accounting while 115 * processing a given message such as virtq indexes, vring pointers, and 116 * vring descriptors. 117 */ 118 struct virtio_vq_acct { 119 120 /* index of previous avail vring message */ 121 uint16_t idx; 122 123 /* index of current message containing the request */ 124 uint16_t req_idx; 125 126 /* index of current message containing the response */ 127 uint16_t resp_idx; 128 129 /* vring descriptor pointer */ 130 struct vring_desc *desc; 131 132 /* vring descriptor pointer for request header and data */ 133 struct vring_desc *req_desc; 134 135 /* vring descriptor pointer for response header and data */ 136 struct vring_desc *resp_desc; 137 138 /* pointer to the available vring */ 139 struct vring_avail *avail; 140 141 /* pointer to the used vring */ 142 struct vring_used *used; 143 }; 144 145 struct viornd_dev { 146 struct virtio_io_cfg cfg; 147 148 struct virtio_vq_info vq[VIRTIO_MAX_QUEUES]; 149 150 uint8_t pci_id; 151 int irq; 152 uint32_t vm_id; 153 }; 154 155 struct vioblk_dev { 156 struct virtio_io_cfg cfg; 157 158 struct virtio_vq_info vq[VIRTIO_MAX_QUEUES]; 159 struct virtio_backing file; 160 161 uint64_t sz; 162 uint32_t max_xfer; 163 164 uint8_t pci_id; 165 int irq; 166 uint32_t vm_id; 167 }; 168 169 /* vioscsi will use at least 3 queues - 5.6.2 Virtqueues 170 * Current implementation will use 3 171 * 0 - control 172 * 1 - event 173 * 2 - requests 174 */ 175 struct vioscsi_dev { 176 struct virtio_io_cfg cfg; 177 178 struct virtio_vq_info vq[VIRTIO_MAX_QUEUES]; 179 180 struct virtio_backing file; 181 182 /* is the device locked */ 183 int locked; 184 /* size of iso file in bytes */ 185 uint64_t sz; 186 /* last block address read */ 187 uint64_t lba; 188 /* number of blocks represented in iso */ 189 uint64_t n_blocks; 190 uint32_t max_xfer; 191 192 uint8_t pci_id; 193 uint32_t vm_id; 194 int irq; 195 }; 196 197 struct vionet_dev { 198 pthread_mutex_t mutex; 199 struct event event; 200 201 struct virtio_io_cfg cfg; 202 203 struct virtio_vq_info vq[VIRTIO_MAX_QUEUES]; 204 205 int fd, rx_added; 206 int rx_pending; 207 uint32_t vm_id; 208 uint32_t vm_vmid; 209 int irq; 210 uint8_t mac[6]; 211 uint8_t hostmac[6]; 212 213 int idx; 214 int lockedmac; 215 int local; 216 int pxeboot; 217 218 uint8_t pci_id; 219 }; 220 221 struct virtio_net_hdr { 222 uint8_t flags; 223 uint8_t gso_type; 224 uint16_t hdr_len; 225 uint16_t gso_size; 226 uint16_t csum_start; 227 uint16_t csum_offset; 228 229 /* 230 * num_buffers is only used if VIRTIO_NET_F_MRG_RXBUF is negotiated. 231 * vmd(8) doesn't negotiate that, but the field is listed here 232 * for completeness sake. 233 */ 234 /* uint16_t num_buffers; */ 235 }; 236 237 enum vmmci_cmd { 238 VMMCI_NONE = 0, 239 VMMCI_SHUTDOWN, 240 VMMCI_REBOOT, 241 VMMCI_SYNCRTC, 242 }; 243 244 struct vmmci_dev { 245 struct virtio_io_cfg cfg; 246 struct event timeout; 247 struct timeval time; 248 enum vmmci_cmd cmd; 249 uint32_t vm_id; 250 int irq; 251 252 uint8_t pci_id; 253 }; 254 255 struct ioinfo { 256 struct virtio_backing *file; 257 uint8_t *buf; 258 ssize_t len; 259 off_t offset; 260 int error; 261 }; 262 263 /* virtio.c */ 264 void virtio_init(struct vmd_vm *, int, int[][VM_MAX_BASE_PER_DISK], int *); 265 void virtio_shutdown(struct vmd_vm *); 266 int virtio_dump(int); 267 int virtio_restore(int, struct vmd_vm *, int, 268 int[][VM_MAX_BASE_PER_DISK], int *); 269 uint32_t vring_size(uint32_t); 270 271 int virtio_rnd_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t); 272 int viornd_dump(int); 273 int viornd_restore(int, struct vm_create_params *); 274 void viornd_update_qs(void); 275 void viornd_update_qa(void); 276 int viornd_notifyq(void); 277 278 ssize_t virtio_qcow2_get_base(int, char *, size_t, const char *); 279 int virtio_qcow2_create(const char *, const char *, long); 280 int virtio_qcow2_init(struct virtio_backing *, off_t *, int*, size_t); 281 int virtio_raw_create(const char *, long); 282 int virtio_raw_init(struct virtio_backing *, off_t *, int*, size_t); 283 284 int virtio_blk_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t); 285 int vioblk_dump(int); 286 int vioblk_restore(int, struct vmop_create_params *, 287 int[][VM_MAX_BASE_PER_DISK]); 288 void vioblk_update_qs(struct vioblk_dev *); 289 void vioblk_update_qa(struct vioblk_dev *); 290 int vioblk_notifyq(struct vioblk_dev *); 291 292 int virtio_net_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t); 293 int vionet_dump(int); 294 int vionet_restore(int, struct vmd_vm *, int *); 295 void vionet_update_qs(struct vionet_dev *); 296 void vionet_update_qa(struct vionet_dev *); 297 int vionet_notifyq(struct vionet_dev *); 298 void vionet_notify_rx(struct vionet_dev *); 299 int vionet_notify_tx(struct vionet_dev *); 300 void vionet_process_rx(uint32_t); 301 int vionet_enq_rx(struct vionet_dev *, char *, size_t, int *); 302 void vionet_set_hostmac(struct vmd_vm *, unsigned int, uint8_t *); 303 304 int vmmci_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t); 305 int vmmci_dump(int); 306 int vmmci_restore(int, uint32_t); 307 int vmmci_ctl(unsigned int); 308 void vmmci_ack(unsigned int); 309 void vmmci_timeout(int, short, void *); 310 311 const char *vioblk_cmd_name(uint32_t); 312 int vioscsi_dump(int); 313 int vioscsi_restore(int, struct vm_create_params *, int); 314 315 /* dhcp.c */ 316 ssize_t dhcp_request(struct vionet_dev *, char *, size_t, char **); 317 318 /* vioscsi.c */ 319 int vioscsi_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t); 320 void vioscsi_update_qs(struct vioscsi_dev *); 321 void vioscsi_update_qa(struct vioscsi_dev *); 322 int vioscsi_notifyq(struct vioscsi_dev *); 323 void virtio_stop(struct vm_create_params *vcp); 324 void virtio_start(struct vm_create_params *vcp); 325