@@ -147,6 +147,8 @@ void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr)
writew(vq->desc + (16 * i), 0);
/* vq->desc[i].next */
writew(vq->desc + (16 * i) + 14, i + 1);
+
+ vq->tokens[i] = NULL;
}
/* vq->avail->flags */
@@ -208,7 +210,7 @@ void qvring_indirect_desc_add(QVRingIndirectDesc *indirect, uint64_t data,
}
uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
- bool next)
+ bool next, void *token)
{
uint16_t flags = 0;
uint16_t idx = vq->free_head;
@@ -233,11 +235,13 @@ uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
vq->free_head = readw(vq->desc + sizeof(struct vring_desc) * idx +
offsetof(struct vring_desc, next));
+ vq->tokens[idx] = token;
return idx;
}
-uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect)
+uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect,
+ void *token)
{
uint16_t idx = vq->free_head;
@@ -258,6 +262,7 @@ uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect)
vq->free_head = readw(vq->desc + sizeof(struct vring_desc) * idx +
offsetof(struct vring_desc, next));
+ vq->tokens[idx] = token;
return idx;
}
@@ -15,6 +15,8 @@
#define QVIRTIO_F_BAD_FEATURE 0x40000000
+#define QVIRTIO_QUEUE_MAX 1024 /* descriptors */
+
typedef struct QVirtioDevice {
/* Device type */
uint16_t device_type;
@@ -31,6 +33,7 @@ typedef struct QVirtQueue {
uint32_t align;
bool indirect;
bool event;
+ void *tokens[QVIRTIO_QUEUE_MAX];
} QVirtQueue;
typedef struct QVRingIndirectDesc {
@@ -125,8 +128,9 @@ QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d,
void qvring_indirect_desc_add(QVRingIndirectDesc *indirect, uint64_t data,
uint32_t len, bool write);
uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
- bool next);
-uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect);
+ bool next, void *token);
+uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect,
+ void *token);
void qvirtqueue_kick(const QVirtioBus *bus, QVirtioDevice *d, QVirtQueue *vq,
uint32_t free_head);
@@ -187,9 +187,9 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
g_free(req.data);
- free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
- qvirtqueue_add(vq, req_addr + 16, 512, false, true);
- qvirtqueue_add(vq, req_addr + 528, 1, true, false);
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true, NULL);
+ qvirtqueue_add(vq, req_addr + 16, 512, false, true, NULL);
+ qvirtqueue_add(vq, req_addr + 528, 1, true, false, NULL);
qvirtqueue_kick(bus, dev, vq, free_head);
@@ -209,9 +209,9 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
g_free(req.data);
- free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
- qvirtqueue_add(vq, req_addr + 16, 512, true, true);
- qvirtqueue_add(vq, req_addr + 528, 1, true, false);
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true, NULL);
+ qvirtqueue_add(vq, req_addr + 16, 512, true, true, NULL);
+ qvirtqueue_add(vq, req_addr + 528, 1, true, false, NULL);
qvirtqueue_kick(bus, dev, vq, free_head);
@@ -239,8 +239,8 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
g_free(req.data);
- free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
- qvirtqueue_add(vq, req_addr + 528, 1, true, false);
+ free_head = qvirtqueue_add(vq, req_addr, 528, false, true, NULL);
+ qvirtqueue_add(vq, req_addr + 528, 1, true, false, NULL);
qvirtqueue_kick(bus, dev, vq, free_head);
qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
@@ -259,8 +259,8 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
g_free(req.data);
- free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
- qvirtqueue_add(vq, req_addr + 16, 513, true, false);
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true, NULL);
+ qvirtqueue_add(vq, req_addr + 16, 513, true, false, NULL);
qvirtqueue_kick(bus, dev, vq, free_head);
@@ -360,7 +360,7 @@ static void pci_indirect(void)
indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);
qvring_indirect_desc_add(indirect, req_addr, 528, false);
qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
- free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
+ free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect, NULL);
qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
@@ -385,7 +385,7 @@ static void pci_indirect(void)
indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);
qvring_indirect_desc_add(indirect, req_addr, 16, false);
qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
- free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
+ free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect, NULL);
qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
@@ -509,9 +509,9 @@ static void pci_msix(void)
g_free(req.data);
- free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
+ free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false, NULL);
qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
@@ -532,9 +532,9 @@ static void pci_msix(void)
g_free(req.data);
- free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
+ free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false, NULL);
qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
@@ -616,9 +616,9 @@ static void pci_idx(void)
g_free(req.data);
- free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
+ free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false, NULL);
qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
@@ -637,9 +637,9 @@ static void pci_idx(void)
/* Notify after processing the third request */
qvirtqueue_set_used_event(&vqpci->vq, 2);
- free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
+ free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false, NULL);
qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
/* No notification expected */
@@ -660,9 +660,9 @@ static void pci_idx(void)
g_free(req.data);
- free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
- qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
+ free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true, NULL);
+ qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false, NULL);
qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
@@ -101,7 +101,7 @@ static void rx_test(const QVirtioBus *bus, QVirtioDevice *dev,
req_addr = guest_alloc(alloc, 64);
- free_head = qvirtqueue_add(vq, req_addr, 64, true, false);
+ free_head = qvirtqueue_add(vq, req_addr, 64, true, false, NULL);
qvirtqueue_kick(bus, dev, vq, free_head);
ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
@@ -127,7 +127,7 @@ static void tx_test(const QVirtioBus *bus, QVirtioDevice *dev,
req_addr = guest_alloc(alloc, 64);
memwrite(req_addr + VNET_HDR_SIZE, "TEST", 4);
- free_head = qvirtqueue_add(vq, req_addr, 64, false, false);
+ free_head = qvirtqueue_add(vq, req_addr, 64, false, false, NULL);
qvirtqueue_kick(bus, dev, vq, free_head);
qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_NET_TIMEOUT_US);
@@ -163,7 +163,7 @@ static void rx_stop_cont_test(const QVirtioBus *bus, QVirtioDevice *dev,
req_addr = guest_alloc(alloc, 64);
- free_head = qvirtqueue_add(vq, req_addr, 64, true, false);
+ free_head = qvirtqueue_add(vq, req_addr, 64, true, false, NULL);
qvirtqueue_kick(bus, dev, vq, free_head);
qmp("{ 'execute' : 'stop'}");
@@ -103,20 +103,20 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
/* Add request header */
req_addr = qvirtio_scsi_alloc(vs, sizeof(req), &req);
- free_head = qvirtqueue_add(vq, req_addr, sizeof(req), false, true);
+ free_head = qvirtqueue_add(vq, req_addr, sizeof(req), false, true, NULL);
if (data_out_len) {
data_out_addr = qvirtio_scsi_alloc(vs, data_out_len, data_out);
- qvirtqueue_add(vq, data_out_addr, data_out_len, false, true);
+ qvirtqueue_add(vq, data_out_addr, data_out_len, false, true, NULL);
}
/* Add response header */
resp_addr = qvirtio_scsi_alloc(vs, sizeof(resp), &resp);
- qvirtqueue_add(vq, resp_addr, sizeof(resp), true, !!data_in_len);
+ qvirtqueue_add(vq, resp_addr, sizeof(resp), true, !!data_in_len, NULL);
if (data_in_len) {
data_in_addr = qvirtio_scsi_alloc(vs, data_in_len, data_in);
- qvirtqueue_add(vq, data_in_addr, data_in_len, true, false);
+ qvirtqueue_add(vq, data_in_addr, data_in_len, true, false, NULL);
}
qvirtqueue_kick(&qvirtio_pci, vs->dev, vq, free_head);
Allow the qvirtqueue_add_buf() caller to associate a void *token with the buffer. The next patch adds a qvirtqueue_get_buf() function which returns the token of the buffer that was popped from the virtqueue. This allows users to identify which buffer was popped. Existing virtio device tests are simple and do not use the token. They pass a NULL token to qvirtqueue_add_buf(). Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> --- tests/libqos/virtio.c | 9 ++++++-- tests/libqos/virtio.h | 8 +++++-- tests/virtio-blk-test.c | 54 ++++++++++++++++++++++++------------------------ tests/virtio-net-test.c | 6 +++--- tests/virtio-scsi-test.c | 8 +++---- 5 files changed, 47 insertions(+), 38 deletions(-)