xref: /illumos-gate/usr/src/compat/bhyve/dev/virtio/virtio.h (revision c3b97060722accbd08cd9eb3f18cc189b2c07b5e)
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