Pablo Greco e6a3ae
From 5bcbdfefff3209a194168dbe772c7e2f45d248f7 Mon Sep 17 00:00:00 2001
Pablo Greco e6a3ae
From: Maxim Levitsky <mlevitsk@redhat.com>
Pablo Greco e6a3ae
Date: Sun, 22 Dec 2019 11:02:07 +0100
Pablo Greco e6a3ae
Subject: [PATCH 2/7] virtio: Return true from virtio_queue_empty if broken
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RH-Author: Maxim Levitsky <mlevitsk@redhat.com>
Pablo Greco e6a3ae
Message-id: <20191222110207.21384-3-mlevitsk@redhat.com>
Pablo Greco e6a3ae
Patchwork-id: 93208
Pablo Greco e6a3ae
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/2] virtio: Return true from virtio_queue_empty if broken
Pablo Greco e6a3ae
Bugzilla: 1769613
Pablo Greco e6a3ae
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Peter Xu <peterx@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
From: Fam Zheng <famz@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Both virtio-blk and virtio-scsi use virtio_queue_empty() as the
Pablo Greco e6a3ae
loop condition in VQ handlers (virtio_blk_handle_vq,
Pablo Greco e6a3ae
virtio_scsi_handle_cmd_vq). When a device is marked broken in
Pablo Greco e6a3ae
virtqueue_pop, for example if a vIOMMU address translation failed, we
Pablo Greco e6a3ae
want to break out of the loop.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
This fixes a hanging problem when booting a CentOS 3.10.0-862.el7.x86_64
Pablo Greco e6a3ae
kernel with ATS enabled:
Pablo Greco e6a3ae
Pablo Greco e6a3ae
  $ qemu-system-x86_64 \
Pablo Greco e6a3ae
    ... \
Pablo Greco e6a3ae
    -device intel-iommu,intremap=on,caching-mode=on,eim=on,device-iotlb=on \
Pablo Greco e6a3ae
    -device virtio-scsi-pci,iommu_platform=on,ats=on,id=scsi0,bus=pci.4,addr=0x0
Pablo Greco e6a3ae
Pablo Greco e6a3ae
The dead loop happens immediately when the kernel boots and initializes
Pablo Greco e6a3ae
the device, where virtio_scsi_data_plane_handle_cmd will not return:
Pablo Greco e6a3ae
Pablo Greco e6a3ae
    > ...
Pablo Greco e6a3ae
    > #13 0x00005586602b7793 in virtio_scsi_handle_cmd_vq
Pablo Greco e6a3ae
    > #14 0x00005586602b8d66 in virtio_scsi_data_plane_handle_cmd
Pablo Greco e6a3ae
    > #15 0x00005586602ddab7 in virtio_queue_notify_aio_vq
Pablo Greco e6a3ae
    > #16 0x00005586602dfc9f in virtio_queue_host_notifier_aio_poll
Pablo Greco e6a3ae
    > #17 0x00005586607885da in run_poll_handlers_once
Pablo Greco e6a3ae
    > #18 0x000055866078880e in try_poll_mode
Pablo Greco e6a3ae
    > #19 0x00005586607888eb in aio_poll
Pablo Greco e6a3ae
    > #20 0x0000558660784561 in aio_wait_bh_oneshot
Pablo Greco e6a3ae
    > #21 0x00005586602b9582 in virtio_scsi_dataplane_stop
Pablo Greco e6a3ae
    > #22 0x00005586605a7110 in virtio_bus_stop_ioeventfd
Pablo Greco e6a3ae
    > #23 0x00005586605a9426 in virtio_pci_stop_ioeventfd
Pablo Greco e6a3ae
    > #24 0x00005586605ab808 in virtio_pci_common_write
Pablo Greco e6a3ae
    > #25 0x0000558660242396 in memory_region_write_accessor
Pablo Greco e6a3ae
    > #26 0x00005586602425ab in access_with_adjusted_size
Pablo Greco e6a3ae
    > #27 0x0000558660245281 in memory_region_dispatch_write
Pablo Greco e6a3ae
    > #28 0x00005586601e008e in flatview_write_continue
Pablo Greco e6a3ae
    > #29 0x00005586601e01d8 in flatview_write
Pablo Greco e6a3ae
    > #30 0x00005586601e04de in address_space_write
Pablo Greco e6a3ae
    > #31 0x00005586601e052f in address_space_rw
Pablo Greco e6a3ae
    > #32 0x00005586602607f2 in kvm_cpu_exec
Pablo Greco e6a3ae
    > #33 0x0000558660227148 in qemu_kvm_cpu_thread_fn
Pablo Greco e6a3ae
    > #34 0x000055866078bde7 in qemu_thread_start
Pablo Greco e6a3ae
    > #35 0x00007f5784906594 in start_thread
Pablo Greco e6a3ae
    > #36 0x00007f5784639e6f in clone
Pablo Greco e6a3ae
Pablo Greco e6a3ae
With this patch, virtio_queue_empty will now return 1 as soon as the
Pablo Greco e6a3ae
vdev is marked as broken, after a "virtio: zero sized buffers are not
Pablo Greco e6a3ae
allowed" error.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
To be consistent, update virtio_queue_empty_rcu as well.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Signed-off-by: Fam Zheng <famz@redhat.com>
Pablo Greco e6a3ae
Message-Id: <20180910145616.8598-2-famz@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Pablo Greco e6a3ae
(cherry picked from commit 2d1df8591022737b8ef19d681ff74eda389f5198)
Pablo Greco e6a3ae
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Pablo Greco e6a3ae
---
Pablo Greco e6a3ae
 hw/virtio/virtio.c | 8 ++++++++
Pablo Greco e6a3ae
 1 file changed, 8 insertions(+)
Pablo Greco e6a3ae
Pablo Greco e6a3ae
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
Pablo Greco e6a3ae
index 1debb01..fce199e 100644
Pablo Greco e6a3ae
--- a/hw/virtio/virtio.c
Pablo Greco e6a3ae
+++ b/hw/virtio/virtio.c
Pablo Greco e6a3ae
@@ -344,6 +344,10 @@ int virtio_queue_ready(VirtQueue *vq)
Pablo Greco e6a3ae
  * Called within rcu_read_lock().  */
Pablo Greco e6a3ae
 static int virtio_queue_empty_rcu(VirtQueue *vq)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
+    if (unlikely(vq->vdev->broken)) {
Pablo Greco e6a3ae
+        return 1;
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
     if (unlikely(!vq->vring.avail)) {
Pablo Greco e6a3ae
         return 1;
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
@@ -359,6 +363,10 @@ int virtio_queue_empty(VirtQueue *vq)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     bool empty;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+    if (unlikely(vq->vdev->broken)) {
Pablo Greco e6a3ae
+        return 1;
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
     if (unlikely(!vq->vring.avail)) {
Pablo Greco e6a3ae
         return 1;
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
-- 
Pablo Greco e6a3ae
1.8.3.1
Pablo Greco e6a3ae