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

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