Set the VIRTIO_RING_F_PUBLISH_INDICES feature and publish
the last_avail index within the ring itself.
This is important for save/restore when using vringfd
because the kernel is the one tracking last_avail, but
we need to be able to peek at that state.
Signed-off-by: Mark McLoughlin <[EMAIL PROTECTED]>
---
qemu/hw/virtio-net.c | 4 ++--
qemu/hw/virtio.c | 16 ++++++++--------
qemu/hw/virtio.h | 7 ++++++-
3 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c
index a61fdb1..6c42bf0 100644
--- a/qemu/hw/virtio-net.c
+++ b/qemu/hw/virtio-net.c
@@ -106,7 +106,7 @@ static int virtio_net_can_receive(void *opaque)
!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
return 0;
- if (n->rx_vq->vring.avail->idx == n->rx_vq->last_avail_idx)
+ if (n->rx_vq->vring.avail->idx == vq_last_avail(n->rx_vq))
return 0;
return 1;
@@ -178,7 +178,7 @@ static void virtio_net_handle_tx(VirtIODevice *vdev,
VirtQueue *vq)
VirtIONet *n = to_virtio_net(vdev);
if (n->tx_timer_active &&
- (vq->vring.avail->idx - vq->last_avail_idx) == 64) {
+ (vq->vring.avail->idx - vq_last_avail(vq)) == 64) {
vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
qemu_del_timer(n->tx_timer);
n->tx_timer_active = 0;
diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
index 3119ea9..a1ee93f 100644
--- a/qemu/hw/virtio.c
+++ b/qemu/hw/virtio.c
@@ -147,17 +147,17 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
unsigned int position;
/* Check it isn't doing very strange things with descriptor numbers. */
- if ((uint16_t)(vq->vring.avail->idx - vq->last_avail_idx) > vq->vring.num)
+ if ((uint16_t)(vq->vring.avail->idx - vq_last_avail(vq)) > vq->vring.num)
errx(1, "Guest moved used index from %u to %u",
- vq->last_avail_idx, vq->vring.avail->idx);
+ vq_last_avail(vq), vq->vring.avail->idx);
/* If there's nothing new since last we looked, return invalid. */
- if (vq->vring.avail->idx == vq->last_avail_idx)
+ if (vq->vring.avail->idx == vq_last_avail(vq))
return 0;
/* Grab the next descriptor number they're advertising, and increment
* the index we've seen. */
- head = vq->vring.avail->ring[vq->last_avail_idx++ % vq->vring.num];
+ head = vq->vring.avail->ring[vq_last_avail(vq)++ % vq->vring.num];
/* If their number is silly, that's a fatal mistake. */
if (head >= vq->vring.num)
@@ -222,7 +222,6 @@ void virtio_reset(void *opaque)
vdev->vq[i].vring.desc = NULL;
vdev->vq[i].vring.avail = NULL;
vdev->vq[i].vring.used = NULL;
- vdev->vq[i].last_avail_idx = 0;
vdev->vq[i].pfn = 0;
}
}
@@ -278,6 +277,7 @@ static uint32_t virtio_ioport_read(void *opaque, uint32_t
addr)
case VIRTIO_PCI_HOST_FEATURES:
ret = vdev->get_features(vdev);
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ ret |= (1 << VIRTIO_RING_F_PUBLISH_INDICES);
break;
case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->features;
@@ -434,7 +434,7 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int
queue_size,
void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
{
/* Always notify when queue is empty */
- if ((vq->inuse || vq->vring.avail->idx != vq->last_avail_idx)) &&
+ if ((vq->inuse || vq->vring.avail->idx != vq_last_avail(vq)) &&
(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
return;
@@ -469,7 +469,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
qemu_put_be32(f, vdev->vq[i].vring.num);
qemu_put_be32s(f, &vdev->vq[i].pfn);
- qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
+ qemu_put_be16(f, vq_last_avail(&vdev->vq[i]));
}
}
@@ -492,7 +492,7 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f)
for (i = 0; i < num; i++) {
vdev->vq[i].vring.num = qemu_get_be32(f);
qemu_get_be32s(f, &vdev->vq[i].pfn);
- qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
+ vq_last_avail(&vdev->vq[i]) = qemu_get_be16(f);
if (vdev->vq[i].pfn) {
size_t size;
diff --git a/qemu/hw/virtio.h b/qemu/hw/virtio.h
index 1adaed3..142ecbd 100644
--- a/qemu/hw/virtio.h
+++ b/qemu/hw/virtio.h
@@ -46,6 +46,9 @@
/* This means don't interrupt guest when buffer consumed. */
#define VRING_AVAIL_F_NO_INTERRUPT 1
+/* We publish the last-seen available index at the end of the used ring */
+#define VIRTIO_RING_F_PUBLISH_INDICES 28
+
typedef struct VirtQueue VirtQueue;
typedef struct VirtIODevice VirtIODevice;
@@ -89,11 +92,13 @@ struct VirtQueue
{
VRing vring;
uint32_t pfn;
- uint16_t last_avail_idx;
int inuse;
void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
};
+/* We publish the last-seen available index at the end of the used ring */
+#define vq_last_avail(q) (*(uint16_t *)&(q)->vring.used->ring[(q)->vring.num])
+
#define VIRTQUEUE_MAX_SIZE 1024
typedef struct VirtQueueElement
--
1.5.4.1
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html