iPXE
virtio.h
Go to the documentation of this file.
1#ifndef _IPXE_VIRTIO_H
2#define _IPXE_VIRTIO_H
3
4/** @file
5 *
6 * Virtual I/O device
7 *
8 */
9
10FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11FILE_SECBOOT ( PERMITTED );
12
13#include <stdint.h>
14#include <byteswap.h>
15#include <ipxe/dma.h>
16#include <ipxe/pci.h>
17
18/** Virtio page alignment */
19#define VIRTIO_PAGE 4096
20
21/** Maximum time to wait for reset (in ms) */
22#define VIRTIO_RESET_MAX_WAIT_MS 100
23
24/**
25 * @defgroup virtio_legacy Original ("legacy") common device registers
26 * @{
27 */
28
29/** Legacy device supported features register */
30#define VIRTIO_LEG_FEAT 0x00
31
32/** Legacy negotiated in-use features register */
33#define VIRTIO_LEG_USED 0x04
34
35/** Legacy queue base address register */
36#define VIRTIO_LEG_BASE 0x08
37
38/** Legacy queue size register */
39#define VIRTIO_LEG_SIZE 0x0c
40
41/** Legacy queue select register */
42#define VIRTIO_LEG_SEL 0x0e
43
44/** Legacy queue doorbell notification register */
45#define VIRTIO_LEG_DB 0x10
46
47/** Legacy driver status register */
48#define VIRTIO_LEG_STAT 0x12
49#define VIRTIO_STAT_ACKNOWLEDGE 0x0001 /**< Guest has found device */
50#define VIRTIO_STAT_DRIVER 0x0002 /**< Guest driver exists */
51#define VIRTIO_STAT_DRIVER_OK 0x0004 /**< Guest driver is ready */
52#define VIRTIO_STAT_FEATURES_OK 0x0008 /**< Guest driver has set features */
53#define VIRTIO_STAT_FAIL 0x0080 /**< Guest driver has failed */
54
55/** Legacy device-specific registers */
56#define VIRTIO_LEG_DEV 0x14
57
58/** Legacy device-specific register (if MSI-X is enabled) */
59#define VIRTIO_LEG_DEV_MSIX 0x18
60
61/** @} */
62
63/**
64 * @defgroup virtio_pci_cap PCI capability registers
65 * @{
66 */
67
68/** Capability type */
69#define VIRTIO_PCI_CAP_TYPE 0x03
70#define VIRTIO_PCI_CAP_TYPE_COMMON 0x01 /**< Common registers */
71#define VIRTIO_PCI_CAP_TYPE_NOTIFY 0x02 /**< Notification doorbells */
72#define VIRTIO_PCI_CAP_TYPE_DEVICE 0x04 /**< Device-specific registers */
73
74/** Capability BAR index */
75#define VIRTIO_PCI_CAP_BAR 0x04
76
77/** Capability BAR offset */
78#define VIRTIO_PCI_CAP_OFFSET 0x08
79
80/** Capability minimum length */
81#define VIRTIO_PCI_CAP_END 0x10
82
83/** Notification doorbell capability multiplier offset */
84#define VIRTIO_PCI_CAP_NOTIFY_MULT 0x10
85
86/** Notification doorbell capability minimum length */
87#define VIRTIO_PCI_CAP_NOTIFY_END 0x14
88
89/** @} */
90
91/** A virtio PCI capability */
93 /** Capability type */
95 /** Capability offset */
97 /** Capability length */
99 /** BAR number */
101 /** Offset within BAR */
103};
104
105/**
106 * @defgroup virtio_pci_common PCI common device registers
107 * @{
108 */
109
110/** PCI device supported features select register */
111#define VIRTIO_PCI_FEAT_SEL 0x00
112
113/** PCI device supported features register */
114#define VIRTIO_PCI_FEAT 0x04
115
116/** PCI negotiated in-use features select register */
117#define VIRTIO_PCI_USED_SEL 0x08
118
119/** PCI negotiated in-use features register */
120#define VIRTIO_PCI_USED 0x0c
121
122/** PCI device status register */
123#define VIRTIO_PCI_STAT 0x14
124
125/** PCI configuration generation register */
126#define VIRTIO_PCI_GEN 0x15
127
128/** PCI queue select register */
129#define VIRTIO_PCI_SEL 0x16
130
131/** PCI queue size register */
132#define VIRTIO_PCI_SIZE 0x18
133
134/** PCI queue enable register */
135#define VIRTIO_PCI_ENABLE 0x1c
136
137/** PCI queue doorbell notification offset register */
138#define VIRTIO_PCI_DBOFF 0x1e
139
140/** PCI queue descriptor array base address register */
141#define VIRTIO_PCI_DESC 0x20
142
143/** PCI queue submission queue base address register */
144#define VIRTIO_PCI_SQ 0x28
145
146/** PCI queue completion queue base address register */
147#define VIRTIO_PCI_CQ 0x30
148
149/** @} */
150
151/** A virtio buffer descriptor */
153 /** Buffer address */
155 /** Buffer length */
157 /** Flags */
159 /** Next descriptor index */
161} __attribute__ (( packed ));
162
163/** Next descriptor index is valid */
164#define VIRTIO_DESC_FL_NEXT 0x0001
165
166/** Buffer is write-only */
167#define VIRTIO_DESC_FL_WRITE 0x0002
168
169/** A virtio submission queue entry */
171 /** Starting descriptor index */
173} __attribute__ (( packed ));
174
175/** A virtio submission ("available") queue */
176struct virtio_sq {
177 /** Flags */
179 /** Producer index */
181 /** Queue entries */
182 struct virtio_sqe sqe[];
183} __attribute__ (( packed ));
184
185/** Do not generate interrupt */
186#define VIRTIO_SQ_FL_NO_INTERRUPT 0x0001
187
188/** A virtio completion queue entry */
190 /** Starting descriptor index */
192 /** Length written */
194} __attribute__ (( packed ));
195
196/** A virtio completion ("used") queue */
197struct virtio_cq {
198 /** Flags */
200 /** Producer index */
202 /** Queue entries */
203 struct virtio_cqe cqe[];
204} __attribute__ (( packed ));
205
206/** A virtio queue */
208 /** Queue index */
209 unsigned int index;
210 /** Queue size (must be a power of two) */
211 unsigned int count;
212 /** Queue mask */
213 unsigned int mask;
214 /** Submission queue producer index */
215 unsigned int prod;
216 /** Completion queue consumer index */
217 unsigned int cons;
218 /** Total length of queue */
219 size_t len;
220 /** DMA mapping */
222 /** Descriptor array (and start of DMA allocation) */
224 /** Submission queue */
225 struct virtio_sq *sq;
226 /** Completion queue */
227 struct virtio_cq *cq;
228 /** Notification doorbell */
229 void *db;
230};
231
232/**
233 * Initialise virtio queue
234 *
235 * @v queue Virtio queue
236 * @v index Queue index
237 */
238static inline __attribute__ (( always_inline )) void
239virtio_queue_init ( struct virtio_queue *queue, unsigned int index ) {
240
241 queue->index = index;
242}
243
244/**
245 * Calculate aligned size
246 *
247 * @v size Unaligned size
248 * @ret size Aligned size
249 */
250static inline __attribute__ (( always_inline )) size_t
251virtio_align ( size_t size ) {
252
253 return ( ( size + VIRTIO_PAGE - 1 ) & ~( VIRTIO_PAGE - 1 ) );
254}
255
256/**
257 * Calculate (unaligned) descriptor array size
258 *
259 * @v queue Virtio queue
260 * @v count Queue size
261 */
262static inline __attribute__ (( always_inline )) size_t
263virtio_desc_size ( unsigned int count ) {
264 struct virtio_desc *desc;
265
266 return ( count * sizeof ( desc[0] ) );
267}
268
269/**
270 * Calculate (unaligned) submission queue size
271 *
272 * @v queue Virtio queue
273 * @v count Queue size
274 */
275static inline __attribute__ (( always_inline )) size_t
276virtio_sq_size ( unsigned int count ) {
277 struct virtio_sq *sq;
278
279 return ( sizeof ( *sq ) + ( count * sizeof ( sq->sqe[0] ) ) );
280}
281
282/**
283 * Calculate (unaligned) completion queue size
284 *
285 * @v queue Virtio queue
286 * @v count Queue size
287 */
288static inline __attribute__ (( always_inline )) size_t
289virtio_cq_size ( unsigned int count ) {
290 struct virtio_cq *cq;
291
292 return ( sizeof ( *cq ) + ( count * sizeof ( cq->cqe[0] ) ) );
293}
294
295/** Number of 32-bit feature words */
296#define VIRTIO_FEATURE_WORDS 2
297
298/** A virtio feature set */
300 /** Feature words */
302};
303
304/** Arbitrary descriptor layouts may be used */
305#define VIRTIO_FEAT0_ANY_LAYOUT 0x08000000
306
307/** Virtio version 1.0 or above */
308#define VIRTIO_FEAT1_MODERN 0x00000001
309
310/** A virtio device */
312 /** Device name */
313 const char *name;
314 /** Device operations */
316 /** DMA device */
318 /** Common registers */
319 void *common;
320 /** Doorbell notification registers */
321 void *notify;
322 /** Device-specific registers */
323 void *device;
324 /** Driver status */
325 unsigned int stat;
326 /** Device supported features */
328 /** Negotiated features */
330 /** Notification doorbell multiplier */
331 unsigned int multiplier;
332};
333
334/** Virtio device operations */
336 /**
337 * Reset device
338 *
339 * @v virtio Virtio device
340 * @ret rc Return status code
341 */
342 int ( * reset ) ( struct virtio_device *virtio );
343 /**
344 * Report driver status
345 *
346 * @v virtio Virtio device
347 * @ret stat Actual device status
348 */
349 unsigned int ( * status ) ( struct virtio_device *virtio );
350 /**
351 * Get supported features
352 *
353 * @v virtio Virtio device
354 */
355 void ( * supported ) ( struct virtio_device *virtio );
356 /**
357 * Set negotiated features
358 *
359 * @v virtio Virtio device
360 */
361 void ( * negotiate ) ( struct virtio_device *virtio );
362 /**
363 * Set queue size
364 *
365 * @v virtio Virtio device
366 * @v queue Virtio queue
367 * @v count Requested size
368 */
369 void ( * size ) ( struct virtio_device *virtio,
370 struct virtio_queue *queue, unsigned int count );
371 /**
372 * Enable queue
373 *
374 * @v virtio Virtio device
375 * @v queue Virtio queue
376 */
377 void ( * enable ) ( struct virtio_device *virtio,
378 struct virtio_queue *queue );
379};
380
381/**
382 * Submit descriptor(s) to queue
383 *
384 * @v queue Virtio queue
385 * @v index Starting descriptor index
386 */
387static inline __attribute__ (( always_inline )) void
388virtio_submit ( struct virtio_queue *queue, unsigned int index ) {
389 struct virtio_sqe *sqe;
390
391 /* Get next submission queue entry */
392 sqe = &queue->sq->sqe[ queue->prod++ & queue->mask ];
393
394 /* Populate submission queue entry */
395 sqe->index = cpu_to_le16 ( index );
396}
397
398/**
399 * Notify queue
400 *
401 * @v queue Virtio queue
402 */
403static inline __attribute__ (( always_inline )) void
405
406 /* Write producer index */
407 wmb();
408 queue->sq->prod = cpu_to_le16 ( queue->prod );
409 wmb();
410
411 /* Ring doorbell */
412 iowrite16 ( queue->index, queue->db );
413}
414
415/**
416 * Check for completed descriptors
417 *
418 * @v queue Virtio queue
419 * @v completions Number of pending completions
420 */
421static inline __attribute__ (( always_inline )) unsigned int
423 uint16_t completions;
424
425 /* Get completion count */
426 completions = ( le16_to_cpu ( queue->cq->prod ) - queue->cons );
427 return completions;
428}
429
430/**
431 * Complete descriptor(s)
432 *
433 * @v queue Virtio queue
434 * @v len Length to fill in, or NULL
435 * @ret index Starting descriptor index
436 */
437static inline __attribute__ (( always_inline )) unsigned int
438virtio_complete ( struct virtio_queue *queue, size_t *len ) {
439 struct virtio_cqe *cqe;
440
441 /* Get next completion queue entry */
442 cqe = &queue->cq->cqe[ queue->cons++ & queue->mask ];
443
444 /* Parse completion queue entry */
445 if ( len )
446 *len = le32_to_cpu ( cqe->len );
447 return le32_to_cpu ( cqe->index );
448}
449
450/**
451 * Check if device is using the legacy interface
452 *
453 * @v virtio Virtio device
454 * @ret is_legacy Device is using the legacy interface
455 */
456static inline __attribute__ (( always_inline )) int
457virtio_is_legacy ( struct virtio_device *virtio ) {
458
459 /* Check negotiation of version 1.0 or above */
460 return ( ! ( virtio->features.word[1] & VIRTIO_FEAT1_MODERN ) );
461}
462
463extern int virtio_pci_map ( struct virtio_device *virtio,
464 struct pci_device *pci );
465extern int virtio_reset ( struct virtio_device *virtio );
466extern unsigned int virtio_status ( struct virtio_device *virtio,
467 unsigned int stat );
468extern int virtio_init ( struct virtio_device *virtio,
469 const struct virtio_features *driver );
470extern int virtio_enable ( struct virtio_device *virtio,
471 struct virtio_queue *queue, unsigned int count );
472extern void virtio_free ( struct virtio_device *virtio,
473 struct virtio_queue *queue );
474extern void virtio_unmap ( struct virtio_device *virtio );
475
476#endif /* _IPXE_VIRTIO_H */
unsigned short uint16_t
Definition stdint.h:11
unsigned int uint32_t
Definition stdint.h:12
unsigned long long uint64_t
Definition stdint.h:13
unsigned char uint8_t
Definition stdint.h:10
long index
Definition bigint.h:30
uint32_t stat
Completion status.
Definition dwmac.h:1
ring len
Length.
Definition dwmac.h:226
struct ena_tx_sqe sqe
Transmit descriptor.
Definition ena.h:3
uint16_t queue
Queue ID.
Definition ena.h:11
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
uint16_t size
Buffer size.
Definition dwmac.h:3
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
#define le16_to_cpu(value)
Definition byteswap.h:113
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le16(value)
Definition byteswap.h:107
#define __attribute__(x)
Definition compiler.h:10
#define wmb()
Definition io.h:546
#define iowrite16(data, io_addr)
Definition io.h:380
DMA mappings.
PCI bus.
A DMA-capable device.
Definition dma.h:48
A DMA mapping.
Definition dma.h:33
A PCI device.
Definition pci.h:214
A virtio completion ("used") queue.
Definition virtio.h:197
struct virtio_cqe cqe[]
Queue entries.
Definition virtio.h:203
uint16_t prod
Producer index.
Definition virtio.h:201
uint16_t flags
Flags.
Definition virtio.h:199
A virtio completion queue entry.
Definition virtio.h:189
uint32_t index
Starting descriptor index.
Definition virtio.h:191
uint32_t len
Length written.
Definition virtio.h:193
A virtio buffer descriptor.
Definition virtio.h:152
uint16_t next
Next descriptor index.
Definition virtio.h:160
uint32_t len
Buffer length.
Definition virtio.h:156
uint64_t addr
Buffer address.
Definition virtio.h:154
uint16_t flags
Flags.
Definition virtio.h:158
A virtio device.
Definition virtio.h:311
struct virtio_features features
Negotiated features.
Definition virtio.h:329
const char * name
Device name.
Definition virtio.h:313
unsigned int multiplier
Notification doorbell multiplier.
Definition virtio.h:331
void * notify
Doorbell notification registers.
Definition virtio.h:321
void * common
Common registers.
Definition virtio.h:319
void * device
Device-specific registers.
Definition virtio.h:323
struct virtio_operations * op
Device operations.
Definition virtio.h:315
struct dma_device * dma
DMA device.
Definition virtio.h:317
unsigned int stat
Driver status.
Definition virtio.h:325
struct virtio_features supported
Device supported features.
Definition virtio.h:327
A virtio feature set.
Definition virtio.h:299
uint32_t word[VIRTIO_FEATURE_WORDS]
Feature words.
Definition virtio.h:301
Virtio device operations.
Definition virtio.h:335
void(* negotiate)(struct virtio_device *virtio)
Set negotiated features.
Definition virtio.h:361
void(* enable)(struct virtio_device *virtio, struct virtio_queue *queue)
Enable queue.
Definition virtio.h:377
void(* supported)(struct virtio_device *virtio)
Get supported features.
Definition virtio.h:355
int(* reset)(struct virtio_device *virtio)
Reset device.
Definition virtio.h:342
unsigned int(* status)(struct virtio_device *virtio)
Report driver status.
Definition virtio.h:349
void(* size)(struct virtio_device *virtio, struct virtio_queue *queue, unsigned int count)
Set queue size.
Definition virtio.h:369
A virtio PCI capability.
Definition virtio.h:92
uint32_t offset
Offset within BAR.
Definition virtio.h:102
uint8_t type
Capability type.
Definition virtio.h:94
uint8_t len
Capability length.
Definition virtio.h:98
uint8_t pos
Capability offset.
Definition virtio.h:96
uint8_t bar
BAR number.
Definition virtio.h:100
A virtio queue.
Definition virtio.h:207
unsigned int mask
Queue mask.
Definition virtio.h:213
struct virtio_sq * sq
Submission queue.
Definition virtio.h:225
struct virtio_cq * cq
Completion queue.
Definition virtio.h:227
unsigned int cons
Completion queue consumer index.
Definition virtio.h:217
struct dma_mapping map
DMA mapping.
Definition virtio.h:221
unsigned int prod
Submission queue producer index.
Definition virtio.h:215
struct virtio_desc * desc
Descriptor array (and start of DMA allocation).
Definition virtio.h:223
size_t len
Total length of queue.
Definition virtio.h:219
unsigned int index
Queue index.
Definition virtio.h:209
unsigned int count
Queue size (must be a power of two).
Definition virtio.h:211
void * db
Notification doorbell.
Definition virtio.h:229
A virtio submission ("available") queue.
Definition virtio.h:176
uint16_t flags
Flags.
Definition virtio.h:178
uint16_t prod
Producer index.
Definition virtio.h:180
struct virtio_sqe sqe[]
Queue entries.
Definition virtio.h:182
A virtio submission queue entry.
Definition virtio.h:170
uint16_t index
Starting descriptor index.
Definition virtio.h:172
static void virtio_notify(struct virtio_queue *queue)
Notify queue.
Definition virtio.h:404
static void virtio_queue_init(struct virtio_queue *queue, unsigned int index)
Initialise virtio queue.
Definition virtio.h:239
#define VIRTIO_FEATURE_WORDS
Number of 32-bit feature words.
Definition virtio.h:296
int virtio_init(struct virtio_device *virtio, const struct virtio_features *driver)
Initialise device.
Definition virtio.c:650
#define VIRTIO_FEAT1_MODERN
Virtio version 1.0 or above.
Definition virtio.h:308
unsigned int virtio_status(struct virtio_device *virtio, unsigned int stat)
Report driver status.
Definition virtio.c:603
int virtio_enable(struct virtio_device *virtio, struct virtio_queue *queue, unsigned int count)
Enable queue.
Definition virtio.c:696
static unsigned int virtio_completions(struct virtio_queue *queue)
Check for completed descriptors.
Definition virtio.h:422
int virtio_reset(struct virtio_device *virtio)
Reset device.
Definition virtio.c:580
static int virtio_is_legacy(struct virtio_device *virtio)
Check if device is using the legacy interface.
Definition virtio.h:457
static void virtio_submit(struct virtio_queue *queue, unsigned int index)
Submit descriptor(s) to queue.
Definition virtio.h:388
static unsigned int virtio_complete(struct virtio_queue *queue, size_t *len)
Complete descriptor(s).
Definition virtio.h:438
static size_t virtio_align(size_t size)
Calculate aligned size.
Definition virtio.h:251
void virtio_free(struct virtio_device *virtio, struct virtio_queue *queue)
Free queue.
Definition virtio.c:764
static size_t virtio_cq_size(unsigned int count)
Calculate (unaligned) completion queue size.
Definition virtio.h:289
void virtio_unmap(struct virtio_device *virtio)
Unmap device.
Definition virtio.c:780
static size_t virtio_sq_size(unsigned int count)
Calculate (unaligned) submission queue size.
Definition virtio.h:276
static size_t virtio_desc_size(unsigned int count)
Calculate (unaligned) descriptor array size.
Definition virtio.h:263
#define VIRTIO_PAGE
Virtio page alignment.
Definition virtio.h:19
int virtio_pci_map(struct virtio_device *virtio, struct pci_device *pci)
Map PCI device.
Definition virtio.c:479