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
vring_size(unsigned int num,unsigned long align)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