[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications
From: |
Michael S. Tsirkin |
Subject: |
Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications |
Date: |
Wed, 16 Nov 2016 22:15:25 +0200 |
On Wed, Nov 16, 2016 at 07:05:51PM +0100, Paolo Bonzini wrote:
> Dataplane has been omitting forever the step of setting ISR when
> an interrupt is raised. This caused little breakage, because the
> specification actually says that ISR may not be updated in MSI mode.
>
> Some versions of the Windows drivers however didn't clear MSI mode
> correctly, and proceeded using polling mode (using ISR, not the used
> ring index!) for crashdump and hibernation. If it were just crashdump
> and hibernation it would not be a big deal, but recent releases of
> Windows do not really shut down, but rather log out and hibernate to
> make the next startup faster. Hence, this manifested as a more serious
> hang during shutdown with e.g. Windows 8.1 and virtio-win 1.8.0 RPMs.
> Newer versions fixed this, while older versions do not use MSI at all.
>
> The failure has always been there for virtio dataplane, but it became
> visible after commits 9ffe337 ("virtio-blk: always use dataplane path
> if ioeventfd is active", 2016-10-30) and ad07cd6 ("virtio-scsi: always
> use dataplane path if ioeventfd is active", 2016-10-30) made virtio-blk
> and virtio-scsi always use the dataplane code under KVM. The good news
> therefore is that it was not a bug in the patches---they were doing
> exactly what they were meant for, i.e. shake out remaining dataplane bugs.
>
> The fix is not hard, so it's worth arranging for the broken drivers.
> The virtio_should_notify+event_notifier_set pair that is common to
> virtio-blk and virtio-scsi dataplane is replaced with a new public
> function virtio_notify_irqfd that also sets ISR. The irqfd emulation
> code now need not set ISR anymore, so virtio_irq is removed.
>
> Signed-off-by: Paolo Bonzini <address@hidden>
> ---
> hw/block/dataplane/virtio-blk.c | 4 +---
> hw/scsi/virtio-scsi-dataplane.c | 7 -------
> hw/scsi/virtio-scsi.c | 2 +-
> hw/virtio/trace-events | 2 +-
> hw/virtio/virtio.c | 20 ++++++++++++--------
> include/hw/virtio/virtio-scsi.h | 1 -
> include/hw/virtio/virtio.h | 2 +-
> 7 files changed, 16 insertions(+), 22 deletions(-)
>
> diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
> index 90ef557..d1f9f63 100644
> --- a/hw/block/dataplane/virtio-blk.c
> +++ b/hw/block/dataplane/virtio-blk.c
> @@ -68,9 +68,7 @@ static void notify_guest_bh(void *opaque)
> unsigned i = j + ctzl(bits);
> VirtQueue *vq = virtio_get_queue(s->vdev, i);
>
> - if (virtio_should_notify(s->vdev, vq)) {
> - event_notifier_set(virtio_queue_get_guest_notifier(vq));
> - }
> + virtio_notify_irqfd(s->vdev, vq);
>
> bits &= bits - 1; /* clear right-most bit */
> }
> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
> index f2ea29d..6b8d0f0 100644
> --- a/hw/scsi/virtio-scsi-dataplane.c
> +++ b/hw/scsi/virtio-scsi-dataplane.c
> @@ -95,13 +95,6 @@ static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue
> *vq, int n,
> return 0;
> }
>
> -void virtio_scsi_dataplane_notify(VirtIODevice *vdev, VirtIOSCSIReq *req)
> -{
> - if (virtio_should_notify(vdev, req->vq)) {
> - event_notifier_set(virtio_queue_get_guest_notifier(req->vq));
> - }
> -}
> -
> /* assumes s->ctx held */
> static void virtio_scsi_clear_aio(VirtIOSCSI *s)
> {
> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> index 3e5ae6a..10fd687 100644
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c
> @@ -69,7 +69,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
> qemu_iovec_from_buf(&req->resp_iov, 0, &req->resp, req->resp_size);
> virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size);
> if (s->dataplane_started && !s->dataplane_fenced) {
> - virtio_scsi_dataplane_notify(vdev, req);
> + virtio_notify_irqfd(vdev, vq);
> } else {
> virtio_notify(vdev, vq);
> }
> diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> index 8756cef..7b6f55e 100644
> --- a/hw/virtio/trace-events
> +++ b/hw/virtio/trace-events
> @@ -5,7 +5,7 @@ virtqueue_fill(void *vq, const void *elem, unsigned int len,
> unsigned int idx) "
> virtqueue_flush(void *vq, unsigned int count) "vq %p count %u"
> virtqueue_pop(void *vq, void *elem, unsigned int in_num, unsigned int
> out_num) "vq %p elem %p in_num %u out_num %u"
> virtio_queue_notify(void *vdev, int n, void *vq) "vdev %p n %d vq %p"
> -virtio_irq(void *vq) "vq %p"
> +virtio_notify_irqfd(void *vdev, void *vq) "vdev %p vq %p"
> virtio_notify(void *vdev, void *vq) "vdev %p vq %p"
> virtio_set_status(void *vdev, uint8_t val) "vdev %p val %u"
>
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index ecf13bd..860ebdb 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -1326,13 +1326,6 @@ static void virtio_set_isr(VirtIODevice *vdev, int
> value)
> }
> }
>
> -void virtio_irq(VirtQueue *vq)
> -{
> - trace_virtio_irq(vq);
> - virtio_set_isr(vq->vdev, 0x1);
> - virtio_notify_vector(vq->vdev, vq->vector);
> -}
> -
> bool virtio_should_notify(VirtIODevice *vdev, VirtQueue *vq)
> {
> uint16_t old, new;
> @@ -1356,6 +1349,17 @@ bool virtio_should_notify(VirtIODevice *vdev,
> VirtQueue *vq)
> return !v || vring_need_event(vring_get_used_event(vq), new, old);
> }
>
> +void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq)
> +{
> + if (!virtio_should_notify(vdev, vq)) {
> + return;
> + }
> +
> + trace_virtio_notify_irqfd(vdev, vq);
> + virtio_set_isr(vq->vdev, 0x1);
So here, I think we need a comment with parts of
the commit log.
/*
* virtio spec 1.0 says ISR bit 0 should be ignored with MSI, but
* windows drivers included in virtio-win 1.8.0 (circa 2015)
* for Windows 8.1 only are incorrectly polling this bit during shutdown
* in MSI mode, causing a hang if this bit is never updated.
* Next driver release from 2016 fixed this problem, so working around it
* is not a must, but it's easy to do so let's do it here.
*
* Note: it's safe to update ISR from any thread as it was switched
* to an atomic operation.
*/
> + event_notifier_set(&vq->guest_notifier);
> +}
> +
> void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
> {
> if (!virtio_should_notify(vdev, vq)) {
> @@ -1990,7 +1994,7 @@ static void
> virtio_queue_guest_notifier_read(EventNotifier *n)
> {
> VirtQueue *vq = container_of(n, VirtQueue, guest_notifier);
> if (event_notifier_test_and_clear(n)) {
> - virtio_irq(vq);
> + virtio_notify_vector(vq->vdev, vq->vector);
> }
> }
>
> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
> index 9fbc7d7..7375196 100644
> --- a/include/hw/virtio/virtio-scsi.h
> +++ b/include/hw/virtio/virtio-scsi.h
> @@ -137,6 +137,5 @@ void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice
> *dev,
> void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp);
> int virtio_scsi_dataplane_start(VirtIODevice *s);
> void virtio_scsi_dataplane_stop(VirtIODevice *s);
> -void virtio_scsi_dataplane_notify(VirtIODevice *vdev, VirtIOSCSIReq *req);
>
> #endif /* QEMU_VIRTIO_SCSI_H */
> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> index 835b085..ab0e030 100644
> --- a/include/hw/virtio/virtio.h
> +++ b/include/hw/virtio/virtio.h
> @@ -181,6 +181,7 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned
> int *in_bytes,
> unsigned max_in_bytes, unsigned
> max_out_bytes);
>
> bool virtio_should_notify(VirtIODevice *vdev, VirtQueue *vq);
> +void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq);
> void virtio_notify(VirtIODevice *vdev, VirtQueue *vq);
>
> void virtio_save(VirtIODevice *vdev, QEMUFile *f);
> @@ -280,7 +281,6 @@ void virtio_queue_host_notifier_read(EventNotifier *n);
> void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext
> *ctx,
> void (*fn)(VirtIODevice *,
> VirtQueue *));
> -void virtio_irq(VirtQueue *vq);
> VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
> VirtQueue *virtio_vector_next_queue(VirtQueue *vq);
>
> --
> 2.9.3
- [Qemu-devel] [PATCH v2 for-2.8 0/3] virtio fixes, Paolo Bonzini, 2016/11/16
- [Qemu-devel] [PATCH 2/3] virtio: access ISR atomically, Paolo Bonzini, 2016/11/16
- [Qemu-devel] [PATCH 1/3] virtio: introduce grab/release_ioeventfd to fix vhost, Paolo Bonzini, 2016/11/16
- [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications, Paolo Bonzini, 2016/11/16
- Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications,
Michael S. Tsirkin <=
- Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications, Paolo Bonzini, 2016/11/16
- Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications, Michael S. Tsirkin, 2016/11/16
- Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications, Paolo Bonzini, 2016/11/16
- Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications, Michael S. Tsirkin, 2016/11/16
- Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications, Paolo Bonzini, 2016/11/17
- Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications, Michael S. Tsirkin, 2016/11/17
- Re: [Qemu-devel] [PATCH 3/3] virtio: set ISR on dataplane notifications, Stefan Hajnoczi, 2016/11/17
Re: [Qemu-devel] [PATCH v2 for-2.8 0/3] virtio fixes, no-reply, 2016/11/16