diff --git a/kvm-memory-Fix-up-memory_region_-add-del-_coalescing.patch b/kvm-memory-Fix-up-memory_region_-add-del-_coalescing.patch new file mode 100644 index 0000000..021125e --- /dev/null +++ b/kvm-memory-Fix-up-memory_region_-add-del-_coalescing.patch @@ -0,0 +1,118 @@ +From b9b48ed46d2b0a3dd6e8406946eb0516ec75a004 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Fri, 23 Aug 2019 06:14:31 +0100 +Subject: [PATCH 4/5] memory: Fix up memory_region_{add|del}_coalescing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +Message-id: <20190823061431.31759-5-peterx@redhat.com> +Patchwork-id: 90136 +O-Subject: [RHEL-AV-8.1 qemu-kvm PATCH 4/4] memory: Fix up memory_region_{add|del}_coalescing +Bugzilla: 1743142 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Philippe Mathieu-Daudé + +The old memory_region_{add|clear}_coalescing() has some defects +because they both changed mr->coalesced before updating the regions +using memory_region_update_coalesced_range_as(). Then when the +regions were updated in memory_region_update_coalesced_range_as() the +mr->coalesced will always be either one more or one less. So: + +- For memory_region_add_coalescing: it'll always trying to remove the + newly added coalesced region while it shouldn't, and, + +- For memory_region_clear_coalescing: when it calls the update there + will be no coalesced ranges on mr->coalesced because they were all + removed before hand so the update will probably do nothing for real. + +Let's fix this. Now we've got flat_range_coalesced_io_notify() to +notify a single CoalescedMemoryRange instance change, so use it in the +existing memory_region_update_coalesced_range() logic by only notify +either an addition or deletion. Then we hammer both the +memory_region_{add|clear}_coalescing() to use it. + +Fixes: 3ac7d43a6fbb5d4a3 +Signed-off-by: Peter Xu +Message-Id: <20190820141328.10009-5-peterx@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit b960fc1796fb078c21121abf01499603b66b3f57) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + memory.c | 36 +++++++++++++++++------------------- + 1 file changed, 17 insertions(+), 19 deletions(-) + +diff --git a/memory.c b/memory.c +index c7cd43f..2f15180 100644 +--- a/memory.c ++++ b/memory.c +@@ -2238,27 +2238,26 @@ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp + qemu_ram_resize(mr->ram_block, newsize, errp); + } + +-static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as) ++/* ++ * Call proper memory listeners about the change on the newly ++ * added/removed CoalescedMemoryRange. ++ */ ++static void memory_region_update_coalesced_range(MemoryRegion *mr, ++ CoalescedMemoryRange *cmr, ++ bool add) + { ++ AddressSpace *as; + FlatView *view; + FlatRange *fr; + +- view = address_space_get_flatview(as); +- FOR_EACH_FLAT_RANGE(fr, view) { +- if (fr->mr == mr) { +- flat_range_coalesced_io_del(fr, as); +- flat_range_coalesced_io_add(fr, as); +- } +- } +- flatview_unref(view); +-} +- +-static void memory_region_update_coalesced_range(MemoryRegion *mr) +-{ +- AddressSpace *as; +- + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { +- memory_region_update_coalesced_range_as(mr, as); ++ view = address_space_get_flatview(as); ++ FOR_EACH_FLAT_RANGE(fr, view) { ++ if (fr->mr == mr) { ++ flat_range_coalesced_io_notify(fr, as, cmr, add); ++ } ++ } ++ flatview_unref(view); + } + } + +@@ -2276,7 +2275,7 @@ void memory_region_add_coalescing(MemoryRegion *mr, + + cmr->addr = addrrange_make(int128_make64(offset), int128_make64(size)); + QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link); +- memory_region_update_coalesced_range(mr); ++ memory_region_update_coalesced_range(mr, cmr, true); + memory_region_set_flush_coalesced(mr); + } + +@@ -2294,10 +2293,9 @@ void memory_region_clear_coalescing(MemoryRegion *mr) + while (!QTAILQ_EMPTY(&mr->coalesced)) { + cmr = QTAILQ_FIRST(&mr->coalesced); + QTAILQ_REMOVE(&mr->coalesced, cmr, link); ++ memory_region_update_coalesced_range(mr, cmr, false); + g_free(cmr); + } +- +- memory_region_update_coalesced_range(mr); + } + + void memory_region_set_flush_coalesced(MemoryRegion *mr) +-- +1.8.3.1 + diff --git a/kvm-memory-Refactor-memory_region_clear_coalescing.patch b/kvm-memory-Refactor-memory_region_clear_coalescing.patch new file mode 100644 index 0000000..6ea7ce5 --- /dev/null +++ b/kvm-memory-Refactor-memory_region_clear_coalescing.patch @@ -0,0 +1,64 @@ +From 134ab69ffdfb7e45a0be385595036d0427928306 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Fri, 23 Aug 2019 06:14:28 +0100 +Subject: [PATCH 1/5] memory: Refactor memory_region_clear_coalescing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +Message-id: <20190823061431.31759-2-peterx@redhat.com> +Patchwork-id: 90134 +O-Subject: [RHEL-AV-8.1 qemu-kvm PATCH 1/4] memory: Refactor memory_region_clear_coalescing +Bugzilla: 1743142 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Philippe Mathieu-Daudé + +Removing the update variable and quit earlier if the memory region has +no coalesced range. This prepares for the next patch. + +Fixes: 3ac7d43a6fbb5d4a3 +Signed-off-by: Peter Xu +Message-Id: <20190820141328.10009-4-peterx@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 9c1aa1c235c770d84462d482460a96e957e95b9c) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + memory.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/memory.c b/memory.c +index 5d8c9a9..9f40742 100644 +--- a/memory.c ++++ b/memory.c +@@ -2276,7 +2276,10 @@ void memory_region_add_coalescing(MemoryRegion *mr, + void memory_region_clear_coalescing(MemoryRegion *mr) + { + CoalescedMemoryRange *cmr; +- bool updated = false; ++ ++ if (QTAILQ_EMPTY(&mr->coalesced)) { ++ return; ++ } + + qemu_flush_coalesced_mmio_buffer(); + mr->flush_coalesced_mmio = false; +@@ -2285,12 +2288,9 @@ void memory_region_clear_coalescing(MemoryRegion *mr) + cmr = QTAILQ_FIRST(&mr->coalesced); + QTAILQ_REMOVE(&mr->coalesced, cmr, link); + g_free(cmr); +- updated = true; + } + +- if (updated) { +- memory_region_update_coalesced_range(mr); +- } ++ memory_region_update_coalesced_range(mr); + } + + void memory_region_set_flush_coalesced(MemoryRegion *mr) +-- +1.8.3.1 + diff --git a/kvm-memory-Remove-has_coalesced_range-counter.patch b/kvm-memory-Remove-has_coalesced_range-counter.patch new file mode 100644 index 0000000..d98baa2 --- /dev/null +++ b/kvm-memory-Remove-has_coalesced_range-counter.patch @@ -0,0 +1,96 @@ +From c1db31bce6d2e5f49e34a2e7282e50bea3f92278 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Fri, 23 Aug 2019 06:14:30 +0100 +Subject: [PATCH 3/5] memory: Remove has_coalesced_range counter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +Message-id: <20190823061431.31759-4-peterx@redhat.com> +Patchwork-id: 90135 +O-Subject: [RHEL-AV-8.1 qemu-kvm PATCH 3/4] memory: Remove has_coalesced_range counter +Bugzilla: 1743142 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Philippe Mathieu-Daudé + +The has_coalesced_range could potentially be problematic in that it +only works for additions of coalesced mmio ranges but not deletions. +The reason is that has_coalesced_range information can be lost when +the FlatView updates the topology again when the updated region is not +covering the coalesced regions. When that happens, due to +flatrange_equal() is not checking against has_coalesced_range, the new +FlatRange will be seen as the same one as the old and the new +instance (whose has_coalesced_range will be zero) will replace the old +instance (whose has_coalesced_range _could_ be non-zero). + +The counter was originally used to make sure every FlatRange will only +notify once for coalesced_io_{add|del} memory listeners, because each +FlatRange can be used by multiple address spaces, so logically +speaking it could be called multiple times. However we should not +limit that, because memory listeners should will only be registered +with specific address space rather than multiple address spaces. + +So let's fix this up by simply removing the whole has_coalesced_range. + +Fixes: 3ac7d43a6fbb5d4a3 +Signed-off-by: Peter Xu +Message-Id: <20190820141328.10009-3-peterx@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 264ef5a5c52c249ff51a16d141fc03df71714a13) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + memory.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/memory.c b/memory.c +index 7b24cb8..c7cd43f 100644 +--- a/memory.c ++++ b/memory.c +@@ -217,7 +217,6 @@ struct FlatRange { + bool romd_mode; + bool readonly; + bool nonvolatile; +- int has_coalesced_range; + }; + + #define FOR_EACH_FLAT_RANGE(var, view) \ +@@ -654,7 +653,6 @@ static void render_memory_region(FlatView *view, + fr.romd_mode = mr->romd_mode; + fr.readonly = readonly; + fr.nonvolatile = nonvolatile; +- fr.has_coalesced_range = 0; + + /* Render the region itself into any gaps left by the current view. */ + for (i = 0; i < view->nr && int128_nz(remain); ++i) { +@@ -888,14 +886,6 @@ static void flat_range_coalesced_io_del(FlatRange *fr, AddressSpace *as) + { + CoalescedMemoryRange *cmr; + +- if (!fr->has_coalesced_range) { +- return; +- } +- +- if (--fr->has_coalesced_range > 0) { +- return; +- } +- + QTAILQ_FOREACH(cmr, &fr->mr->coalesced, link) { + flat_range_coalesced_io_notify(fr, as, cmr, false); + } +@@ -910,10 +900,6 @@ static void flat_range_coalesced_io_add(FlatRange *fr, AddressSpace *as) + return; + } + +- if (fr->has_coalesced_range++) { +- return; +- } +- + QTAILQ_FOREACH(cmr, &mr->coalesced, link) { + flat_range_coalesced_io_notify(fr, as, cmr, true); + } +-- +1.8.3.1 + diff --git a/kvm-memory-Split-zones-when-do-coalesced_io_del.patch b/kvm-memory-Split-zones-when-do-coalesced_io_del.patch new file mode 100644 index 0000000..498cd26 --- /dev/null +++ b/kvm-memory-Split-zones-when-do-coalesced_io_del.patch @@ -0,0 +1,123 @@ +From bdd5394047f7fbecac82d067b9e67db8a20c49d2 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Fri, 23 Aug 2019 06:14:29 +0100 +Subject: [PATCH 2/5] memory: Split zones when do coalesced_io_del() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +Message-id: <20190823061431.31759-3-peterx@redhat.com> +Patchwork-id: 90133 +O-Subject: [RHEL-AV-8.1 qemu-kvm PATCH 2/4] memory: Split zones when do coalesced_io_del() +Bugzilla: 1743142 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Philippe Mathieu-Daudé + +It is a workaround of current KVM's KVM_UNREGISTER_COALESCED_MMIO +interface. The kernel interface only allows to unregister an mmio +device with exactly the zone size when registered, or any smaller zone +that is included in the device mmio zone. It does not support the +userspace to specify a very large zone to remove all the small mmio +devices within the zone covered. + +Logically speaking it would be nicer to fix this from KVM side, though +in all cases we still need to coop with old kernels so let's do this. + +Fixes: 3ac7d43a6fbb5d4a3 +Signed-off-by: Peter Xu +Message-Id: <20190820141328.10009-2-peterx@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 23f1174aac4181f86bb7e13ca8bc2d4a0bdf1e5c) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + memory.c | 49 +++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 35 insertions(+), 14 deletions(-) + +diff --git a/memory.c b/memory.c +index 9f40742..7b24cb8 100644 +--- a/memory.c ++++ b/memory.c +@@ -855,8 +855,39 @@ static void address_space_update_ioeventfds(AddressSpace *as) + flatview_unref(view); + } + ++/* ++ * Notify the memory listeners about the coalesced IO change events of ++ * range `cmr'. Only the part that has intersection of the specified ++ * FlatRange will be sent. ++ */ ++static void flat_range_coalesced_io_notify(FlatRange *fr, AddressSpace *as, ++ CoalescedMemoryRange *cmr, bool add) ++{ ++ AddrRange tmp; ++ ++ tmp = addrrange_shift(cmr->addr, ++ int128_sub(fr->addr.start, ++ int128_make64(fr->offset_in_region))); ++ if (!addrrange_intersects(tmp, fr->addr)) { ++ return; ++ } ++ tmp = addrrange_intersection(tmp, fr->addr); ++ ++ if (add) { ++ MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, coalesced_io_add, ++ int128_get64(tmp.start), ++ int128_get64(tmp.size)); ++ } else { ++ MEMORY_LISTENER_UPDATE_REGION(fr, as, Reverse, coalesced_io_del, ++ int128_get64(tmp.start), ++ int128_get64(tmp.size)); ++ } ++} ++ + static void flat_range_coalesced_io_del(FlatRange *fr, AddressSpace *as) + { ++ CoalescedMemoryRange *cmr; ++ + if (!fr->has_coalesced_range) { + return; + } +@@ -865,16 +896,15 @@ static void flat_range_coalesced_io_del(FlatRange *fr, AddressSpace *as) + return; + } + +- MEMORY_LISTENER_UPDATE_REGION(fr, as, Reverse, coalesced_io_del, +- int128_get64(fr->addr.start), +- int128_get64(fr->addr.size)); ++ QTAILQ_FOREACH(cmr, &fr->mr->coalesced, link) { ++ flat_range_coalesced_io_notify(fr, as, cmr, false); ++ } + } + + static void flat_range_coalesced_io_add(FlatRange *fr, AddressSpace *as) + { + MemoryRegion *mr = fr->mr; + CoalescedMemoryRange *cmr; +- AddrRange tmp; + + if (QTAILQ_EMPTY(&mr->coalesced)) { + return; +@@ -885,16 +915,7 @@ static void flat_range_coalesced_io_add(FlatRange *fr, AddressSpace *as) + } + + QTAILQ_FOREACH(cmr, &mr->coalesced, link) { +- tmp = addrrange_shift(cmr->addr, +- int128_sub(fr->addr.start, +- int128_make64(fr->offset_in_region))); +- if (!addrrange_intersects(tmp, fr->addr)) { +- continue; +- } +- tmp = addrrange_intersection(tmp, fr->addr); +- MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, coalesced_io_add, +- int128_get64(tmp.start), +- int128_get64(tmp.size)); ++ flat_range_coalesced_io_notify(fr, as, cmr, true); + } + } + +-- +1.8.3.1 + diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 22fa3d6..e1168f4 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -67,7 +67,7 @@ Obsoletes: %1-rhev Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 4.1.0 -Release: 5%{?dist} +Release: 6%{?dist} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY @@ -142,6 +142,14 @@ Patch28: kvm-redhat-s390x-Rename-s390-ccw-virtio-rhel8.0.0-to-s39.patch Patch29: kvm-redhat-s390x-Add-proper-compatibility-options-for-th.patch # For bz#1744170 - [IBM Power] New 8.1.0 machine type for pseries Patch31: kvm-redhat-update-pseries-rhel8.1.0-machine-type.patch +# For bz#1743142 - Boot guest with multiple e1000 devices, qemu will crash after several guest reboots: kvm_mem_ioeventfd_add: error adding ioeventfd: No space left on device (28) +Patch32: kvm-memory-Refactor-memory_region_clear_coalescing.patch +# For bz#1743142 - Boot guest with multiple e1000 devices, qemu will crash after several guest reboots: kvm_mem_ioeventfd_add: error adding ioeventfd: No space left on device (28) +Patch33: kvm-memory-Split-zones-when-do-coalesced_io_del.patch +# For bz#1743142 - Boot guest with multiple e1000 devices, qemu will crash after several guest reboots: kvm_mem_ioeventfd_add: error adding ioeventfd: No space left on device (28) +Patch34: kvm-memory-Remove-has_coalesced_range-counter.patch +# For bz#1743142 - Boot guest with multiple e1000 devices, qemu will crash after several guest reboots: kvm_mem_ioeventfd_add: error adding ioeventfd: No space left on device (28) +Patch35: kvm-memory-Fix-up-memory_region_-add-del-_coalescing.patch BuildRequires: wget BuildRequires: rpm-build @@ -575,7 +583,6 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" --enable-vhost-vsock \ --enable-vnc \ --enable-mpath \ - --disable-virglrenderer \ --disable-xen-pci-passthrough \ --enable-tcg \ --with-git=git \ @@ -1037,6 +1044,10 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %if 0%{have_memlock_limits} %{_sysconfdir}/security/limits.d/95-kvm-memlock.conf %endif +%if %{have_spice} +%{_libexecdir}/vhost-user-gpu +%{_datadir}/%{name}/vhost-user/50-qemu-gpu.json +%endif %files -n qemu-img %defattr(-,root,root) @@ -1080,6 +1091,17 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog +* Wed Sep 04 2019 Danilo Cesar Lemes de Paula - 4.1.0-6.el8 +- kvm-memory-Refactor-memory_region_clear_coalescing.patch [bz#1743142] +- kvm-memory-Split-zones-when-do-coalesced_io_del.patch [bz#1743142] +- kvm-memory-Remove-has_coalesced_range-counter.patch [bz#1743142] +- kvm-memory-Fix-up-memory_region_-add-del-_coalescing.patch [bz#1743142] +- kvm-enable-virgl-for-real-this-time.patch [bz#1559740] +- Resolves: bz#1559740 + ([RFE] Enable virgl as TechPreview (qemu)) +- Resolves: bz#1743142 + (Boot guest with multiple e1000 devices, qemu will crash after several guest reboots: kvm_mem_ioeventfd_add: error adding ioeventfd: No space left on device (28)) + * Tue Aug 27 2019 Danilo Cesar Lemes de Paula - 4.1.0-5.el8 - kvm-redhat-s390x-Rename-s390-ccw-virtio-rhel8.0.0-to-s39.patch [bz#1693772] - kvm-redhat-s390x-Add-proper-compatibility-options-for-th.patch [bz#1693772]