From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mark McLoughlin Subject: [PATCH 3/5] kvm: qemu: Publish last_avail index in the ring Date: Fri, 13 Jun 2008 14:57:59 +0100 Message-ID: <1213365481-23460-4-git-send-email-markmc@redhat.com> References: <1213365481-23460-1-git-send-email-markmc@redhat.com> <1213365481-23460-2-git-send-email-markmc@redhat.com> <1213365481-23460-3-git-send-email-markmc@redhat.com> Cc: kvm@vger.kernel.org, Mark McLoughlin To: Anthony Liguori , Avi Kivity , Rusty Russell Return-path: Received: from mail05.svc.cra.dublin.eircom.net ([159.134.118.21]:31411 "HELO mail05.svc.cra.dublin.eircom.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1756263AbYFMN6F (ORCPT ); Fri, 13 Jun 2008 09:58:05 -0400 In-Reply-To: <1213365481-23460-3-git-send-email-markmc@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: 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 --- 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