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