1
2
3
4
5
6
7
8
9
10#ifndef LIBQOS_VIRTIO_H
11#define LIBQOS_VIRTIO_H
12
13#include "libqos/malloc.h"
14#include "standard-headers/linux/virtio_ring.h"
15
16#define QVIRTIO_F_BAD_FEATURE 0x40000000
17
18typedef struct QVirtioDevice {
19
20 uint16_t device_type;
21} QVirtioDevice;
22
23typedef struct QVirtQueue {
24 uint64_t desc;
25 uint64_t avail;
26 uint64_t used;
27 uint16_t index;
28 uint32_t size;
29 uint32_t free_head;
30 uint32_t num_free;
31 uint32_t align;
32 bool indirect;
33 bool event;
34} QVirtQueue;
35
36typedef struct QVRingIndirectDesc {
37 uint64_t desc;
38 uint16_t index;
39 uint16_t elem;
40} QVRingIndirectDesc;
41
42typedef struct QVirtioBus {
43 uint8_t (*config_readb)(QVirtioDevice *d, uint64_t addr);
44 uint16_t (*config_readw)(QVirtioDevice *d, uint64_t addr);
45 uint32_t (*config_readl)(QVirtioDevice *d, uint64_t addr);
46 uint64_t (*config_readq)(QVirtioDevice *d, uint64_t addr);
47
48
49 uint32_t (*get_features)(QVirtioDevice *d);
50
51
52 void (*set_features)(QVirtioDevice *d, uint32_t features);
53
54
55 uint32_t (*get_guest_features)(QVirtioDevice *d);
56
57
58 uint8_t (*get_status)(QVirtioDevice *d);
59
60
61 void (*set_status)(QVirtioDevice *d, uint8_t status);
62
63
64 bool (*get_queue_isr_status)(QVirtioDevice *d, QVirtQueue *vq);
65
66
67 bool (*get_config_isr_status)(QVirtioDevice *d);
68
69
70 void (*queue_select)(QVirtioDevice *d, uint16_t index);
71
72
73 uint16_t (*get_queue_size)(QVirtioDevice *d);
74
75
76 void (*set_queue_address)(QVirtioDevice *d, uint32_t pfn);
77
78
79 QVirtQueue *(*virtqueue_setup)(QVirtioDevice *d, QGuestAllocator *alloc,
80 uint16_t index);
81
82
83 void (*virtqueue_cleanup)(QVirtQueue *vq, QGuestAllocator *alloc);
84
85
86 void (*virtqueue_kick)(QVirtioDevice *d, QVirtQueue *vq);
87} QVirtioBus;
88
89static inline uint32_t qvring_size(uint32_t num, uint32_t align)
90{
91 return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num)
92 + align - 1) & ~(align - 1))
93 + sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num;
94}
95
96uint8_t qvirtio_config_readb(const QVirtioBus *bus, QVirtioDevice *d,
97 uint64_t addr);
98uint16_t qvirtio_config_readw(const QVirtioBus *bus, QVirtioDevice *d,
99 uint64_t addr);
100uint32_t qvirtio_config_readl(const QVirtioBus *bus, QVirtioDevice *d,
101 uint64_t addr);
102uint64_t qvirtio_config_readq(const QVirtioBus *bus, QVirtioDevice *d,
103 uint64_t addr);
104uint32_t qvirtio_get_features(const QVirtioBus *bus, QVirtioDevice *d);
105void qvirtio_set_features(const QVirtioBus *bus, QVirtioDevice *d,
106 uint32_t features);
107
108void qvirtio_reset(const QVirtioBus *bus, QVirtioDevice *d);
109void qvirtio_set_acknowledge(const QVirtioBus *bus, QVirtioDevice *d);
110void qvirtio_set_driver(const QVirtioBus *bus, QVirtioDevice *d);
111void qvirtio_set_driver_ok(const QVirtioBus *bus, QVirtioDevice *d);
112
113void qvirtio_wait_queue_isr(const QVirtioBus *bus, QVirtioDevice *d,
114 QVirtQueue *vq, gint64 timeout_us);
115uint8_t qvirtio_wait_status_byte_no_isr(const QVirtioBus *bus,
116 QVirtioDevice *d,
117 QVirtQueue *vq,
118 uint64_t addr,
119 gint64 timeout_us);
120void qvirtio_wait_config_isr(const QVirtioBus *bus, QVirtioDevice *d,
121 gint64 timeout_us);
122QVirtQueue *qvirtqueue_setup(const QVirtioBus *bus, QVirtioDevice *d,
123 QGuestAllocator *alloc, uint16_t index);
124void qvirtqueue_cleanup(const QVirtioBus *bus, QVirtQueue *vq,
125 QGuestAllocator *alloc);
126
127void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr);
128QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d,
129 QGuestAllocator *alloc, uint16_t elem);
130void qvring_indirect_desc_add(QVRingIndirectDesc *indirect, uint64_t data,
131 uint32_t len, bool write);
132uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
133 bool next);
134uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect);
135void qvirtqueue_kick(const QVirtioBus *bus, QVirtioDevice *d, QVirtQueue *vq,
136 uint32_t free_head);
137
138void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx);
139#endif
140