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 QVirtioBus QVirtioBus;
19
20typedef struct QVirtioDevice {
21 const QVirtioBus *bus;
22
23 uint16_t device_type;
24} QVirtioDevice;
25
26typedef struct QVirtQueue {
27 uint64_t desc;
28 uint64_t avail;
29 uint64_t used;
30 uint16_t index;
31 uint32_t size;
32 uint32_t free_head;
33 uint32_t num_free;
34 uint32_t align;
35 uint16_t last_used_idx;
36 bool indirect;
37 bool event;
38} QVirtQueue;
39
40typedef struct QVRingIndirectDesc {
41 uint64_t desc;
42 uint16_t index;
43 uint16_t elem;
44} QVRingIndirectDesc;
45
46struct QVirtioBus {
47 uint8_t (*config_readb)(QVirtioDevice *d, uint64_t addr);
48 uint16_t (*config_readw)(QVirtioDevice *d, uint64_t addr);
49 uint32_t (*config_readl)(QVirtioDevice *d, uint64_t addr);
50 uint64_t (*config_readq)(QVirtioDevice *d, uint64_t addr);
51
52
53 uint32_t (*get_features)(QVirtioDevice *d);
54
55
56 void (*set_features)(QVirtioDevice *d, uint32_t features);
57
58
59 uint32_t (*get_guest_features)(QVirtioDevice *d);
60
61
62 uint8_t (*get_status)(QVirtioDevice *d);
63
64
65 void (*set_status)(QVirtioDevice *d, uint8_t status);
66
67
68 bool (*get_queue_isr_status)(QVirtioDevice *d, QVirtQueue *vq);
69
70
71 bool (*get_config_isr_status)(QVirtioDevice *d);
72
73
74 void (*queue_select)(QVirtioDevice *d, uint16_t index);
75
76
77 uint16_t (*get_queue_size)(QVirtioDevice *d);
78
79
80 void (*set_queue_address)(QVirtioDevice *d, uint32_t pfn);
81
82
83 QVirtQueue *(*virtqueue_setup)(QVirtioDevice *d, QGuestAllocator *alloc,
84 uint16_t index);
85
86
87 void (*virtqueue_cleanup)(QVirtQueue *vq, QGuestAllocator *alloc);
88
89
90 void (*virtqueue_kick)(QVirtioDevice *d, QVirtQueue *vq);
91};
92
93static inline bool qvirtio_is_big_endian(QVirtioDevice *d)
94{
95
96 return qtest_big_endian(global_qtest);
97}
98
99static inline uint32_t qvring_size(uint32_t num, uint32_t align)
100{
101 return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num)
102 + align - 1) & ~(align - 1))
103 + sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num;
104}
105
106uint8_t qvirtio_config_readb(QVirtioDevice *d, uint64_t addr);
107uint16_t qvirtio_config_readw(QVirtioDevice *d, uint64_t addr);
108uint32_t qvirtio_config_readl(QVirtioDevice *d, uint64_t addr);
109uint64_t qvirtio_config_readq(QVirtioDevice *d, uint64_t addr);
110uint32_t qvirtio_get_features(QVirtioDevice *d);
111void qvirtio_set_features(QVirtioDevice *d, uint32_t features);
112
113void qvirtio_reset(QVirtioDevice *d);
114void qvirtio_set_acknowledge(QVirtioDevice *d);
115void qvirtio_set_driver(QVirtioDevice *d);
116void qvirtio_set_driver_ok(QVirtioDevice *d);
117
118void qvirtio_wait_queue_isr(QVirtioDevice *d,
119 QVirtQueue *vq, gint64 timeout_us);
120uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
121 QVirtQueue *vq,
122 uint64_t addr,
123 gint64 timeout_us);
124void qvirtio_wait_used_elem(QVirtioDevice *d,
125 QVirtQueue *vq,
126 uint32_t desc_idx,
127 uint32_t *len,
128 gint64 timeout_us);
129void qvirtio_wait_config_isr(QVirtioDevice *d, gint64 timeout_us);
130QVirtQueue *qvirtqueue_setup(QVirtioDevice *d,
131 QGuestAllocator *alloc, uint16_t index);
132void qvirtqueue_cleanup(const QVirtioBus *bus, QVirtQueue *vq,
133 QGuestAllocator *alloc);
134
135void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr);
136QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d,
137 QGuestAllocator *alloc, uint16_t elem);
138void qvring_indirect_desc_add(QVRingIndirectDesc *indirect, uint64_t data,
139 uint32_t len, bool write);
140uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
141 bool next);
142uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect);
143void qvirtqueue_kick(QVirtioDevice *d, QVirtQueue *vq, uint32_t free_head);
144bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx, uint32_t *len);
145
146void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx);
147
148const char *qvirtio_get_dev_type(void);
149
150#endif
151