From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38732) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WwpIQ-0005Ci-QK for qemu-devel@nongnu.org; Tue, 17 Jun 2014 05:03:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WwpIA-0000Ox-E4 for qemu-devel@nongnu.org; Tue, 17 Jun 2014 05:03:14 -0400 Received: from mail-we0-x230.google.com ([2a00:1450:400c:c03::230]:63783) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WwpIA-0000Oj-3y for qemu-devel@nongnu.org; Tue, 17 Jun 2014 05:02:58 -0400 Received: by mail-we0-f176.google.com with SMTP id u56so6940053wes.35 for ; Tue, 17 Jun 2014 02:02:57 -0700 (PDT) From: =?UTF-8?q?Marc=20Mar=C3=AD?= Date: Tue, 17 Jun 2014 11:02:48 +0200 Message-Id: <1402995768-4282-1-git-send-email-marc.mari.barcelo@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: [Qemu-devel] [RFC] Libqos virtio API List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Marc=20Mar=C3=AD?= , Paolo Bonzini , Paolo Bonzini , Stefan Hajnoczi 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Ă­ --- 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