qemu/virtio-don-t-enable-notifications-during.patch
Bruce Rogers 405ca57e69 Accepting request 784401 from home:bfrogers:branches:Virtualization
- Include upstream patches targeted for the next stable release
  (bug fixes only)
  audio-oss-fix-buffer-pos-calculation.patch
  blkdebug-Allow-taking-unsharing-permissi.patch
  block-Add-bdrv_qapi_perm_to_blk_perm.patch
  block-backup-top-fix-failure-path.patch
  block-block-copy-fix-progress-calculatio.patch
  block-fix-crash-on-zero-length-unaligned.patch
  block-fix-memleaks-in-bdrv_refresh_filen.patch
  block-Fix-VM-size-field-width-in-snapsho.patch
  block-nbd-extract-the-common-cleanup-cod.patch
  block-nbd-fix-memory-leak-in-nbd_open.patch
  block-qcow2-threads-fix-qcow2_decompress.patch
  hw-arm-cubieboard-use-ARM-Cortex-A8-as-t.patch
  hw-intc-arm_gicv3_kvm-Stop-wrongly-progr.patch
  iotests-add-test-for-backup-top-failure-.patch
  iotests-Fix-nonportable-use-of-od-endian.patch
  job-refactor-progress-to-separate-object.patch
  target-arm-Correct-definition-of-PMCRDP.patch
  target-arm-fix-TCG-leak-for-fcvt-half-do.patch
  tpm-ppi-page-align-PPI-RAM.patch
  vhost-user-blk-delete-virtioqueues-in-un.patch
  virtio-add-ability-to-delete-vq-through-.patch
  virtio-crypto-do-delete-ctrl_vq-in-virti.patch
  virtio-pmem-do-delete-rq_vq-in-virtio_pm.patch
- Add Obsoletes directive for qemu-audio-sdl and qemu-ui-sdl since
  for a qemu package upgrade from SLE12-SP5, support for SDL is
  dropped

OBS-URL: https://build.opensuse.org/request/show/784401
OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=534
2020-03-12 19:48:43 +00:00

146 lines
5.0 KiB
Diff

From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Mon, 9 Dec 2019 21:09:57 +0000
Subject: virtio: don't enable notifications during polling
Git-commit: d0435bc513e23a4961b6af20164d1c6c219eb4ea
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>
Signed-off-by: Bruce Rogers <brogers@suse.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 4c357d2928ff1cfe94a601c93ffa..c4e55fb3defb711dbc39b67e00a1 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -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 e8b2b64d09fb185404fa83882ba9..f080545f48e6a3e411caf641b935 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -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 31dd140990f784884b541b293105..d63a3691bf00e9d7951b2c85ef5f 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -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;
@@ -3389,17 +3394,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 e18756d50d21259dda81bf1d1b1d..91167f609aca8f50948b1b28fdf2 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -226,6 +226,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);