xref: /qemu/tests/qtest/libqos/virtio.h (revision bf3c63d2010c5ef52f8b988bee2a1486a056795f)
1311e666aSMarc Marí /*
2311e666aSMarc Marí  * libqos virtio definitions
3311e666aSMarc Marí  *
4311e666aSMarc Marí  * Copyright (c) 2014 Marc Marí
5311e666aSMarc Marí  *
6311e666aSMarc Marí  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7311e666aSMarc Marí  * See the COPYING file in the top-level directory.
8311e666aSMarc Marí  */
9311e666aSMarc Marí 
10311e666aSMarc Marí #ifndef LIBQOS_VIRTIO_H
11311e666aSMarc Marí #define LIBQOS_VIRTIO_H
12311e666aSMarc Marí 
13*bf3c63d2SMarc Marí #include "libqos/malloc.h"
14*bf3c63d2SMarc Marí 
15311e666aSMarc Marí #define QVIRTIO_VENDOR_ID       0x1AF4
16311e666aSMarc Marí 
1746e0cf76SMarc Marí #define QVIRTIO_RESET           0x0
1846e0cf76SMarc Marí #define QVIRTIO_ACKNOWLEDGE     0x1
1946e0cf76SMarc Marí #define QVIRTIO_DRIVER          0x2
20*bf3c63d2SMarc Marí #define QVIRTIO_DRIVER_OK       0x4
2146e0cf76SMarc Marí 
22311e666aSMarc Marí #define QVIRTIO_NET_DEVICE_ID   0x1
23311e666aSMarc Marí #define QVIRTIO_BLK_DEVICE_ID   0x2
24311e666aSMarc Marí 
25*bf3c63d2SMarc Marí #define QVRING_DESC_F_NEXT      0x1
26*bf3c63d2SMarc Marí #define QVRING_DESC_F_WRITE     0x2
27*bf3c63d2SMarc Marí #define QVRING_DESC_F_INDIRECT  0x4
28*bf3c63d2SMarc Marí 
29*bf3c63d2SMarc Marí #define QVIRTIO_F_NOTIFY_ON_EMPTY       0x01000000
30*bf3c63d2SMarc Marí #define QVIRTIO_F_ANY_LAYOUT            0x08000000
31*bf3c63d2SMarc Marí #define QVIRTIO_F_RING_INDIRECT_DESC    0x10000000
32*bf3c63d2SMarc Marí #define QVIRTIO_F_RING_EVENT_IDX        0x20000000
33*bf3c63d2SMarc Marí #define QVIRTIO_F_BAD_FEATURE           0x40000000
34*bf3c63d2SMarc Marí 
35*bf3c63d2SMarc Marí #define QVRING_AVAIL_F_NO_INTERRUPT     1
36*bf3c63d2SMarc Marí 
37*bf3c63d2SMarc Marí #define QVRING_USED_F_NO_NOTIFY     1
38*bf3c63d2SMarc Marí 
39311e666aSMarc Marí typedef struct QVirtioDevice {
40311e666aSMarc Marí     /* Device type */
41311e666aSMarc Marí     uint16_t device_type;
42311e666aSMarc Marí } QVirtioDevice;
43311e666aSMarc Marí 
44*bf3c63d2SMarc Marí typedef struct QVRingDesc {
45*bf3c63d2SMarc Marí     uint64_t addr;
46*bf3c63d2SMarc Marí     uint32_t len;
47*bf3c63d2SMarc Marí     uint16_t flags;
48*bf3c63d2SMarc Marí     uint16_t next;
49*bf3c63d2SMarc Marí } QVRingDesc;
50*bf3c63d2SMarc Marí 
51*bf3c63d2SMarc Marí typedef struct QVRingAvail {
52*bf3c63d2SMarc Marí     uint16_t flags;
53*bf3c63d2SMarc Marí     uint16_t idx;
54*bf3c63d2SMarc Marí     uint16_t ring[0]; /* This is an array of uint16_t */
55*bf3c63d2SMarc Marí } QVRingAvail;
56*bf3c63d2SMarc Marí 
57*bf3c63d2SMarc Marí typedef struct QVRingUsedElem {
58*bf3c63d2SMarc Marí     uint32_t id;
59*bf3c63d2SMarc Marí     uint32_t len;
60*bf3c63d2SMarc Marí } QVRingUsedElem;
61*bf3c63d2SMarc Marí 
62*bf3c63d2SMarc Marí typedef struct QVRingUsed {
63*bf3c63d2SMarc Marí     uint16_t flags;
64*bf3c63d2SMarc Marí     uint16_t idx;
65*bf3c63d2SMarc Marí     QVRingUsedElem ring[0]; /* This is an array of QVRingUsedElem structs */
66*bf3c63d2SMarc Marí } QVRingUsed;
67*bf3c63d2SMarc Marí 
68*bf3c63d2SMarc Marí typedef struct QVirtQueue {
69*bf3c63d2SMarc Marí     uint64_t desc; /* This points to an array of QVRingDesc */
70*bf3c63d2SMarc Marí     uint64_t avail; /* This points to a QVRingAvail */
71*bf3c63d2SMarc Marí     uint64_t used; /* This points to a QVRingDesc */
72*bf3c63d2SMarc Marí     uint16_t index;
73*bf3c63d2SMarc Marí     uint32_t size;
74*bf3c63d2SMarc Marí     uint32_t free_head;
75*bf3c63d2SMarc Marí     uint32_t num_free;
76*bf3c63d2SMarc Marí     uint32_t align;
77*bf3c63d2SMarc Marí } QVirtQueue;
78*bf3c63d2SMarc Marí 
7946e0cf76SMarc Marí typedef struct QVirtioBus {
8046e0cf76SMarc Marí     uint8_t (*config_readb)(QVirtioDevice *d, void *addr);
8146e0cf76SMarc Marí     uint16_t (*config_readw)(QVirtioDevice *d, void *addr);
8246e0cf76SMarc Marí     uint32_t (*config_readl)(QVirtioDevice *d, void *addr);
8346e0cf76SMarc Marí     uint64_t (*config_readq)(QVirtioDevice *d, void *addr);
8446e0cf76SMarc Marí 
85*bf3c63d2SMarc Marí     /* Get features of the device */
86*bf3c63d2SMarc Marí     uint32_t (*get_features)(QVirtioDevice *d);
87*bf3c63d2SMarc Marí 
88*bf3c63d2SMarc Marí     /* Get features of the device */
89*bf3c63d2SMarc Marí     void (*set_features)(QVirtioDevice *d, uint32_t features);
90*bf3c63d2SMarc Marí 
9146e0cf76SMarc Marí     /* Get status of the device */
9246e0cf76SMarc Marí     uint8_t (*get_status)(QVirtioDevice *d);
9346e0cf76SMarc Marí 
9446e0cf76SMarc Marí     /* Set status of the device  */
9546e0cf76SMarc Marí     void (*set_status)(QVirtioDevice *d, uint8_t status);
96*bf3c63d2SMarc Marí 
97*bf3c63d2SMarc Marí     /* Get the ISR status of the device */
98*bf3c63d2SMarc Marí     uint8_t (*get_isr_status)(QVirtioDevice *d);
99*bf3c63d2SMarc Marí 
100*bf3c63d2SMarc Marí     /* Select a queue to work on */
101*bf3c63d2SMarc Marí     void (*queue_select)(QVirtioDevice *d, uint16_t index);
102*bf3c63d2SMarc Marí 
103*bf3c63d2SMarc Marí     /* Get the size of the selected queue */
104*bf3c63d2SMarc Marí     uint16_t (*get_queue_size)(QVirtioDevice *d);
105*bf3c63d2SMarc Marí 
106*bf3c63d2SMarc Marí     /* Set the address of the selected queue */
107*bf3c63d2SMarc Marí     void (*set_queue_address)(QVirtioDevice *d, uint32_t pfn);
108*bf3c63d2SMarc Marí 
109*bf3c63d2SMarc Marí     /* Setup the virtqueue specified by index */
110*bf3c63d2SMarc Marí     QVirtQueue *(*virtqueue_setup)(QVirtioDevice *d, QGuestAllocator *alloc,
111*bf3c63d2SMarc Marí                                                                 uint16_t index);
112*bf3c63d2SMarc Marí 
113*bf3c63d2SMarc Marí     /* Notify changes in virtqueue */
114*bf3c63d2SMarc Marí     void (*virtqueue_kick)(QVirtioDevice *d, QVirtQueue *vq);
11546e0cf76SMarc Marí } QVirtioBus;
11646e0cf76SMarc Marí 
117*bf3c63d2SMarc Marí static inline uint32_t qvring_size(uint32_t num, uint32_t align)
118*bf3c63d2SMarc Marí {
119*bf3c63d2SMarc Marí     return ((sizeof(struct QVRingDesc) * num + sizeof(uint16_t) * (3 + num)
120*bf3c63d2SMarc Marí         + align - 1) & ~(align - 1))
121*bf3c63d2SMarc Marí         + sizeof(uint16_t) * 3 + sizeof(struct QVRingUsedElem) * num;
122*bf3c63d2SMarc Marí }
123*bf3c63d2SMarc Marí 
12446e0cf76SMarc Marí uint8_t qvirtio_config_readb(const QVirtioBus *bus, QVirtioDevice *d,
12546e0cf76SMarc Marí                                                                 void *addr);
12646e0cf76SMarc Marí uint16_t qvirtio_config_readw(const QVirtioBus *bus, QVirtioDevice *d,
12746e0cf76SMarc Marí                                                                 void *addr);
12846e0cf76SMarc Marí uint32_t qvirtio_config_readl(const QVirtioBus *bus, QVirtioDevice *d,
12946e0cf76SMarc Marí                                                                 void *addr);
13046e0cf76SMarc Marí uint64_t qvirtio_config_readq(const QVirtioBus *bus, QVirtioDevice *d,
13146e0cf76SMarc Marí                                                                 void *addr);
132*bf3c63d2SMarc Marí uint32_t qvirtio_get_features(const QVirtioBus *bus, QVirtioDevice *d);
133*bf3c63d2SMarc Marí void qvirtio_set_features(const QVirtioBus *bus, QVirtioDevice *d,
134*bf3c63d2SMarc Marí                                                             uint32_t features);
13546e0cf76SMarc Marí 
13646e0cf76SMarc Marí void qvirtio_reset(const QVirtioBus *bus, QVirtioDevice *d);
13746e0cf76SMarc Marí void qvirtio_set_acknowledge(const QVirtioBus *bus, QVirtioDevice *d);
13846e0cf76SMarc Marí void qvirtio_set_driver(const QVirtioBus *bus, QVirtioDevice *d);
139*bf3c63d2SMarc Marí void qvirtio_set_driver_ok(const QVirtioBus *bus, QVirtioDevice *d);
140*bf3c63d2SMarc Marí 
141*bf3c63d2SMarc Marí bool qvirtio_wait_isr(const QVirtioBus *bus, QVirtioDevice *d, uint8_t mask,
142*bf3c63d2SMarc Marí                                                             uint64_t timeout);
143*bf3c63d2SMarc Marí QVirtQueue *qvirtqueue_setup(const QVirtioBus *bus, QVirtioDevice *d,
144*bf3c63d2SMarc Marí                                         QGuestAllocator *alloc, uint16_t index);
145*bf3c63d2SMarc Marí 
146*bf3c63d2SMarc Marí void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr);
147*bf3c63d2SMarc Marí uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
148*bf3c63d2SMarc Marí                                                                     bool next);
149*bf3c63d2SMarc Marí void qvirtqueue_kick(const QVirtioBus *bus, QVirtioDevice *d, QVirtQueue *vq,
150*bf3c63d2SMarc Marí                                                             uint32_t free_head);
15146e0cf76SMarc Marí 
152311e666aSMarc Marí #endif
153