Blame SOURCES/kvm-virtio-don-t-enable-notifications-during-polling.patch

ddf19c
From 351dd07d7b5e69cdf47260c9ea848c0c93cd2c8a Mon Sep 17 00:00:00 2001
ddf19c
From: Stefan Hajnoczi <stefanha@redhat.com>
ddf19c
Date: Thu, 9 Jan 2020 11:13:25 +0000
ddf19c
Subject: [PATCH 3/5] virtio: don't enable notifications during polling
ddf19c
ddf19c
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
ddf19c
Message-id: <20200109111325.559557-2-stefanha@redhat.com>
ddf19c
Patchwork-id: 93298
ddf19c
O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 1/1] virtio: don't enable notifications during polling
ddf19c
Bugzilla: 1789301
ddf19c
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
ddf19c
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
ddf19c
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
ddf19c
ddf19c
Virtqueue notifications are not necessary during polling, so we disable
ddf19c
them.  This allows the guest driver to avoid MMIO vmexits.
ddf19c
Unfortunately the virtio-blk and virtio-scsi handler functions re-enable
ddf19c
notifications, defeating this optimization.
ddf19c
ddf19c
Fix virtio-blk and virtio-scsi emulation so they leave notifications
ddf19c
disabled.  The key thing to remember for correctness is that polling
ddf19c
always checks one last time after ending its loop, therefore it's safe
ddf19c
to lose the race when re-enabling notifications at the end of polling.
ddf19c
ddf19c
There is a measurable performance improvement of 5-10% with the null-co
ddf19c
block driver.  Real-life storage configurations will see a smaller
ddf19c
improvement because the MMIO vmexit overhead contributes less to
ddf19c
latency.
ddf19c
ddf19c
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
ddf19c
Message-Id: <20191209210957.65087-1-stefanha@redhat.com>
ddf19c
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
ddf19c
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
ddf19c
(cherry picked from commit d0435bc513e23a4961b6af20164d1c6c219eb4ea)
ddf19c
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
ddf19c
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ddf19c
---
ddf19c
 hw/block/virtio-blk.c      |  9 +++++++--
ddf19c
 hw/scsi/virtio-scsi.c      |  9 +++++++--
ddf19c
 hw/virtio/virtio.c         | 12 ++++++------
ddf19c
 include/hw/virtio/virtio.h |  1 +
ddf19c
 4 files changed, 21 insertions(+), 10 deletions(-)
ddf19c
ddf19c
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
ddf19c
index 4c357d2..c4e55fb 100644
ddf19c
--- a/hw/block/virtio-blk.c
ddf19c
+++ b/hw/block/virtio-blk.c
ddf19c
@@ -764,13 +764,16 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
ddf19c
 {
ddf19c
     VirtIOBlockReq *req;
ddf19c
     MultiReqBuffer mrb = {};
ddf19c
+    bool suppress_notifications = virtio_queue_get_notification(vq);
ddf19c
     bool progress = false;
ddf19c
 
ddf19c
     aio_context_acquire(blk_get_aio_context(s->blk));
ddf19c
     blk_io_plug(s->blk);
ddf19c
 
ddf19c
     do {
ddf19c
-        virtio_queue_set_notification(vq, 0);
ddf19c
+        if (suppress_notifications) {
ddf19c
+            virtio_queue_set_notification(vq, 0);
ddf19c
+        }
ddf19c
 
ddf19c
         while ((req = virtio_blk_get_request(s, vq))) {
ddf19c
             progress = true;
ddf19c
@@ -781,7 +784,9 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
ddf19c
             }
ddf19c
         }
ddf19c
 
ddf19c
-        virtio_queue_set_notification(vq, 1);
ddf19c
+        if (suppress_notifications) {
ddf19c
+            virtio_queue_set_notification(vq, 1);
ddf19c
+        }
ddf19c
     } while (!virtio_queue_empty(vq));
ddf19c
 
ddf19c
     if (mrb.num_reqs) {
ddf19c
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
ddf19c
index 54108c0..e2cd1df 100644
ddf19c
--- a/hw/scsi/virtio-scsi.c
ddf19c
+++ b/hw/scsi/virtio-scsi.c
ddf19c
@@ -597,12 +597,15 @@ bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
ddf19c
 {
ddf19c
     VirtIOSCSIReq *req, *next;
ddf19c
     int ret = 0;
ddf19c
+    bool suppress_notifications = virtio_queue_get_notification(vq);
ddf19c
     bool progress = false;
ddf19c
 
ddf19c
     QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
ddf19c
 
ddf19c
     do {
ddf19c
-        virtio_queue_set_notification(vq, 0);
ddf19c
+        if (suppress_notifications) {
ddf19c
+            virtio_queue_set_notification(vq, 0);
ddf19c
+        }
ddf19c
 
ddf19c
         while ((req = virtio_scsi_pop_req(s, vq))) {
ddf19c
             progress = true;
ddf19c
@@ -622,7 +625,9 @@ bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
ddf19c
             }
ddf19c
         }
ddf19c
 
ddf19c
-        virtio_queue_set_notification(vq, 1);
ddf19c
+        if (suppress_notifications) {
ddf19c
+            virtio_queue_set_notification(vq, 1);
ddf19c
+        }
ddf19c
     } while (ret != -EINVAL && !virtio_queue_empty(vq));
ddf19c
 
ddf19c
     QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
ddf19c
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
ddf19c
index 04716b5..3211135 100644
ddf19c
--- a/hw/virtio/virtio.c
ddf19c
+++ b/hw/virtio/virtio.c
ddf19c
@@ -432,6 +432,11 @@ static void virtio_queue_packed_set_notification(VirtQueue *vq, int enable)
ddf19c
     }
ddf19c
 }
ddf19c
 
ddf19c
+bool virtio_queue_get_notification(VirtQueue *vq)
ddf19c
+{
ddf19c
+    return vq->notification;
ddf19c
+}
ddf19c
+
ddf19c
 void virtio_queue_set_notification(VirtQueue *vq, int enable)
ddf19c
 {
ddf19c
     vq->notification = enable;
ddf19c
@@ -3384,17 +3389,12 @@ static bool virtio_queue_host_notifier_aio_poll(void *opaque)
ddf19c
 {
ddf19c
     EventNotifier *n = opaque;
ddf19c
     VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
ddf19c
-    bool progress;
ddf19c
 
ddf19c
     if (!vq->vring.desc || virtio_queue_empty(vq)) {
ddf19c
         return false;
ddf19c
     }
ddf19c
 
ddf19c
-    progress = virtio_queue_notify_aio_vq(vq);
ddf19c
-
ddf19c
-    /* In case the handler function re-enabled notifications */
ddf19c
-    virtio_queue_set_notification(vq, 0);
ddf19c
-    return progress;
ddf19c
+    return virtio_queue_notify_aio_vq(vq);
ddf19c
 }
ddf19c
 
ddf19c
 static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n)
ddf19c
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
ddf19c
index c32a815..6a20442 100644
ddf19c
--- a/include/hw/virtio/virtio.h
ddf19c
+++ b/include/hw/virtio/virtio.h
ddf19c
@@ -224,6 +224,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id);
ddf19c
 
ddf19c
 void virtio_notify_config(VirtIODevice *vdev);
ddf19c
 
ddf19c
+bool virtio_queue_get_notification(VirtQueue *vq);
ddf19c
 void virtio_queue_set_notification(VirtQueue *vq, int enable);
ddf19c
 
ddf19c
 int virtio_queue_ready(VirtQueue *vq);
ddf19c
-- 
ddf19c
1.8.3.1
ddf19c