1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2013 Chris Torek <torek @ torek net> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 /* 29 * This file and its contents are supplied under the terms of the 30 * Common Development and Distribution License ("CDDL"), version 1.0. 31 * You may only use this file in accordance with the terms of version 32 * 1.0 of the CDDL. 33 * 34 * A full copy of the text of the CDDL should have accompanied this 35 * source. A copy of the CDDL is also available via the Internet at 36 * http://www.illumos.org/license/CDDL. 37 */ 38 /* This file is dual-licensed; see usr/src/contrib/bhyve/LICENSE */ 39 40 /* 41 * Copyright 2025 Oxide Computer Company 42 */ 43 44 #ifndef _BHYVE_COMPAT_VIRTIO_H_ 45 #define _BHYVE_COMPAT_VIRTIO_H_ 46 47 #include <stddef.h> 48 49 #define VIRTIO_PCI_DEVICEID_MODERN_MIN 0x1040 50 51 #define VRING_DESC_F_NEXT (1 << 0) 52 #define VRING_DESC_F_WRITE (1 << 1) 53 #define VRING_DESC_F_INDIRECT (1 << 2) 54 55 struct vring_desc { 56 uint64_t addr; /* guest physical address */ 57 uint32_t len; /* length of scatter/gather seg */ 58 uint16_t flags; /* VRING_F_DESC_* */ 59 uint16_t next; /* next desc if F_NEXT */ 60 } __packed; 61 62 struct vring_used_elem { 63 uint32_t id; /* head of used descriptor chain */ 64 uint32_t len; /* length written-to */ 65 } __packed; 66 67 #define VRING_AVAIL_F_NO_INTERRUPT 1 68 69 struct vring_avail { 70 uint16_t flags; /* VRING_AVAIL_F_* */ 71 uint16_t idx; /* counts to 65535, then cycles */ 72 uint16_t ring[]; /* size N, reported in QNUM value */ 73 /* uint16_t used_event; -- after N ring entries */ 74 } __packed; 75 76 #define VRING_USED_F_NO_NOTIFY 1 77 struct vring_used { 78 uint16_t flags; /* VRING_USED_F_* */ 79 uint16_t idx; /* counts to 65535, then cycles */ 80 struct vring_used_elem ring[]; /* size N */ 81 /* uint16_t avail_event; -- after N ring entries */ 82 } __packed; 83 84 /* 85 * Virtio device types 86 */ 87 #define VIRTIO_ID_NETWORK 1 88 #define VIRTIO_ID_BLOCK 2 89 #define VIRTIO_ID_CONSOLE 3 90 #define VIRTIO_ID_ENTROPY 4 91 #define VIRTIO_ID_BALLOON 5 92 #define VIRTIO_ID_IOMEMORY 6 93 #define VIRTIO_ID_RPMSG 7 94 #define VIRTIO_ID_SCSI 8 95 #define VIRTIO_ID_9P 9 96 97 /* experimental IDs start at 65535 and work down */ 98 99 /* 100 * PCI config space constants. 101 * 102 * If MSI-X is enabled, the ISR register is generally not used, 103 * and the configuration vector and queue vector appear at offsets 104 * 20 and 22 with the remaining configuration registers at 24. 105 * If MSI-X is not enabled, those two registers disappear and 106 * the remaining configuration registers start at offset 20. 107 */ 108 #define VIRTIO_PCI_HOST_FEATURES 0 109 #define VIRTIO_PCI_GUEST_FEATURES 4 110 #define VIRTIO_PCI_QUEUE_PFN 8 111 #define VIRTIO_PCI_QUEUE_NUM 12 112 #define VIRTIO_PCI_QUEUE_SEL 14 113 #define VIRTIO_PCI_QUEUE_NOTIFY 16 114 #define VIRTIO_PCI_STATUS 18 115 #define VIRTIO_PCI_ISR 19 116 #define VIRTIO_MSI_CONFIG_VECTOR 20 117 #define VIRTIO_MSI_QUEUE_VECTOR 22 118 #define VIRTIO_PCI_CONFIG_OFF(msix_enabled) ((msix_enabled) ? 24 : 20) 119 120 /* 121 * Bits in VTCFG_R_STATUS. Guests need not actually set any of these, 122 * but a guest writing 0 to this register means "please reset". 123 */ 124 #define VTCFG_STATUS_ACK 0x01 /* guest OS has acknowledged dev */ 125 #define VTCFG_STATUS_DRIVER 0x02 /* guest OS driver is loaded */ 126 #define VTCFG_STATUS_DRIVER_OK 0x04 /* guest OS driver ready */ 127 #define VTCFG_STATUS_FEAT_OK 0x08 /* driver finished cfg features */ 128 #define VTCFG_STATUS_NEEDS_RST 0x40 /* device needs reset */ 129 #define VTCFG_STATUS_FAILED 0x80 /* guest has given up on this dev */ 130 131 #define VIRTIO_CONFIG_STATUS_DRIVER_OK VTCFG_STATUS_DRIVER_OK 132 #define VIRTIO_CONFIG_S_FEATURES_OK VTCFG_STATUS_FEAT_OK 133 134 /* 135 * Bits in VTCFG_R_ISR. These apply only if not using MSI-X. 136 */ 137 /* The bit of the ISR which indicates a device has an interrupt. */ 138 #define VIRTIO_PCI_ISR_INTR 0x01 139 /* The bit of the ISR which indicates a device configuration change. */ 140 #define VIRTIO_PCI_ISR_CONFIG 0x02 141 142 #define VIRTIO_MSI_NO_VECTOR 0xFFFF 143 144 /* 145 * Feature flags. 146 * Note: bits 0 through 23 are reserved to each device type. 147 */ 148 #define VIRTIO_F_NOTIFY_ON_EMPTY (1ULL << 24) 149 #define VIRTIO_F_ANY_LAYOUT (1ULL << 27) 150 #define VIRTIO_RING_F_INDIRECT_DESC (1ULL << 28) 151 #define VIRTIO_RING_F_EVENT_IDX (1ULL << 29) 152 #define VIRTIO_F_BAD_FEATURE (1ULL << 30) 153 #define VIRTIO_F_VERSION_1 (1ULL << 32) 154 155 static inline int 156 vring_size(unsigned int num, unsigned long align) 157 { 158 int size; 159 160 size = num * sizeof(struct vring_desc); 161 size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)) + 162 sizeof(uint16_t); 163 size = (size + align - 1) & ~(align - 1); 164 size += sizeof(struct vring_used) + 165 (num * sizeof(struct vring_used_elem)) + sizeof(uint16_t); 166 return (size); 167 } 168 169 #define VIRTIO_PCI_CAP_COMMON_CFG 1 170 #define VIRTIO_PCI_CAP_NOTIFY_CFG 2 171 #define VIRTIO_PCI_CAP_ISR_CFG 3 172 #define VIRTIO_PCI_CAP_DEVICE_CFG 4 173 #define VIRTIO_PCI_CAP_PCI_CFG 5 174 #define VIRTIO_PCI_CAP_MAX VIRTIO_PCI_CAP_PCI_CFG 175 176 /* 177 * Alignment requirements for the BAR regions pointed to by each capability. 178 * Note that some have multiple alignment requirements based on negotiated 179 * features and for those we choose the larger value. There are no alignment 180 * requirements for VIRTIO_PCI_CAP_PCI_CFG as it does not point to a fixed BAR 181 * area. 182 */ 183 #define VIRTIO_PCI_CAP_COMMON_CFG_ALIGN 4 184 #define VIRTIO_PCI_CAP_NOTIFY_CFG_ALIGN 4 185 #define VIRTIO_PCI_CAP_ISR_CFG_ALIGN 1 186 #define VIRTIO_PCI_CAP_DEVICE_CFG_ALIGN 4 187 188 189 /* This is the PCI capability header: */ 190 typedef struct virtio_pci_cap { 191 uint8_t cap_vndr; 192 uint8_t cap_next; 193 uint8_t cap_len; 194 uint8_t cfg_type; 195 uint8_t bar; 196 uint8_t id; 197 uint8_t padding[2]; 198 uint32_t offset; 199 uint32_t length; 200 } virtio_pci_cap_t; 201 202 typedef struct virtio_pci_notify_cap { 203 struct virtio_pci_cap cap; 204 uint32_t notify_off_multiplier; 205 } virtio_pci_notify_cap_t; 206 207 /* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */ 208 typedef struct virtio_pci_common_cfg { 209 /* About the whole device. */ 210 uint32_t device_feature_select; /* read-write */ 211 uint32_t device_feature; /* read-only */ 212 uint32_t driver_feature_select; /* read-write */ 213 uint32_t driver_feature; /* read-write */ 214 uint16_t msix_config; /* read-write */ 215 uint16_t num_queues; /* read-only */ 216 uint8_t device_status; /* read-write */ 217 uint8_t config_generation; /* read-only */ 218 219 /* About a specific virtqueue. */ 220 uint16_t queue_select; /* read-write */ 221 uint16_t queue_size; /* read-write */ 222 uint16_t queue_msix_vector; /* read-write */ 223 uint16_t queue_enable; /* read-write */ 224 uint16_t queue_notify_off; /* read-only */ 225 uint32_t queue_desc_lo; /* read-write */ 226 uint32_t queue_desc_hi; /* read-write */ 227 uint32_t queue_avail_lo; /* read-write */ 228 uint32_t queue_avail_hi; /* read-write */ 229 uint32_t queue_used_lo; /* read-write */ 230 uint32_t queue_used_hi; /* read-write */ 231 } virtio_pci_common_cfg_t; 232 233 /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */ 234 typedef struct virtio_pci_cfg_cap { 235 struct virtio_pci_cap cap; 236 uint8_t pci_cfg_data[4]; /* Data for BAR access. */ 237 } virtio_pci_cfg_cap_t; 238 239 /* Macro versions of offsets */ 240 241 #define __VPCO(x) offsetof(virtio_pci_cap_t, x) 242 #define VIRTIO_PCI_CAP_VNDR __VPCO(cap_vndr) 243 #define VIRTIO_PCI_CAP_NEXT __VPCO(cap_next) 244 #define VIRTIO_PCI_CAP_LEN __VPCO(cap_len) 245 #define VIRTIO_PCI_CAP_CFG_TYPE __VPCO(cfg_type) 246 #define VIRTIO_PCI_CAP_BAR __VPCO(bar) 247 #define VIRTIO_PCI_CAP_ID __VPCO(id) 248 #define VIRTIO_PCI_CAP_OFFSET __VPCO(offset) 249 #define VIRTIO_PCI_CAP_LENGTH __VPCO(length) 250 251 #define V__VPNCO(x) offsetof(virtio_pci_notify_cap_t, x) 252 #define VIRTIO_PCI_NOTIFY_CAP_MULT V__VPNCO(notify_off_multiplier) 253 254 #define __VPCCO(x) offsetof(virtio_pci_common_cfg_t, x) 255 #define VIRTIO_PCI_COMMON_DFSELECT __VPCCO(device_feature_select) 256 #define VIRTIO_PCI_COMMON_DF __VPCCO(device_feature) 257 #define VIRTIO_PCI_COMMON_GFSELECT __VPCCO(driver_feature_select) 258 #define VIRTIO_PCI_COMMON_GF __VPCCO(driver_feature) 259 #define VIRTIO_PCI_COMMON_MSIX __VPCCO(msix_config) 260 #define VIRTIO_PCI_COMMON_NUMQ __VPCCO(num_queues) 261 #define VIRTIO_PCI_COMMON_STATUS __VPCCO(device_status) 262 #define VIRTIO_PCI_COMMON_CFGGENERATION __VPCCO(config_generation) 263 #define VIRTIO_PCI_COMMON_Q_SELECT __VPCCO(queue_select) 264 #define VIRTIO_PCI_COMMON_Q_SIZE __VPCCO(queue_size) 265 #define VIRTIO_PCI_COMMON_Q_MSIX __VPCCO(queue_msix_vector) 266 #define VIRTIO_PCI_COMMON_Q_ENABLE __VPCCO(queue_enable) 267 #define VIRTIO_PCI_COMMON_Q_NOFF __VPCCO(queue_notify_off) 268 #define VIRTIO_PCI_COMMON_Q_DESCLO __VPCCO(queue_desc_lo) 269 #define VIRTIO_PCI_COMMON_Q_DESCHI __VPCCO(queue_desc_hi) 270 #define VIRTIO_PCI_COMMON_Q_AVAILLO __VPCCO(queue_avail_lo) 271 #define VIRTIO_PCI_COMMON_Q_AVAILHI __VPCCO(queue_avail_hi) 272 #define VIRTIO_PCI_COMMON_Q_USEDLO __VPCCO(queue_used_lo) 273 #define VIRTIO_PCI_COMMON_Q_USEDHI __VPCCO(queue_used_hi) 274 275 #endif /* _BHYVE_COMPAT_VIRTIO_H_ */ 276