From fb0679d236e40cb4fa29ca9a1465b0ac1fbf8f44 Mon Sep 17 00:00:00 2001 From: yezengruan Date: Thu, 25 Aug 2022 12:39:12 +0800 Subject: [PATCH] Qemu update to version 10:6.2.0-46 vhost-user: remove VirtQ notifier restore vhost-user: fix VirtQ notifier cleanup enable vDPA build params Provides qemu-kvm for upgrade Signed-off-by: yezengruan (cherry picked from commit a6c5c96c0b65904db08e803692a01447553a725a) --- qemu.spec | 21 ++- vhost-user-fix-VirtQ-notifier-cleanup.patch | 151 ++++++++++++++++++ ...t-user-remove-VirtQ-notifier-restore.patch | 100 ++++++++++++ 3 files changed, 270 insertions(+), 2 deletions(-) create mode 100644 vhost-user-fix-VirtQ-notifier-cleanup.patch create mode 100644 vhost-user-remove-VirtQ-notifier-restore.patch diff --git a/qemu.spec b/qemu.spec index ebe08ff..acaa3fb 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,7 +1,7 @@ Name: qemu Version: 6.2.0 -Release: 45 -Epoch: 2 +Release: 46 +Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 URL: http://www.qemu.org @@ -292,6 +292,8 @@ Patch0278: target-ppc-enhance-error-report-in-kvmppc_read_int_c.patch Patch0279: target-ppc-use-g_autofree-in-kvmppc_read_int_cpu_dt.patch Patch0280: target-ppc-exit-1-on-failure-in-kvmppc_get_clockfreq.patch Patch0281: bugfix-pointer-double-free-in-func-qemu_savevm_state.patch +Patch0282: vhost-user-remove-VirtQ-notifier-restore.patch +Patch0283: vhost-user-fix-VirtQ-notifier-cleanup.patch BuildRequires: flex BuildRequires: gcc @@ -342,6 +344,10 @@ BuildRequires: glib2 BuildRequires: libfdt-devel BuildRequires: virglrenderer-devel +# for upgrade from qemu-kvm +Provides: qemu-kvm +Obsoletes: qemu-kvm < 10:6.2.0 + Requires(post): /usr/bin/getent Requires(post): /usr/sbin/groupadd Requires(post): /usr/sbin/useradd @@ -498,6 +504,11 @@ cd ../ --enable-linux-aio \ --enable-cap-ng \ --enable-vhost-user \ + --enable-vhost-net \ + --enable-vhost-kernel \ + --enable-vhost-user-blk-server \ + --enable-vhost-vdpa \ + --enable-vhost-vsock \ --enable-tpm \ --enable-modules \ --enable-libssh \ @@ -795,6 +806,12 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Thu Aug 25 2022 yezengruan - 10:6.2.0-46 +- vhost-user: remove VirtQ notifier restore +- vhost-user: fix VirtQ notifier cleanup +- enable vDPA build params +- Provides qemu-kvm for upgrade + * Thu Aug 11 2022 yezengruan - 2:6.2.0-45 - numa: Enable numa for SGX EPC sections - target/ppc: enhance error handling in kvmppc_read_int* diff --git a/vhost-user-fix-VirtQ-notifier-cleanup.patch b/vhost-user-fix-VirtQ-notifier-cleanup.patch new file mode 100644 index 0000000..96bba60 --- /dev/null +++ b/vhost-user-fix-VirtQ-notifier-cleanup.patch @@ -0,0 +1,151 @@ +From 0d022f741ab510b52453bb9e9e07b968e7d5e0df Mon Sep 17 00:00:00 2001 +From: Xueming Li +Date: Mon, 7 Feb 2022 15:19:29 +0800 +Subject: [PATCH 2/2] vhost-user: fix VirtQ notifier cleanup + +When vhost-user device cleanup, remove notifier MR and munmaps notifier +address in the event-handling thread, VM CPU thread writing the notifier +in concurrent fails with an error of accessing invalid address. It +happens because MR is still being referenced and accessed in another +thread while the underlying notifier mmap address is being freed and +becomes invalid. + +This patch calls RCU and munmap notifiers in the callback after the +memory flatview update finish. + +Fixes: 44866521bd6e ("vhost-user: support registering external host notifiers") +Cc: qemu-stable@nongnu.org +Signed-off-by: Xueming Li +Message-Id: <20220207071929.527149-3-xuemingl@nvidia.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 0b0af4d62f7002b31cd7b2762b26d2fcb76bb2ba) +--- + hw/virtio/vhost-user.c | 48 ++++++++++++++++++++-------------- + include/hw/virtio/vhost-user.h | 2 ++ + 2 files changed, 31 insertions(+), 19 deletions(-) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index 7b21e09723..42a9e16cd9 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -26,6 +26,7 @@ + #include "migration/postcopy-ram.h" + #include "migration/register.h" + #include "trace.h" ++#include "exec/ramblock.h" + + #include + #include +@@ -1145,15 +1146,26 @@ static int vhost_user_set_vring_num(struct vhost_dev *dev, + return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring); + } + +-static void vhost_user_host_notifier_remove(struct vhost_dev *dev, +- int queue_idx) ++static void vhost_user_host_notifier_free(VhostUserHostNotifier *n) + { +- struct vhost_user *u = dev->opaque; +- VhostUserHostNotifier *n = &u->user->notifier[queue_idx]; +- VirtIODevice *vdev = dev->vdev; ++ assert(n && n->unmap_addr); ++ munmap(n->unmap_addr, qemu_real_host_page_size); ++ n->unmap_addr = NULL; ++} ++ ++static void vhost_user_host_notifier_remove(VhostUserState *user, ++ VirtIODevice *vdev, int queue_idx) ++{ ++ VhostUserHostNotifier *n = &user->notifier[queue_idx]; + + if (n->addr) { +- virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); ++ if (vdev) { ++ virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); ++ } ++ assert(!n->unmap_addr); ++ n->unmap_addr = n->addr; ++ n->addr = NULL; ++ call_rcu(n, vhost_user_host_notifier_free, rcu); + } + } + +@@ -1192,8 +1204,9 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev, + .payload.state = *ring, + .hdr.size = sizeof(msg.payload.state), + }; ++ struct vhost_user *u = dev->opaque; + +- vhost_user_host_notifier_remove(dev, ring->index); ++ vhost_user_host_notifier_remove(u->user, dev->vdev, ring->index); + + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + return -1; +@@ -1488,12 +1501,7 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, + + n = &user->notifier[queue_idx]; + +- if (n->addr) { +- virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); +- object_unparent(OBJECT(&n->mr)); +- munmap(n->addr, page_size); +- n->addr = NULL; +- } ++ vhost_user_host_notifier_remove(user, vdev, queue_idx); + + if (area->u64 & VHOST_USER_VRING_NOFD_MASK) { + return 0; +@@ -1512,9 +1520,12 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, + + name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]", + user, queue_idx); +- if (!n->mr.ram) /* Don't init again after suspend. */ ++ if (!n->mr.ram) { /* Don't init again after suspend. */ + memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name, + page_size, addr); ++ } else { ++ n->mr.ram_block->host = addr; ++ } + g_free(name); + + if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) { +@@ -2492,17 +2503,16 @@ bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp) + void vhost_user_cleanup(VhostUserState *user) + { + int i; ++ VhostUserHostNotifier *n; + + if (!user->chr) { + return; + } + memory_region_transaction_begin(); + for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { +- if (user->notifier[i].addr) { +- object_unparent(OBJECT(&user->notifier[i].mr)); +- munmap(user->notifier[i].addr, qemu_real_host_page_size); +- user->notifier[i].addr = NULL; +- } ++ n = &user->notifier[i]; ++ vhost_user_host_notifier_remove(user, NULL, i); ++ object_unparent(OBJECT(&n->mr)); + } + memory_region_transaction_commit(); + user->chr = NULL; +diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h +index f6012b2078..e44a41bb70 100644 +--- a/include/hw/virtio/vhost-user.h ++++ b/include/hw/virtio/vhost-user.h +@@ -12,8 +12,10 @@ + #include "hw/virtio/virtio.h" + + typedef struct VhostUserHostNotifier { ++ struct rcu_head rcu; + MemoryRegion mr; + void *addr; ++ void *unmap_addr; + } VhostUserHostNotifier; + + typedef struct VhostUserState { +-- +2.27.0 + diff --git a/vhost-user-remove-VirtQ-notifier-restore.patch b/vhost-user-remove-VirtQ-notifier-restore.patch new file mode 100644 index 0000000..fae278a --- /dev/null +++ b/vhost-user-remove-VirtQ-notifier-restore.patch @@ -0,0 +1,100 @@ +From f06e65cb747cbd32f4d12f1d880625c14a8bd9da Mon Sep 17 00:00:00 2001 +From: Xueming Li +Date: Mon, 7 Feb 2022 15:19:28 +0800 +Subject: [PATCH 1/2] vhost-user: remove VirtQ notifier restore + +Notifier set when vhost-user backend asks qemu to mmap an FD and +offset. When vhost-user backend restart or getting killed, VQ notifier +FD and mmap addresses become invalid. After backend restart, MR contains +the invalid address will be restored and fail on notifier access. + +On the other hand, qemu should munmap the notifier, release underlying +hardware resources to enable backend restart and allocate hardware +notifier resources correctly. + +Qemu shouldn't reference and use resources of disconnected backend. + +This patch removes VQ notifier restore, uses the default vhost-user +notifier to avoid invalid address access. + +After backend restart, the backend should ask qemu to install a hardware +notifier if needed. + +Fixes: 44866521bd6e ("vhost-user: support registering external host notifiers") +Cc: qemu-stable@nongnu.org +Signed-off-by: Xueming Li +Message-Id: <20220207071929.527149-2-xuemingl@nvidia.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit e867144b73b3c5009266b6df07d5ff44acfb82c3) +--- + hw/virtio/vhost-user.c | 19 +------------------ + include/hw/virtio/vhost-user.h | 1 - + 2 files changed, 1 insertion(+), 19 deletions(-) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index 176cae9244..7b21e09723 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -1145,19 +1145,6 @@ static int vhost_user_set_vring_num(struct vhost_dev *dev, + return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring); + } + +-static void vhost_user_host_notifier_restore(struct vhost_dev *dev, +- int queue_idx) +-{ +- struct vhost_user *u = dev->opaque; +- VhostUserHostNotifier *n = &u->user->notifier[queue_idx]; +- VirtIODevice *vdev = dev->vdev; +- +- if (n->addr && !n->set) { +- virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true); +- n->set = true; +- } +-} +- + static void vhost_user_host_notifier_remove(struct vhost_dev *dev, + int queue_idx) + { +@@ -1165,17 +1152,14 @@ static void vhost_user_host_notifier_remove(struct vhost_dev *dev, + VhostUserHostNotifier *n = &u->user->notifier[queue_idx]; + VirtIODevice *vdev = dev->vdev; + +- if (n->addr && n->set) { ++ if (n->addr) { + virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); +- n->set = false; + } + } + + static int vhost_user_set_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) + { +- vhost_user_host_notifier_restore(dev, ring->index); +- + return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring); + } + +@@ -1540,7 +1524,6 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, + } + + n->addr = addr; +- n->set = true; + + return 0; + } +diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h +index a9abca3288..f6012b2078 100644 +--- a/include/hw/virtio/vhost-user.h ++++ b/include/hw/virtio/vhost-user.h +@@ -14,7 +14,6 @@ + typedef struct VhostUserHostNotifier { + MemoryRegion mr; + void *addr; +- bool set; + } VhostUserHostNotifier; + + typedef struct VhostUserState { +-- +2.27.0 + -- Gitee