This is the draft for the libqos virtio API to create test cases for virtio devices. I'm looking forward to your comments.
Signed-off-by: Marc Marí <marc.mari.barc...@gmail.com> --- tests/libqos/virtio.h | 148 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 tests/libqos/virtio.h diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h new file mode 100644 index 0000000..03f28dc --- /dev/null +++ b/tests/libqos/virtio.h @@ -0,0 +1,148 @@ +#define VIRTQUEUE_MAX_SIZE 1024 + +struct QVirtioBus +{ + /* Send a notification IRQ to the device */ + void (*notify)(QVirtioDevice *d, uint16_t vector); + + /* Get configuration of the device */ + void (*get_config)(QVirtioDevice *d, void *config); + + /* Set configuration of the device */ + void (*set_config)(QVirtioDevice *d, void *config); + + /* Get features of the device */ + uint32_t (*get_features)(QVirtioDevice *d); + + /* Get status of the device */ + uint8_t (*get_status)(QVirtioDevice *d); + + /* Set status of the device */ + void (*set_status)(QVirtioDevice *d, uint8_t val); + + /* Reset the device */ + void (*reset)(QVirtioDevice *d); + + /* Check pending IRQs */ + uint8_t (*query_isr)(QVirtioDevice *d); + + /* Loop all devices, applying a function to all, or the one specified */ + void (*device_foreach)(QVirtioBus *bus, uint16_t device_id, + void (*func)(QVirtioDevice *dev, void *data), void *data); + + /* Find and return a device */ + QVirtioDevice *(*device_find)(uint16_t device_id, int index); +}; + +QVirtioBus *qvirtio_pci_init(); +QVirtioBus *qvirtio_mmio_init(); +QVirtioBus *qvirtio_ccw_init(); + +struct QVirtioDevice +{ + /* Index in all devices of the same type in the bus */ + int index; + + /* Device type */ + uint16_t device_id; + + /* VQs associated with the device */ + QVirtQueue *vq; +}; + +/* +I'm not sure what implementation of VirtQueue is better, QEMU's or Linux's. I +think QEMU implementation is better, because it will be easier to connect the +QEMU Virtqueue with the Libaos VirtQueue. + +The functions to use the VirtQueue are the ones I think necessary in Libqos, but +probably there are some missing and some others that are not necessary. +*/ +struct QVirtQueue +{ + QVRing vring; + uint64_t pa; + uint16_t last_avail_idx; + uint16_t signalled_used; + bool signalled_used_valid; + bool notification; + uint16_t queue_index; + int inuse; + uint16_t vector; + void (*handle_output)(QVirtioDevice *d, VirtQueue *vq); + QVirtioDevice *dev; +}; + +typedef struct QVirtQueueElement +{ + unsigned int index; + unsigned int out_num; + unsigned int in_num; + uint64_t in_addr[VIRTQUEUE_MAX_SIZE]; + uint64_t out_addr[VIRTQUEUE_MAX_SIZE]; + struct iovec in_sg[VIRTQUEUE_MAX_SIZE]; + struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; +} QVirtQueueElement; + +typedef struct QVRingDesc +{ + uint64_t addr; + uint32_t len; + uint16_t flags; + uint16_t next; +} QVRingDesc; + +typedef struct QVRingAvail +{ + uint16_t flags; + uint16_t idx; + uint16_t ring[0]; +} VRingAvail; + +typedef struct QVRingUsedElem +{ + uint32_t id; + uint32_t len; +} QVRingUsedElem; + +typedef struct QVRingUsed +{ + uint16_t flags; + uint16_t idx; + VRingUsedElem ring[0]; +} QVRingUsed; + +typedef struct QVRing +{ + unsigned int num; + unsigned int align; + uint64_t desc; + uint64_t avail; + uint64_t used; +} QVRing; + +uint64_t qvring_desc_addr(uint64_t desc_pa, int i); +uint32_t qvring_desc_len(uint64_t desc_pa, int i); +uint16_t qvring_desc_flags(uint64_t desc_pa, int i); +uint16_t qvring_desc_next(uint64_t desc_pa, int i); +uint16_t qvring_avail_flags(QVirtQueue *vq); +uint16_t qvring_avail_idx(QVirtQueue *vq); +uint16_t qvring_avail_ring(QVirtQueue *vq, int i); +uint16_t qvring_used_event(QVirtQueue *vq); +void qvring_used_ring_id(QVirtQueue *vq, int i, uint32_t val); +void qvring_used_ring_len(QVirtQueue *vq, int i, uint32_t val); +uint16_t qvring_used_idx(QVirtQueue *vq); +void qvring_used_idx_set(QVirtQueue *vq, uint16_t val); +void qvring_used_flags_set_bit(QVirtQueue *vq, int mask); +void qvring_used_flags_unset_bit(QVirtQueue *vq, int mask); +void qvring_avail_event(QVirtQueue *vq, uint16_t val); + +void qvirtqueue_push(QVirtQueue *vq, const QVirtQueueElement *elem, unsigned int len); +void qvirtqueue_flush(QVirtQueue *vq, unsigned int count); +void qvirtqueue_fill(QVirtQueue *vq, const VirtQueueElement *elem, unsigned int len, unsigned int idx); +void qvirtqueue_pop(QVirtQueue *vq, VirtQueueElement *elem); +void qvirtqueue_map_sg(struct iovec *sg, uint64_t *addr, + size_t num_sg, int is_write); +void qvirtio_notify(QVirtioDevice *vdev, QVirtQueue *vq); +int qvirtio_queue_ready(QVirtQueue *vq); +int qvirtio_queue_empty(QVirtQueue *vq); -- 1.7.10.4