diff --git a/SPECS/qemu/0001-Disable-9p-local-tests-that-fail-on-copr-aarch64.patch b/SPECS/qemu/0001-Disable-9p-local-tests-that-fail-on-copr-aarch64.patch index c1bbf76244..1835b6a906 100644 --- a/SPECS/qemu/0001-Disable-9p-local-tests-that-fail-on-copr-aarch64.patch +++ b/SPECS/qemu/0001-Disable-9p-local-tests-that-fail-on-copr-aarch64.patch @@ -1,49 +1,36 @@ -From 34acc8e0028bf059c9c4e725c653df56eac7c296 Mon Sep 17 00:00:00 2001 -Message-ID: <34acc8e0028bf059c9c4e725c653df56eac7c296.1724767601.git.crobinso@redhat.com> +From 22e852dae425014c4bc511ab4dc7c7f9c0752eb3 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Mon, 26 Aug 2024 14:06:14 -0400 -Subject: [PATCH] Disable 9p `local` tests that fail on copr aarch64 -Content-type: text/plain +Subject: [PATCH 1/8] Disable 9p `local` tests that fail on copr aarch64 Upstream issue: https://gitlab.com/qemu-project/qemu/-/issues/2541 Signed-off-by: Cole Robinson --- - tests/qtest/virtio-9p-test.c | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) + tests/qtest/virtio-9p-test.c | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c -index 3c8cd235cf..1d550eafb1 100644 +index ab3a12c816..261b0c17f1 100644 --- a/tests/qtest/virtio-9p-test.c +++ b/tests/qtest/virtio-9p-test.c -@@ -748,16 +748,16 @@ static void register_virtio_9p_test(void) +@@ -792,6 +792,7 @@ static void register_virtio_9p_test(void) /* 9pfs test cases using the 'local' filesystem driver */ opts.before = assign_9p_local_driver; qos_add_test("local/config", "virtio-9p", pci_config, &opts); -- qos_add_test("local/create_dir", "virtio-9p", fs_create_dir, &opts); -- qos_add_test("local/unlinkat_dir", "virtio-9p", fs_unlinkat_dir, &opts); -- qos_add_test("local/create_file", "virtio-9p", fs_create_file, &opts); -- qos_add_test("local/unlinkat_file", "virtio-9p", fs_unlinkat_file, &opts); -- qos_add_test("local/symlink_file", "virtio-9p", fs_symlink_file, &opts); -- qos_add_test("local/unlinkat_symlink", "virtio-9p", fs_unlinkat_symlink, -- &opts); -- qos_add_test("local/hardlink_file", "virtio-9p", fs_hardlink_file, &opts); -- qos_add_test("local/unlinkat_hardlink", "virtio-9p", fs_unlinkat_hardlink, -- &opts); -+ /* qos_add_test("local/create_dir", "virtio-9p", fs_create_dir, &opts); */ -+ /* qos_add_test("local/unlinkat_dir", "virtio-9p", fs_unlinkat_dir, &opts); */ -+ /* qos_add_test("local/create_file", "virtio-9p", fs_create_file, &opts); */ -+ /* qos_add_test("local/unlinkat_file", "virtio-9p", fs_unlinkat_file, &opts); */ -+ /* qos_add_test("local/symlink_file", "virtio-9p", fs_symlink_file, &opts); */ -+ /* qos_add_test("local/unlinkat_symlink", "virtio-9p", fs_unlinkat_symlink, */ -+ /* &opts); */ -+ /* qos_add_test("local/hardlink_file", "virtio-9p", fs_hardlink_file, &opts); */ -+ /* qos_add_test("local/unlinkat_hardlink", "virtio-9p", fs_unlinkat_hardlink, */ -+ /* &opts); */ ++#if 0 + qos_add_test("local/create_dir", "virtio-9p", fs_create_dir, &opts); + qos_add_test("local/unlinkat_dir", "virtio-9p", fs_unlinkat_dir, &opts); + qos_add_test("local/create_file", "virtio-9p", fs_create_file, &opts); +@@ -804,6 +805,7 @@ static void register_virtio_9p_test(void) + &opts); + qos_add_test("local/use_after_unlink", "virtio-9p", fs_use_after_unlink, + &opts); ++#endif } libqos_init(register_virtio_9p_test); -- -2.46.0 +2.48.1 diff --git a/SPECS/qemu/0001-pc-bios-optionrom-Fix-pvh.img-ld-build-failure-on-fe.patch b/SPECS/qemu/0001-pc-bios-optionrom-Fix-pvh.img-ld-build-failure-on-fe.patch deleted file mode 100644 index 87d8a11677..0000000000 --- a/SPECS/qemu/0001-pc-bios-optionrom-Fix-pvh.img-ld-build-failure-on-fe.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 98287d67f3ea6c49795838beda4b020cf236fc20 Mon Sep 17 00:00:00 2001 -From: Cole Robinson -Date: Mon, 27 Nov 2023 12:51:25 -0500 -Subject: [PATCH] pc-bios/optionrom: Fix pvh.img ld build failure on fedora - rawhide -Content-type: text/plain - -binutils 2.39 shows some warnings when building pvh.img - -/usr/bin/ld: warning: pvh.o: missing .note.GNU-stack section implies executable stack -/usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker -/usr/bin/ld: warning: pvh.img has a LOAD segment with RWX permissions - -The latter of which is fatal on Fedora rawhide for some reason. - -Add linker options to suppress the errors - -Signed-off-by: Cole Robinson ---- - pc-bios/optionrom/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile -index 30d07026c7..f54ed39b54 100644 ---- a/pc-bios/optionrom/Makefile -+++ b/pc-bios/optionrom/Makefile -@@ -36,7 +36,7 @@ config-cc.mak: Makefile - $(call cc-option,-Wno-array-bounds)) 3> config-cc.mak - -include config-cc.mak - --override LDFLAGS = -nostdlib -Wl,--build-id=none,-T,$(SRC_DIR)/flat.lds -+override LDFLAGS = -nostdlib -Wl,--build-id=none,-T,$(SRC_DIR)/flat.lds -Wl,--no-warn-rwx-segments -Wl,--no-warn-execstack - - pvh.img: pvh.o pvh_main.o - diff --git a/SPECS/qemu/0001-ui-gtk-Attach-fullscreen-toggling-cb-to-all-detached.patch b/SPECS/qemu/0001-ui-gtk-Attach-fullscreen-toggling-cb-to-all-detached.patch deleted file mode 100644 index 86cd287b40..0000000000 --- a/SPECS/qemu/0001-ui-gtk-Attach-fullscreen-toggling-cb-to-all-detached.patch +++ /dev/null @@ -1,79 +0,0 @@ -From ccf7f89cd612541885a6919d113cf95a7743df69 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Wed, 26 Jun 2024 00:47:00 +0000 -Subject: [PATCH 01/50] ui/gtk: Attach fullscreen toggling cb to all detached - VCs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Enable hotkey for toggling window fullscreening for all individual -untabified VCs - -Cc: Marc-André Lureau -Cc: Vivek Kasireddy -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 39 +++++++++++++++++++++++++++++++++++---- - 1 file changed, 35 insertions(+), 4 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 8e14c2ac81..bdd12246b9 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1396,6 +1396,34 @@ static gboolean gd_win_grab(void *opaque) - return TRUE; - } - -+static void gd_vc_fullscreen_toggle(void *opaque) -+{ -+ VirtualConsole *vc = opaque; -+ GdkWindow *window; -+ GdkWindowState state; -+ -+ if (!vc->window) -+ return; -+ -+ window = gtk_widget_get_window(vc->window); -+ state = gdk_window_get_state(window); -+ -+ if (state & GDK_WINDOW_STATE_FULLSCREEN) { -+ gtk_window_unfullscreen(GTK_WINDOW(vc->window)); -+ -+ if (vc->type == GD_VC_GFX) { -+ vc->gfx.scale_x = 1.0; -+ vc->gfx.scale_y = 1.0; -+ gd_update_windowsize(vc); -+ } -+ } else { -+ if (vc->type == GD_VC_GFX) { -+ gtk_widget_set_size_request(vc->gfx.drawing_area, -1, -1); -+ } -+ gtk_window_fullscreen(GTK_WINDOW(vc->window)); -+ } -+} -+ - static void gd_menu_untabify(GtkMenuItem *item, void *opaque) - { - GtkDisplayState *s = opaque; -@@ -1428,10 +1456,13 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) - if (qemu_console_is_graphic(vc->gfx.dcl.con)) { - GtkAccelGroup *ag = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag); -- -- GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), -- vc, NULL); -- gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb); -+ GClosure *cb_grab = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), -+ vc, NULL); -+ gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb_grab); -+ GClosure *cb_fs = g_cclosure_new_swap( -+ G_CALLBACK(gd_vc_fullscreen_toggle), -+ vc, NULL); -+ gtk_accel_group_connect(ag, GDK_KEY_f, HOTKEY_MODIFIERS, 0, cb_fs); - } - - gd_update_geometry_hints(vc); --- -2.35.3 - diff --git a/SPECS/qemu/0002-Disable-failing-tests-on-azl.patch b/SPECS/qemu/0002-Disable-failing-tests-on-azl.patch deleted file mode 100644 index b2199c1888..0000000000 --- a/SPECS/qemu/0002-Disable-failing-tests-on-azl.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 7cd14cebcfd56cbe126cce843c6f84dec95fbc8a Mon Sep 17 00:00:00 2001 -From: Kanika Nema -Date: Thu, 4 Apr 2024 14:33:33 +0000 -Subject: [PATCH] Disable tests that fail during azl rpmbuild check - -1. Disable post-copy eventfd based tests as they hang -2. Disable TLS-PSK test as they fail (curve is unsupported error, -possibily because psktool doesn't work on azl). - -Signed-off-by: Kanika Nema ---- - tests/qtest/migration-test.c | 28 +++++++++++++++++++++++++++- - 1 file changed, 27 insertions(+), 1 deletion(-) - -diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c -index 0fbaa6a90f..29217922b1 100644 ---- a/tests/qtest/migration-test.c -+++ b/tests/qtest/migration-test.c -@@ -3306,6 +3306,8 @@ int main(int argc, char **argv) - } - - has_uffd = ufd_version_check(); -+ /* Unblock azl qemu tests, eventfd may not be working properly */ -+ has_uffd = 0; - arch = qtest_get_arch(); - - /* -@@ -3393,9 +3395,19 @@ int main(int argc, char **argv) - } - - #ifdef CONFIG_GNUTLS -+/* -+ * TLSPSK doesn't work in azl builds and fails with this error: -+ * "qemu-system-x86_64: TLS handshake failed: The curve is unsupported" -+ * "qemu-system-x86_64: TLS handshake failed: Error in the pull function." -+ * "{\"return\": {\"status\": \"failed\", \"error-desc\": \"TLS handshake -+ * failed: The curve is unsupported\"}}" -+ * "ERROR:../tests/qtest/migration-helpers.c:181:check_migration_status: -+ * assertion failed (current_status != \"failed\"): (\"failed\" != \"failed\")" -+ */ -+#if 0 - qtest_add_func("/migration/precopy/unix/tls/psk", - test_precopy_unix_tls_psk); -- -+#endif - if (has_uffd) { - /* - * NOTE: psk test is enough for postcopy, as other types of TLS -@@ -3424,10 +3436,19 @@ int main(int argc, char **argv) - test_precopy_tcp_switchover_ack); - - #ifdef CONFIG_GNUTLS -+/* -+ * TLS PSK tests fail on azl rmpbuilds with error: -+ * "qemu-system-x86_64: TLS handshake failed: The curve is unsupported" -+ * "qemu-system-x86_64: TLS handshake failed: Error in the pull function." -+ * "ERROR:../tests/qtest/migration-helpers.c:181:check_migration_status: -+ * assertion failed (current_status != \"failed\"): (\"failed\" != \"failed\")" -+ */ -+#if 0 - qtest_add_func("/migration/precopy/tcp/tls/psk/match", - test_precopy_tcp_tls_psk_match); - qtest_add_func("/migration/precopy/tcp/tls/psk/mismatch", - test_precopy_tcp_tls_psk_mismatch); -+#endif - #ifdef CONFIG_TASN1 - qtest_add_func("/migration/precopy/tcp/tls/x509/default-host", - test_precopy_tcp_tls_x509_default_host); -@@ -3483,10 +3504,15 @@ int main(int argc, char **argv) - test_multifd_tcp_zstd); - #endif - #ifdef CONFIG_GNUTLS -+/* -+ * TLS PSK tests fail on azl RPMBUILDS -+ */ -+#if 0 - qtest_add_func("/migration/multifd/tcp/tls/psk/match", - test_multifd_tcp_tls_psk_match); - qtest_add_func("/migration/multifd/tcp/tls/psk/mismatch", - test_multifd_tcp_tls_psk_mismatch); -+#endif - #ifdef CONFIG_TASN1 - qtest_add_func("/migration/multifd/tcp/tls/x509/default-host", - test_multifd_tcp_tls_x509_default_host); --- -2.25.1 - diff --git a/SPECS/qemu/0002-TEMPORARY-increase-test-timeout.patch b/SPECS/qemu/0002-TEMPORARY-increase-test-timeout.patch new file mode 100644 index 0000000000..1aafe1fb73 --- /dev/null +++ b/SPECS/qemu/0002-TEMPORARY-increase-test-timeout.patch @@ -0,0 +1,26 @@ +From fe43f40a7acfd93493ac587a74e147732a39c782 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 15 Jul 2025 18:06:55 +0100 +Subject: [PATCH 2/2] TEMPORARY: increase test timeout + +https://gitlab.com/qemu-project/qemu/-/issues/3035 +--- + tests/unit/meson.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/unit/meson.build b/tests/unit/meson.build +index d5248ae51d..a490fe0316 100644 +--- a/tests/unit/meson.build ++++ b/tests/unit/meson.build +@@ -176,7 +176,7 @@ slow_tests = { + 'test-crypto-block' : 300, + 'test-crypto-tlscredsx509': 90, + 'test-crypto-tlssession': 90, +- 'test-replication': 60, ++ 'test-replication': 6000, + } + + foreach test_name, extra: tests +-- +2.50.1 + diff --git a/SPECS/qemu/0002-nfs-Add-support-for-libnfs-v2-api.patch b/SPECS/qemu/0002-nfs-Add-support-for-libnfs-v2-api.patch new file mode 100644 index 0000000000..ded125265f --- /dev/null +++ b/SPECS/qemu/0002-nfs-Add-support-for-libnfs-v2-api.patch @@ -0,0 +1,53 @@ +From 379565f41b2b2ddf50c162a917405244d2f992f2 Mon Sep 17 00:00:00 2001 +From: Ronnie Sahlberg +Date: Sun, 26 Jan 2025 12:59:45 +1000 +Subject: [PATCH 2/8] nfs: Add support for libnfs v2 api + +Signed-off-by: Ronnie Sahlberg +--- + block/nfs.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/block/nfs.c b/block/nfs.c +index 0500f60c08..f768ee0c4b 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -268,11 +268,18 @@ static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, int64_t offset, + NFSRPC task; + + nfs_co_init_task(bs, &task); +- task.iov = iov; + + WITH_QEMU_LOCK_GUARD(&client->mutex) { ++#ifdef LIBNFS_API_V2 ++ if (nfs_pread_async(client->context, client->fh, ++ iov->iov[0].iov_base, ++ bytes > iov->iov[0].iov_len ? iov->iov[0].iov_len : bytes, ++ offset, nfs_co_generic_cb, &task) != 0) { ++#else ++ task.iov = iov; + if (nfs_pread_async(client->context, client->fh, + offset, bytes, nfs_co_generic_cb, &task) != 0) { ++#endif + return -ENOMEM; + } + +@@ -317,9 +324,15 @@ static int coroutine_fn nfs_co_pwritev(BlockDriverState *bs, int64_t offset, + } + + WITH_QEMU_LOCK_GUARD(&client->mutex) { ++#ifdef LIBNFS_API_V2 ++ if (nfs_pwrite_async(client->context, client->fh, ++ buf, bytes, offset, ++ nfs_co_generic_cb, &task) != 0) { ++#else + if (nfs_pwrite_async(client->context, client->fh, + offset, bytes, buf, + nfs_co_generic_cb, &task) != 0) { ++#endif + if (my_buffer) { + g_free(buf); + } +-- +2.48.1 + diff --git a/SPECS/qemu/0002-ui-egl-helpers-Consolidates-create-sync-and-create-f.patch b/SPECS/qemu/0002-ui-egl-helpers-Consolidates-create-sync-and-create-f.patch deleted file mode 100644 index 81bc867630..0000000000 --- a/SPECS/qemu/0002-ui-egl-helpers-Consolidates-create-sync-and-create-f.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 8d078f6518d985b079cee9127792cb04b98741ee Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Fri, 31 May 2024 19:53:45 +0000 -Subject: [PATCH 02/50] ui/egl-helpers: Consolidates create-sync and - create-fence -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There is no reason to split those two operations so combining -two functions - egl_dmabuf_create_sync and egl_dmabuf_create_fence. - -v2: egl_dmabuf_create_fence -> egl_dmabuf_create_fence_fd - (Marc-André Lureau ) - -v3: create fence only if current QemuDmaBuf->fence_fd = -1 - to make sure there is no fence currently bound to the - QemuDmaBuf - -v4: assert dmabuf->fence_fd before creating a fence - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Cc: Vivek Kasireddy -Signed-off-by: Dongwon Kim ---- - include/ui/egl-helpers.h | 3 +-- - ui/egl-helpers.c | 25 ++++++++++--------------- - ui/gtk-egl.c | 17 ++++------------- - ui/gtk-gl-area.c | 12 +++--------- - 4 files changed, 18 insertions(+), 39 deletions(-) - -diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h -index 4b8c0d2281..221548e3c9 100644 ---- a/include/ui/egl-helpers.h -+++ b/include/ui/egl-helpers.h -@@ -51,8 +51,7 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc, - - void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf); - void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf); --void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf); --void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf); -+int egl_dmabuf_create_fence_fd(QemuDmaBuf *dmabuf); - - #endif - -diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c -index 99b2ebbe23..698a021823 100644 ---- a/ui/egl-helpers.c -+++ b/ui/egl-helpers.c -@@ -371,9 +371,10 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) - qemu_dmabuf_set_texture(dmabuf, 0); - } - --void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) -+int egl_dmabuf_create_fence_fd(QemuDmaBuf *dmabuf) - { - EGLSyncKHR sync; -+ int fence_fd = -1; - - if (epoxy_has_egl_extension(qemu_egl_display, - "EGL_KHR_fence_sync") && -@@ -382,23 +383,17 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) - sync = eglCreateSyncKHR(qemu_egl_display, - EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); - if (sync != EGL_NO_SYNC_KHR) { -- qemu_dmabuf_set_sync(dmabuf, sync); -+ assert(qemu_dmabuf_get_fence_fd(dmabuf) == -1); -+ fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, -+ sync); -+ if (fence_fd >= 0) { -+ qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); -+ } -+ eglDestroySyncKHR(qemu_egl_display, sync); - } - } --} -- --void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) --{ -- void *sync = qemu_dmabuf_get_sync(dmabuf); -- int fence_fd; - -- if (sync) { -- fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, -- sync); -- qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); -- eglDestroySyncKHR(qemu_egl_display, sync); -- qemu_dmabuf_set_sync(dmabuf, NULL); -- } -+ return fence_fd; - } - - #endif /* CONFIG_GBM */ -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 9831c10e1b..9983b0423a 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -68,7 +68,6 @@ void gd_egl_draw(VirtualConsole *vc) - GdkWindow *window; - #ifdef CONFIG_GBM - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -- int fence_fd; - #endif - int ww, wh, ws; - -@@ -98,14 +97,13 @@ void gd_egl_draw(VirtualConsole *vc) - - glFlush(); - #ifdef CONFIG_GBM -- if (dmabuf) { -- egl_dmabuf_create_fence(dmabuf); -- fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); -+ if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) == -1) { -+ int fence_fd = egl_dmabuf_create_fence_fd(dmabuf); - if (fence_fd >= 0) { - qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -- return; -+ } else { -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); - } -- graphic_hw_gl_block(vc->gfx.dcl.con, false); - } - #endif - } else { -@@ -364,12 +362,6 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, - egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); - } - --#ifdef CONFIG_GBM -- if (vc->gfx.guest_fb.dmabuf) { -- egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf); -- } --#endif -- - eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); - } - -@@ -387,7 +379,6 @@ void gd_egl_flush(DisplayChangeListener *dcl, - gtk_widget_queue_draw_area(area, x, y, w, h); - return; - } -- - gd_egl_scanout_flush(&vc->gfx.dcl, x, y, w, h); - } - -diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c -index b628b35451..929bb49290 100644 ---- a/ui/gtk-gl-area.c -+++ b/ui/gtk-gl-area.c -@@ -78,16 +78,9 @@ void gd_gl_area_draw(VirtualConsole *vc) - 0, 0, ww, wh, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - #ifdef CONFIG_GBM -- if (dmabuf) { -- egl_dmabuf_create_sync(dmabuf); -- } --#endif -- glFlush(); --#ifdef CONFIG_GBM -- if (dmabuf) { -+ if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) == -1) { - int fence_fd; -- egl_dmabuf_create_fence(dmabuf); -- fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); -+ fence_fd = egl_dmabuf_create_fence_fd(dmabuf); - if (fence_fd >= 0) { - qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); - return; -@@ -95,6 +88,7 @@ void gd_gl_area_draw(VirtualConsole *vc) - graphic_hw_gl_block(vc->gfx.dcl.con, false); - } - #endif -+ glFlush(); - } else { - if (!vc->gfx.ds) { - return; --- -2.35.3 - diff --git a/SPECS/qemu/0003-ui-dmabuf-Remove-sync-from-QemuDmaBuf-struct.patch b/SPECS/qemu/0003-ui-dmabuf-Remove-sync-from-QemuDmaBuf-struct.patch deleted file mode 100644 index fe6c203dcb..0000000000 --- a/SPECS/qemu/0003-ui-dmabuf-Remove-sync-from-QemuDmaBuf-struct.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 479ab43b3d1c78b100be06d54f844be539793b2a Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Tue, 2 Jul 2024 20:25:09 +0000 -Subject: [PATCH 03/50] ui/dmabuf: Remove 'sync' from QemuDmaBuf struct -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Sync object is not used so removing it from QemuDmaBuf struct - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Cc: Vivek Kasireddy -Signed-off-by: Dongwon Kim ---- - include/ui/dmabuf.h | 2 -- - ui/dmabuf.c | 14 -------------- - 2 files changed, 16 deletions(-) - -diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h -index dc74ba895a..7f0f7f3f6e 100644 ---- a/include/ui/dmabuf.h -+++ b/include/ui/dmabuf.h -@@ -36,13 +36,11 @@ uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); - uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); - uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); - bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); --void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); - int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); - bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); - bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); - void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); - void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); --void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); - void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); - void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); - -diff --git a/ui/dmabuf.c b/ui/dmabuf.c -index df7a09703f..2332292a08 100644 ---- a/ui/dmabuf.c -+++ b/ui/dmabuf.c -@@ -23,7 +23,6 @@ struct QemuDmaBuf { - uint32_t backing_width; - uint32_t backing_height; - bool y0_top; -- void *sync; - int fence_fd; - bool allow_fences; - bool draw_submitted; -@@ -170,13 +169,6 @@ bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf) - return dmabuf->y0_top; - } - --void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf) --{ -- assert(dmabuf != NULL); -- -- return dmabuf->sync; --} -- - int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf) - { - assert(dmabuf != NULL); -@@ -210,12 +202,6 @@ void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd) - dmabuf->fence_fd = fence_fd; - } - --void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync) --{ -- assert(dmabuf != NULL); -- dmabuf->sync = sync; --} -- - void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted) - { - assert(dmabuf != NULL); --- -2.35.3 - diff --git a/SPECS/qemu/0004-hw-display-virtio-gpu-Introducing-render_sync-param.patch b/SPECS/qemu/0004-hw-display-virtio-gpu-Introducing-render_sync-param.patch deleted file mode 100644 index 5f5a7e2549..0000000000 --- a/SPECS/qemu/0004-hw-display-virtio-gpu-Introducing-render_sync-param.patch +++ /dev/null @@ -1,214 +0,0 @@ -From 111284a85a28320d10f7bc14cdfb2b615b482fe5 Mon Sep 17 00:00:00 2001 -From: "Kim, Dongwon" -Date: Fri, 16 Aug 2024 05:49:17 +0800 -Subject: [PATCH 04/50] hw/display/virtio-gpu: Introducing render_sync param -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Introducing new virtio-gpu param, 'render_sync' when guest scanout blob -is used (blob=true). The new param is used to specify when to start -rendering a guest scanout frame. - -By default (and so far) rendering of the guest frame is started in -the draw event to make sure guest display update is sychronized with -host's vsync. But this method inevitably brings some extra wait because -most of time, the draw event is not happening right after the guest -scanout frame is flushed. - -This delay often makes the guest stuck at certain frame for too long and -causes general performance degradation of graphic workloads on the guest's -side especially when the display update rate is high. This unwanted perf -drop can be reduced if the guest scanout frame is rendered as soon as it is -flushed through 'VIRTIO_GPU_CMD_RESOURCE_FLUSH' msg. The gl display -pipeline can be unblocked a lot earlier in this case so that guest can -move to the next display frame right away. - -However, this "asynchrounous" render mode may cause some waste of resources -as the guest could produce more frames than what are actually displayed -on the host display. This is similar as running rendering apps with no vblank -or vsync option. This is why this feature should stay as optional. - -The param 'render_sync' is set to 'true' by default and this is in line -with traditional way while setting it to 'false' is basically enabling -this asynchronouse mode. - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Cc: Vivek Kasireddy -Signed-off-by: Kim, Dongwon ---- - hw/display/vhost-user-gpu.c | 3 ++- - hw/display/virtio-gpu-udmabuf.c | 3 ++- - hw/display/virtio-gpu.c | 2 ++ - hw/vfio/display.c | 3 ++- - include/hw/virtio/virtio-gpu.h | 3 +++ - include/ui/dmabuf.h | 4 +++- - ui/dbus-listener.c | 2 +- - ui/dmabuf.c | 11 ++++++++++- - 8 files changed, 25 insertions(+), 6 deletions(-) - -diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c -index c0c66910f1..0cdf0aec00 100644 ---- a/hw/display/vhost-user-gpu.c -+++ b/hw/display/vhost-user-gpu.c -@@ -286,7 +286,8 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) - m->fd_width, m->fd_height, - m->fd_drm_fourcc, modifier, - fd, false, m->fd_flags & -- VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP); -+ VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -+ false); - - dpy_gl_scanout_dmabuf(con, dmabuf); - g->dmabuf[m->scanout_id] = dmabuf; -diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c -index c02ec6d37d..8fcc0c3055 100644 ---- a/hw/display/virtio-gpu-udmabuf.c -+++ b/hw/display/virtio-gpu-udmabuf.c -@@ -176,6 +176,7 @@ static VGPUDMABuf - struct virtio_gpu_rect *r) - { - VGPUDMABuf *dmabuf; -+ bool render_sync = virtio_gpu_render_sync_enabled(g->parent_obj.conf); - - if (res->dmabuf_fd < 0) { - return NULL; -@@ -185,7 +186,7 @@ static VGPUDMABuf - dmabuf->buf = qemu_dmabuf_new(r->width, r->height, fb->stride, - r->x, r->y, fb->width, fb->height, - qemu_pixman_to_drm_format(fb->format), -- 0, res->dmabuf_fd, true, false); -+ 0, res->dmabuf_fd, true, false, render_sync); - dmabuf->scanout_id = scanout_id; - QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next); - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index 3281842bfe..363e8ea9e5 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -1670,6 +1670,8 @@ static Property virtio_gpu_properties[] = { - 256 * MiB), - DEFINE_PROP_BIT("blob", VirtIOGPU, parent_obj.conf.flags, - VIRTIO_GPU_FLAG_BLOB_ENABLED, false), -+ DEFINE_PROP_BIT("render_sync", VirtIOGPU, parent_obj.conf.flags, -+ VIRTIO_GPU_FLAG_RENDER_SYNC_ENABLED, true), - DEFINE_PROP_SIZE("hostmem", VirtIOGPU, parent_obj.conf.hostmem, 0), - DEFINE_PROP_UINT8("x-scanout-vmstate-version", VirtIOGPU, scanout_vmstate_version, 2), - DEFINE_PROP_END_OF_LIST(), -diff --git a/hw/vfio/display.c b/hw/vfio/display.c -index ea87830fe0..5285758a2c 100644 ---- a/hw/vfio/display.c -+++ b/hw/vfio/display.c -@@ -249,7 +249,8 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, - dmabuf->buf = qemu_dmabuf_new(plane.width, plane.height, - plane.stride, 0, 0, plane.width, - plane.height, plane.drm_format, -- plane.drm_format_mod, fd, false, false); -+ plane.drm_format_mod, fd, false, -+ false, false); - - if (plane_type == DRM_PLANE_TYPE_CURSOR) { - vfio_display_update_cursor(dmabuf, &plane); -diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h -index 7a59379f5a..9bcc572eab 100644 ---- a/include/hw/virtio/virtio-gpu.h -+++ b/include/hw/virtio/virtio-gpu.h -@@ -97,6 +97,7 @@ enum virtio_gpu_base_conf_flags { - VIRTIO_GPU_FLAG_EDID_ENABLED, - VIRTIO_GPU_FLAG_DMABUF_ENABLED, - VIRTIO_GPU_FLAG_BLOB_ENABLED, -+ VIRTIO_GPU_FLAG_RENDER_SYNC_ENABLED, - VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED, - VIRTIO_GPU_FLAG_RUTABAGA_ENABLED, - }; -@@ -111,6 +112,8 @@ enum virtio_gpu_base_conf_flags { - (_cfg.flags & (1 << VIRTIO_GPU_FLAG_DMABUF_ENABLED)) - #define virtio_gpu_blob_enabled(_cfg) \ - (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED)) -+#define virtio_gpu_render_sync_enabled(_cfg) \ -+ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_RENDER_SYNC_ENABLED)) - #define virtio_gpu_context_init_enabled(_cfg) \ - (_cfg.flags & (1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED)) - #define virtio_gpu_rutabaga_enabled(_cfg) \ -diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h -index 7f0f7f3f6e..07e8178d76 100644 ---- a/include/ui/dmabuf.h -+++ b/include/ui/dmabuf.h -@@ -17,7 +17,8 @@ QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, - uint32_t y, uint32_t backing_width, - uint32_t backing_height, uint32_t fourcc, - uint64_t modifier, int dmabuf_fd, -- bool allow_fences, bool y0_top); -+ bool allow_fences, bool y0_top, -+ bool render_sync); - void qemu_dmabuf_free(QemuDmaBuf *dmabuf); - - G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); -@@ -39,6 +40,7 @@ bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); - int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); - bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); - bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); -+bool qemu_dmabuf_get_render_sync(QemuDmaBuf *dmabuf); - void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); - void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); - void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); -diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c -index a54123acea..d4f1078c68 100644 ---- a/ui/dbus-listener.c -+++ b/ui/dbus-listener.c -@@ -456,7 +456,7 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl, - } - dmabuf = qemu_dmabuf_new(w, h, stride, x, y, backing_width, - backing_height, fourcc, modifier, fd, -- false, backing_y_0_top); -+ false, backing_y_0_top, false); - - dbus_scanout_dmabuf(dcl, dmabuf); - qemu_dmabuf_close(dmabuf); -diff --git a/ui/dmabuf.c b/ui/dmabuf.c -index 2332292a08..0adaea0089 100644 ---- a/ui/dmabuf.c -+++ b/ui/dmabuf.c -@@ -25,6 +25,7 @@ struct QemuDmaBuf { - bool y0_top; - int fence_fd; - bool allow_fences; -+ bool render_sync; - bool draw_submitted; - }; - -@@ -33,7 +34,7 @@ QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, - uint32_t y, uint32_t backing_width, - uint32_t backing_height, uint32_t fourcc, - uint64_t modifier, int32_t dmabuf_fd, -- bool allow_fences, bool y0_top) { -+ bool allow_fences, bool y0_top, bool render_sync) { - QemuDmaBuf *dmabuf; - - dmabuf = g_new0(QemuDmaBuf, 1); -@@ -50,6 +51,7 @@ QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, - dmabuf->fd = dmabuf_fd; - dmabuf->allow_fences = allow_fences; - dmabuf->y0_top = y0_top; -+ dmabuf->render_sync = render_sync; - dmabuf->fence_fd = -1; - - return dmabuf; -@@ -190,6 +192,13 @@ bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf) - return dmabuf->draw_submitted; - } - -+bool qemu_dmabuf_get_render_sync(QemuDmaBuf *dmabuf) -+{ -+ assert(dmabuf != NULL); -+ -+ return dmabuf->render_sync; -+} -+ - void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture) - { - assert(dmabuf != NULL); --- -2.35.3 - diff --git a/SPECS/qemu/0005-ui-gtk-Start-rendering-of-guest-blob-scandout-if-ren.patch b/SPECS/qemu/0005-ui-gtk-Start-rendering-of-guest-blob-scandout-if-ren.patch deleted file mode 100644 index fa87cd4170..0000000000 --- a/SPECS/qemu/0005-ui-gtk-Start-rendering-of-guest-blob-scandout-if-ren.patch +++ /dev/null @@ -1,310 +0,0 @@ -From f7cfda7cbadf89e4cfce9d7a269cfc031866641c Mon Sep 17 00:00:00 2001 -From: "Kim, Dongwon" -Date: Fri, 16 Aug 2024 06:54:16 +0800 -Subject: [PATCH 05/50] ui/gtk: Start rendering of guest blob scandout if - render_sync is off -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Draw (executing glBlitFramebuffer) immediately as soon as the frame -is flushed instead of getting it done in the next draw event if render_sync -flag is reset. With this, the fence will be signaled way ealier so the guest -can be working on the next frame right away. - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Cc: Vivek Kasireddy -Signed-off-by: Kim, Dongwon ---- - ui/gtk-egl.c | 87 ++++++++++++++++++++++++++++-------------------- - ui/gtk-gl-area.c | 72 ++++++++++++++++++++++++++++----------- - 2 files changed, 103 insertions(+), 56 deletions(-) - -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 9983b0423a..a5a439c1db 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -80,6 +80,12 @@ void gd_egl_draw(VirtualConsole *vc) - ww = gdk_window_get_width(window) * ws; - wh = gdk_window_get_height(window) * ws; - -+ vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds); -+ vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds); -+ -+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -+ vc->gfx.esurface, vc->gfx.ectx); -+ - if (vc->gfx.scanout_mode) { - #ifdef CONFIG_GBM - if (dmabuf) { -@@ -88,21 +94,10 @@ void gd_egl_draw(VirtualConsole *vc) - } else { - qemu_dmabuf_set_draw_submitted(dmabuf, false); - } -- } --#endif -- gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h); -- -- vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds); -- vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds); - -- glFlush(); --#ifdef CONFIG_GBM -- if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) == -1) { -- int fence_fd = egl_dmabuf_create_fence_fd(dmabuf); -- if (fence_fd >= 0) { -- qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -- } else { -- graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ if (!dmabuf || -+ (dmabuf && qemu_dmabuf_get_render_sync(dmabuf))) { -+ gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h); - } - } - #endif -@@ -110,19 +105,12 @@ void gd_egl_draw(VirtualConsole *vc) - if (!vc->gfx.ds) { - return; - } -- eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -- vc->gfx.esurface, vc->gfx.ectx); -- - surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh); - surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds); -- -- eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -- -- vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds); -- vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds); -- -- glFlush(); - } -+ -+ eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -+ glFlush(); - } - - void gd_egl_update(DisplayChangeListener *dcl, -@@ -146,14 +134,20 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); - -+#ifdef CONFIG_GBM -+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -+#endif -+ - gd_update_monitor_refresh_rate( - vc, vc->window ? vc->window : vc->gfx.drawing_area); - -- if (vc->gfx.guest_fb.dmabuf && -- qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { -+#ifdef CONFIG_GBM -+ if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf) && -+ qemu_dmabuf_get_render_sync(dmabuf)) { - gd_egl_draw(vc); - return; - } -+#endif - - if (!vc->gfx.esurface) { - gd_egl_init(vc); -@@ -166,9 +160,9 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds); - } - #ifdef CONFIG_GBM -- if (vc->gfx.guest_fb.dmabuf) { -- egl_dmabuf_release_texture(vc->gfx.guest_fb.dmabuf); -- gd_egl_scanout_dmabuf(dcl, vc->gfx.guest_fb.dmabuf); -+ if (dmabuf) { -+ egl_dmabuf_release_texture(dmabuf); -+ gd_egl_scanout_dmabuf(dcl, dmabuf); - } - #endif - } -@@ -336,6 +330,10 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, - GdkWindow *window; - int ww, wh, ws; - -+#ifdef CONFIG_GBM -+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -+#endif -+ - if (!vc->gfx.scanout_mode) { - return; - } -@@ -362,7 +360,16 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, - egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); - } - -- eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -+#ifdef CONFIG_GBM -+ if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) == -1) { -+ int fence_fd = egl_dmabuf_create_fence_fd(dmabuf); -+ if (fence_fd >= 0) { -+ qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -+ } else { -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ } -+ } -+#endif - } - - void gd_egl_flush(DisplayChangeListener *dcl, -@@ -371,14 +378,22 @@ void gd_egl_flush(DisplayChangeListener *dcl, - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); - GtkWidget *area = vc->gfx.drawing_area; - -- if (vc->gfx.guest_fb.dmabuf && -- !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { -- graphic_hw_gl_block(vc->gfx.dcl.con, true); -- qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); -- gtk_egl_set_scanout_mode(vc, true); -- gtk_widget_queue_draw_area(area, x, y, w, h); -+#ifdef CONFIG_GBM -+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -+ if (dmabuf) { -+ if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { -+ graphic_hw_gl_block(vc->gfx.dcl.con, true); -+ gtk_egl_set_scanout_mode(vc, true); -+ if (!qemu_dmabuf_get_render_sync(dmabuf)) { -+ gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h); -+ } -+ qemu_dmabuf_set_draw_submitted(dmabuf, true); -+ gtk_widget_queue_draw_area(area, x, y, w, h); -+ } - return; - } -+#endif -+ - gd_egl_scanout_flush(&vc->gfx.dcl, x, y, w, h); - } - -diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c -index 929bb49290..cc4765403d 100644 ---- a/ui/gtk-gl-area.c -+++ b/ui/gtk-gl-area.c -@@ -65,39 +65,39 @@ void gd_gl_area_draw(VirtualConsole *vc) - } else { - qemu_dmabuf_set_draw_submitted(dmabuf, false); - } -+ } -+ -+ if (!dmabuf || -+ (dmabuf && qemu_dmabuf_get_render_sync(dmabuf))) { -+ glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer); -+ /* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */ -+ glViewport(0, 0, ww, wh); -+ y1 = vc->gfx.y0_top ? 0 : vc->gfx.h; -+ y2 = vc->gfx.y0_top ? vc->gfx.h : 0; -+ glBlitFramebuffer(0, y1, vc->gfx.w, y2, -+ 0, 0, ww, wh, -+ GL_COLOR_BUFFER_BIT, GL_NEAREST); - } --#endif -- -- glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer); -- /* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */ - -- glViewport(0, 0, ww, wh); -- y1 = vc->gfx.y0_top ? 0 : vc->gfx.h; -- y2 = vc->gfx.y0_top ? vc->gfx.h : 0; -- glBlitFramebuffer(0, y1, vc->gfx.w, y2, -- 0, 0, ww, wh, -- GL_COLOR_BUFFER_BIT, GL_NEAREST); --#ifdef CONFIG_GBM - if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) == -1) { - int fence_fd; - fence_fd = egl_dmabuf_create_fence_fd(dmabuf); - if (fence_fd >= 0) { - qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -- return; -+ } else { -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); - } -- graphic_hw_gl_block(vc->gfx.dcl.con, false); - } - #endif -- glFlush(); - } else { - if (!vc->gfx.ds) { - return; - } -- gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); - - surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh); - surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds); - } -+ glFlush(); - } - - void gd_gl_area_update(DisplayChangeListener *dcl, -@@ -118,14 +118,19 @@ void gd_gl_area_update(DisplayChangeListener *dcl, - void gd_gl_area_refresh(DisplayChangeListener *dcl) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); -+#ifdef CONFIG_GBM -+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -+#endif - - gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area); - -- if (vc->gfx.guest_fb.dmabuf && -- qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { -+#ifdef CONFIG_GBM -+ if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf) && -+ qemu_dmabuf_get_render_sync(dmabuf)) { - gd_gl_area_draw(vc); - return; - } -+#endif - - if (!vc->gfx.gls) { - if (!gtk_widget_get_realized(vc->gfx.drawing_area)) { -@@ -282,13 +287,40 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, - uint32_t x, uint32_t y, uint32_t w, uint32_t h) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); -+#ifdef CONFIG_GBM -+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - -- if (vc->gfx.guest_fb.dmabuf && -- !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { -+ if (dmabuf && !qemu_dmabuf_get_draw_submitted(dmabuf)) { -+ gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); - graphic_hw_gl_block(vc->gfx.dcl.con, true); -- qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); -+ qemu_dmabuf_set_draw_submitted(dmabuf, true); - gtk_gl_area_set_scanout_mode(vc, true); -+ if (!qemu_dmabuf_get_render_sync(dmabuf)) { -+ int ws = gdk_window_get_scale_factor(gtk_widget_get_window(vc->gfx.drawing_area)); -+ int ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area) * ws; -+ int wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area) * ws; -+ int y1 = vc->gfx.y0_top ? 0 : vc->gfx.h; -+ int y2 = vc->gfx.y0_top ? vc->gfx.h : 0; -+ -+ glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer); -+ /* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */ -+ glViewport(0, 0, ww, wh); -+ glBlitFramebuffer(0, y1, vc->gfx.w, y2, -+ 0, 0, ww, wh, -+ GL_COLOR_BUFFER_BIT, GL_NEAREST); -+ -+ if (qemu_dmabuf_get_fence_fd(dmabuf) == -1) { -+ int fence_fd; -+ fence_fd = egl_dmabuf_create_fence_fd(dmabuf); -+ if (fence_fd >= 0) { -+ qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -+ } else { -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ } -+ } -+ } - } -+#endif - gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); - } - --- -2.35.3 - diff --git a/SPECS/qemu/0006-ui-gtk-Factor-out-tab-window-creation-into-a-separat.patch b/SPECS/qemu/0006-ui-gtk-Factor-out-tab-window-creation-into-a-separat.patch deleted file mode 100644 index c3bc5035b5..0000000000 --- a/SPECS/qemu/0006-ui-gtk-Factor-out-tab-window-creation-into-a-separat.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 44cbb8b9566e4843e504f2426b763a4145672928 Mon Sep 17 00:00:00 2001 -From: "Kim, Dongwon" -Date: Sat, 17 Aug 2024 07:30:56 +0800 -Subject: [PATCH 06/50] ui/gtk: Factor out tab window creation into a separate -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Pull the code that creates a new window associated with a notebook -tab into a separate function. This new function can be useful not -just when user wants to detach a tab but also in the future when -a new window creation is needed in other scenarios. - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Signed-off-by: Vivek Kasireddy -Signed-off-by: Kim, Dongwon ---- - ui/gtk.c | 71 +++++++++++++++++++++++++++++++------------------------- - 1 file changed, 39 insertions(+), 32 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index bdd12246b9..53030516b2 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1424,6 +1424,44 @@ static void gd_vc_fullscreen_toggle(void *opaque) - } - } - -+static void gd_tab_window_create(VirtualConsole *vc) -+{ -+ GtkDisplayState *s = vc->s; -+ -+ gtk_widget_set_sensitive(vc->menu_item, false); -+ vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); -+#if defined(CONFIG_OPENGL) -+ if (vc->gfx.esurface) { -+ eglDestroySurface(qemu_egl_display, vc->gfx.esurface); -+ vc->gfx.esurface = NULL; -+ } -+ if (vc->gfx.ectx) { -+ eglDestroyContext(qemu_egl_display, vc->gfx.ectx); -+ vc->gfx.ectx = NULL; -+ } -+#endif -+ gd_widget_reparent(s->notebook, vc->window, vc->tab_item); -+ -+ g_signal_connect(vc->window, "delete-event", -+ G_CALLBACK(gd_tab_window_close), vc); -+ gtk_widget_show_all(vc->window); -+ -+ if (qemu_console_is_graphic(vc->gfx.dcl.con)) { -+ GtkAccelGroup *ag = gtk_accel_group_new(); -+ gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag); -+ GClosure *cb_grab = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), -+ vc, NULL); -+ gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb_grab); -+ GClosure *cb_fs = g_cclosure_new_swap( -+ G_CALLBACK(gd_vc_fullscreen_toggle), -+ vc, NULL); -+ gtk_accel_group_connect(ag, GDK_KEY_f, HOTKEY_MODIFIERS, 0, cb_fs); -+ } -+ -+ gd_update_geometry_hints(vc); -+ gd_update_caption(s); -+} -+ - static void gd_menu_untabify(GtkMenuItem *item, void *opaque) - { - GtkDisplayState *s = opaque; -@@ -1435,38 +1473,7 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) - FALSE); - } - if (!vc->window) { -- gtk_widget_set_sensitive(vc->menu_item, false); -- vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); --#if defined(CONFIG_OPENGL) -- if (vc->gfx.esurface) { -- eglDestroySurface(qemu_egl_display, vc->gfx.esurface); -- vc->gfx.esurface = NULL; -- } -- if (vc->gfx.ectx) { -- eglDestroyContext(qemu_egl_display, vc->gfx.ectx); -- vc->gfx.ectx = NULL; -- } --#endif -- gd_widget_reparent(s->notebook, vc->window, vc->tab_item); -- -- g_signal_connect(vc->window, "delete-event", -- G_CALLBACK(gd_tab_window_close), vc); -- gtk_widget_show_all(vc->window); -- -- if (qemu_console_is_graphic(vc->gfx.dcl.con)) { -- GtkAccelGroup *ag = gtk_accel_group_new(); -- gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag); -- GClosure *cb_grab = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), -- vc, NULL); -- gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb_grab); -- GClosure *cb_fs = g_cclosure_new_swap( -- G_CALLBACK(gd_vc_fullscreen_toggle), -- vc, NULL); -- gtk_accel_group_connect(ag, GDK_KEY_f, HOTKEY_MODIFIERS, 0, cb_fs); -- } -- -- gd_update_geometry_hints(vc); -- gd_update_caption(s); -+ gd_tab_window_create(vc); - } - } - --- -2.35.3 - diff --git a/SPECS/qemu/0007-ui-gtk-Add-a-new-parameter-to-assign-connectors-moni.patch b/SPECS/qemu/0007-ui-gtk-Add-a-new-parameter-to-assign-connectors-moni.patch deleted file mode 100644 index 3372660d43..0000000000 --- a/SPECS/qemu/0007-ui-gtk-Add-a-new-parameter-to-assign-connectors-moni.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 0bb774b2deafb7be37c1a1970760c0e5f1d84ce1 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Thu, 25 Apr 2024 19:24:26 +0000 -Subject: [PATCH 07/50] ui/gtk: Add a new parameter to assign - connectors/monitors -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The new parameter named "connector" can be used to assign physical -monitors/connectors to individual GFX VCs such that when the monitor -is connected or hotplugged, the associated GTK window would be -moved to it. If the monitor is disconnected or unplugged, the -associated GTK window would be hidden and a relevant disconnect -event would be sent to the Guest. - -Usage: -device virtio-gpu-pci,max_outputs=2,blob=true,... - -display gtk,gl=on,connectors.0=eDP-1,connectors.1=DP-1..... - -v2: updated the description for 'connectors' param with more details - -Cc: Gerd Hoffmann -Cc: Markus Armbruster -Cc: Marc-André Lureau -Signed-off-by: Vivek Kasireddy -Signed-off-by: Dongwon Kim ---- - include/ui/gtk.h | 1 + - qapi/ui.json | 26 ++++- - qemu-options.hx | 4 + - ui/gtk.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++- - 4 files changed, 270 insertions(+), 2 deletions(-) - -diff --git a/include/ui/gtk.h b/include/ui/gtk.h -index aa3d637029..3f78ee5996 100644 ---- a/include/ui/gtk.h -+++ b/include/ui/gtk.h -@@ -83,6 +83,7 @@ typedef struct VirtualConsole { - GtkWidget *menu_item; - GtkWidget *tab_item; - GtkWidget *focus; -+ GdkMonitor *monitor; - VirtualConsoleType type; - union { - VirtualGfxConsole gfx; -diff --git a/qapi/ui.json b/qapi/ui.json -index 8c8464faac..40c1f61020 100644 ---- a/qapi/ui.json -+++ b/qapi/ui.json -@@ -1334,13 +1334,37 @@ - # @show-menubar: Display the main window menubar. Defaults to "on". - # (Since 8.0) - # -+# @connectors: List of physical monitor/connector names where the -+# GTK windows containing the respective graphics virtual consoles -+# (VCs) are to be placed. Index of the connector name in the list -+# directly indicates the id of the VC. For example, with "-device -+# gtk,connectors.0=DP-1, connectors.1=HDMI-2", a physical display -+# connected to DP-1 will be the target monitor for VC0 and the one -+# on HDMI-2 will be the target for VC1. If there is no valid -+# connector name for a VC, it won't be displayed anywhere in any -+# situations and the associated virtual display will be shown -+# as disconnected in the guest. If a valid connector name exists for -+# a VC but its display cable is not plugged in when guest is launched, -+# the VC won't be displayed at first but will show up on the display -+# as soon as the cable is plugged in. If the cable is disconnected -+# again, the VC will immediately be hidden and guest will see its -+# virtual display disconnected. When this list param is used, there -+# shouldn't be any missing elements before the last one in the list. -+# For example, if connectors.3 is specified, then connector names for -+# connectors.0 through connectors.2 should also be given. Multiple -+# VCs can have a same connector name. In this case, all of those -+# VCs will be displayed on the same physical monitor. But multiple -+# different connector names can't be assigned to one VC. -+# (Since 9.1) -+# - # Since: 2.12 - ## - { 'struct' : 'DisplayGTK', - 'data' : { '*grab-on-hover' : 'bool', - '*zoom-to-fit' : 'bool', - '*show-tabs' : 'bool', -- '*show-menubar' : 'bool' } } -+ '*show-menubar' : 'bool', -+ '*connectors' : ['str'] } } - - ## - # @DisplayEGLHeadless: -diff --git a/qemu-options.hx b/qemu-options.hx -index d94e2cbbae..575c72e9a5 100644 ---- a/qemu-options.hx -+++ b/qemu-options.hx -@@ -2099,6 +2099,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, - "-display gtk[,full-screen=on|off][,gl=on|off][,grab-on-hover=on|off]\n" - " [,show-tabs=on|off][,show-cursor=on|off][,window-close=on|off]\n" - " [,show-menubar=on|off][,zoom-to-fit=on|off]\n" -+ " [,connectors.=]\n" - #endif - #if defined(CONFIG_VNC) - "-display vnc=[,]\n" -@@ -2195,6 +2196,9 @@ SRST - ``zoom-to-fit=on|off`` : Expand video output to the window size, - defaults to "off" - -+ ``connectors=`` : VC to connector mappings to display the VC -+ window on a specific monitor -+ - ``curses[,charset=]`` - Display video output via curses. For graphics device models - which support a text mode, QEMU can display this output using a -diff --git a/ui/gtk.c b/ui/gtk.c -index 53030516b2..421cc7fae5 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -38,6 +38,7 @@ - #include "qemu/cutils.h" - #include "qemu/error-report.h" - #include "qemu/main-loop.h" -+#include "qemu/option.h" - - #include "ui/console.h" - #include "ui/gtk.h" -@@ -1477,6 +1478,227 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) - } - } - -+static void gd_window_show_on_monitor(GdkDisplay *dpy, VirtualConsole *vc, -+ gint monitor_num) -+{ -+ GtkDisplayState *s = vc->s; -+ GdkMonitor *monitor = gdk_display_get_monitor(dpy, monitor_num); -+ GdkRectangle geometry; -+ GdkWindow *window; -+ QemuUIInfo info; -+ -+ if (!vc->window) { -+ gd_tab_window_create(vc); -+ } -+ -+ gdk_window_show(gtk_widget_get_window(vc->window)); -+ gd_update_windowsize(vc); -+ gdk_monitor_get_geometry(monitor, &geometry); -+ /* -+ * Note: some compositors (mainly Wayland ones) may not honor a -+ * request to move to a particular location. The user is expected -+ * to drag the window to the preferred location in this case. -+ */ -+ gtk_window_move(GTK_WINDOW(vc->window), geometry.x, geometry.y); -+ -+ if (s->opts->has_full_screen && s->opts->full_screen) { -+ gtk_widget_set_size_request(vc->gfx.drawing_area, -1, -1); -+ gtk_window_fullscreen(GTK_WINDOW(vc->window)); -+ } else if ((s->window == vc->window) && s->full_screen) { -+ gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s); -+ if (gtk_check_menu_item_get_active( -+ GTK_CHECK_MENU_ITEM(s->show_menubar_item))) { -+ gtk_widget_show(s->menu_bar); -+ } -+ s->full_screen = false; -+ } -+ -+ vc->monitor = monitor; -+ -+ window = gtk_widget_get_window(vc->gfx.drawing_area); -+ info = *dpy_get_ui_info(vc->gfx.dcl.con); -+ info.width = gdk_window_get_width(window); -+ info.height = gdk_window_get_height(window); -+ dpy_set_ui_info(vc->gfx.dcl.con, &info, false); -+ -+ if (gd_is_grab_active(s)) { -+ gd_grab_keyboard(vc, "user-request-main-window"); -+ gd_grab_pointer(vc, "user-request-main-window"); -+ } else { -+ gd_ungrab_keyboard(s); -+ gd_ungrab_pointer(s); -+ } -+ -+ gd_update_cursor(vc); -+} -+ -+static int gd_monitor_lookup(GdkDisplay *dpy, char *label) -+{ -+ GdkMonitor *monitor; -+ int total_monitors = gdk_display_get_n_monitors(dpy); -+ int i; -+ -+ for (i = 0; i < total_monitors; i++) { -+ monitor = gdk_display_get_monitor(dpy, i); -+ if (monitor && !g_strcmp0(gdk_monitor_get_model(monitor), label)) { -+ return i; -+ } -+ } -+ return -1; -+} -+ -+static gboolean gd_vc_is_misplaced(GdkDisplay *dpy, GdkMonitor *monitor, -+ VirtualConsole *vc) -+{ -+ GdkWindow *window = gtk_widget_get_window(vc->gfx.drawing_area); -+ GdkMonitor *mon = gdk_display_get_monitor_at_window(dpy, window); -+ const char *monitor_name = gdk_monitor_get_model(monitor); -+ -+ if (!vc->monitor) { -+ if (!g_strcmp0(monitor_name, vc->label)) { -+ return TRUE; -+ } -+ } else { -+ if (mon && mon != vc->monitor) { -+ return TRUE; -+ } -+ } -+ return FALSE; -+} -+ -+static void gd_vc_add_remove_monitor(GdkDisplay *dpy, GtkDisplayState *s) -+{ -+ VirtualConsole *vc; -+ GdkMonitor *monitor; -+ gint monitor_num; -+ int i; -+ -+ /* -+ * We need to call gd_vc_is_misplaced() after a monitor is added to -+ * ensure that the Host compositor has not moved our windows around. -+ */ -+ for (i = 0; i < s->nb_vcs; i++) { -+ vc = &s->vc[i]; -+ if (vc->label) { -+ monitor_num = gd_monitor_lookup(dpy, vc->label); -+ if (monitor_num >= 0) { -+ monitor = gdk_display_get_monitor(dpy, monitor_num); -+ if (gd_vc_is_misplaced(dpy, monitor, vc)) { -+ gd_window_show_on_monitor(dpy, vc, monitor_num); -+ } -+ } else { -+ if (vc->monitor) { -+ vc->monitor = NULL; -+ } -+ -+ if (dpy_ui_info_supported(vc->gfx.dcl.con)) { -+ QemuUIInfo info = *dpy_get_ui_info(vc->gfx.dcl.con); -+ info.width = 0; -+ info.height = 0; -+ dpy_set_ui_info(vc->gfx.dcl.con, &info, false); -+ } -+ -+ /* if window exist, hide it */ -+ if (vc->window) { -+ gdk_window_hide(gtk_widget_get_window(vc->window)); -+ } -+ } -+ } -+ } -+} -+ -+static void gd_monitors_reset_timer(void *opaque) -+{ -+ GtkDisplayState *s = opaque; -+ GdkDisplay *dpy = gdk_display_get_default(); -+ -+ gd_vc_add_remove_monitor(dpy, s); -+} -+ -+static void gd_monitors_changed(GdkScreen *scr, void *opaque) -+{ -+ GtkDisplayState *s = opaque; -+ QEMUTimer *mon_reset_timer; -+ -+ mon_reset_timer = timer_new_ms(QEMU_CLOCK_REALTIME, -+ gd_monitors_reset_timer, s); -+ timer_mod(mon_reset_timer, -+ qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 2000); -+} -+ -+static VirtualConsole *gd_next_gfx_vc(GtkDisplayState *s) -+{ -+ VirtualConsole *vc; -+ int i; -+ -+ for (i = 0; i < s->nb_vcs; i++) { -+ vc = &s->vc[i]; -+ if (vc->type == GD_VC_GFX && -+ qemu_console_is_graphic(vc->gfx.dcl.con) && -+ !vc->label) { -+ return vc; -+ } -+ } -+ return NULL; -+} -+ -+static void gd_vc_free_labels(GtkDisplayState *s) -+{ -+ VirtualConsole *vc; -+ int i; -+ -+ for (i = 0; i < s->nb_vcs; i++) { -+ vc = &s->vc[i]; -+ if (vc->type == GD_VC_GFX && -+ qemu_console_is_graphic(vc->gfx.dcl.con)) { -+ g_free(vc->label); -+ vc->label = NULL; -+ if (dpy_ui_info_supported(vc->gfx.dcl.con)) { -+ QemuUIInfo info = *dpy_get_ui_info(vc->gfx.dcl.con); -+ -+ info.width = 0; -+ info.height = 0; -+ dpy_set_ui_info(vc->gfx.dcl.con, &info, false); -+ } -+ } -+ } -+} -+ -+static void gd_connectors_init(GdkDisplay *dpy, GtkDisplayState *s) -+{ -+ VirtualConsole *vc; -+ QEMUTimer *mon_reset_timer; -+ strList *conn; -+ gint monitor_num; -+ gboolean first_vc = TRUE; -+ -+ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE); -+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), -+ FALSE); -+ gd_vc_free_labels(s); -+ for (conn = s->opts->u.gtk.connectors; conn; conn = conn->next) { -+ vc = gd_next_gfx_vc(s); -+ if (!vc) { -+ break; -+ } -+ if (first_vc) { -+ vc->window = s->window; -+ first_vc = FALSE; -+ } -+ -+ vc->label = g_strdup(conn->value); -+ monitor_num = gd_monitor_lookup(dpy, vc->label); -+ if (monitor_num >= 0) { -+ gd_window_show_on_monitor(dpy, vc, monitor_num); -+ } -+ } -+ -+ mon_reset_timer = timer_new_ms(QEMU_CLOCK_REALTIME, -+ gd_monitors_reset_timer, s); -+ timer_mod(mon_reset_timer, -+ qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 100); -+} -+ - static void gd_menu_show_menubar(GtkMenuItem *item, void *opaque) - { - GtkDisplayState *s = opaque; -@@ -1797,8 +2019,18 @@ static gboolean gd_configure(GtkWidget *widget, - GdkEventConfigure *cfg, gpointer opaque) - { - VirtualConsole *vc = opaque; -+ QemuUIInfo info; -+ -+ if (!dpy_ui_info_supported(vc->gfx.dcl.con)) { -+ return FALSE; -+ } -+ -+ info = *dpy_get_ui_info(vc->gfx.dcl.con); -+ -+ if (info.width || info.height) { -+ gd_set_ui_size(vc, cfg->width, cfg->height); -+ } - -- gd_set_ui_size(vc, cfg->width, cfg->height); - return FALSE; - } - -@@ -2133,6 +2365,10 @@ static void gd_connect_signals(GtkDisplayState *s) - G_CALLBACK(gd_menu_grab_input), s); - g_signal_connect(s->notebook, "switch-page", - G_CALLBACK(gd_change_page), s); -+ if (s->opts->u.gtk.has_connectors) { -+ g_signal_connect(gdk_screen_get_default(), "monitors-changed", -+ G_CALLBACK(gd_monitors_changed), s); -+ } - } - - static GtkWidget *gd_create_menu_machine(GtkDisplayState *s) -@@ -2520,6 +2756,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) - opts->u.gtk.show_tabs) { - gtk_menu_item_activate(GTK_MENU_ITEM(s->show_tabs_item)); - } -+ if (s->opts->u.gtk.has_connectors) { -+ gd_connectors_init(window_display, s); -+ } - #ifdef CONFIG_GTK_CLIPBOARD - gd_clipboard_init(s); - #endif /* CONFIG_GTK_CLIPBOARD */ --- -2.35.3 - diff --git a/SPECS/qemu/0008-Revert-meson.build-Disallow-libnfs-v6-to-fix-the-bro.patch b/SPECS/qemu/0008-Revert-meson.build-Disallow-libnfs-v6-to-fix-the-bro.patch new file mode 100644 index 0000000000..02a110d342 --- /dev/null +++ b/SPECS/qemu/0008-Revert-meson.build-Disallow-libnfs-v6-to-fix-the-bro.patch @@ -0,0 +1,27 @@ +From 9b6deac9e49210b270e2592bfedd250769e75970 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sun, 16 Mar 2025 09:17:55 +0000 +Subject: [PATCH 8/8] Revert "meson.build: Disallow libnfs v6 to fix the broken + macOS build" + +This reverts commit 42490ac98088a744113589aa75400d9db714776d. +--- + meson.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/meson.build b/meson.build +index 7f6f638676..08d242e870 100644 +--- a/meson.build ++++ b/meson.build +@@ -1122,7 +1122,7 @@ endif + + libnfs = not_found + if not get_option('libnfs').auto() or have_block +- libnfs = dependency('libnfs', version: ['>=1.9.3', '<6.0.0'], ++ libnfs = dependency('libnfs', version: '>=1.9.3', + required: get_option('libnfs'), + method: 'pkg-config') + endif +-- +2.48.1 + diff --git a/SPECS/qemu/0008-ui-gtk-Page-number-of-1-is-not-a-valid-page-number.patch b/SPECS/qemu/0008-ui-gtk-Page-number-of-1-is-not-a-valid-page-number.patch deleted file mode 100644 index edb7db4519..0000000000 --- a/SPECS/qemu/0008-ui-gtk-Page-number-of-1-is-not-a-valid-page-number.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 368de9a98fa35f2d91561d8f542919704ed0b12f Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Fri, 3 May 2024 23:42:39 +0000 -Subject: [PATCH 08/50] ui/gtk: Page number of '-1' is not a valid page number -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Page number of '-1' means the page does not belong to the -notebook so it shouldn't be used as a valid page number in -gd_vc_find_by_page. It should just return null if that is -the case. - -This change, however, will cause a segfault during detaching -/untabifying process in gtk_release_modifiers because the -current VC's page number suddenly becomes '-1' as soon as -it is detached then this invalid page number will eventually -bring in a null VC. So gtk_relaese_modifiers should do the -null check on the VC and just returns if VC == null. - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Signed-off-by: Vivek Kasireddy -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 421cc7fae5..32050533b7 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -165,7 +165,7 @@ static VirtualConsole *gd_vc_find_by_page(GtkDisplayState *s, gint page) - for (i = 0; i < s->nb_vcs; i++) { - vc = &s->vc[i]; - p = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), vc->tab_item); -- if (p == page) { -+ if (p >= 0 && p == page) { - return vc; - } - } -@@ -358,7 +358,7 @@ static void gtk_release_modifiers(GtkDisplayState *s) - { - VirtualConsole *vc = gd_vc_find_current(s); - -- if (vc->type != GD_VC_GFX || -+ if (!vc || vc->type != GD_VC_GFX || - !qemu_console_is_graphic(vc->gfx.dcl.con)) { - return; - } --- -2.35.3 - diff --git a/SPECS/qemu/0009-ui-gtk-move-guest-mouse-cursor-after-host-cursor-hit.patch b/SPECS/qemu/0009-ui-gtk-move-guest-mouse-cursor-after-host-cursor-hit.patch deleted file mode 100644 index baf0f8d556..0000000000 --- a/SPECS/qemu/0009-ui-gtk-move-guest-mouse-cursor-after-host-cursor-hit.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 6ea532059ec648f379b136ac52a5a5316d67de77 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Mon, 5 Feb 2024 13:42:44 -0800 -Subject: [PATCH 09/50] ui/gtk: move guest mouse cursor after host cursor hits - the edge of the display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When the host mouse cursor hits the boundary of the surface, the guest -mouse cursor also stops moving to one direction even if it is still in -the middle of the guest display. This is because dX and/or dY won't be -generated anymore. So it is needed to create those delta position data -artificially when the mouse cursor is still in move. - -Cc: Marc-André Lureau -Cc: Vivek Kasireddy -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 26 +++++++++++++++++++++++--- - 1 file changed, 23 insertions(+), 3 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 32050533b7..84e2f4bca5 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -889,6 +889,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, - { - VirtualConsole *vc = opaque; - GtkDisplayState *s = vc->s; -+ GdkDisplay *dpy = gtk_widget_get_display(vc->gfx.drawing_area); -+ GdkWindow *window = gtk_widget_get_window(vc->gfx.drawing_area); - int x, y; - int mx, my; - int fbh, fbw; -@@ -938,8 +940,27 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, - 0, surface_height(vc->gfx.ds)); - qemu_input_event_sync(); - } else if (s->last_set && s->ptr_owner == vc) { -- qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_X, x - s->last_x); -- qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_Y, y - s->last_y); -+ GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, window); -+ int dx = x - s->last_x; -+ int dy = y - s->last_y; -+ GdkRectangle curr_geometry; -+ -+ monitor = gdk_display_get_monitor_at_point(dpy, motion->x_root, motion->y_root); -+ gdk_monitor_get_geometry(monitor, &curr_geometry); -+ -+ if (motion->x_root <= curr_geometry.x) { -+ dx = -5; -+ } else if (motion->x_root >= curr_geometry.x + curr_geometry.width - 1) { -+ dx = 5; -+ } -+ -+ if (motion->y_root <= curr_geometry.y) { -+ dy = -5; -+ } else if (motion->y_root >= curr_geometry.y + curr_geometry.height - 1) { -+ dy = 5; -+ } -+ qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_X, dx); -+ qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_Y, dy); - qemu_input_event_sync(); - } - s->last_x = x; -@@ -948,7 +969,6 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, - - if (!qemu_input_is_absolute(vc->gfx.dcl.con) && s->ptr_owner == vc) { - GdkScreen *screen = gtk_widget_get_screen(vc->gfx.drawing_area); -- GdkDisplay *dpy = gtk_widget_get_display(widget); - GdkWindow *win = gtk_widget_get_window(widget); - GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); - GdkRectangle geometry; --- -2.35.3 - diff --git a/SPECS/qemu/0010-ui-gtk-Register-shortcut-key-for-grab_input-to-accel.patch b/SPECS/qemu/0010-ui-gtk-Register-shortcut-key-for-grab_input-to-accel.patch deleted file mode 100644 index 9618f5dcb7..0000000000 --- a/SPECS/qemu/0010-ui-gtk-Register-shortcut-key-for-grab_input-to-accel.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 5466f6fab7215da44caf9b1ecbc385d3738ad580 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Tue, 7 May 2024 01:01:34 +0000 -Subject: [PATCH 10/50] ui/gtk: Register shortcut key for grab_input to - accel_group - -To make the shortcut key when the window is fullscreened, it -should be registered to s->accel_group. - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 84e2f4bca5..79f6620803 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1956,6 +1956,12 @@ static void gd_menu_grab_input(GtkMenuItem *item, void *opaque) - gd_update_cursor(vc); - } - -+static void gd_accel_grab_input(void *opaque) -+{ -+ GtkDisplayState *s = opaque; -+ gtk_menu_item_activate(GTK_MENU_ITEM(s->grab_item)); -+} -+ - static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2, - gpointer data) - { -@@ -2599,6 +2605,11 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, DisplayOptions *opts) - gtk_accel_map_add_entry("/View/Grab Input", GDK_KEY_g, - HOTKEY_MODIFIERS); - gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->grab_item); -+ gtk_accel_group_connect(s->accel_group, GDK_KEY_g, HOTKEY_MODIFIERS, 0, -+ g_cclosure_new_swap(G_CALLBACK(gd_accel_grab_input), s, NULL)); -+ gtk_accel_label_set_accel( -+ GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(s->grab_item))), -+ GDK_KEY_g, HOTKEY_MODIFIERS); - - separator = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator); --- -2.35.3 - diff --git a/SPECS/qemu/0011-audio-Switch-audio-status-with-Guest-VM-switch-from-.patch b/SPECS/qemu/0011-audio-Switch-audio-status-with-Guest-VM-switch-from-.patch deleted file mode 100644 index d3fc500093..0000000000 --- a/SPECS/qemu/0011-audio-Switch-audio-status-with-Guest-VM-switch-from-.patch +++ /dev/null @@ -1,282 +0,0 @@ -From fbb9d2dd29343d60111bdef5db5c4c155243e901 Mon Sep 17 00:00:00 2001 -From: Pawan Kumar Tumkur Srinivasan -Date: Wed, 6 Mar 2024 20:44:12 -0800 -Subject: [PATCH 11/50] audio: Switch audio status with Guest VM switch from - QMP command - -Signed-off-by: Pawan Kumar Tumkur Srinivasan -Rebased-by: Mazlan, Hazwan Arif -Signed-off-by: Dongwon Kim ---- - audio/audio.c | 64 +++++++++++++++++++++++++++++++++++++++ - audio/audio_int.h | 2 ++ - include/qemu/typedefs.h | 1 + - include/sysemu/runstate.h | 8 +++++ - monitor/qmp-cmds.c | 8 +++++ - qapi/misc.json | 19 ++++++++++++ - system/runstate.c | 33 ++++++++++++++++++++ - 7 files changed, 135 insertions(+) - -diff --git a/audio/audio.c b/audio/audio.c -index af0ae33fed..062b15f611 100644 ---- a/audio/audio.c -+++ b/audio/audio.c -@@ -1609,6 +1609,53 @@ static void audio_vm_change_state_handler (void *opaque, bool running, - audio_reset_timer (s); - } - -+//This function handles Guest VM audio state during VM switch -+static void qemu_audio_status_change_handler (void *opaque, int status) -+{ -+ AudioState *s = opaque; -+ HWVoiceOut *hwo = NULL; -+ HWVoiceIn *hwi = NULL; -+ Volume out_vol , in_vol ; -+ -+ if (status > AUDIO_STATUS_ENABLE || status < AUDIO_STATUS_DISABLE) -+ return; -+ -+ while ((hwo = audio_pcm_hw_find_any_enabled_out(s, hwo))) { -+ if (hwo->pcm_ops->enable_out) { -+ //This reference is taken from above vm_change_state -+ hwo->pcm_ops->enable_out(hwo, status); -+ } -+ else if (hwo->pcm_ops->volume_out) { -+ //paaudio doesn't support enable_out , hence muting out volume -+ memcpy(&out_vol,&(hwo->out_set_vol),sizeof(Volume)); -+ -+ if (status == AUDIO_STATUS_DISABLE) -+ { -+ //If disable then mute out volume -+ out_vol.mute = 1; -+ } -+ hwo->pcm_ops->volume_out(hwo,&out_vol); -+ } -+ } -+ while ((hwi = audio_pcm_hw_find_any_enabled_in(s, hwi))) { -+ if (hwi->pcm_ops->enable_in) { -+ //This reference is taken from above vm_change_state -+ hwi->pcm_ops->enable_in(hwi, status); -+ } -+ else if (hwi->pcm_ops->volume_in) { -+ //paaudio doesn't support enable_in , hence muting in volume -+ memcpy(&in_vol,&(hwi->in_set_vol),sizeof(Volume)); -+ if (status == AUDIO_STATUS_DISABLE) -+ { -+ //If disable then mute in volume -+ in_vol.mute = 1; -+ } -+ hwi->pcm_ops->volume_in(hwi,&in_vol); -+ } -+ } -+ audio_reset_timer (s); -+} -+ - static void free_audio_state(AudioState *s) - { - HWVoiceOut *hwo, *hwon; -@@ -1721,6 +1768,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) - int done = 0; - const char *drvname; - VMChangeStateEntry *vmse; -+ qemu_audio_status_notifiers *q = NULL; - AudioState *s; - struct audio_driver *driver; - -@@ -1782,6 +1830,12 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) - "(Audio can continue looping even after stopping the VM)\n"); - } - -+ q = qemu_add_audio_status_change_notifier (qemu_audio_status_change_handler, s); -+ if (!q) { -+ dolog ("warning: Could not register audio change state handler\n" -+ "(Audio state toggle wont happen during VM switch)\n"); -+ } -+ - QTAILQ_INSERT_TAIL(&audio_states, s, list); - QLIST_INIT (&s->card_head); - vmstate_register_any(NULL, &vmstate_audio, s); -@@ -1959,6 +2013,11 @@ void audio_set_volume_out(SWVoiceOut *sw, Volume *vol) - sw->vol.r = nominal_volume.l * vol->vol[vol->channels > 1 ? 1 : 0] / - 255; - -+ hw->out_set_vol.mute = vol->mute; -+ hw->out_set_vol.channels = vol->channels; -+ hw->out_set_vol.vol[0] = vol->vol[0]; -+ hw->out_set_vol.vol[1] = vol->vol[1]; -+ - if (hw->pcm_ops->volume_out) { - hw->pcm_ops->volume_out(hw, vol); - } -@@ -1981,6 +2040,11 @@ void audio_set_volume_in(SWVoiceIn *sw, Volume *vol) - sw->vol.r = nominal_volume.r * vol->vol[vol->channels > 1 ? 1 : 0] / - 255; - -+ hw->in_set_vol.mute = vol->mute; -+ hw->in_set_vol.channels = vol->channels; -+ hw->in_set_vol.vol[0] = vol->vol[0]; -+ hw->in_set_vol.vol[1] = vol->vol[1]; -+ - if (hw->pcm_ops->volume_in) { - hw->pcm_ops->volume_in(hw, vol); - } -diff --git a/audio/audio_int.h b/audio/audio_int.h -index 2d079d00a2..9a6e04f259 100644 ---- a/audio/audio_int.h -+++ b/audio/audio_int.h -@@ -68,6 +68,7 @@ typedef struct HWVoiceOut { - int pending_disable; - struct audio_pcm_info info; - -+ Volume out_set_vol; - f_sample *clip; - uint64_t ts_helper; - -@@ -88,6 +89,7 @@ typedef struct HWVoiceIn { - int poll_mode; - struct audio_pcm_info info; - -+ Volume in_set_vol; - t_sample *conv; - - size_t total_samples_captured; -diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h -index 9d222dc376..5938fbad28 100644 ---- a/include/qemu/typedefs.h -+++ b/include/qemu/typedefs.h -@@ -117,6 +117,7 @@ typedef struct VirtIODevice VirtIODevice; - typedef struct Visitor Visitor; - typedef struct VMChangeStateEntry VMChangeStateEntry; - typedef struct VMStateDescription VMStateDescription; -+typedef struct qemu_audio_status_notifiers qemu_audio_status_notifiers; - - /* - * Pointer types -diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h -index 11c7ff3ffb..3bd3c8af82 100644 ---- a/include/sysemu/runstate.h -+++ b/include/sysemu/runstate.h -@@ -4,6 +4,9 @@ - #include "qapi/qapi-types-run-state.h" - #include "qemu/notify.h" - -+#define AUDIO_STATUS_ENABLE (1) -+#define AUDIO_STATUS_DISABLE (0) -+ - bool runstate_check(RunState state); - void runstate_set(RunState new_state); - RunState runstate_get(void); -@@ -11,8 +14,13 @@ bool runstate_is_running(void); - bool runstate_needs_reset(void); - void runstate_replay_enable(void); - -+typedef void qemu_audio_handler(void *opaque, int status); - typedef void VMChangeStateHandler(void *opaque, bool running, RunState state); - -+qemu_audio_status_notifiers* qemu_add_audio_status_change_notifier( -+ qemu_audio_handler *cb, void *opaque); -+void qemu_audio_status_change_notify(int status); -+ - VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, - void *opaque); - VMChangeStateEntry *qemu_add_vm_change_state_handler_prio( -diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c -index f84a0dc523..d56a58f956 100644 ---- a/monitor/qmp-cmds.c -+++ b/monitor/qmp-cmds.c -@@ -208,3 +208,11 @@ static void __attribute__((__constructor__)) monitor_init_qmp_commands(void) - qmp_marshal_qmp_capabilities, - QCO_ALLOW_PRECONFIG, 0); - } -+ -+void qmp_toggle_audio_status(int64_t value, Error **errp) -+{ -+ if (value > AUDIO_STATUS_ENABLE || value < AUDIO_STATUS_DISABLE) -+ return; -+ -+ qemu_audio_status_change_notify(value); -+} -diff --git a/qapi/misc.json b/qapi/misc.json -index 559b66f201..7a03210132 100644 ---- a/qapi/misc.json -+++ b/qapi/misc.json -@@ -151,6 +151,25 @@ - ## - { 'command': 'stop' } - -+## -+# @toggle-audio-status: -+# -+# @value: 1 for Enable , 0 for Disable -+# -+# TOGGLE_AUDIO_STATUS -+# -+# Since: 2.9 -+# -+# .. note:: Enables audio functionality on or off for guest VM switch -+# when done -+# -+# .. example:: -+# -+# -> { "execute": "toggle-audio-status","arguments": { "value": 1 } } -+# <- { "return": {} } -+## -+{ 'command': 'toggle-audio-status', 'data': {'value': 'int'} } -+ - ## - # @cont: - # -diff --git a/system/runstate.c b/system/runstate.c -index a0e2a5fd22..61176a60fc 100644 ---- a/system/runstate.c -+++ b/system/runstate.c -@@ -293,6 +293,13 @@ void qemu_system_vmstop_request(RunState state) - qemu_mutex_unlock(&vmstop_lock); - qemu_notify_event(); - } -+ -+struct qemu_audio_status_notifiers { -+ qemu_audio_handler *cb; -+ void *opaque; -+ QTAILQ_ENTRY(qemu_audio_status_notifiers) entries; -+}; -+ - struct VMChangeStateEntry { - VMChangeStateHandler *cb; - VMChangeStateHandler *prepare_cb; -@@ -304,6 +311,32 @@ struct VMChangeStateEntry { - static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head = - QTAILQ_HEAD_INITIALIZER(vm_change_state_head); - -+static QTAILQ_HEAD(, qemu_audio_status_notifiers) qemu_audio_status_notifiers_head = -+ QTAILQ_HEAD_INITIALIZER(qemu_audio_status_notifiers_head); -+ -+qemu_audio_status_notifiers* qemu_add_audio_status_change_notifier( -+ qemu_audio_handler *cb, void *opaque) -+{ -+ qemu_audio_status_notifiers *e = NULL; -+ e = g_malloc0(sizeof(*e)); -+ -+ if (e != NULL) { -+ e->cb = cb; -+ e->opaque = opaque; -+ QTAILQ_INSERT_TAIL(&qemu_audio_status_notifiers_head, e, entries); -+ } -+ -+ return e; -+} -+ -+void qemu_audio_status_change_notify(int status) -+{ -+ qemu_audio_status_notifiers *e = NULL, *next = NULL; -+ QTAILQ_FOREACH_SAFE(e, &qemu_audio_status_notifiers_head, entries, next){ -+ e->cb(e->opaque, status); -+ } -+} -+ - /** - * qemu_add_vm_change_state_handler_prio: - * @cb: the callback to invoke --- -2.35.3 - diff --git a/SPECS/qemu/0012-usb-hid-added-new-type-for-touch-stylus.patch b/SPECS/qemu/0012-usb-hid-added-new-type-for-touch-stylus.patch deleted file mode 100644 index 885fbc3eae..0000000000 --- a/SPECS/qemu/0012-usb-hid-added-new-type-for-touch-stylus.patch +++ /dev/null @@ -1,126 +0,0 @@ -From a8482084765d44adb4d089f53e3bf27ca6be00ac Mon Sep 17 00:00:00 2001 -From: "Raja Subramanian, Lakshmi Bai" -Date: Thu, 1 Dec 2022 22:26:19 +0530 -Subject: [PATCH 12/50] usb/hid: added new type for touch, stylus - -Stylus extension is provided using additional property for usb-tablet. - - -device usb-tablet,tablet_type=N - -where N=0 for Pointer type (default when no property is passed), - N=1 for Stylus/Touch type - -Signed-off-by: Raja Subramanian, Lakshmi Bai -Signed-off-by: Dongwon Kim ---- - hw/usb/dev-hid.c | 66 +++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 62 insertions(+), 4 deletions(-) - -diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c -index 9e358c934e..3a230f1b85 100644 ---- a/hw/usb/dev-hid.c -+++ b/hw/usb/dev-hid.c -@@ -43,6 +43,7 @@ struct USBHIDState { - uint32_t usb_version; - char *display; - uint32_t head; -+ uint32_t type; - }; - - #define TYPE_USB_HID "usb-hid" -@@ -483,7 +484,9 @@ static const uint8_t qemu_mouse_hid_report_descriptor[] = { - 0xc0, /* End Collection */ - }; - --static const uint8_t qemu_tablet_hid_report_descriptor[] = { -+#define QEMU_TABLET_TYPES_MAX 2 -+static const uint8_t qemu_tablet_hid_report_descriptor0[] = { -+ /* [0] defaults to Pointer type. if touch type is required, choose it through -device usb-tablet,tablet-type=1 */ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x02, /* Usage (Mouse) */ - 0xa1, 0x01, /* Collection (Application) */ -@@ -522,6 +525,55 @@ static const uint8_t qemu_tablet_hid_report_descriptor[] = { - 0xc0, /* End Collection */ - 0xc0, /* End Collection */ - }; -+static const uint8_t qemu_tablet_hid_report_descriptor1[] = { -+// [1] Selected using -device usb-tablet,tablet-type=1 -+ 0x05, 0x0d, /* Usage Page (Digitizer) */ -+ 0x09, 0x02, /* Usage (Pen) */ -+ 0xa1, 0x01, /* Collection (Application) */ -+// declare a finger collection -+ 0x09, 0x20, /* Usage (Stylus) */ -+ 0xA1, 0x00, /* Collection (Physical) */ -+// Declare a finger touch (finger up/down) -+ 0x09, 0x42, /* Usage (Tip Switch) */ -+ 0x09, 0x32, /* Usage (In Range) */ -+ 0x15, 0x00, /* Logical Minimum (0) */ -+ 0x25, 0x01, /* Logical Maximum (1) */ -+ 0x75, 0x01, /* Report Size (1) */ -+ 0x95, 0x02, /* Report Count (2) */ -+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ -+// Declare the remaining 6 bits of the first data byte as constant -> the driver will ignore them -+ 0x75, 0x01, /* Report Size (1) */ -+ 0x95, 0x06, /* Report Count (6) */ -+ 0x81, 0x01, /* Input (Constant) */ -+ 0x05, 0x01, /* Usage Page (Generic Desktop) */ -+ 0x09, 0x30, /* Usage (X) */ -+ 0x09, 0x31, /* Usage (Y) */ -+ 0x15, 0x00, /* Logical Minimum (0) */ -+ 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */ -+ 0x35, 0x00, /* Physical Minimum (0) */ -+ 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */ -+ 0x75, 0x10, /* Report Size (16) */ -+ 0x95, 0x02, /* Report Count (2) */ -+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ -+ 0x05, 0x01, /* Usage Page (Generic Desktop) */ -+ 0x09, 0x38, /* Usage (Wheel) */ -+ 0x15, 0x81, /* Logical Minimum (-0x7f) */ -+ 0x25, 0x7f, /* Logical Maximum (0x7f) */ -+ 0x35, 0x00, /* Physical Minimum (same as logical) */ -+ 0x45, 0x00, /* Physical Maximum (same as logical) */ -+ 0x75, 0x08, /* Report Size (8) */ -+ 0x95, 0x01, /* Report Count (1) */ -+ 0x81, 0x06, /* Input (Data, Variable, Relative) */ -+ 0xc0, /* End Collection */ -+ 0xc0, /* End Collection */ -+}; -+static const struct { -+ const uint8_t *descr; -+ size_t size; -+} qemu_tablet_hid_report_descriptor[QEMU_TABLET_TYPES_MAX] = { -+ { qemu_tablet_hid_report_descriptor0, sizeof (qemu_tablet_hid_report_descriptor0) }, -+ { qemu_tablet_hid_report_descriptor1, sizeof (qemu_tablet_hid_report_descriptor1) } -+}; - - static const uint8_t qemu_keyboard_hid_report_descriptor[] = { - 0x05, 0x01, /* Usage Page (Generic Desktop) */ -@@ -594,9 +646,14 @@ static void usb_hid_handle_control(USBDevice *dev, USBPacket *p, - sizeof(qemu_mouse_hid_report_descriptor)); - p->actual_length = sizeof(qemu_mouse_hid_report_descriptor); - } else if (hs->kind == HID_TABLET) { -- memcpy(data, qemu_tablet_hid_report_descriptor, -- sizeof(qemu_tablet_hid_report_descriptor)); -- p->actual_length = sizeof(qemu_tablet_hid_report_descriptor); -+ uint32_t type = us->type; -+ -+ if (type >= QEMU_TABLET_TYPES_MAX) -+ type = 0; -+ -+ memcpy(data, qemu_tablet_hid_report_descriptor[type].descr, -+ qemu_tablet_hid_report_descriptor[type].size); -+ p->actual_length = qemu_tablet_hid_report_descriptor[type].size; - } else if (hs->kind == HID_KEYBOARD) { - memcpy(data, qemu_keyboard_hid_report_descriptor, - sizeof(qemu_keyboard_hid_report_descriptor)); -@@ -797,6 +854,7 @@ static Property usb_tablet_properties[] = { - DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2), - DEFINE_PROP_STRING("display", USBHIDState, display), - DEFINE_PROP_UINT32("head", USBHIDState, head, 0), -+ DEFINE_PROP_UINT32("tablet_type", USBHIDState, type, 0), - DEFINE_PROP_END_OF_LIST(), - }; - --- -2.35.3 - diff --git a/SPECS/qemu/0013-ui-gtk-Adds-status-bar-and-display-guest-ups-and-dra.patch b/SPECS/qemu/0013-ui-gtk-Adds-status-bar-and-display-guest-ups-and-dra.patch deleted file mode 100644 index 225537b98c..0000000000 --- a/SPECS/qemu/0013-ui-gtk-Adds-status-bar-and-display-guest-ups-and-dra.patch +++ /dev/null @@ -1,224 +0,0 @@ -From f2f294d2fca412a114e2cb93b38a789b198f6db2 Mon Sep 17 00:00:00 2001 -From: "Kim, Dongwon" -Date: Tue, 20 Aug 2024 08:00:34 +0800 -Subject: [PATCH 13/50] ui/gtk: Adds status bar and display guest ups and draw - fps - -With a display option, "show-fps=on", qemu adds a status bar and print -following performance numbers on the bar, - -ups = update per seconds - the rate the guest scanout is flushed -fps = frame per seconds - the frame rate of actual draw done in QEMU - -One function, gd_gl_count_frame is added to count # frames -and calculate ups and fps every 100 frames or guest scanout updates. - -Signed-off-by: Kim, Dongwon ---- - include/ui/gtk.h | 4 ++++ - qapi/ui.json | 8 +++++-- - qemu-options.hx | 5 +++++ - ui/gtk-egl.c | 2 ++ - ui/gtk-gl-area.c | 1 + - ui/gtk.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ - 6 files changed, 74 insertions(+), 2 deletions(-) - -diff --git a/include/ui/gtk.h b/include/ui/gtk.h -index 3f78ee5996..07a65254ef 100644 ---- a/include/ui/gtk.h -+++ b/include/ui/gtk.h -@@ -57,6 +57,8 @@ typedef struct VirtualGfxConsole { - bool y0_top; - bool scanout_mode; - bool has_dmabuf; -+ unsigned int ups_cnt; -+ unsigned int fps_cnt; - #endif - } VirtualGfxConsole; - -@@ -124,6 +126,7 @@ struct GtkDisplayState { - GtkWidget *show_tabs_item; - GtkWidget *untabify_item; - GtkWidget *show_menubar_item; -+ GtkWidget *status_bar; - - GtkWidget *vbox; - GtkWidget *notebook; -@@ -158,6 +161,7 @@ extern bool gtk_use_gl_area; - void gd_update_windowsize(VirtualConsole *vc); - void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget); - void gd_hw_gl_flushed(void *vc); -+void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups); - - /* ui/gtk-egl.c */ - void gd_egl_init(VirtualConsole *vc); -diff --git a/qapi/ui.json b/qapi/ui.json -index 40c1f61020..3b98d51e80 100644 ---- a/qapi/ui.json -+++ b/qapi/ui.json -@@ -1355,7 +1355,10 @@ - # VCs can have a same connector name. In this case, all of those - # VCs will be displayed on the same physical monitor. But multiple - # different connector names can't be assigned to one VC. --# (Since 9.1) -+# (Since Pending) -+# -+# @show-fps: Enable showing frame update rate (default: off). -+# (Since Pending) - # - # Since: 2.12 - ## -@@ -1364,7 +1367,8 @@ - '*zoom-to-fit' : 'bool', - '*show-tabs' : 'bool', - '*show-menubar' : 'bool', -- '*connectors' : ['str'] } } -+ '*connectors' : ['str'], -+ '*show-fps' : 'bool' } } - - ## - # @DisplayEGLHeadless: -diff --git a/qemu-options.hx b/qemu-options.hx -index 575c72e9a5..e2dbf08b05 100644 ---- a/qemu-options.hx -+++ b/qemu-options.hx -@@ -2100,6 +2100,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, - " [,show-tabs=on|off][,show-cursor=on|off][,window-close=on|off]\n" - " [,show-menubar=on|off][,zoom-to-fit=on|off]\n" - " [,connectors.=]\n" -+ " [,show-fps=on|off]\n" - #endif - #if defined(CONFIG_VNC) - "-display vnc=[,]\n" -@@ -2199,6 +2200,10 @@ SRST - ``connectors=`` : VC to connector mappings to display the VC - window on a specific monitor - -+ ``show-fps=on|off`` : Display Guest Scanout's update rate (UPS) and -+ QEMU draw rate (FPS) on a status bar attached to -+ QEMU window. -+ - ``curses[,charset=]`` - Display video output via curses. For graphics device models - which support a text mode, QEMU can display this output using a -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index a5a439c1db..0bc6d08faa 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -390,11 +390,13 @@ void gd_egl_flush(DisplayChangeListener *dcl, - qemu_dmabuf_set_draw_submitted(dmabuf, true); - gtk_widget_queue_draw_area(area, x, y, w, h); - } -+ gd_gl_count_frame(&vc->gfx.dcl, 1); - return; - } - #endif - - gd_egl_scanout_flush(&vc->gfx.dcl, x, y, w, h); -+ gd_gl_count_frame(&vc->gfx.dcl, 1); - } - - void gtk_egl_init(DisplayGLMode mode) -diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c -index cc4765403d..4ac364bddf 100644 ---- a/ui/gtk-gl-area.c -+++ b/ui/gtk-gl-area.c -@@ -322,6 +322,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, - } - #endif - gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); -+ gd_gl_count_frame(&vc->gfx.dcl, 1); - } - - void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl, -diff --git a/ui/gtk.c b/ui/gtk.c -index 79f6620803..7df9a98d6c 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -554,6 +554,55 @@ static void gd_switch(DisplayChangeListener *dcl, - } - } - -+void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups) -+{ -+ VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); -+ GtkDisplayState *s = vc->s; -+ gchar ups_fps_str[200]; -+ static guint prev, curr, delta; -+ static guint status_bar_id; -+ struct timeval tv; -+ int offset = 0, i; -+ -+ if (!s->opts->u.gtk.has_show_fps || !s->opts->u.gtk.show_fps) { -+ return; -+ } -+ -+ if (prev == 0) { -+ gettimeofday(&tv, NULL); -+ prev = tv.tv_sec * 1000000 + tv.tv_usec; -+ } -+ -+ if (ups) { -+ vc->gfx.ups_cnt++; -+ } else { -+ vc->gfx.fps_cnt++; -+ } -+ -+ gettimeofday(&tv, NULL); -+ curr = tv.tv_sec * 1000000 + tv.tv_usec; -+ -+ delta = curr - prev; -+ if (delta > 5000000) { -+ /* update rate is calculated and displayed at every 5 secs */ -+ prev = curr; -+ for (i = 0; i < vc->s->nb_vcs; i++) { -+ vc = &s->vc[i]; -+ offset += sprintf(ups_fps_str + offset, -+ "%d [%0.2fu/s %0.2ff/s] ", i, -+ vc->gfx.ups_cnt * 1000000/(gfloat)delta, -+ vc->gfx.fps_cnt * 1000000/(gfloat)delta); -+ vc->gfx.fps_cnt = 0; -+ vc->gfx.ups_cnt = 0; -+ } -+ -+ status_bar_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(vc->s->status_bar), -+ "Display Update Rate"); -+ gtk_statusbar_pop(GTK_STATUSBAR(vc->s->status_bar), status_bar_id); -+ gtk_statusbar_push(GTK_STATUSBAR(vc->s->status_bar), status_bar_id, ups_fps_str); -+ } -+} -+ - static const DisplayChangeListenerOps dcl_ops = { - .dpy_name = "gtk", - .dpy_gfx_update = gd_update, -@@ -605,6 +654,7 @@ void gd_hw_gl_flushed(void *vcon) - close(fence_fd); - qemu_dmabuf_set_fence_fd(dmabuf, -1); - graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ gd_gl_count_frame(&vc->gfx.dcl, 0); - } - } - -@@ -2710,6 +2760,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) - s->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - s->notebook = gtk_notebook_new(); - s->menu_bar = gtk_menu_bar_new(); -+ if (opts->u.gtk.has_show_fps && opts->u.gtk.show_fps) { -+ s->status_bar = gtk_statusbar_new(); -+ } - - s->free_scale = FALSE; - -@@ -2750,6 +2803,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) - - gtk_box_pack_start(GTK_BOX(s->vbox), s->menu_bar, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(s->vbox), s->notebook, TRUE, TRUE, 0); -+ if (opts->u.gtk.has_show_fps && opts->u.gtk.show_fps) { -+ gtk_box_pack_start(GTK_BOX(s->vbox), s->status_bar, FALSE, TRUE, 0); -+ } - - gtk_container_add(GTK_CONTAINER(s->window), s->vbox); - --- -2.35.3 - diff --git a/SPECS/qemu/0014-ui-gtk-Refresh-grabbing-status-when-the-window-is-fo.patch b/SPECS/qemu/0014-ui-gtk-Refresh-grabbing-status-when-the-window-is-fo.patch deleted file mode 100644 index 7cd24d6723..0000000000 --- a/SPECS/qemu/0014-ui-gtk-Refresh-grabbing-status-when-the-window-is-fo.patch +++ /dev/null @@ -1,108 +0,0 @@ -From f638f783fa16efcb7377597c7af56d2e6a589eab Mon Sep 17 00:00:00 2001 -From: "Kim, Dongwon" -Date: Tue, 20 Aug 2024 08:41:38 +0800 -Subject: [PATCH 14/50] ui/gtk: Refresh grabbing status when the window is - focused - -The grabbing is lost when the window become invisible (e.g. -windows minimization), so it is required to make it reacquire -it when it is visible again. - -Signed-off-by: Kim, Dongwon ---- - ui/gtk.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 45 insertions(+), 6 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 7df9a98d6c..90caf7785b 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1495,6 +1495,32 @@ static void gd_vc_fullscreen_toggle(void *opaque) - } - } - -+static gboolean gd_window_state_event(GtkWidget *widget, GdkEvent *event, -+ void *opaque) -+{ -+ VirtualConsole *vc = opaque; -+ GtkDisplayState *s = vc->s; -+ -+ if (!vc) { -+ return TRUE; -+ } -+ -+ if (event->window_state.new_window_state & GDK_WINDOW_STATE_FOCUSED) { -+ if (s->ptr_owner == vc && s->kbd_owner == vc) { -+ if (gd_is_grab_active(s)) { -+ s->ptr_owner = NULL; -+ s->kbd_owner = NULL; -+ gd_grab_keyboard(vc, "windows-focused"); -+ gd_grab_pointer(vc, "windows-focused"); -+ } else { -+ gd_ungrab_keyboard(s); -+ gd_ungrab_pointer(s); -+ } -+ } -+ } -+ return TRUE; -+} -+ - static void gd_tab_window_create(VirtualConsole *vc) - { - GtkDisplayState *s = vc->s; -@@ -1527,6 +1553,8 @@ static void gd_tab_window_create(VirtualConsole *vc) - G_CALLBACK(gd_vc_fullscreen_toggle), - vc, NULL); - gtk_accel_group_connect(ag, GDK_KEY_f, HOTKEY_MODIFIERS, 0, cb_fs); -+ g_signal_connect(vc->window, "window-state-event", -+ G_CALLBACK(gd_window_state_event), vc); - } - - gd_update_geometry_hints(vc); -@@ -1548,6 +1576,9 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) - } - } - -+static void gd_accel_grab_input(void *opaque); -+static void gd_grab_update(VirtualConsole *vc, bool kbd, bool ptr); -+ - static void gd_window_show_on_monitor(GdkDisplay *dpy, VirtualConsole *vc, - gint monitor_num) - { -@@ -1591,12 +1622,17 @@ static void gd_window_show_on_monitor(GdkDisplay *dpy, VirtualConsole *vc, - info.height = gdk_window_get_height(window); - dpy_set_ui_info(vc->gfx.dcl.con, &info, false); - -- if (gd_is_grab_active(s)) { -- gd_grab_keyboard(vc, "user-request-main-window"); -- gd_grab_pointer(vc, "user-request-main-window"); -- } else { -- gd_ungrab_keyboard(s); -- gd_ungrab_pointer(s); -+ if (s->ptr_owner && s->kbd_owner && -+ s->ptr_owner == vc && s->kbd_owner == vc) { -+ if (gd_is_grab_active(s)) { -+ s->ptr_owner = NULL; -+ s->kbd_owner = NULL; -+ gd_grab_keyboard(vc, "user-request-main-window"); -+ gd_grab_pointer(vc, "user-request-main-window"); -+ } else { -+ gd_ungrab_keyboard(s); -+ gd_ungrab_pointer(s); -+ } - } - - gd_update_cursor(vc); -@@ -2825,6 +2861,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) - } - - vc = gd_vc_find_current(s); -+ g_signal_connect(s->window, "window-state-event", -+ G_CALLBACK(gd_window_state_event), vc); -+ - gtk_widget_set_sensitive(s->view_menu, vc != NULL); - #ifdef CONFIG_VTE - gtk_widget_set_sensitive(s->copy_item, --- -2.35.3 - diff --git a/SPECS/qemu/0015-ui-gtk-untabifying-even-the-primary-window.patch b/SPECS/qemu/0015-ui-gtk-untabifying-even-the-primary-window.patch deleted file mode 100644 index bbca849700..0000000000 --- a/SPECS/qemu/0015-ui-gtk-untabifying-even-the-primary-window.patch +++ /dev/null @@ -1,27 +0,0 @@ -From a0b2944c7c3b5883ecb0f48e5f7458ea592e26a3 Mon Sep 17 00:00:00 2001 -From: "Kim, Dongwon" -Date: Tue, 20 Aug 2024 08:43:33 +0800 -Subject: [PATCH 15/50] ui/gtk: untabifying even the primary window - -Signed-off-by: Kim, Dongwon ---- - ui/gtk.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 90caf7785b..5a2fb5a008 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1571,7 +1571,8 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), - FALSE); - } -- if (!vc->window) { -+ -+ if (!vc->window || (vc->window == s->window)) { - gd_tab_window_create(vc); - } - } --- -2.35.3 - diff --git a/SPECS/qemu/0016-ui-gtk-Forcefully-full-screening-window.patch b/SPECS/qemu/0016-ui-gtk-Forcefully-full-screening-window.patch deleted file mode 100644 index 114edbb7a1..0000000000 --- a/SPECS/qemu/0016-ui-gtk-Forcefully-full-screening-window.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 5724bb94775a585f68eed1a1dbbb7038c5c56c06 Mon Sep 17 00:00:00 2001 -From: "Kim, Dongwon" -Date: Wed, 21 Aug 2024 02:26:55 +0800 -Subject: [PATCH 16/50] ui/gtk: Forcefully full-screening window - -Re-fullscreen the window if it was shrunk by the compositor after -QEMU is launched. - -This is to WA the problem in Ubuntu 24.04 - -Signed-off-by: Kim, Dongwon ---- - include/ui/gtk.h | 1 + - ui/gtk.c | 17 +++++++++++++++++ - 2 files changed, 18 insertions(+) - -diff --git a/include/ui/gtk.h b/include/ui/gtk.h -index 07a65254ef..e9cdb12ef2 100644 ---- a/include/ui/gtk.h -+++ b/include/ui/gtk.h -@@ -87,6 +87,7 @@ typedef struct VirtualConsole { - GtkWidget *focus; - GdkMonitor *monitor; - VirtualConsoleType type; -+ bool full_screen; - union { - VirtualGfxConsole gfx; - #if defined(CONFIG_VTE) -diff --git a/ui/gtk.c b/ui/gtk.c -index 5a2fb5a008..9df7e03094 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1487,11 +1487,13 @@ static void gd_vc_fullscreen_toggle(void *opaque) - vc->gfx.scale_y = 1.0; - gd_update_windowsize(vc); - } -+ vc->full_screen = false; - } else { - if (vc->type == GD_VC_GFX) { - gtk_widget_set_size_request(vc->gfx.drawing_area, -1, -1); - } - gtk_window_fullscreen(GTK_WINDOW(vc->window)); -+ vc->full_screen = true; - } - } - -@@ -1518,6 +1520,20 @@ static gboolean gd_window_state_event(GtkWidget *widget, GdkEvent *event, - } - } - } -+ -+ /* WA to fullscreen window if it's forcefully un-fullscreened by -+ * the compositor */ -+ if (!(event->window_state.new_window_state & -+ GDK_WINDOW_STATE_FULLSCREEN)) { -+ if (vc == gd_vc_find_current(vc->s) && vc->s->full_screen) { -+ vc->s->full_screen = false; -+ gtk_menu_item_activate(GTK_MENU_ITEM(vc->s->full_screen_item)); -+ } else if (vc->full_screen) { -+ vc->full_screen = false; -+ gd_vc_fullscreen_toggle(vc); -+ } -+ } -+ - return TRUE; - } - -@@ -1606,6 +1622,7 @@ static void gd_window_show_on_monitor(GdkDisplay *dpy, VirtualConsole *vc, - if (s->opts->has_full_screen && s->opts->full_screen) { - gtk_widget_set_size_request(vc->gfx.drawing_area, -1, -1); - gtk_window_fullscreen(GTK_WINDOW(vc->window)); -+ vc->full_screen = true; - } else if ((s->window == vc->window) && s->full_screen) { - gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s); - if (gtk_check_menu_item_get_active( --- -2.35.3 - diff --git a/SPECS/qemu/0017-ui-spice-Add-an-option-for-users-to-provide-a-prefer.patch b/SPECS/qemu/0017-ui-spice-Add-an-option-for-users-to-provide-a-prefer.patch deleted file mode 100644 index 50c0cd3c2c..0000000000 --- a/SPECS/qemu/0017-ui-spice-Add-an-option-for-users-to-provide-a-prefer.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 919dd0c928f7e6a858c6dcb2254f434359754792 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Tue, 10 Jan 2023 12:59:21 -0800 -Subject: [PATCH 17/50] ui/spice: Add an option for users to provide a - preferred codec -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Giving users an option to choose a particular codec will enable -them to make an appropriate decision based on their hardware and -use-case. - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Cc: Frediano Ziglio -Cc: Dongwon Kim -Signed-off-by: Vivek Kasireddy ---- - qemu-options.hx | 5 +++++ - ui/spice-core.c | 12 ++++++++++++ - 2 files changed, 17 insertions(+) - -diff --git a/qemu-options.hx b/qemu-options.hx -index e2dbf08b05..cad6d85b8c 100644 ---- a/qemu-options.hx -+++ b/qemu-options.hx -@@ -2290,6 +2290,7 @@ DEF("spice", HAS_ARG, QEMU_OPTION_spice, - " [,streaming-video=[off|all|filter]][,disable-copy-paste=on|off]\n" - " [,disable-agent-file-xfer=on|off][,agent-mouse=[on|off]]\n" - " [,playback-compression=[on|off]][,seamless-migration=[on|off]]\n" -+ " [,preferred-codec=:\n" - " [,gl=[on|off]][,rendernode=]\n" - " enable spice\n" - " at least one of {port, tls-port} is mandatory\n", -@@ -2378,6 +2379,10 @@ SRST - ``seamless-migration=[on|off]`` - Enable/disable spice seamless migration. Default is off. - -+ ``preferred-codec=:`` -+ Provide the preferred codec the Spice server should use. -+ Default would be spice:mjpeg. -+ - ``gl=[on|off]`` - Enable/disable OpenGL context. Default is off. - -diff --git a/ui/spice-core.c b/ui/spice-core.c -index 15be640286..d7c57d49fe 100644 ---- a/ui/spice-core.c -+++ b/ui/spice-core.c -@@ -488,6 +488,9 @@ static QemuOptsList qemu_spice_opts = { - },{ - .name = "streaming-video", - .type = QEMU_OPT_STRING, -+ },{ -+ .name = "preferred-codec", -+ .type = QEMU_OPT_STRING, - },{ - .name = "agent-mouse", - .type = QEMU_OPT_BOOL, -@@ -662,6 +665,7 @@ static void qemu_spice_init(void) - char *x509_key_file = NULL, - *x509_cert_file = NULL, - *x509_cacert_file = NULL; -+ const char *preferred_codec = NULL; - int port, tls_port, addr_flags; - spice_image_compression_t compression; - spice_wan_compression_t wan_compr; -@@ -801,6 +805,14 @@ static void qemu_spice_init(void) - spice_server_set_streaming_video(spice_server, SPICE_STREAM_VIDEO_OFF); - } - -+ preferred_codec = qemu_opt_get(opts, "preferred-codec"); -+ if (preferred_codec) { -+ if (spice_server_set_video_codecs(spice_server, preferred_codec)) { -+ error_report("Preferred codec name is not valid"); -+ exit(1); -+ } -+ } -+ - spice_server_set_agent_mouse - (spice_server, qemu_opt_get_bool(opts, "agent-mouse", 1)); - spice_server_set_playback_compression --- -2.35.3 - diff --git a/SPECS/qemu/0018-ui-spice-Enable-gl-on-option-for-non-local-or-remote.patch b/SPECS/qemu/0018-ui-spice-Enable-gl-on-option-for-non-local-or-remote.patch deleted file mode 100644 index ca7cfc26ae..0000000000 --- a/SPECS/qemu/0018-ui-spice-Enable-gl-on-option-for-non-local-or-remote.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 78f53216a721b42c9220215480dd249c481a361e Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Wed, 15 Mar 2023 22:18:00 -0700 -Subject: [PATCH 18/50] ui/spice: Enable gl=on option for non-local or remote - clients -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Newer versions of Spice server should be able to accept dmabuf -fds from Qemu for clients that are connected via the network. -In other words, when this option is enabled, Qemu would share -a dmabuf fd with Spice which would encode and send the data -associated with the fd to a client that could be located on -a different machine. - -v2: spice-server version 0.15.1 onwards since in BKC we are cherry-pick -the patches - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Cc: Frediano Ziglio -Cc: Dongwon Kim -Signed-off-by: Vivek Kasireddy -Signed-off-by: Mazlan, Hazwan Arif ---- - include/ui/spice-display.h | 1 + - ui/spice-core.c | 4 ++++ - ui/spice-display.c | 1 + - 3 files changed, 6 insertions(+) - -diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h -index e1a9b36185..f4922dd74b 100644 ---- a/include/ui/spice-display.h -+++ b/include/ui/spice-display.h -@@ -151,6 +151,7 @@ struct SimpleSpiceCursor { - }; - - extern bool spice_opengl; -+extern bool remote_client; - - int qemu_spice_rect_is_empty(const QXLRect* r); - void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r); -diff --git a/ui/spice-core.c b/ui/spice-core.c -index d7c57d49fe..39991c1686 100644 ---- a/ui/spice-core.c -+++ b/ui/spice-core.c -@@ -848,9 +848,13 @@ static void qemu_spice_init(void) - #ifdef HAVE_SPICE_GL - if (qemu_opt_get_bool(opts, "gl", 0)) { - if ((port != 0) || (tls_port != 0)) { -+#if SPICE_SERVER_VERSION >= 0x000f01 /* release 0.15.1 */ -+ remote_client = 1; -+#else - error_report("SPICE GL support is local-only for now and " - "incompatible with -spice port/tls-port"); - exit(1); -+#endif - } - egl_init(qemu_opt_get(opts, "rendernode"), DISPLAYGL_MODE_ON, &error_fatal); - spice_opengl = 1; -diff --git a/ui/spice-display.c b/ui/spice-display.c -index c794ae0649..bf4caf0d1b 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -29,6 +29,7 @@ - #include "ui/spice-display.h" - - bool spice_opengl; -+bool remote_client; - - int qemu_spice_rect_is_empty(const QXLRect* r) - { --- -2.35.3 - diff --git a/SPECS/qemu/0019-ui-spice-Submit-the-gl_draw-requests-at-60-FPS-for-r.patch b/SPECS/qemu/0019-ui-spice-Submit-the-gl_draw-requests-at-60-FPS-for-r.patch deleted file mode 100644 index 64abcd811a..0000000000 --- a/SPECS/qemu/0019-ui-spice-Submit-the-gl_draw-requests-at-60-FPS-for-r.patch +++ /dev/null @@ -1,103 +0,0 @@ -From db25d97d5a50e705a0274691008005ccd5722377 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Tue, 5 Sep 2023 14:53:37 -0700 -Subject: [PATCH 19/50] ui/spice: Submit the gl_draw requests at 60 FPS for - remote clients -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In the specific case where the display layer (virtio-gpu) is using -dmabuf, and if remote clients are enabled (-spice gl=on,port=xxxx), -it makes sense to limit the maximum (streaming) rate to 60 FPS -using the GUI timer. This matches the behavior of GTK UI where the -display updates are submitted at 60 FPS (assuming the underlying -mode is WxY@60). - -Cc: Gerd Hoffmann -Cc: Marc-André Lureau -Cc: Frediano Ziglio -Cc: Dongwon Kim -Signed-off-by: Vivek Kasireddy ---- - ui/spice-display.c | 39 +++++++++++++++++++++++++++++---------- - 1 file changed, 29 insertions(+), 10 deletions(-) - -diff --git a/ui/spice-display.c b/ui/spice-display.c -index bf4caf0d1b..9a185d360d 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -842,12 +842,32 @@ static void qemu_spice_gl_block_timer(void *opaque) - warn_report("spice: no gl-draw-done within one second"); - } - -+static void spice_gl_draw(SimpleSpiceDisplay *ssd, -+ uint32_t x, uint32_t y, uint32_t w, uint32_t h) -+{ -+ uint64_t cookie; -+ -+ cookie = (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0); -+ spice_qxl_gl_draw_async(&ssd->qxl, x, y, w, h, cookie); -+} -+ - static void spice_gl_refresh(DisplayChangeListener *dcl) - { - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); -- uint64_t cookie; - -- if (!ssd->ds || qemu_console_is_gl_blocked(ssd->dcl.con)) { -+ if (!ssd->ds) { -+ return; -+ } -+ -+ if (qemu_console_is_gl_blocked(ssd->dcl.con)) { -+ if (remote_client && ssd->gl_updates && ssd->have_scanout) { -+ glFlush(); -+ spice_gl_draw(ssd, 0, 0, -+ surface_width(ssd->ds), surface_height(ssd->ds)); -+ ssd->gl_updates = 0; -+ /* To stream at 60 FPS, the (GUI) timer delay needs to be ~17 ms */ -+ dcl->update_interval = 1000 / (2 * GUI_REFRESH_INTERVAL_DEFAULT) + 1; -+ } - return; - } - -@@ -855,11 +875,8 @@ static void spice_gl_refresh(DisplayChangeListener *dcl) - if (ssd->gl_updates && ssd->have_surface) { - qemu_spice_gl_block(ssd, true); - glFlush(); -- cookie = (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0); -- spice_qxl_gl_draw_async(&ssd->qxl, 0, 0, -- surface_width(ssd->ds), -- surface_height(ssd->ds), -- cookie); -+ spice_gl_draw(ssd, 0, 0, -+ surface_width(ssd->ds), surface_height(ssd->ds)); - ssd->gl_updates = 0; - } - } -@@ -1029,7 +1046,6 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, - EGLint stride = 0, fourcc = 0; - bool render_cursor = false; - bool y_0_top = false; /* FIXME */ -- uint64_t cookie; - int fd; - uint32_t width, height, texture; - -@@ -1107,8 +1123,11 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, - trace_qemu_spice_gl_update(ssd->qxl.id, w, h, x, y); - qemu_spice_gl_block(ssd, true); - glFlush(); -- cookie = (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0); -- spice_qxl_gl_draw_async(&ssd->qxl, x, y, w, h, cookie); -+ if (remote_client) { -+ ssd->gl_updates++; -+ } else { -+ spice_gl_draw(ssd, x, y, w, h); -+ } - } - - static const DisplayChangeListenerOps display_listener_gl_ops = { --- -2.35.3 - diff --git a/SPECS/qemu/0020-ui-console-gl-Add-a-helper-to-create-a-texture-with-.patch b/SPECS/qemu/0020-ui-console-gl-Add-a-helper-to-create-a-texture-with-.patch deleted file mode 100644 index 4d92b5756d..0000000000 --- a/SPECS/qemu/0020-ui-console-gl-Add-a-helper-to-create-a-texture-with-.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0ab0ac2bdb86c9c2287b0bbf052563fbf0c81aae Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Tue, 16 Jan 2024 23:02:37 -0800 -Subject: [PATCH 20/50] ui/console-gl: Add a helper to create a texture with - linear memory layout - -There are cases where we do not want the memory layout of a texture to -be tiled as the component processing the texture would not know how to -de-tile either via software or hardware. Therefore, ensuring that the -memory backing the texture has a linear layout is absolutely necessary -in these situations. - -Signed-off-by: Vivek Kasireddy ---- - include/ui/console.h | 2 ++ - ui/console-gl.c | 26 ++++++++++++++++++++++++++ - 2 files changed, 28 insertions(+) - -diff --git a/include/ui/console.h b/include/ui/console.h -index fa986ab97e..8010b17095 100644 ---- a/include/ui/console.h -+++ b/include/ui/console.h -@@ -425,6 +425,8 @@ bool console_gl_check_format(DisplayChangeListener *dcl, - pixman_format_code_t format); - void surface_gl_create_texture(QemuGLShader *gls, - DisplaySurface *surface); -+void surface_gl_create_texture_from_fd(DisplaySurface *surface, -+ int fd, GLuint *texture); - void surface_gl_update_texture(QemuGLShader *gls, - DisplaySurface *surface, - int x, int y, int w, int h); -diff --git a/ui/console-gl.c b/ui/console-gl.c -index 103b954017..8ee882bc3c 100644 ---- a/ui/console-gl.c -+++ b/ui/console-gl.c -@@ -96,6 +96,32 @@ void surface_gl_create_texture(QemuGLShader *gls, - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - -+void surface_gl_create_texture_from_fd(DisplaySurface *surface, -+ int fd, GLuint *texture) -+{ -+ unsigned long size = surface_stride(surface) * surface_height(surface); -+ GLuint mem_obj; -+ -+ if (!epoxy_has_gl_extension("GL_EXT_memory_object") || -+ !epoxy_has_gl_extension("GL_EXT_memory_object_fd")) { -+ return; -+ } -+ -+#ifdef GL_EXT_memory_object_fd -+ glCreateMemoryObjectsEXT(1, &mem_obj); -+ glImportMemoryFdEXT(mem_obj, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd); -+ if (!glIsMemoryObjectEXT(mem_obj)) { -+ return; -+ } -+ -+ glGenTextures(1, texture); -+ glBindTexture(GL_TEXTURE_2D, *texture); -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, GL_LINEAR_TILING_EXT); -+ glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, surface_width(surface), -+ surface_height(surface), mem_obj, 0); -+#endif -+} -+ - void surface_gl_update_texture(QemuGLShader *gls, - DisplaySurface *surface, - int x, int y, int w, int h) --- -2.35.3 - diff --git a/SPECS/qemu/0021-ui-spice-Create-another-texture-with-linear-layout-w.patch b/SPECS/qemu/0021-ui-spice-Create-another-texture-with-linear-layout-w.patch deleted file mode 100644 index 36c73c6dbe..0000000000 --- a/SPECS/qemu/0021-ui-spice-Create-another-texture-with-linear-layout-w.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 5aced1dc9bcd4eba6f5a5ff2f4b724eddf779280 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Tue, 16 Jan 2024 23:14:59 -0800 -Subject: [PATCH 21/50] ui/spice: Create another texture with linear layout - when gl=on is enabled - -Since most encoders (invoked by Spice) may not work with tiled memory -associated with a texture, we need to create another texture that has -linear memory layout and use that instead. - -Note that, there does not seem to be a direct way to indicate to the -GL implementation that a texture's backing memory needs to be linear. -Instead, we have to do it in a roundabout way where we need to first -create a tiled texture and import that as a memory object to create -a new texture that has a linear memory layout. - -Signed-off-by: Vivek Kasireddy ---- - ui/spice-display.c | 62 +++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 61 insertions(+), 1 deletion(-) - -diff --git a/ui/spice-display.c b/ui/spice-display.c -index 9a185d360d..b33bfdd6f2 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -26,6 +26,7 @@ - #include "ui/console.h" - #include "trace.h" - -+#include "standard-headers/drm/drm_fourcc.h" - #include "ui/spice-display.h" - - bool spice_opengl; -@@ -890,11 +891,64 @@ static void spice_gl_update(DisplayChangeListener *dcl, - ssd->gl_updates++; - } - -+static bool spice_gl_replace_fd_texture(SimpleSpiceDisplay *ssd, -+ EGLint *stride, EGLint *fourcc, -+ EGLuint64KHR *modifier, -+ int *fd) -+{ -+ GLuint texture = 0; -+ -+ if (!remote_client) { -+ return true; -+ } -+ -+ if (surface_format(ssd->ds) == PIXMAN_r5g6b5) { -+ return true; -+ } -+ -+ if (*modifier == DRM_FORMAT_MOD_LINEAR) { -+ return true; -+ } -+ -+ /* -+ * We really want to ensure that the memory layout of the texture -+ * is linear; otherwise, the encoder's output may show corruption. -+ */ -+ surface_gl_create_texture_from_fd(ssd->ds, *fd, &texture); -+ -+ /* -+ * A successful return after glImportMemoryFdEXT() means that -+ * the ownership of fd has been passed to GL. In other words, -+ * the fd we got above should not be used anymore. -+ */ -+ if (texture > 0) { -+ *fd = egl_get_fd_for_texture(texture, -+ stride, fourcc, -+ NULL); -+ if (*fd < 0) { -+ glDeleteTextures(1, &texture); -+ *fd = egl_get_fd_for_texture(ssd->ds->texture, -+ stride, fourcc, -+ NULL); -+ if (*fd < 0) { -+ surface_gl_destroy_texture(ssd->gls, ssd->ds); -+ return false; -+ } -+ } else { -+ surface_gl_destroy_texture(ssd->gls, ssd->ds); -+ ssd->ds->texture = texture; -+ } -+ } -+ return true; -+} -+ - static void spice_gl_switch(DisplayChangeListener *dcl, - struct DisplaySurface *new_surface) - { - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - EGLint stride, fourcc; -+ EGLuint64KHR modifier; -+ bool ret; - int fd; - - if (ssd->ds) { -@@ -905,12 +959,18 @@ static void spice_gl_switch(DisplayChangeListener *dcl, - surface_gl_create_texture(ssd->gls, ssd->ds); - fd = egl_get_fd_for_texture(ssd->ds->texture, - &stride, &fourcc, -- NULL); -+ &modifier); - if (fd < 0) { - surface_gl_destroy_texture(ssd->gls, ssd->ds); - return; - } - -+ ret = spice_gl_replace_fd_texture(ssd, &stride, &fourcc, &modifier, &fd); -+ if (!ret) { -+ surface_gl_destroy_texture(ssd->gls, ssd->ds); -+ return; -+ } -+ - trace_qemu_spice_gl_surface(ssd->qxl.id, - surface_width(ssd->ds), - surface_height(ssd->ds), --- -2.35.3 - diff --git a/SPECS/qemu/0022-ui-spice-Blit-the-scanout-texture-if-its-memory-layo.patch b/SPECS/qemu/0022-ui-spice-Blit-the-scanout-texture-if-its-memory-layo.patch deleted file mode 100644 index 692fda1ce9..0000000000 --- a/SPECS/qemu/0022-ui-spice-Blit-the-scanout-texture-if-its-memory-layo.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 1f8f29b54a3a51c78750087697e85b4f8915d911 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Thu, 6 Jun 2024 00:16:13 -0700 -Subject: [PATCH 22/50] ui/spice: Blit the scanout texture if its memory layout - is not linear - -In cases where the scanout buffer is provided as a texture (e.g. Virgl) -we need to check to see if it has a linear memory layout or not. If -it doesn't have a linear layout, then blitting it onto the texture -associated with the display surface (which already has a linear layout) -seems to ensure that there is no corruption seen regardless of which -encoder or decoder is used. - -Signed-off-by: Vivek Kasireddy ---- - include/ui/spice-display.h | 3 ++ - ui/spice-display.c | 67 +++++++++++++++++++++++++++++++++++--- - 2 files changed, 65 insertions(+), 5 deletions(-) - -diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h -index f4922dd74b..d087d7198a 100644 ---- a/include/ui/spice-display.h -+++ b/include/ui/spice-display.h -@@ -132,6 +132,9 @@ struct SimpleSpiceDisplay { - egl_fb guest_fb; - egl_fb blit_fb; - egl_fb cursor_fb; -+ bool backing_y_0_top; -+ bool blit_scanout_texture; -+ bool new_scanout_texture; - bool have_hot; - #endif - }; -diff --git a/ui/spice-display.c b/ui/spice-display.c -index b33bfdd6f2..d8f58b10b6 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -1020,20 +1020,34 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl, - { - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - EGLint stride = 0, fourcc = 0; -+ EGLuint64KHR modifier = 0; - int fd = -1; - - assert(tex_id); -- fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc, NULL); -+ -+ fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc, &modifier); - if (fd < 0) { - fprintf(stderr, "%s: failed to get fd for texture\n", __func__); - return; - } - trace_qemu_spice_gl_scanout_texture(ssd->qxl.id, w, h, fourcc); - -- /* note: spice server will close the fd */ -- spice_qxl_gl_scanout(&ssd->qxl, fd, backing_width, backing_height, -- stride, fourcc, y_0_top); -- qemu_spice_gl_monitor_config(ssd, x, y, w, h); -+ if (remote_client && modifier != DRM_FORMAT_MOD_LINEAR) { -+ egl_fb_destroy(&ssd->guest_fb); -+ egl_fb_setup_for_tex(&ssd->guest_fb, -+ backing_width, backing_height, -+ tex_id, false); -+ ssd->backing_y_0_top = y_0_top; -+ ssd->blit_scanout_texture = true; -+ ssd->new_scanout_texture = true; -+ close(fd); -+ } else { -+ /* note: spice server will close the fd */ -+ spice_qxl_gl_scanout(&ssd->qxl, fd, backing_width, backing_height, -+ stride, fourcc, y_0_top); -+ qemu_spice_gl_monitor_config(ssd, x, y, w, h); -+ } -+ - ssd->have_surface = false; - ssd->have_scanout = true; - } -@@ -1099,6 +1113,41 @@ static void qemu_spice_gl_release_dmabuf(DisplayChangeListener *dcl, - egl_dmabuf_release_texture(dmabuf); - } - -+static bool spice_gl_blit_scanout_texture(SimpleSpiceDisplay *ssd) -+{ -+ EGLint stride = 0, fourcc = 0; -+ int fd; -+ -+ egl_fb_destroy(&ssd->blit_fb); -+ egl_fb_setup_for_tex(&ssd->blit_fb, -+ surface_width(ssd->ds), surface_height(ssd->ds), -+ ssd->ds->texture, false); -+ egl_fb_blit(&ssd->blit_fb, &ssd->guest_fb, false); -+ glFlush(); -+ -+ if (!ssd->new_scanout_texture) { -+ return true; -+ } -+ -+ fd = egl_get_fd_for_texture(ssd->ds->texture, -+ &stride, &fourcc, -+ NULL); -+ if (fd < 0) { -+ fprintf(stderr, "%s: failed to get fd for texture\n", __func__); -+ return false; -+ } -+ -+ spice_qxl_gl_scanout(&ssd->qxl, fd, -+ surface_width(ssd->ds), -+ surface_height(ssd->ds), -+ stride, fourcc, ssd->backing_y_0_top); -+ qemu_spice_gl_monitor_config(ssd, 0, 0, -+ surface_width(ssd->ds), -+ surface_height(ssd->ds)); -+ ssd->new_scanout_texture = false; -+ return true; -+} -+ - static void qemu_spice_gl_update(DisplayChangeListener *dcl, - uint32_t x, uint32_t y, uint32_t w, uint32_t h) - { -@@ -1106,6 +1155,7 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, - EGLint stride = 0, fourcc = 0; - bool render_cursor = false; - bool y_0_top = false; /* FIXME */ -+ bool ret; - int fd; - uint32_t width, height, texture; - -@@ -1180,6 +1230,13 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, - glFlush(); - } - -+ if (remote_client && ssd->blit_scanout_texture) { -+ ret = spice_gl_blit_scanout_texture(ssd); -+ if (!ret) { -+ return; -+ } -+ } -+ - trace_qemu_spice_gl_update(ssd->qxl.id, w, h, x, y); - qemu_spice_gl_block(ssd, true); - glFlush(); --- -2.35.3 - diff --git a/SPECS/qemu/0023-ui-gtk-Enables-HW-cursor.patch b/SPECS/qemu/0023-ui-gtk-Enables-HW-cursor.patch deleted file mode 100644 index 57f428b94e..0000000000 --- a/SPECS/qemu/0023-ui-gtk-Enables-HW-cursor.patch +++ /dev/null @@ -1,281 +0,0 @@ -From 319d44b4a402a4b4a2f5edbcc92440351a88f5e8 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Tue, 29 Oct 2024 16:33:26 -0700 -Subject: [PATCH 23/50] ui/gtk: Enables HW cursor - -Blend guest's cursor plane with the guest frame when updating -the scanout. This feature is enabled when an gtk option, 'hw-cursor' -is set to true. - -Signed-off-by: Dongwon Kim ---- - include/ui/gtk.h | 3 +++ - qapi/ui.json | 6 ++++- - qemu-options.hx | 5 +++- - ui/gtk-egl.c | 68 +++++++++++++++++++++++++++++++++++++++++++----- - ui/gtk.c | 68 ++++++++++++++++++++++++++++++++++++------------ - 5 files changed, 124 insertions(+), 26 deletions(-) - -diff --git a/include/ui/gtk.h b/include/ui/gtk.h -index e9cdb12ef2..782484a374 100644 ---- a/include/ui/gtk.h -+++ b/include/ui/gtk.h -@@ -52,6 +52,9 @@ typedef struct VirtualGfxConsole { - egl_fb guest_fb; - egl_fb win_fb; - egl_fb cursor_fb; -+ uint32_t *cursor_image; -+ bool cursor_moved; -+ bool new_cursor; - int cursor_x; - int cursor_y; - bool y0_top; -diff --git a/qapi/ui.json b/qapi/ui.json -index 3b98d51e80..8e2b36fa38 100644 ---- a/qapi/ui.json -+++ b/qapi/ui.json -@@ -1360,6 +1360,9 @@ - # @show-fps: Enable showing frame update rate (default: off). - # (Since Pending) - # -+# @hw-cursor: Blend guest cursor plane (default: off). -+# (Since: Pending) -+# - # Since: 2.12 - ## - { 'struct' : 'DisplayGTK', -@@ -1368,7 +1371,8 @@ - '*show-tabs' : 'bool', - '*show-menubar' : 'bool', - '*connectors' : ['str'], -- '*show-fps' : 'bool' } } -+ '*show-fps' : 'bool', -+ '*hw-cursor' : 'bool' } } - - ## - # @DisplayEGLHeadless: -diff --git a/qemu-options.hx b/qemu-options.hx -index cad6d85b8c..07c5262223 100644 ---- a/qemu-options.hx -+++ b/qemu-options.hx -@@ -2100,7 +2100,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, - " [,show-tabs=on|off][,show-cursor=on|off][,window-close=on|off]\n" - " [,show-menubar=on|off][,zoom-to-fit=on|off]\n" - " [,connectors.=]\n" -- " [,show-fps=on|off]\n" -+ " [,show-fps=on|off][,hw-cursor=on|off]\n" - #endif - #if defined(CONFIG_VNC) - "-display vnc=[,]\n" -@@ -2204,6 +2204,9 @@ SRST - QEMU draw rate (FPS) on a status bar attached to - QEMU window. - -+ ``hw-cursor=on|off`` : Blend cursor plane from the guest with the guest display -+ output. -+ - ``curses[,charset=]`` - Display video output via curses. For graphics device models - which support a text mode, QEMU can display this output using a -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 0bc6d08faa..1c05b4a7b4 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -130,9 +130,31 @@ void gd_egl_update(DisplayChangeListener *dcl, - EGL_NO_SURFACE, EGL_NO_CONTEXT); - } - -+static void gd_egl_cursor_texture(VirtualConsole *vc) -+{ -+#ifdef CONFIG_GBM -+ uint32_t texture; -+ -+ glGenTextures(1, &texture); -+ glBindTexture(GL_TEXTURE_2D, texture); -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -+ -+ glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); -+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vc->gfx.cursor_fb.width, -+ vc->gfx.cursor_fb.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, -+ vc->gfx.cursor_image); -+ -+ egl_fb_setup_for_tex(&vc->gfx.cursor_fb, vc->gfx.cursor_fb.width, -+ vc->gfx.cursor_fb.height, texture, true); -+#endif -+} -+ - void gd_egl_refresh(DisplayChangeListener *dcl) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); -+ bool cursor_updated = vc->gfx.cursor_image && -+ (vc->gfx.cursor_moved || vc->gfx.new_cursor); - - #ifdef CONFIG_GBM - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -@@ -147,6 +169,31 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - gd_egl_draw(vc); - return; - } -+ -+ if (cursor_updated) { -+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -+ vc->gfx.esurface, vc->gfx.ectx); -+ -+ egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); -+ if (vc->gfx.cursor_x > 0 && -+ vc->gfx.cursor_x < vc->gfx.win_fb.width - 1 && -+ vc->gfx.cursor_y > 0 && -+ vc->gfx.cursor_y < vc->gfx.win_fb.height - 1) { -+ if (vc->gfx.new_cursor) { -+ gd_egl_cursor_texture(vc); -+ vc->gfx.new_cursor = false; -+ } -+ -+ egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, -+ &vc->gfx.cursor_fb, vc->gfx.y0_top, -+ vc->gfx.cursor_x, vc->gfx.cursor_y, -+ vc->gfx.scale_x, vc->gfx.scale_y); -+ } -+ -+ eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -+ vc->gfx.cursor_moved = false; -+ return; -+ } - #endif - - if (!vc->gfx.esurface) { -@@ -349,15 +396,22 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, - ww = gdk_window_get_width(window) * ws; - wh = gdk_window_get_height(window) * ws; - egl_fb_setup_default(&vc->gfx.win_fb, ww, wh); -- if (vc->gfx.cursor_fb.texture) { -- egl_texture_blit(vc->gfx.gls, &vc->gfx.win_fb, &vc->gfx.guest_fb, -- vc->gfx.y0_top); -- egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, &vc->gfx.cursor_fb, -- vc->gfx.y0_top, -+ egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); -+ if (vc->gfx.cursor_image && -+ vc->gfx.cursor_x > 0 && -+ vc->gfx.cursor_x < vc->gfx.win_fb.width - 1 && -+ vc->gfx.cursor_y > 0 && -+ vc->gfx.cursor_y < vc->gfx.win_fb.height - 1) { -+ if (vc->gfx.new_cursor) { -+ gd_egl_cursor_texture(vc); -+ vc->gfx.new_cursor = false; -+ } -+ -+ egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, -+ &vc->gfx.cursor_fb, vc->gfx.y0_top, - vc->gfx.cursor_x, vc->gfx.cursor_y, - vc->gfx.scale_x, vc->gfx.scale_y); -- } else { -- egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); -+ vc->gfx.cursor_moved = false; - } - - #ifdef CONFIG_GBM -diff --git a/ui/gtk.c b/ui/gtk.c -index 9df7e03094..7e7240b4fc 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -450,28 +450,55 @@ static void gd_mouse_set(DisplayChangeListener *dcl, - int x, int y, bool visible) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); -+ GtkDisplayState *s = vc->s; - GdkDisplay *dpy; - gint x_root, y_root; -+ gint x_origin, y_origin; -+ int new_cursor_x; -+ int new_cursor_y; -+ bool hw_cursor = s->opts->u.gtk.has_hw_cursor && s->opts->u.gtk.hw_cursor; - - if (!gtk_widget_get_realized(vc->gfx.drawing_area) || -- qemu_input_is_absolute(dcl->con)) { -+ (!hw_cursor && qemu_input_is_absolute(dcl->con))) { - return; - } - - dpy = gtk_widget_get_display(vc->gfx.drawing_area); -+ - gdk_window_get_root_coords(gtk_widget_get_window(vc->gfx.drawing_area), -- x, y, &x_root, &y_root); -- gdk_device_warp(gd_get_pointer(dpy), -- gtk_widget_get_screen(vc->gfx.drawing_area), -- x_root, y_root); -- vc->s->last_x = x; -- vc->s->last_y = y; -+ x * vc->gfx.scale_x, y * vc->gfx.scale_y, -+ &x_root, &y_root); -+ -+ gdk_window_get_origin(gtk_widget_get_window(vc->gfx.drawing_area), -+ &x_origin, &y_origin); -+ -+ if (hw_cursor) { -+ new_cursor_x = x_root - x_origin; -+ new_cursor_y = y_root - y_origin; -+ -+ if (vc->gfx.cursor_x != new_cursor_x || -+ vc->gfx.cursor_y != new_cursor_y) { -+ vc->gfx.cursor_moved = true; -+ vc->gfx.cursor_x = new_cursor_x; -+ vc->gfx.cursor_y = new_cursor_y; -+ } -+ } else { -+ dpy = gtk_widget_get_display(vc->gfx.drawing_area); -+ -+ gdk_device_warp(gd_get_pointer(dpy), -+ gtk_widget_get_screen(vc->gfx.drawing_area), -+ x_root, y_root); -+ -+ vc->s->last_x = x; -+ vc->s->last_y = y; -+ } - } - - static void gd_cursor_define(DisplayChangeListener *dcl, - QEMUCursor *c) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); -+ GtkDisplayState *s = vc->s; - GdkPixbuf *pixbuf; - GdkCursor *cursor; - -@@ -479,16 +506,23 @@ static void gd_cursor_define(DisplayChangeListener *dcl, - return; - } - -- pixbuf = gdk_pixbuf_new_from_data((guchar *)(c->data), -- GDK_COLORSPACE_RGB, true, 8, -- c->width, c->height, c->width * 4, -- NULL, NULL); -- cursor = gdk_cursor_new_from_pixbuf -- (gtk_widget_get_display(vc->gfx.drawing_area), -- pixbuf, c->hot_x, c->hot_y); -- gdk_window_set_cursor(gtk_widget_get_window(vc->gfx.drawing_area), cursor); -- g_object_unref(pixbuf); -- g_object_unref(cursor); -+ if (s->opts->u.gtk.has_hw_cursor && s->opts->u.gtk.hw_cursor) { -+ vc->gfx.cursor_image = c->data; -+ vc->gfx.cursor_fb.width = c->width; -+ vc->gfx.cursor_fb.height = c->height; -+ vc->gfx.new_cursor = true; -+ } else { -+ pixbuf = gdk_pixbuf_new_from_data((guchar *)(c->data), -+ GDK_COLORSPACE_RGB, true, 8, -+ c->width, c->height, c->width * 4, -+ NULL, NULL); -+ cursor = gdk_cursor_new_from_pixbuf -+ (gtk_widget_get_display(vc->gfx.drawing_area), -+ pixbuf, c->hot_x, c->hot_y); -+ gdk_window_set_cursor(gtk_widget_get_window(vc->gfx.drawing_area), cursor); -+ g_object_unref(pixbuf); -+ g_object_unref(cursor); -+ } - } - - static void gd_switch(DisplayChangeListener *dcl, --- -2.35.3 - diff --git a/SPECS/qemu/0024-ui-gtk-Hardcode-default-size-of-new-tab-window-to-96.patch b/SPECS/qemu/0024-ui-gtk-Hardcode-default-size-of-new-tab-window-to-96.patch deleted file mode 100644 index b15f973a2a..0000000000 --- a/SPECS/qemu/0024-ui-gtk-Hardcode-default-size-of-new-tab-window-to-96.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 4abcdf90835a14e33d2f4daa2fff1ea45971f4af Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Tue, 29 Oct 2024 19:17:49 -0700 -Subject: [PATCH 24/50] ui/gtk: Hardcode default size of new tab window to 960 - by 540 - -This is a WA to keep the display resolution from windows VM -after waking up from S4. - -Signed-off-by: Dongwon Kim ---- - ui/console.c | 4 ++-- - ui/gtk.c | 4 ++++ - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/ui/console.c b/ui/console.c -index 105a0e2c70..506e72d1eb 100644 ---- a/ui/console.c -+++ b/ui/console.c -@@ -1204,8 +1204,8 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head, - { - static const char noinit[] = - "Guest has not initialized the display (yet)."; -- int width = 640; -- int height = 480; -+ int width = 960; -+ int height = 540; - QemuConsole *s; - DisplaySurface *surface; - -diff --git a/ui/gtk.c b/ui/gtk.c -index 7e7240b4fc..6ee39b4816 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1574,9 +1574,13 @@ static gboolean gd_window_state_event(GtkWidget *widget, GdkEvent *event, - static void gd_tab_window_create(VirtualConsole *vc) - { - GtkDisplayState *s = vc->s; -+ int default_width = 960; -+ int default_height = 540; - - gtk_widget_set_sensitive(vc->menu_item, false); - vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); -+ gtk_window_set_default_size(GTK_WINDOW(vc->window), -+ default_width, default_height); - #if defined(CONFIG_OPENGL) - if (vc->gfx.esurface) { - eglDestroySurface(qemu_egl_display, vc->gfx.esurface); --- -2.35.3 - diff --git a/SPECS/qemu/0025-ui-gtk-Added-an-input-mode.patch b/SPECS/qemu/0025-ui-gtk-Added-an-input-mode.patch deleted file mode 100644 index 3475c43756..0000000000 --- a/SPECS/qemu/0025-ui-gtk-Added-an-input-mode.patch +++ /dev/null @@ -1,183 +0,0 @@ -From 778b324c2cc18be6be284d747d8641114ac96cb0 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Wed, 30 Oct 2024 22:11:37 -0700 -Subject: [PATCH 25/50] ui/gtk: Added an input mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In a multi-seat scenario where multiple keyboards and mice are -connected to the host but some are dedicated for the guests only -(through pass through mode) and some are only for the host, there -is a strong use case where a customer does not want a HID device -connected to the host to be able to control the guest. - -In such a scenario, neither should we bind any input events to -Qemu UI, nor should we show menu options like "Grab on Hover" or -"Grab Input". This patch adds a GTK command line option called -"input". It can be set like this: - - gtk,input=off/on - -If set to on or completely left out, it will default to normal -operation where host HID devices can control the guests. However, -if turned off, then host HID devices will not be able to control -the guest windows. - -Cc: Dongwon Kim -Cc: Vivek Kasireddy -Cc: Gerd Hoffmann -Cc: Marc-André Lureau > -Cc: Daniel P. Berrangé -Signed-off-by: Satyeshwar Singh -Signed-off-by: Dongwon Kim ---- - qapi/ui.json | 9 ++++++-- - qemu-options.hx | 4 ++++ - ui/gtk.c | 60 ++++++++++++++++++++++++++++++++----------------- - 3 files changed, 50 insertions(+), 23 deletions(-) - -diff --git a/qapi/ui.json b/qapi/ui.json -index 8e2b36fa38..0262329b0c 100644 ---- a/qapi/ui.json -+++ b/qapi/ui.json -@@ -1361,7 +1361,11 @@ - # (Since Pending) - # - # @hw-cursor: Blend guest cursor plane (default: off). --# (Since: Pending) -+# (Since Pending) -+# -+# @input: Don't let host's HID devices control the guest. Defaults to -+# "on" so they can control the guest. -+# (Since Pending) - # - # Since: 2.12 - ## -@@ -1372,7 +1376,8 @@ - '*show-menubar' : 'bool', - '*connectors' : ['str'], - '*show-fps' : 'bool', -- '*hw-cursor' : 'bool' } } -+ '*hw-cursor' : 'bool', -+ '*input' : 'bool' } } - - ## - # @DisplayEGLHeadless: -diff --git a/qemu-options.hx b/qemu-options.hx -index 07c5262223..dd972180cd 100644 ---- a/qemu-options.hx -+++ b/qemu-options.hx -@@ -2101,6 +2101,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, - " [,show-menubar=on|off][,zoom-to-fit=on|off]\n" - " [,connectors.=]\n" - " [,show-fps=on|off][,hw-cursor=on|off]\n" -+ " [,input=on|off]\n" - #endif - #if defined(CONFIG_VNC) - "-display vnc=[,]\n" -@@ -2207,6 +2208,9 @@ SRST - ``hw-cursor=on|off`` : Blend cursor plane from the guest with the guest display - output. - -+ ``input=on|off`` : Don't let host's HID devices control the guest -+ if set to "off", defaults to "on" -+ - ``curses[,charset=]`` - Display video output via curses. For graphics device models - which support a text mode, QEMU can display this output using a -diff --git a/ui/gtk.c b/ui/gtk.c -index 6ee39b4816..fe2610b90f 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -2461,6 +2461,20 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc) - G_CALLBACK(gd_resize_event), vc); - } - #endif -+ if (qemu_console_is_graphic(vc->gfx.dcl.con)) { -+ g_signal_connect(vc->gfx.drawing_area, "configure-event", -+ G_CALLBACK(gd_configure), vc); -+ } -+ -+ /* -+ * Don't configure input events if the user has provided an option -+ * for input and explicitly set it to off. In this case, they want -+ * passthrough HID devices to control the guest. -+ */ -+ if (vc->s->opts->u.gtk.has_input && !vc->s->opts->u.gtk.input ) { -+ return; -+ } -+ - if (qemu_console_is_graphic(vc->gfx.dcl.con)) { - g_signal_connect(vc->gfx.drawing_area, "event", - G_CALLBACK(gd_event), vc); -@@ -2485,8 +2499,6 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc) - G_CALLBACK(gd_focus_in_event), vc); - g_signal_connect(vc->gfx.drawing_area, "focus-out-event", - G_CALLBACK(gd_focus_out_event), vc); -- g_signal_connect(vc->gfx.drawing_area, "configure-event", -- G_CALLBACK(gd_configure), vc); - g_signal_connect(vc->gfx.drawing_area, "grab-broken-event", - G_CALLBACK(gd_grab_broken_event), vc); - } else { -@@ -2529,8 +2541,10 @@ static void gd_connect_signals(GtkDisplayState *s) - G_CALLBACK(gd_menu_zoom_fixed), s); - g_signal_connect(s->zoom_fit_item, "activate", - G_CALLBACK(gd_menu_zoom_fit), s); -- g_signal_connect(s->grab_item, "activate", -- G_CALLBACK(gd_menu_grab_input), s); -+ if (!s->opts->u.gtk.has_input || s->opts->u.gtk.input) { -+ g_signal_connect(s->grab_item, "activate", -+ G_CALLBACK(gd_menu_grab_input), s); -+ } - g_signal_connect(s->notebook, "switch-page", - G_CALLBACK(gd_change_page), s); - if (s->opts->u.gtk.has_connectors) { -@@ -2735,23 +2749,27 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, DisplayOptions *opts) - s->zoom_fit_item = gtk_check_menu_item_new_with_mnemonic(_("Zoom To _Fit")); - gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_fit_item); - -- separator = gtk_separator_menu_item_new(); -- gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator); -- -- s->grab_on_hover_item = gtk_check_menu_item_new_with_mnemonic(_("Grab On _Hover")); -- gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->grab_on_hover_item); -- -- s->grab_item = gtk_check_menu_item_new_with_mnemonic(_("_Grab Input")); -- gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->grab_item), -- "/View/Grab Input"); -- gtk_accel_map_add_entry("/View/Grab Input", GDK_KEY_g, -- HOTKEY_MODIFIERS); -- gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->grab_item); -- gtk_accel_group_connect(s->accel_group, GDK_KEY_g, HOTKEY_MODIFIERS, 0, -- g_cclosure_new_swap(G_CALLBACK(gd_accel_grab_input), s, NULL)); -- gtk_accel_label_set_accel( -- GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(s->grab_item))), -- GDK_KEY_g, HOTKEY_MODIFIERS); -+ if (!s->opts->u.gtk.has_input || s->opts->u.gtk.input) { -+ separator = gtk_separator_menu_item_new(); -+ gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator); -+ -+ s->grab_on_hover_item = gtk_check_menu_item_new_with_mnemonic( -+ _("Grab On _Hover")); -+ gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), -+ s->grab_on_hover_item); -+ -+ s->grab_item = gtk_check_menu_item_new_with_mnemonic(_("_Grab Input")); -+ gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->grab_item), -+ "/View/Grab Input"); -+ gtk_accel_map_add_entry("/View/Grab Input", GDK_KEY_g, -+ HOTKEY_MODIFIERS); -+ gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->grab_item); -+ gtk_accel_group_connect(s->accel_group, GDK_KEY_g, HOTKEY_MODIFIERS, 0, -+ g_cclosure_new_swap(G_CALLBACK(gd_accel_grab_input), s, NULL)); -+ gtk_accel_label_set_accel( -+ GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(s->grab_item))), -+ GDK_KEY_g, HOTKEY_MODIFIERS); -+ } - - separator = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator); --- -2.35.3 - diff --git a/SPECS/qemu/0026-ui-gtk-Scanout-flush-only-if-guest-framebuffer-exist.patch b/SPECS/qemu/0026-ui-gtk-Scanout-flush-only-if-guest-framebuffer-exist.patch deleted file mode 100644 index 69dbe45d15..0000000000 --- a/SPECS/qemu/0026-ui-gtk-Scanout-flush-only-if-guest-framebuffer-exist.patch +++ /dev/null @@ -1,62 +0,0 @@ -From ac59d2c7a275021a9b54c57e8478ac9a6626fb41 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 7 Nov 2024 12:34:19 -0800 -Subject: [PATCH 26/50] ui/gtk: Scanout flush only if guest framebuffer exist - -Draw should be done only if guest framebuffer exist. - -Signed-off-by: Dongwon Kim ---- - ui/gtk-egl.c | 6 ++++-- - ui/gtk-gl-area.c | 6 ++++-- - 2 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 1c05b4a7b4..6b9ae3b3b2 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -96,7 +96,8 @@ void gd_egl_draw(VirtualConsole *vc) - } - - if (!dmabuf || -- (dmabuf && qemu_dmabuf_get_render_sync(dmabuf))) { -+ (dmabuf && qemu_dmabuf_get_render_sync(dmabuf) && -+ vc->gfx.guest_fb.framebuffer)) { - gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h); - } - } -@@ -435,7 +436,8 @@ void gd_egl_flush(DisplayChangeListener *dcl, - #ifdef CONFIG_GBM - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - if (dmabuf) { -- if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { -+ if (!qemu_dmabuf_get_draw_submitted(dmabuf) && -+ vc->gfx.guest_fb.framebuffer) { - graphic_hw_gl_block(vc->gfx.dcl.con, true); - gtk_egl_set_scanout_mode(vc, true); - if (!qemu_dmabuf_get_render_sync(dmabuf)) { -diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c -index 4ac364bddf..4a2f9538ef 100644 ---- a/ui/gtk-gl-area.c -+++ b/ui/gtk-gl-area.c -@@ -290,13 +290,15 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, - #ifdef CONFIG_GBM - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - -- if (dmabuf && !qemu_dmabuf_get_draw_submitted(dmabuf)) { -+ if (dmabuf && !qemu_dmabuf_get_draw_submitted(dmabuf) && -+ vc->gfx.guest_fb.framebuffer) { - gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); - graphic_hw_gl_block(vc->gfx.dcl.con, true); - qemu_dmabuf_set_draw_submitted(dmabuf, true); - gtk_gl_area_set_scanout_mode(vc, true); - if (!qemu_dmabuf_get_render_sync(dmabuf)) { -- int ws = gdk_window_get_scale_factor(gtk_widget_get_window(vc->gfx.drawing_area)); -+ int ws = gdk_window_get_scale_factor(gtk_widget_get_window( -+ vc->gfx.drawing_area)); - int ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area) * ws; - int wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area) * ws; - int y1 = vc->gfx.y0_top ? 0 : vc->gfx.h; --- -2.35.3 - diff --git a/SPECS/qemu/0027-virtio-gpu-Replace-the-surface-with-null-surface-onl.patch b/SPECS/qemu/0027-virtio-gpu-Replace-the-surface-with-null-surface-onl.patch deleted file mode 100644 index b701e4e48f..0000000000 --- a/SPECS/qemu/0027-virtio-gpu-Replace-the-surface-with-null-surface-onl.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 4b073c5a5c61206561ae07979e722e08564931f3 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 7 Nov 2024 12:45:15 -0800 -Subject: [PATCH 27/50] virtio-gpu: Replace the surface with null surface only - when resetting -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Update the current surface with a place holder surface only when -virtio-gpu device is being reset. It is required to keep the most -recent frame on the display even if the resource associated with it -is unreferenced. Otherwise, frequent blnking will happen whenever -the resource associated with the scanout is unreferenced. - -Cc: Marc-André Lureau -Cc: Vivek Kasireddy -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index 363e8ea9e5..6a553bc4a5 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -393,7 +393,6 @@ static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id) - res->scanout_bitmask &= ~(1 << scanout_id); - } - -- dpy_gfx_replace_surface(scanout->con, NULL); - scanout->resource_id = 0; - scanout->ds = NULL; - scanout->width = 0; -@@ -1559,6 +1558,7 @@ void virtio_gpu_reset(VirtIODevice *vdev) - { - VirtIOGPU *g = VIRTIO_GPU(vdev); - struct virtio_gpu_ctrl_command *cmd; -+ int i = 0; - - if (qemu_in_vcpu_thread()) { - g->reset_finished = false; -@@ -1583,6 +1583,10 @@ void virtio_gpu_reset(VirtIODevice *vdev) - g_free(cmd); - } - -+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { -+ dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL); -+ } -+ - virtio_gpu_base_reset(VIRTIO_GPU_BASE(vdev)); - } - --- -2.35.3 - diff --git a/SPECS/qemu/0028-virtio-gpu-Recreate-the-resource-s-dmabuf-if-new-bac.patch b/SPECS/qemu/0028-virtio-gpu-Recreate-the-resource-s-dmabuf-if-new-bac.patch deleted file mode 100644 index 246bcb5d63..0000000000 --- a/SPECS/qemu/0028-virtio-gpu-Recreate-the-resource-s-dmabuf-if-new-bac.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 5978331dd14f2914bc363d2c90b3afcbdf824864 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Wed, 27 Mar 2024 17:49:21 -0700 -Subject: [PATCH 28/50] virtio-gpu: Recreate the resource's dmabuf if new - backing is attached - -There can be cases where a blob resource's backing might get -detached and re-attached such as when the backing object might -get migrated in the Guest. In this case, we need to create the -dmabuf fd again by calling udmabuf_create. - -Signed-off-by: Vivek Kasireddy ---- - hw/display/virtio-gpu.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index 6a553bc4a5..63b64a60ab 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -940,6 +940,10 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g, - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; - return; - } -+ -+ if (res->blob_size && res->dmabuf_fd < 0) { -+ virtio_gpu_init_udmabuf(res); -+ } - } - - static void --- -2.35.3 - diff --git a/SPECS/qemu/0029-virtio-gpu-Find-the-host-addr-given-gpa-associated-w.patch b/SPECS/qemu/0029-virtio-gpu-Find-the-host-addr-given-gpa-associated-w.patch deleted file mode 100644 index e75b4cca74..0000000000 --- a/SPECS/qemu/0029-virtio-gpu-Find-the-host-addr-given-gpa-associated-w.patch +++ /dev/null @@ -1,78 +0,0 @@ -From e668c82fd3b02ef4f9b43edb191a345667d7db38 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Mon, 25 Mar 2024 17:56:11 -0700 -Subject: [PATCH 29/50] virtio-gpu: Find the host addr given gpa associated - with a ram device - -If the Guest provides a gpa associated with a PCI region, then the -right API to use to obtain the hva is gpa2hva() instead of -dma_memory_map() API does not seem to return the correct host addr. - -Signed-off-by: Vivek Kasireddy ---- - hw/display/virtio-gpu.c | 35 ++++++++++++++++++++++++++++++++--- - 1 file changed, 32 insertions(+), 3 deletions(-) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index 63b64a60ab..d8b45d844b 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -31,6 +31,7 @@ - #include "qemu/module.h" - #include "qapi/error.h" - #include "qemu/error-report.h" -+#include "monitor/monitor.h" - - #define VIRTIO_GPU_VM_VERSION 1 - -@@ -801,6 +802,36 @@ static void virtio_gpu_set_scanout_blob(VirtIOGPU *g, - &fb, res, &ss.r, &cmd->error); - } - -+static void *map_gpa2hva(VirtIOGPU *g, -+ struct virtio_gpu_ctrl_command *cmd, -+ uint64_t gpa, hwaddr *len) -+{ -+ MemoryRegion *mr = NULL; -+ Error *errp = NULL; -+ void *map; -+ -+ if (cmd->cmd_hdr.type != VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB) { -+ return dma_memory_map(VIRTIO_DEVICE(g)->dma_as, gpa, len, -+ DMA_DIRECTION_TO_DEVICE, -+ MEMTXATTRS_UNSPECIFIED); -+ } -+ -+ map = gpa2hva(&mr, gpa, 1, &errp); -+ if (errp) { -+ error_report_err(errp); -+ return NULL; -+ } -+ -+ if (!memory_region_is_ram_device(mr)) { -+ memory_region_unref(mr); -+ map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, gpa, len, -+ DMA_DIRECTION_TO_DEVICE, -+ MEMTXATTRS_UNSPECIFIED); -+ } -+ -+ return map; -+} -+ - int virtio_gpu_create_mapping_iov(VirtIOGPU *g, - uint32_t nr_entries, uint32_t offset, - struct virtio_gpu_ctrl_command *cmd, -@@ -842,9 +873,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, - - do { - len = l; -- map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len, -- DMA_DIRECTION_TO_DEVICE, -- MEMTXATTRS_UNSPECIFIED); -+ map = map_gpa2hva(g, cmd, a, &len); - if (!map) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for" - " element %d\n", __func__, e); --- -2.35.3 - diff --git a/SPECS/qemu/0030-virtio-gpu-udmabuf-Create-dmabuf-from-mr-associated-.patch b/SPECS/qemu/0030-virtio-gpu-udmabuf-Create-dmabuf-from-mr-associated-.patch deleted file mode 100644 index e54414ead6..0000000000 --- a/SPECS/qemu/0030-virtio-gpu-udmabuf-Create-dmabuf-from-mr-associated-.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 0951e54c6274b119961a346e44da6ebe4b195826 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Mon, 25 Mar 2024 17:57:21 -0700 -Subject: [PATCH 30/50] virtio-gpu-udmabuf: Create dmabuf from mr associated - with a VFIO dev - -Once we have the ramblock and the associated mr, we try to find the -VFIO device that owns the mr and also determine the relevant VFIO -region and index. We then provide this info (i.e, region index) -along with offsets and lengths to the VFIO PCI driver (via -VFIO_DEVICE_FEATURE_GET | VFIO_DEVICE_FEATURE_DMA_BUF) to get -a new dmabuf fd created. - -Signed-off-by: Vivek Kasireddy ---- - hw/display/virtio-gpu-udmabuf.c | 97 ++++++++++++++++++++++++++++++++- - linux-headers/linux/vfio.h | 25 +++++++++ - 2 files changed, 121 insertions(+), 1 deletion(-) - -diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c -index 8fcc0c3055..a843d5cf9e 100644 ---- a/hw/display/virtio-gpu-udmabuf.c -+++ b/hw/display/virtio-gpu-udmabuf.c -@@ -18,6 +18,7 @@ - #include "ui/console.h" - #include "hw/virtio/virtio-gpu.h" - #include "hw/virtio/virtio-gpu-pixman.h" -+#include "hw/vfio/vfio-common.h" - #include "trace.h" - #include "exec/ramblock.h" - #include "sysemu/hostmem.h" -@@ -26,6 +27,88 @@ - #include "qemu/memfd.h" - #include "standard-headers/linux/udmabuf.h" - -+static void vfio_create_dmabuf(struct virtio_gpu_simple_resource *res) -+{ -+ g_autofree struct vfio_device_feature *feature; -+ struct vfio_device_feature_dma_buf *dma_buf; -+ VFIODevice *vbasedev = NULL; -+ VFIORegion *region = NULL; -+ ram_addr_t offset; -+ MemoryRegion *mr; -+ RAMBlock *rb; -+ size_t argsz; -+ int i; -+ -+ if (res->iov_cnt <= 0) { -+ return; -+ } -+ -+ argsz = sizeof(*feature) + sizeof (*dma_buf) + -+ sizeof(struct vfio_region_dma_range) * res->iov_cnt; -+ feature = g_malloc0(argsz); -+ dma_buf = (struct vfio_device_feature_dma_buf *)feature->data; -+ -+ for (i = 0; i < res->iov_cnt; i++) { -+ rcu_read_lock(); -+ rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset); -+ rcu_read_unlock(); -+ -+ if (!rb) { -+ return; -+ } -+ -+ mr = rb->mr; -+ if (mr->ops != &vfio_region_ops) { -+ mr = mr->container; -+ if (mr->ops != &vfio_region_ops) { -+ return; -+ } -+ } -+ -+ region = mr->opaque; -+ -+ if (!region) { -+ return; -+ } -+ -+ dma_buf->dma_ranges[i].region_index = region->nr; -+ dma_buf->dma_ranges[i].offset = offset; -+ dma_buf->dma_ranges[i].length = res->iov[i].iov_len; -+ } -+ -+ dma_buf->nr_ranges = res->iov_cnt; -+ dma_buf->open_flags = O_RDONLY | O_CLOEXEC; -+ feature->argsz = argsz; -+ feature->flags = VFIO_DEVICE_FEATURE_GET | VFIO_DEVICE_FEATURE_DMA_BUF; -+ -+ if (!vbasedev) { -+ vbasedev = region->vbasedev; -+ } -+ -+ res->dmabuf_fd = ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature); -+ -+ if (res->dmabuf_fd < 0) { -+ warn_report("%s: VFIO_DEVICE_FEATURE_DMA_BUF: %s", __func__, -+ strerror(errno)); -+ } -+} -+ -+static bool is_device_owner_vfio(MemoryRegion *mr) -+{ -+ VFIODevice *vdev; -+ -+ if (QLIST_EMPTY(&vfio_device_list)) { -+ return false; -+ } -+ -+ QLIST_FOREACH(vdev, &vfio_device_list, next) { -+ if (vdev->dev == mr->dev) { -+ return true; -+ } -+ } -+ return false; -+} -+ - static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res) - { - struct udmabuf_create_list *list; -@@ -129,6 +212,8 @@ bool virtio_gpu_have_udmabuf(void) - - void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res) - { -+ ram_addr_t offset; -+ RAMBlock *rb; - void *pdata = NULL; - - res->dmabuf_fd = -1; -@@ -136,7 +221,17 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res) - res->iov[0].iov_len < 4096) { - pdata = res->iov[0].iov_base; - } else { -- virtio_gpu_create_udmabuf(res); -+ rb = qemu_ram_block_from_host(res->iov[0].iov_base, false, &offset); -+ if (rb && memory_region_is_ram_device(rb->mr)) { -+ if (!is_device_owner_vfio(rb->mr)) { -+ warn_report("Could not find device to create dmabuf"); -+ return; -+ } -+ vfio_create_dmabuf(res); -+ } else { -+ virtio_gpu_create_udmabuf(res); -+ } -+ - if (res->dmabuf_fd < 0) { - return; - } -diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h -index b4be37b225..35d7992da5 100644 ---- a/linux-headers/linux/vfio.h -+++ b/linux-headers/linux/vfio.h -@@ -1458,6 +1458,31 @@ struct vfio_device_feature_bus_master { - }; - #define VFIO_DEVICE_FEATURE_BUS_MASTER 10 - -+/** -+ * Upon VFIO_DEVICE_FEATURE_GET create a dma_buf fd for the -+ * region selected. -+ * -+ * open_flags are the typical flags passed to open(2), eg O_RDWR, O_CLOEXEC, -+ * etc. offset/length specify a slice of the region to create the dmabuf from. -+ * If both are 0 then the whole region is used. -+ * -+ * Return: The fd number on success, -1 and errno is set on failure. -+ */ -+#define VFIO_DEVICE_FEATURE_DMA_BUF 11 -+ -+struct vfio_region_dma_range { -+ __u32 region_index; -+ __u32 __pad; -+ __u64 offset; -+ __u64 length; -+}; -+ -+struct vfio_device_feature_dma_buf { -+ __u32 open_flags; -+ __u32 nr_ranges; -+ struct vfio_region_dma_range dma_ranges[]; -+}; -+ - /* -------- API for Type1 VFIO IOMMU -------- */ - - /** --- -2.35.3 - diff --git a/SPECS/qemu/0031-gtk-Skip-to-configure-the-size-only-in-HPD-case.patch b/SPECS/qemu/0031-gtk-Skip-to-configure-the-size-only-in-HPD-case.patch deleted file mode 100644 index 0a45f0c371..0000000000 --- a/SPECS/qemu/0031-gtk-Skip-to-configure-the-size-only-in-HPD-case.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 3ad17114b9bd99f0e29ef0f2fc9f2407ea3f6c0d Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Mon, 13 Jan 2025 09:10:14 -0800 -Subject: [PATCH 31/50] gtk: Skip to configure the size only in HPD case - -Size shouldn't be reconfigured in case width and height -are both zeros, as this combination indicates disconnected -guest display. But this protocol is only valid in HPD use -case where connectors array param is provided. - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index fe2610b90f..29782093aa 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -2195,10 +2195,11 @@ static gboolean gd_configure(GtkWidget *widget, - - info = *dpy_get_ui_info(vc->gfx.dcl.con); - -- if (info.width || info.height) { -- gd_set_ui_size(vc, cfg->width, cfg->height); -+ if (vc->s->opts->u.gtk.has_connectors && !info.width && !info.height) { -+ return FALSE; - } - -+ gd_set_ui_size(vc, cfg->width, cfg->height); - return FALSE; - } - --- -2.35.3 - diff --git a/SPECS/qemu/0032-ui-spice-unblock-the-console-when-the-scanout-is-bei.patch b/SPECS/qemu/0032-ui-spice-unblock-the-console-when-the-scanout-is-bei.patch deleted file mode 100644 index 831c9b25f3..0000000000 --- a/SPECS/qemu/0032-ui-spice-unblock-the-console-when-the-scanout-is-bei.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 51c0bf81db85021aa79929299d2c6b947cfe5f58 Mon Sep 17 00:00:00 2001 -From: Vivek Kasireddy -Date: Sun, 12 Jan 2025 20:59:17 -0800 -Subject: [PATCH 32/50] ui/spice: unblock the console when the scanout is being - disabled - -When the scanout is being disabled, we need to check to see if the -console is blocked or not. If it is, we need to unblock it to let -the newer updates to take effect. - -Signed-off-by: Vivek Kasireddy ---- - ui/spice-display.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/ui/spice-display.c b/ui/spice-display.c -index d8f58b10b6..0d75bb57fe 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -951,6 +951,20 @@ static void spice_gl_switch(DisplayChangeListener *dcl, - bool ret; - int fd; - -+ /* -+ * We need to check for the case of "lost" updates, where a gl_draw -+ * was not submitted because the timer did not get a chance to run. -+ * One case where this happens is when the Guest VM is getting -+ * rebooted. If the console is blocked in this situation, we need -+ * to unblock it. Otherwise, newer updates would not take effect. -+ */ -+ if (qemu_console_is_gl_blocked(ssd->dcl.con)) { -+ if (remote_client && ssd->gl_updates && ssd->have_scanout) { -+ ssd->gl_updates = 0; -+ qemu_spice_gl_block(ssd, false); -+ } -+ } -+ - if (ssd->ds) { - surface_gl_destroy_texture(ssd->gls, ssd->ds); - } --- -2.35.3 - diff --git a/SPECS/qemu/0033-virtio-gpu-Update-cursor-data-only-if-it-is-valid.patch b/SPECS/qemu/0033-virtio-gpu-Update-cursor-data-only-if-it-is-valid.patch deleted file mode 100644 index 0201eb4966..0000000000 --- a/SPECS/qemu/0033-virtio-gpu-Update-cursor-data-only-if-it-is-valid.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 9b9ff8214f9a0319d395e764e1718464b6c9bc3d Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Fri, 17 Jan 2025 01:57:02 -0800 -Subject: [PATCH 33/50] virtio-gpu: Update cursor data only if it is valid - -Cursor blob image buffer could have already been ummapped by -the time the cursor update request is received. In such case, -it should be ignored to prevent any possible segfault. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index d8b45d844b..d1d1659ffc 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -62,12 +62,14 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g, - return; - } - data = res->blob; -- } else { -+ } else if (res->image) { - if (pixman_image_get_width(res->image) != s->current_cursor->width || - pixman_image_get_height(res->image) != s->current_cursor->height) { - return; - } - data = pixman_image_get_data(res->image); -+ } else { -+ return; - } - - pixels = s->current_cursor->width * s->current_cursor->height; -@@ -935,6 +937,8 @@ void virtio_gpu_cleanup_mapping(VirtIOGPU *g, - - if (res->blob) { - virtio_gpu_fini_udmabuf(res); -+ res->blob = NULL; -+ res->blob_size = 0; - } - } - --- -2.35.3 - diff --git a/SPECS/qemu/0034-virtio-gpu-Freeing-udmabuf-and-make-dmabuf-NULL-when.patch b/SPECS/qemu/0034-virtio-gpu-Freeing-udmabuf-and-make-dmabuf-NULL-when.patch deleted file mode 100644 index 6b1a04af90..0000000000 --- a/SPECS/qemu/0034-virtio-gpu-Freeing-udmabuf-and-make-dmabuf-NULL-when.patch +++ /dev/null @@ -1,110 +0,0 @@ -From dabaf87efa72f31ed4ac0361ec7aaf3cfb78ae41 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Wed, 22 Jan 2025 10:42:18 -0800 -Subject: [PATCH 34/50] virtio-gpu: Freeing udmabuf and make dmabuf NULL when - resource is destroyed - -DMABUF attached to the scanout needs to be freed and the field -should be reset to NULL when the associated resources are destroyed -as the backing buffers are all invalid from that point. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu-udmabuf.c | 21 +++++++++++++++++---- - hw/display/virtio-gpu.c | 4 ++-- - include/hw/virtio/virtio-gpu.h | 3 ++- - ui/gtk-egl.c | 2 +- - 4 files changed, 22 insertions(+), 8 deletions(-) - -diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c -index a843d5cf9e..2eef08d8bc 100644 ---- a/hw/display/virtio-gpu-udmabuf.c -+++ b/hw/display/virtio-gpu-udmabuf.c -@@ -245,18 +245,31 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res) - res->blob = pdata; - } - --void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res) -+void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *res) - { -- if (res->remapped) { -- virtio_gpu_destroy_udmabuf(res); -+ int i; -+ -+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { -+ if (g->dmabuf.primary[i] && -+ qemu_dmabuf_get_fd(g->dmabuf.primary[i]->buf) == res->dmabuf_fd) { -+ virtio_gpu_free_dmabuf(g, g->dmabuf.primary[i]); -+ g->dmabuf.primary[i] = NULL; -+ } - } -+ -+ virtio_gpu_destroy_udmabuf(res); - } - --static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf) -+void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf) - { - struct virtio_gpu_scanout *scanout; - - scanout = &g->parent_obj.scanout[dmabuf->scanout_id]; -+ -+ if (!scanout->con || !dmabuf->buf) { -+ return; -+ } -+ - dpy_gl_release_dmabuf(scanout->con, dmabuf->buf); - g_clear_pointer(&dmabuf->buf, qemu_dmabuf_free); - QTAILQ_REMOVE(&g->dmabuf.bufs, dmabuf, next); -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index d1d1659ffc..cf84c54ac3 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -936,7 +936,7 @@ void virtio_gpu_cleanup_mapping(VirtIOGPU *g, - res->addrs = NULL; - - if (res->blob) { -- virtio_gpu_fini_udmabuf(res); -+ virtio_gpu_fini_udmabuf(g, res); - res->blob = NULL; - res->blob_size = 0; - } -@@ -1621,7 +1621,7 @@ void virtio_gpu_reset(VirtIODevice *vdev) - } - - for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { -- dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL); -+ dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL); - } - - virtio_gpu_base_reset(VIRTIO_GPU_BASE(vdev)); -diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h -index 9bcc572eab..e1737d106e 100644 ---- a/include/hw/virtio/virtio-gpu.h -+++ b/include/hw/virtio/virtio-gpu.h -@@ -326,7 +326,8 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g, - /* virtio-gpu-udmabuf.c */ - bool virtio_gpu_have_udmabuf(void); - void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res); --void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res); -+void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *res); -+void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf); - int virtio_gpu_update_dmabuf(VirtIOGPU *g, - uint32_t scanout_id, - struct virtio_gpu_simple_resource *res, -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 6b9ae3b3b2..8a3a0df5ba 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -171,7 +171,7 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - return; - } - -- if (cursor_updated) { -+ if (dmabuf && cursor_updated) { - eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, - vc->gfx.esurface, vc->gfx.ectx); - --- -2.35.3 - diff --git a/SPECS/qemu/0035-Revert-ui-gtk-Fix-mouse-motion-event-scaling-issue-w.patch b/SPECS/qemu/0035-Revert-ui-gtk-Fix-mouse-motion-event-scaling-issue-w.patch deleted file mode 100644 index 40bd5d1dd8..0000000000 --- a/SPECS/qemu/0035-Revert-ui-gtk-Fix-mouse-motion-event-scaling-issue-w.patch +++ /dev/null @@ -1,60 +0,0 @@ -From a8d5ef9cc46c1f5bbea476a942cbf8d8882fce92 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Wed, 26 Feb 2025 14:22:48 -0800 -Subject: [PATCH 35/50] Revert "ui/gtk: Fix mouse/motion event scaling issue - with GTK display backend" - -This reverts commit 37e91415018db3656b46cdea8f9e4d47b3ff130d. ---- - ui/gtk.c | 18 +++++------------- - 1 file changed, 5 insertions(+), 13 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 29782093aa..b84b759f95 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -978,7 +978,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, - int x, y; - int mx, my; - int fbh, fbw; -- int ww, wh; -+ int ww, wh, ws; - - if (!vc->gfx.ds) { - return TRUE; -@@ -986,15 +986,11 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, - - fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x; - fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y; -+ - ww = gtk_widget_get_allocated_width(widget); - wh = gtk_widget_get_allocated_height(widget); -+ ws = gtk_widget_get_scale_factor(widget); - -- /* -- * `widget` may not have the same size with the frame buffer. -- * In such cases, some paddings are needed around the `vc`. -- * To achieve that, `vc` will be displayed at (mx, my) -- * so that it is displayed at the center of the widget. -- */ - mx = my = 0; - if (ww > fbw) { - mx = (ww - fbw) / 2; -@@ -1003,12 +999,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, - my = (wh - fbh) / 2; - } - -- /* -- * `motion` is reported in `widget` coordinates -- * so translating it to the coordinates in `vc`. -- */ -- x = (motion->x - mx) / vc->gfx.scale_x; -- y = (motion->y - my) / vc->gfx.scale_y; -+ x = (motion->x - mx) / vc->gfx.scale_x * ws; -+ y = (motion->y - my) / vc->gfx.scale_y * ws; - - trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y); - --- -2.35.3 - diff --git a/SPECS/qemu/0036-virtio-gpu-udmabuf-gtk-Set-dmabuf_fd-1-to-prevent-fu.patch b/SPECS/qemu/0036-virtio-gpu-udmabuf-gtk-Set-dmabuf_fd-1-to-prevent-fu.patch deleted file mode 100644 index cdf04fce30..0000000000 --- a/SPECS/qemu/0036-virtio-gpu-udmabuf-gtk-Set-dmabuf_fd-1-to-prevent-fu.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 6c96ea22eb47847ce647b22999a4f54cf62d41c8 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Tue, 25 Feb 2025 14:38:20 -0800 -Subject: [PATCH 36/50] virtio-gpu-udmabuf/gtk: Set dmabuf_fd -1 to prevent - further mapping/use - -Once the resource that is the source of udmabuf is destroyed, it -should be assumed that pages behind the udmabuf are invalid and -shouldn't be used anymore. For this, we mark dmabuf_fd -1 and also -checking it before remapping the udmabuf or rendering the contents -in it. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu-udmabuf.c | 3 ++- - ui/gtk-egl.c | 15 ++++++++++++--- - ui/gtk-gl-area.c | 6 ++++-- - 3 files changed, 18 insertions(+), 6 deletions(-) - -diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c -index 2eef08d8bc..7b6d282824 100644 ---- a/hw/display/virtio-gpu-udmabuf.c -+++ b/hw/display/virtio-gpu-udmabuf.c -@@ -252,7 +252,8 @@ void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *re - for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { - if (g->dmabuf.primary[i] && - qemu_dmabuf_get_fd(g->dmabuf.primary[i]->buf) == res->dmabuf_fd) { -- virtio_gpu_free_dmabuf(g, g->dmabuf.primary[i]); -+ /* preventing further mapping/use of the dmabuf */ -+ qemu_dmabuf_set_fd(g->dmabuf.primary[i]->buf, -1); - g->dmabuf.primary[i] = NULL; - } - } -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 8a3a0df5ba..fd9b05508b 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -165,13 +165,15 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - vc, vc->window ? vc->window : vc->gfx.drawing_area); - - #ifdef CONFIG_GBM -- if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf) && -+ if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) && -+ qemu_dmabuf_get_draw_submitted(dmabuf) && - qemu_dmabuf_get_render_sync(dmabuf)) { - gd_egl_draw(vc); - return; - } - -- if (dmabuf && cursor_updated) { -+ if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) -+ && cursor_updated) { - eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, - vc->gfx.esurface, vc->gfx.ectx); - -@@ -382,6 +384,13 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - #endif - -+ if (!dmabuf) { -+ return; -+ } -+ if (qemu_dmabuf_get_fd(dmabuf) < 0) { -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ return; -+ } - if (!vc->gfx.scanout_mode) { - return; - } -@@ -416,7 +425,7 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, - } - - #ifdef CONFIG_GBM -- if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) == -1) { -+ if (qemu_dmabuf_get_fence_fd(dmabuf) == -1) { - int fence_fd = egl_dmabuf_create_fence_fd(dmabuf); - if (fence_fd >= 0) { - qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c -index 4a2f9538ef..4ba4bda62b 100644 ---- a/ui/gtk-gl-area.c -+++ b/ui/gtk-gl-area.c -@@ -125,7 +125,8 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl) - gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area); - - #ifdef CONFIG_GBM -- if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf) && -+ if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) && -+ qemu_dmabuf_get_draw_submitted(dmabuf) && - qemu_dmabuf_get_render_sync(dmabuf)) { - gd_gl_area_draw(vc); - return; -@@ -290,7 +291,8 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, - #ifdef CONFIG_GBM - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - -- if (dmabuf && !qemu_dmabuf_get_draw_submitted(dmabuf) && -+ if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) && -+ !qemu_dmabuf_get_draw_submitted(dmabuf) && - vc->gfx.guest_fb.framebuffer) { - gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); - graphic_hw_gl_block(vc->gfx.dcl.con, true); --- -2.35.3 - diff --git a/SPECS/qemu/0037-ui-gtk-egl-Skip-refreshing-frame-and-hw-cursor-if-th.patch b/SPECS/qemu/0037-ui-gtk-egl-Skip-refreshing-frame-and-hw-cursor-if-th.patch deleted file mode 100644 index 28c9b5f996..0000000000 --- a/SPECS/qemu/0037-ui-gtk-egl-Skip-refreshing-frame-and-hw-cursor-if-th.patch +++ /dev/null @@ -1,56 +0,0 @@ -From ac0f6b9351c3122ea5ba48c5009fc1a4e04931b4 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 13 Mar 2025 15:51:09 -0700 -Subject: [PATCH 37/50] ui/gtk-egl: Skip refreshing frame and hw-cursor if the - same frame was just rendered - -More optimization on refresh - -Signed-off-by: Dongwon Kim ---- - include/ui/gtk.h | 1 + - ui/gtk-egl.c | 8 ++++++++ - 2 files changed, 9 insertions(+) - -diff --git a/include/ui/gtk.h b/include/ui/gtk.h -index 782484a374..723958794d 100644 ---- a/include/ui/gtk.h -+++ b/include/ui/gtk.h -@@ -47,6 +47,7 @@ typedef struct VirtualGfxConsole { - QemuGLShader *gls; - EGLContext ectx; - EGLSurface esurface; -+ bool recently_updated; - int glupdates; - int x, y, w, h; - egl_fb guest_fb; -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index fd9b05508b..8f84b3a19c 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -95,6 +95,8 @@ void gd_egl_draw(VirtualConsole *vc) - qemu_dmabuf_set_draw_submitted(dmabuf, false); - } - -+ vc->gfx.recently_updated = true; -+ - if (!dmabuf || - (dmabuf && qemu_dmabuf_get_render_sync(dmabuf) && - vc->gfx.guest_fb.framebuffer)) { -@@ -173,7 +175,13 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - } - - if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) -+ && !qemu_dmabuf_get_draw_submitted(dmabuf) - && cursor_updated) { -+ if (vc->gfx.recently_updated) { -+ vc->gfx.recently_updated = 0; -+ return; -+ } -+ - eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, - vc->gfx.esurface, vc->gfx.ectx); - --- -2.35.3 - diff --git a/SPECS/qemu/0038-ui-gtk-Refreshing-is-also-counted-when-calculating-F.patch b/SPECS/qemu/0038-ui-gtk-Refreshing-is-also-counted-when-calculating-F.patch deleted file mode 100644 index cdbba87656..0000000000 --- a/SPECS/qemu/0038-ui-gtk-Refreshing-is-also-counted-when-calculating-F.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 56e56600ff5124349e9798f7058937c0e00bec8e Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 13 Mar 2025 16:29:25 -0700 -Subject: [PATCH 38/50] ui/gtk: Refreshing is also counted when calculating FPS - -Signed-off-by: Dongwon Kim ---- - ui/gtk-egl.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 8f84b3a19c..4d91792537 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -202,6 +202,7 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - } - - eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -+ gd_gl_count_frame(&vc->gfx.dcl, 0); - vc->gfx.cursor_moved = false; - return; - } --- -2.35.3 - diff --git a/SPECS/qemu/0039-ui-gtk-FPS-and-UPS-are-updated-every-1-sec-instead-o.patch b/SPECS/qemu/0039-ui-gtk-FPS-and-UPS-are-updated-every-1-sec-instead-o.patch deleted file mode 100644 index 2422cd6038..0000000000 --- a/SPECS/qemu/0039-ui-gtk-FPS-and-UPS-are-updated-every-1-sec-instead-o.patch +++ /dev/null @@ -1,29 +0,0 @@ -From e5ec0b10569b161057c138f26f0c594b28396bea Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 13 Mar 2025 16:30:54 -0700 -Subject: [PATCH 39/50] ui/gtk: FPS and UPS are updated every 1 sec instead of - 5 sec - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index b84b759f95..179efd29be 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -617,8 +617,8 @@ void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups) - curr = tv.tv_sec * 1000000 + tv.tv_usec; - - delta = curr - prev; -- if (delta > 5000000) { -- /* update rate is calculated and displayed at every 5 secs */ -+ if (delta > 1000000) { -+ /* update rate is calculated and displayed at every 1 secs */ - prev = curr; - for (i = 0; i < vc->s->nb_vcs; i++) { - vc = &s->vc[i]; --- -2.35.3 - diff --git a/SPECS/qemu/0040-ui-gtk-fps-param-for-gd_gl_count_frame.patch b/SPECS/qemu/0040-ui-gtk-fps-param-for-gd_gl_count_frame.patch deleted file mode 100644 index 59d4595d66..0000000000 --- a/SPECS/qemu/0040-ui-gtk-fps-param-for-gd_gl_count_frame.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 6838d90312f714b66c056a0e38bf4750b766116a Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 13 Mar 2025 16:36:47 -0700 -Subject: [PATCH 40/50] ui/gtk: fps param for gd_gl_count_frame - -Adding fps param separately for incrementing fps_cnt - -Signed-off-by: Dongwon Kim ---- - include/ui/gtk.h | 2 +- - ui/gtk-egl.c | 7 ++++--- - ui/gtk-gl-area.c | 2 +- - ui/gtk.c | 8 ++++---- - 4 files changed, 10 insertions(+), 9 deletions(-) - -diff --git a/include/ui/gtk.h b/include/ui/gtk.h -index 723958794d..df9eed24a9 100644 ---- a/include/ui/gtk.h -+++ b/include/ui/gtk.h -@@ -166,7 +166,7 @@ extern bool gtk_use_gl_area; - void gd_update_windowsize(VirtualConsole *vc); - void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget); - void gd_hw_gl_flushed(void *vc); --void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups); -+void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups, bool fps); - - /* ui/gtk-egl.c */ - void gd_egl_init(VirtualConsole *vc); -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 4d91792537..7e7938a0fc 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -167,6 +167,7 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - vc, vc->window ? vc->window : vc->gfx.drawing_area); - - #ifdef CONFIG_GBM -+ gd_gl_count_frame(&vc->gfx.dcl, false, false); - if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) && - qemu_dmabuf_get_draw_submitted(dmabuf) && - qemu_dmabuf_get_render_sync(dmabuf)) { -@@ -202,7 +203,7 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - } - - eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -- gd_gl_count_frame(&vc->gfx.dcl, 0); -+ gd_gl_count_frame(&vc->gfx.dcl, false, true); - vc->gfx.cursor_moved = false; - return; - } -@@ -464,13 +465,13 @@ void gd_egl_flush(DisplayChangeListener *dcl, - qemu_dmabuf_set_draw_submitted(dmabuf, true); - gtk_widget_queue_draw_area(area, x, y, w, h); - } -- gd_gl_count_frame(&vc->gfx.dcl, 1); -+ gd_gl_count_frame(&vc->gfx.dcl, true, false); - return; - } - #endif - - gd_egl_scanout_flush(&vc->gfx.dcl, x, y, w, h); -- gd_gl_count_frame(&vc->gfx.dcl, 1); -+ gd_gl_count_frame(&vc->gfx.dcl, true, false); - } - - void gtk_egl_init(DisplayGLMode mode) -diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c -index 4ba4bda62b..08afa9864a 100644 ---- a/ui/gtk-gl-area.c -+++ b/ui/gtk-gl-area.c -@@ -326,7 +326,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, - } - #endif - gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); -- gd_gl_count_frame(&vc->gfx.dcl, 1); -+ gd_gl_count_frame(&vc->gfx.dcl, true, false); - } - - void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl, -diff --git a/ui/gtk.c b/ui/gtk.c -index 179efd29be..db136fa90d 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -588,7 +588,7 @@ static void gd_switch(DisplayChangeListener *dcl, - } - } - --void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups) -+void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups, bool fps) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); - GtkDisplayState *s = vc->s; -@@ -609,7 +609,7 @@ void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups) - - if (ups) { - vc->gfx.ups_cnt++; -- } else { -+ } else if (fps) { - vc->gfx.fps_cnt++; - } - -@@ -623,7 +623,7 @@ void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups) - for (i = 0; i < vc->s->nb_vcs; i++) { - vc = &s->vc[i]; - offset += sprintf(ups_fps_str + offset, -- "%d [%0.2fu/s %0.2ff/s] ", i, -+ "Disp%d[guest %0.1f fps / host %0.1f fps] ", i, - vc->gfx.ups_cnt * 1000000/(gfloat)delta, - vc->gfx.fps_cnt * 1000000/(gfloat)delta); - vc->gfx.fps_cnt = 0; -@@ -688,7 +688,7 @@ void gd_hw_gl_flushed(void *vcon) - close(fence_fd); - qemu_dmabuf_set_fence_fd(dmabuf, -1); - graphic_hw_gl_block(vc->gfx.dcl.con, false); -- gd_gl_count_frame(&vc->gfx.dcl, 0); -+ gd_gl_count_frame(&vc->gfx.dcl, false, true); - } - } - --- -2.35.3 - diff --git a/SPECS/qemu/0041-hw-virtio-gpu-udmabuf-g-dmabuf.primary-i-shouldn-t-b.patch b/SPECS/qemu/0041-hw-virtio-gpu-udmabuf-g-dmabuf.primary-i-shouldn-t-b.patch deleted file mode 100644 index 8adfaf1f7f..0000000000 --- a/SPECS/qemu/0041-hw-virtio-gpu-udmabuf-g-dmabuf.primary-i-shouldn-t-b.patch +++ /dev/null @@ -1,30 +0,0 @@ -From f395c2318b69b27aad1636f95992463bdfa40599 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Tue, 18 Mar 2025 16:50:15 -0700 -Subject: [PATCH 41/50] hw/virtio-gpu-udmabuf: g->dmabuf.primary[i] shouldn't - be nullified - -g->dmabuf.primary[i] will be used to point to udmabuf when -it is needed to be freed. So it shouldn't be nullified when -resource is destroyed. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu-udmabuf.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c -index 7b6d282824..005bfa67fa 100644 ---- a/hw/display/virtio-gpu-udmabuf.c -+++ b/hw/display/virtio-gpu-udmabuf.c -@@ -254,7 +254,6 @@ void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *re - qemu_dmabuf_get_fd(g->dmabuf.primary[i]->buf) == res->dmabuf_fd) { - /* preventing further mapping/use of the dmabuf */ - qemu_dmabuf_set_fd(g->dmabuf.primary[i]->buf, -1); -- g->dmabuf.primary[i] = NULL; - } - } - --- -2.35.3 - diff --git a/SPECS/qemu/0042-ui-gtk-Unblock-zero-copy-display-pipeline-before-sav.patch b/SPECS/qemu/0042-ui-gtk-Unblock-zero-copy-display-pipeline-before-sav.patch deleted file mode 100644 index 7553df4ec9..0000000000 --- a/SPECS/qemu/0042-ui-gtk-Unblock-zero-copy-display-pipeline-before-sav.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 9ca2d062e78faa8df8a23c5d61036a018e8402ae Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Sun, 23 Mar 2025 21:21:05 -0700 -Subject: [PATCH 42/50] ui/gtk: Unblock zero copy display pipeline before - saving/restoring VM - -System will be stuck if VM state is saved/restored in the middle of -guest display rendering. - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) - -diff --git a/ui/gtk.c b/ui/gtk.c -index db136fa90d..90fa4fb1a3 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -678,6 +678,7 @@ static void gd_gl_release_dmabuf(DisplayChangeListener *dcl, - - void gd_hw_gl_flushed(void *vcon) - { -+#ifdef CONFIG_GBM - VirtualConsole *vc = vcon; - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - int fence_fd; -@@ -690,6 +691,7 @@ void gd_hw_gl_flushed(void *vcon) - graphic_hw_gl_block(vc->gfx.dcl.con, false); - gd_gl_count_frame(&vc->gfx.dcl, false, true); - } -+#endif - } - - /** DisplayState Callbacks (opengl version) **/ -@@ -767,7 +769,28 @@ static const DisplayGLCtxOps egl_ctx_ops = { - static void gd_change_runstate(void *opaque, bool running, RunState state) - { - GtkDisplayState *s = opaque; -+#ifdef CONFIG_GBM -+ int i; -+ -+ if (state == RUN_STATE_SAVE_VM || state == RUN_STATE_RESTORE_VM) { -+ for (i = 0; i < s->nb_vcs; i++) { -+ VirtualConsole *vc = &s->vc[i]; -+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -+ -+ if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf)) { -+ qemu_dmabuf_set_draw_submitted(dmabuf, false); -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ } -+ -+ if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) >= 0) { - -+ /* force flushing current scanout blob rendering process -+ * just in case the fence is still not signaled */ -+ gd_hw_gl_flushed(vc); -+ } -+ } -+ } -+#endif - gd_update_caption(s); - } - --- -2.35.3 - diff --git a/SPECS/qemu/0043-ui-gtk-show-fps-works-on-GFX-consoles.patch b/SPECS/qemu/0043-ui-gtk-show-fps-works-on-GFX-consoles.patch deleted file mode 100644 index b140a57ea7..0000000000 --- a/SPECS/qemu/0043-ui-gtk-show-fps-works-on-GFX-consoles.patch +++ /dev/null @@ -1,57 +0,0 @@ -From f9a1573f2e318119c7d5957361c52ce6c76dd3ea Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Tue, 25 Mar 2025 11:00:27 -0700 -Subject: [PATCH 43/50] ui/gtk: show-fps works on GFX consoles - -show-fps causes stack overflow due to memory leak when -there are default VCs (if '-nodefaults' option is not added). - -The fix is to add frame counters only for GFX-supported VCs. - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 24 ++++++++++++++++++------ - 1 file changed, 18 insertions(+), 6 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 90fa4fb1a3..5499c32142 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -618,16 +618,28 @@ void gd_gl_count_frame(DisplayChangeListener *dcl, bool ups, bool fps) - - delta = curr - prev; - if (delta > 1000000) { -+ int d = 0; - /* update rate is calculated and displayed at every 1 secs */ - prev = curr; - for (i = 0; i < vc->s->nb_vcs; i++) { - vc = &s->vc[i]; -- offset += sprintf(ups_fps_str + offset, -- "Disp%d[guest %0.1f fps / host %0.1f fps] ", i, -- vc->gfx.ups_cnt * 1000000/(gfloat)delta, -- vc->gfx.fps_cnt * 1000000/(gfloat)delta); -- vc->gfx.fps_cnt = 0; -- vc->gfx.ups_cnt = 0; -+ if (vc->type == GD_VC_GFX && -+ qemu_console_is_graphic(vc->gfx.dcl.con)) { -+ if (vc->label) { -+ offset += sprintf(ups_fps_str + offset, -+ "%s[guest %0.1f fps / host %0.1f fps] ", -+ vc->label, -+ vc->gfx.ups_cnt * 1000000/(gfloat)delta, -+ vc->gfx.fps_cnt * 1000000/(gfloat)delta); -+ } else { -+ offset += sprintf(ups_fps_str + offset, -+ "Disp%d[guest %0.1f fps / host %0.1f fps] ", -+ d++, vc->gfx.ups_cnt * 1000000/(gfloat)delta, -+ vc->gfx.fps_cnt * 1000000/(gfloat)delta); -+ } -+ vc->gfx.fps_cnt = 0; -+ vc->gfx.ups_cnt = 0; -+ } - } - - status_bar_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(vc->s->status_bar), --- -2.35.3 - diff --git a/SPECS/qemu/0044-ui-gtk-egl-Skipping-frame-drawing-if-not-necessary.patch b/SPECS/qemu/0044-ui-gtk-egl-Skipping-frame-drawing-if-not-necessary.patch deleted file mode 100644 index 04b76bc9c0..0000000000 --- a/SPECS/qemu/0044-ui-gtk-egl-Skipping-frame-drawing-if-not-necessary.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 6d0c3ea7921233f460b880a9ee2aabeda95c7ee6 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Tue, 25 Mar 2025 11:54:14 -0700 -Subject: [PATCH 44/50] ui/gtk-egl: Skipping frame drawing if not necessary - -A flag 'new_cursor' would never be cleared in some corner case -where the cursor is not inside the frame or is not moved in -the next refresh cycle. This situation forces it to keep drawing -the cursor-less frame at every refresh cycle. This is a buggy -situation so needs to be adjusted as followed. - -1. Draw the cursor then blend it with the existing frame if - the cursor is moved AND the new location is inside the - frame - -2. Draw only the existing frame without cursor only if - the cursor is moved AND the cursor was drawn during the - previous cycle BUT the new location is not within the - frame boundary. - -3. Skipping redrawing anything otherwise. - -Signed-off-by: Dongwon Kim ---- - include/ui/gtk.h | 1 + - ui/gtk-egl.c | 30 ++++++++++++++++++++++-------- - 2 files changed, 23 insertions(+), 8 deletions(-) - -diff --git a/include/ui/gtk.h b/include/ui/gtk.h -index df9eed24a9..3b95310795 100644 ---- a/include/ui/gtk.h -+++ b/include/ui/gtk.h -@@ -56,6 +56,7 @@ typedef struct VirtualGfxConsole { - uint32_t *cursor_image; - bool cursor_moved; - bool new_cursor; -+ bool cursor_prev_drawn; - int cursor_x; - int cursor_y; - bool y0_top; -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 7e7938a0fc..42582d054a 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -178,33 +178,47 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) - && !qemu_dmabuf_get_draw_submitted(dmabuf) - && cursor_updated) { -+ - if (vc->gfx.recently_updated) { - vc->gfx.recently_updated = 0; - return; - } - -- eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -- vc->gfx.esurface, vc->gfx.ectx); -- -- egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); - if (vc->gfx.cursor_x > 0 && - vc->gfx.cursor_x < vc->gfx.win_fb.width - 1 && - vc->gfx.cursor_y > 0 && - vc->gfx.cursor_y < vc->gfx.win_fb.height - 1) { -+ -+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -+ vc->gfx.esurface, vc->gfx.ectx); -+ - if (vc->gfx.new_cursor) { - gd_egl_cursor_texture(vc); - vc->gfx.new_cursor = false; - } - -+ egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); - egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, - &vc->gfx.cursor_fb, vc->gfx.y0_top, - vc->gfx.cursor_x, vc->gfx.cursor_y, - vc->gfx.scale_x, vc->gfx.scale_y); -- } - -- eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -- gd_gl_count_frame(&vc->gfx.dcl, false, true); -- vc->gfx.cursor_moved = false; -+ eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -+ gd_gl_count_frame(&vc->gfx.dcl, false, true); -+ vc->gfx.cursor_moved = false; -+ vc->gfx.cursor_prev_drawn = true; -+ } else if (vc->gfx.cursor_prev_drawn) { -+ /* Cursor moved outside the window, so we need to redraw the -+ * window without the cursor */ -+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -+ vc->gfx.esurface, vc->gfx.ectx); -+ -+ egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); -+ eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -+ gd_gl_count_frame(&vc->gfx.dcl, false, true); -+ vc->gfx.cursor_prev_drawn = false; -+ } -+ - return; - } - #endif --- -2.35.3 - diff --git a/SPECS/qemu/0045-ui-gtk-HPD-handling-disconnection-immediately.patch b/SPECS/qemu/0045-ui-gtk-HPD-handling-disconnection-immediately.patch deleted file mode 100644 index 1029730ef0..0000000000 --- a/SPECS/qemu/0045-ui-gtk-HPD-handling-disconnection-immediately.patch +++ /dev/null @@ -1,136 +0,0 @@ -From cb56b335d18133ce81fb68d675281a7b6239df31 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 27 Mar 2025 10:30:00 -0700 -Subject: [PATCH 45/50] ui/gtk: HPD handling disconnection immediately - -Display will be inactive immediately upon disconnection -of the cable, so the monitor remove process should be kicked -right away instead of waiting for 2 sec. - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 59 ++++++++++++++++++++++++++++++++++++++++++-------------- - 1 file changed, 45 insertions(+), 14 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index 5499c32142..b7cee461b2 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -695,6 +695,10 @@ void gd_hw_gl_flushed(void *vcon) - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - int fence_fd; - -+ if (!dmabuf) { -+ return; -+ } -+ - fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); - if (fence_fd >= 0) { - qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); -@@ -795,7 +799,6 @@ static void gd_change_runstate(void *opaque, bool running, RunState state) - } - - if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) >= 0) { -- - /* force flushing current scanout blob rendering process - * just in case the fence is still not signaled */ - gd_hw_gl_flushed(vc); -@@ -1755,27 +1758,17 @@ static gboolean gd_vc_is_misplaced(GdkDisplay *dpy, GdkMonitor *monitor, - return FALSE; - } - --static void gd_vc_add_remove_monitor(GdkDisplay *dpy, GtkDisplayState *s) -+static void gd_vc_disconn_monitor(GdkDisplay *dpy, GtkDisplayState *s) - { - VirtualConsole *vc; -- GdkMonitor *monitor; - gint monitor_num; - int i; - -- /* -- * We need to call gd_vc_is_misplaced() after a monitor is added to -- * ensure that the Host compositor has not moved our windows around. -- */ - for (i = 0; i < s->nb_vcs; i++) { - vc = &s->vc[i]; - if (vc->label) { - monitor_num = gd_monitor_lookup(dpy, vc->label); -- if (monitor_num >= 0) { -- monitor = gdk_display_get_monitor(dpy, monitor_num); -- if (gd_vc_is_misplaced(dpy, monitor, vc)) { -- gd_window_show_on_monitor(dpy, vc, monitor_num); -- } -- } else { -+ if (monitor_num < 0) { - if (vc->monitor) { - vc->monitor = NULL; - } -@@ -1789,7 +1782,42 @@ static void gd_vc_add_remove_monitor(GdkDisplay *dpy, GtkDisplayState *s) - - /* if window exist, hide it */ - if (vc->window) { -+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - gdk_window_hide(gtk_widget_get_window(vc->window)); -+ -+ if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf)) { -+ qemu_dmabuf_set_draw_submitted(dmabuf, false); -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ } -+ -+ /* force flushing current scanout blob rendering process -+ * just in case the fence is still not signaled */ -+ gd_hw_gl_flushed(vc); -+ } -+ } -+ } -+ } -+} -+ -+static void gd_vc_conn_monitor(GdkDisplay *dpy, GtkDisplayState *s) -+{ -+ VirtualConsole *vc; -+ GdkMonitor *monitor; -+ gint monitor_num; -+ int i; -+ -+ /* -+ * We need to call gd_vc_is_misplaced() after a monitor is added to -+ * ensure that the Host compositor has not moved our windows around. -+ */ -+ for (i = 0; i < s->nb_vcs; i++) { -+ vc = &s->vc[i]; -+ if (vc->label) { -+ monitor_num = gd_monitor_lookup(dpy, vc->label); -+ if (monitor_num >= 0) { -+ monitor = gdk_display_get_monitor(dpy, monitor_num); -+ if (gd_vc_is_misplaced(dpy, monitor, vc)) { -+ gd_window_show_on_monitor(dpy, vc, monitor_num); - } - } - } -@@ -1801,18 +1829,21 @@ static void gd_monitors_reset_timer(void *opaque) - GtkDisplayState *s = opaque; - GdkDisplay *dpy = gdk_display_get_default(); - -- gd_vc_add_remove_monitor(dpy, s); -+ gd_vc_conn_monitor(dpy, s); - } - - static void gd_monitors_changed(GdkScreen *scr, void *opaque) - { - GtkDisplayState *s = opaque; -+ GdkDisplay *dpy = gdk_display_get_default(); - QEMUTimer *mon_reset_timer; - -+ gd_vc_disconn_monitor(dpy, s); - mon_reset_timer = timer_new_ms(QEMU_CLOCK_REALTIME, - gd_monitors_reset_timer, s); - timer_mod(mon_reset_timer, - qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 2000); -+ - } - - static VirtualConsole *gd_next_gfx_vc(GtkDisplayState *s) --- -2.35.3 - diff --git a/SPECS/qemu/0046-ui-gtk-egl-Cursor-image-texture-filtering-using-GL_N.patch b/SPECS/qemu/0046-ui-gtk-egl-Cursor-image-texture-filtering-using-GL_N.patch deleted file mode 100644 index 0b7976a79a..0000000000 --- a/SPECS/qemu/0046-ui-gtk-egl-Cursor-image-texture-filtering-using-GL_N.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 49a600fb668678520ae2c4c09a1315ae37133e44 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Wed, 9 Apr 2025 11:29:29 -0700 -Subject: [PATCH 46/50] ui/gtk-egl: Cursor image texture filtering using - GL_NEAREST - -For the faster rendering and avoiding an artifact (grey line) - -Signed-off-by: Dongwon Kim ---- - ui/gtk-egl.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 42582d054a..aeaad34d72 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -140,8 +140,8 @@ static void gd_egl_cursor_texture(VirtualConsole *vc) - - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vc->gfx.cursor_fb.width, --- -2.35.3 - diff --git a/SPECS/qemu/0047-ui-gtk-Covering-render_sync-false-case-when-dealing-.patch b/SPECS/qemu/0047-ui-gtk-Covering-render_sync-false-case-when-dealing-.patch deleted file mode 100644 index 5561ae6247..0000000000 --- a/SPECS/qemu/0047-ui-gtk-Covering-render_sync-false-case-when-dealing-.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 9e9dab144bb25f7482ea83f743ddfa1b289dc9b0 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Mon, 14 Apr 2025 11:09:46 -0700 -Subject: [PATCH 47/50] ui/gtk: Covering render_sync=false case when dealing - with fence - -There are a situation where fence_fd is positive or zero and -draw_submitted is true when render_sync=false. Unblocking -the display pipeline shouldn't be done when draw_submitted is -found to be true in this case to prevent double unblocking. - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index b7cee461b2..eeb41cb496 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -795,14 +795,14 @@ static void gd_change_runstate(void *opaque, bool running, RunState state) - - if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf)) { - qemu_dmabuf_set_draw_submitted(dmabuf, false); -- graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ if (qemu_dmabuf_get_render_sync(dmabuf)) { -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ } - } - -- if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) >= 0) { -- /* force flushing current scanout blob rendering process -- * just in case the fence is still not signaled */ -- gd_hw_gl_flushed(vc); -- } -+ /* force flushing current scanout blob rendering process -+ * just in case the fence is still not signaled */ -+ gd_hw_gl_flushed(vc); - } - } - #endif -@@ -1787,7 +1787,9 @@ static void gd_vc_disconn_monitor(GdkDisplay *dpy, GtkDisplayState *s) - - if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf)) { - qemu_dmabuf_set_draw_submitted(dmabuf, false); -- graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ if (qemu_dmabuf_get_render_sync(dmabuf)) { -+ graphic_hw_gl_block(vc->gfx.dcl.con, false); -+ } - } - - /* force flushing current scanout blob rendering process --- -2.35.3 - diff --git a/SPECS/qemu/0048-ui-gtk-egl-Cursor-texture-needs-to-be-re-created-whe.patch b/SPECS/qemu/0048-ui-gtk-egl-Cursor-texture-needs-to-be-re-created-whe.patch deleted file mode 100644 index a6f47c8f1c..0000000000 --- a/SPECS/qemu/0048-ui-gtk-egl-Cursor-texture-needs-to-be-re-created-whe.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 302814f2a0677a4b9b390251c97932b135d022a1 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Fri, 2 May 2025 12:36:53 -0700 -Subject: [PATCH 48/50] ui/gtk-egl: Cursor texture needs to be re-created when - ctx is new - -EGL surface and ctx are destroyed when new GTK window is created. Then -those should be recreated and initialized before rendering happens -in gd_egl_refresh. - -Also, texture shouldn't be deleted if the new texture has the same -number as previous texture created for the old ctx. - -Signed-off-by: Dongwon Kim ---- - ui/egl-helpers.c | 11 +++++++---- - ui/gtk-egl.c | 43 +++++++++++++++++++++++-------------------- - 2 files changed, 30 insertions(+), 24 deletions(-) - -diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c -index 698a021823..3bee1c11c0 100644 ---- a/ui/egl-helpers.c -+++ b/ui/egl-helpers.c -@@ -106,15 +106,18 @@ void egl_fb_setup_default(egl_fb *fb, int width, int height) - void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, - GLuint texture, bool delete) - { -- egl_fb_delete_texture(fb); -+ if (fb->texture != texture) { -+ egl_fb_delete_texture(fb); -+ } -+ -+ if (!fb->framebuffer || (fb->texture == texture)) { -+ glGenFramebuffers(1, &fb->framebuffer); -+ } - - fb->width = width; - fb->height = height; - fb->texture = texture; - fb->delete_texture = delete; -- if (!fb->framebuffer) { -- glGenFramebuffers(1, &fb->framebuffer); -- } - - glBindFramebuffer(GL_FRAMEBUFFER_EXT, fb->framebuffer); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index aeaad34d72..e3e3a7deb1 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -156,8 +156,7 @@ static void gd_egl_cursor_texture(VirtualConsole *vc) - void gd_egl_refresh(DisplayChangeListener *dcl) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); -- bool cursor_updated = vc->gfx.cursor_image && -- (vc->gfx.cursor_moved || vc->gfx.new_cursor); -+ bool cursor_updated; - - #ifdef CONFIG_GBM - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -@@ -166,6 +165,28 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - gd_update_monitor_refresh_rate( - vc, vc->window ? vc->window : vc->gfx.drawing_area); - -+ if (!vc->gfx.esurface) { -+ gd_egl_init(vc); -+ if (!vc->gfx.esurface) { -+ return; -+ } -+ vc->gfx.gls = qemu_gl_init_shader(); -+ if (vc->gfx.ds) { -+ surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds); -+ surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds); -+ } -+#ifdef CONFIG_GBM -+ if (dmabuf) { -+ egl_dmabuf_release_texture(dmabuf); -+ gd_egl_scanout_dmabuf(dcl, dmabuf); -+ } -+#endif -+ vc->gfx.new_cursor = true; -+ } -+ -+ cursor_updated = vc->gfx.cursor_image && -+ (vc->gfx.cursor_moved || vc->gfx.new_cursor); -+ - #ifdef CONFIG_GBM - gd_gl_count_frame(&vc->gfx.dcl, false, false); - if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) && -@@ -223,24 +244,6 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - } - #endif - -- if (!vc->gfx.esurface) { -- gd_egl_init(vc); -- if (!vc->gfx.esurface) { -- return; -- } -- vc->gfx.gls = qemu_gl_init_shader(); -- if (vc->gfx.ds) { -- surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds); -- surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds); -- } --#ifdef CONFIG_GBM -- if (dmabuf) { -- egl_dmabuf_release_texture(dmabuf); -- gd_egl_scanout_dmabuf(dcl, dmabuf); -- } --#endif -- } -- - graphic_hw_update(dcl->con); - - if (vc->gfx.glupdates) { --- -2.35.3 - diff --git a/SPECS/qemu/0049-Adding-default-docs.patch b/SPECS/qemu/0049-Adding-default-docs.patch deleted file mode 100644 index 7ff2324546..0000000000 --- a/SPECS/qemu/0049-Adding-default-docs.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 2964bb5df1d6c1568392ad8902a367e91b1f766f Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 29 May 2025 16:44:38 -0700 -Subject: [PATCH 49/50] Adding default docs - -Signed-off-by: Dongwon Kim ---- - CODE_OF_CONDUCT.md | 3 +++ - CONTRIBUTING.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++ - SECURITY.md | 5 ++++ - 3 files changed, 65 insertions(+) - create mode 100644 CODE_OF_CONDUCT.md - create mode 100644 CONTRIBUTING.md - create mode 100644 SECURITY.md - -diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md -new file mode 100644 -index 0000000000..4fab55a117 ---- /dev/null -+++ b/CODE_OF_CONDUCT.md -@@ -0,0 +1,3 @@ -+# Contributor Covenant Code of Conduct -+ -+The QEMU Community Code of Conduct can be found at https://qemu-project.gitlab.io/qemu/devel/code-of-conduct.html. -diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md -new file mode 100644 -index 0000000000..f682f4e4cc ---- /dev/null -+++ b/CONTRIBUTING.md -@@ -0,0 +1,57 @@ -+# Contributing -+ -+### License -+ -+ is licensed under the terms in [LICENSE]. By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. -+ -+### Sign your work -+ -+Please use the sign-off line at the end of the patch. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. The rules are pretty simple: if you can certify -+the below (from [developercertificate.org](http://developercertificate.org/)): -+ -+``` -+Developer Certificate of Origin -+Version 1.1 -+ -+Copyright (C) 2004, 2006 The Linux Foundation and its contributors. -+660 York Street, Suite 102, -+San Francisco, CA 94110 USA -+ -+Everyone is permitted to copy and distribute verbatim copies of this -+license document, but changing it is not allowed. -+ -+Developer's Certificate of Origin 1.1 -+ -+By making a contribution to this project, I certify that: -+ -+(a) The contribution was created in whole or in part by me and I -+ have the right to submit it under the open source license -+ indicated in the file; or -+ -+(b) The contribution is based upon previous work that, to the best -+ of my knowledge, is covered under an appropriate open source -+ license and I have the right under that license to submit that -+ work with modifications, whether created in whole or in part -+ by me, under the same open source license (unless I am -+ permitted to submit under a different license), as indicated -+ in the file; or -+ -+(c) The contribution was provided directly to me by some other -+ person who certified (a), (b) or (c) and I have not modified -+ it. -+ -+(d) I understand and agree that this project and the contribution -+ are public and that a record of the contribution (including all -+ personal information I submit with it, including my sign-off) is -+ maintained indefinitely and may be redistributed consistent with -+ this project or the open source license(s) involved. -+``` -+ -+Then you just add a line to every git commit message: -+ -+ Signed-off-by: Joe Smith -+ -+Use your real name (sorry, no pseudonyms or anonymous contributions.) -+ -+If you set your `user.name` and `user.email` git configs, you can sign your -+commit automatically with `git commit -s`. -diff --git a/SECURITY.md b/SECURITY.md -new file mode 100644 -index 0000000000..cb59eb8938 ---- /dev/null -+++ b/SECURITY.md -@@ -0,0 +1,5 @@ -+# Security Policy -+Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. -+ -+## Reporting a Vulnerability -+Please report any security vulnerabilities in this project utilizing the guidelines [here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html). --- -2.35.3 - diff --git a/SPECS/qemu/0050-gtk-Abort-if-there-is-no-connector-set-for-primary-w.patch b/SPECS/qemu/0050-gtk-Abort-if-there-is-no-connector-set-for-primary-w.patch deleted file mode 100644 index 160b06e288..0000000000 --- a/SPECS/qemu/0050-gtk-Abort-if-there-is-no-connector-set-for-primary-w.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0e33000c917458cd1c6d884377d6442d50b14a58 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Wed, 4 Jun 2025 16:06:41 -0700 -Subject: [PATCH 50/50] gtk: Abort if there is no connector set for primary - window - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index eeb41cb496..3b5b550b64 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1905,14 +1905,18 @@ static void gd_connectors_init(GdkDisplay *dpy, GtkDisplayState *s) - } - if (first_vc) { - vc->window = s->window; -- first_vc = FALSE; - } - - vc->label = g_strdup(conn->value); - monitor_num = gd_monitor_lookup(dpy, vc->label); - if (monitor_num >= 0) { - gd_window_show_on_monitor(dpy, vc, monitor_num); -+ } else if (first_vc) { -+ fprintf(stderr, "gtk: no monitor found for '%s' so terminating..\n", -+ vc->label); -+ abort(); - } -+ first_vc = FALSE; - } - - mon_reset_timer = timer_new_ms(QEMU_CLOCK_REALTIME, --- -2.35.3 - diff --git a/SPECS/qemu/0051-hw-display-virtio-gpu-Initialize-dmabuf_fd-for-the-b.patch b/SPECS/qemu/0051-hw-display-virtio-gpu-Initialize-dmabuf_fd-for-the-b.patch deleted file mode 100644 index aec1d2a6fa..0000000000 --- a/SPECS/qemu/0051-hw-display-virtio-gpu-Initialize-dmabuf_fd-for-the-b.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 2f62ec53fe143baf3b3d359387a2a1c2fe28d6de Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Mon, 28 Jul 2025 15:41:46 -0700 -Subject: [PATCH 1/3] hw/display/virtio-gpu: Initialize dmabuf_fd for the blob - resource with -1 - -0 of dmabuf_fd is supposed to be a valid file desriptor value so it can't -be its initial value before file is open. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index cf84c54ac3..76a594973c 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -368,6 +368,7 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g, - res = g_new0(struct virtio_gpu_simple_resource, 1); - res->resource_id = cblob.resource_id; - res->blob_size = cblob.size; -+ res->dmabuf_fd = -1; - - ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob), - cmd, &res->addrs, &res->iov, --- -2.43.0 - diff --git a/SPECS/qemu/0052-gtk-Adding-funcs-for-destroying-textures-in-gtk-egl-.patch b/SPECS/qemu/0052-gtk-Adding-funcs-for-destroying-textures-in-gtk-egl-.patch deleted file mode 100644 index b68bb3bdf3..0000000000 --- a/SPECS/qemu/0052-gtk-Adding-funcs-for-destroying-textures-in-gtk-egl-.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 429bc458341385f0964164c2020a8269a315957b Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Mon, 28 Jul 2025 15:54:49 -0700 -Subject: [PATCH 2/3] gtk: Adding funcs for destroying textures in - gtk-egl/gtk-gl-area - -Currently, surface->texture is not properly deleted due to missing -functions mapped to "dpy_gl_ctx_destroy_texture". This may lead to -memleak. - -Signed-off-by: Dongwon Kim ---- - include/ui/gtk.h | 4 ++++ - ui/gtk-egl.c | 10 ++++++++++ - ui/gtk-gl-area.c | 8 ++++++++ - ui/gtk.c | 2 ++ - 4 files changed, 24 insertions(+) - -diff --git a/include/ui/gtk.h b/include/ui/gtk.h -index 3b95310795..04b9f64e61 100644 ---- a/include/ui/gtk.h -+++ b/include/ui/gtk.h -@@ -179,6 +179,8 @@ void gd_egl_switch(DisplayChangeListener *dcl, - DisplaySurface *surface); - QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc, - QEMUGLParams *params); -+void gd_egl_destroy_texture(DisplayGLCtx *dgc, -+ DisplaySurface *surface); - void gd_egl_scanout_disable(DisplayChangeListener *dcl); - void gd_egl_scanout_texture(DisplayChangeListener *dcl, - uint32_t backing_id, -@@ -215,6 +217,8 @@ QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc, - QEMUGLParams *params); - void gd_gl_area_destroy_context(DisplayGLCtx *dgc, - QEMUGLContext ctx); -+void gd_gl_area_destroy_texture(DisplayGLCtx *dgc, -+ DisplaySurface *surface); - void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl, - QemuDmaBuf *dmabuf); - void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index e3e3a7deb1..768da2e33a 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -293,6 +293,16 @@ QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc, - return qemu_egl_create_context(dgc, params); - } - -+void gd_egl_destroy_texture(DisplayGLCtx *dgc, DisplaySurface *surface) -+{ -+ VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc); -+ -+ if (!eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -+ vc->gfx.esurface, vc->gfx.ectx)) printf("**dw_debug:: %s, eglMakeCurrent failed\n", __func__); -+ -+ surface_gl_destroy_texture(dgc->gls, surface); -+} -+ - void gd_egl_scanout_disable(DisplayChangeListener *dcl) - { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); -diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c -index 08afa9864a..4d8b4e2685 100644 ---- a/ui/gtk-gl-area.c -+++ b/ui/gtk-gl-area.c -@@ -248,6 +248,14 @@ void gd_gl_area_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx) - g_clear_object(&ctx); - } - -+void gd_gl_area_destroy_texture(DisplayGLCtx *dgc, DisplaySurface *surface) -+{ -+ VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc); -+ -+ gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); -+ surface_gl_destroy_texture(dgc->gls, surface); -+} -+ - void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, - uint32_t backing_id, - bool backing_y_0_top, -diff --git a/ui/gtk.c b/ui/gtk.c -index eeb41cb496..bee763c318 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -740,6 +740,7 @@ static const DisplayGLCtxOps gl_area_ctx_ops = { - .dpy_gl_ctx_is_compatible_dcl = gd_gl_area_is_compatible_dcl, - .dpy_gl_ctx_create = gd_gl_area_create_context, - .dpy_gl_ctx_destroy = gd_gl_area_destroy_context, -+ .dpy_gl_ctx_destroy_texture = gd_gl_area_destroy_texture, - .dpy_gl_ctx_make_current = gd_gl_area_make_current, - }; - -@@ -774,6 +775,7 @@ static const DisplayGLCtxOps egl_ctx_ops = { - .dpy_gl_ctx_is_compatible_dcl = gd_egl_is_compatible_dcl, - .dpy_gl_ctx_create = gd_egl_create_context, - .dpy_gl_ctx_destroy = qemu_egl_destroy_context, -+ .dpy_gl_ctx_destroy_texture = gd_egl_destroy_texture, - .dpy_gl_ctx_make_current = gd_egl_make_current, - }; - #endif --- -2.43.0 - diff --git a/SPECS/qemu/0053-hw-virtio-gpu-Cursor-size-can-be-changed.patch b/SPECS/qemu/0053-hw-virtio-gpu-Cursor-size-can-be-changed.patch deleted file mode 100644 index bd7778d060..0000000000 --- a/SPECS/qemu/0053-hw-virtio-gpu-Cursor-size-can-be-changed.patch +++ /dev/null @@ -1,47 +0,0 @@ -From d09ac8c3ef4159434e15a4793474be49ac64d082 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 24 Jul 2025 11:56:02 -0700 -Subject: [PATCH] hw/virtio-gpu: Cursor size can be changed - -HW cursor image size is set to 128, 128 in windows guest (using ZC -driver). QEMU should be able to resize (via reallocation) the container -of guest mouse cursor to accomodate this new size. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index cf84c54ac3..418c0598dd 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -15,6 +15,7 @@ - #include "qemu/units.h" - #include "qemu/iov.h" - #include "sysemu/cpus.h" -+#include - #include "ui/console.h" - #include "ui/rect.h" - #include "trace.h" -@@ -57,9 +58,14 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g, - } - - if (res->blob_size) { -- if (res->blob_size < (s->current_cursor->width * -- s->current_cursor->height * 4)) { -- return; -+ if (res->blob_size != (s->current_cursor->width * -+ s->current_cursor->height * 4)) { -+ /* resize 'current_cursor' for the new blob_size -+ * The assumption is the cursor image is square. -+ */ -+ int width = sqrt(res->blob_size / 4); -+ g_free(s->current_cursor); -+ s->current_cursor = cursor_alloc(width, width); - } - data = res->blob; - } else if (res->image) { --- -2.43.0 - diff --git a/SPECS/qemu/0054-hw-display-virtio-gpu-Redundant-call-of-dpy_gfx_repl.patch b/SPECS/qemu/0054-hw-display-virtio-gpu-Redundant-call-of-dpy_gfx_repl.patch deleted file mode 100644 index 5d84a7a9c4..0000000000 --- a/SPECS/qemu/0054-hw-display-virtio-gpu-Redundant-call-of-dpy_gfx_repl.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 4c50a5626930baa5edec350162888654c0006ec5 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Mon, 28 Jul 2025 19:49:55 -0700 -Subject: [PATCH 3/3] hw/display/virtio-gpu: Redundant call of - dpy_gfx_replace_surface - -'dpy_gfx_replace_surface' to null surface is done upon reset is done -in virtio_gpu_reset_bh. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu.c | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index 76a594973c..7e7f97baae 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -1596,7 +1596,6 @@ void virtio_gpu_reset(VirtIODevice *vdev) - { - VirtIOGPU *g = VIRTIO_GPU(vdev); - struct virtio_gpu_ctrl_command *cmd; -- int i = 0; - - if (qemu_in_vcpu_thread()) { - g->reset_finished = false; -@@ -1621,10 +1620,6 @@ void virtio_gpu_reset(VirtIODevice *vdev) - g_free(cmd); - } - -- for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { -- dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL); -- } -- - virtio_gpu_base_reset(VIRTIO_GPU_BASE(vdev)); - } - --- -2.43.0 - diff --git a/SPECS/qemu/0055-hw-display-virtio-gpu-Manual-res-flush-to-redraw-sav.patch b/SPECS/qemu/0055-hw-display-virtio-gpu-Manual-res-flush-to-redraw-sav.patch deleted file mode 100644 index a562e08b51..0000000000 --- a/SPECS/qemu/0055-hw-display-virtio-gpu-Manual-res-flush-to-redraw-sav.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 15210296c14bdbac54e178a14b2cd91f66e65531 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Wed, 20 Aug 2025 19:40:56 -0700 -Subject: [PATCH 1/3] hw/display/virtio-gpu: Manual res-flush to redraw saved - resource - -After restoring from saved state, scanouts are restored but -the very last guest frame is not rendered as resource-flush -is missing. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu.c | 8 +++- - ui/gtk-egl.c | 97 +++++++++++++++++++---------------------- - 2 files changed, 53 insertions(+), 52 deletions(-) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index 26a53d685a..c90e242e12 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -1498,6 +1498,12 @@ static int virtio_gpu_post_load(void *opaque, int version_id) - if (!virtio_gpu_do_set_scanout(g, i, &scanout->fb, res, &r, &error)) { - return -EINVAL; - } -+ -+ if (scanout->resource_id == res->resource_id && -+ console_has_gl(scanout->con)) { -+ dpy_gl_update(scanout->con, 0, 0, scanout->width, -+ scanout->height); -+ } - } else { - /* legacy v1 migration support */ - if (!res->image) { -@@ -1508,9 +1514,9 @@ static int virtio_gpu_post_load(void *opaque, int version_id) - qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0); - #endif - dpy_gfx_replace_surface(scanout->con, scanout->ds); -+ dpy_gfx_update_full(scanout->con); - } - -- dpy_gfx_update_full(scanout->con); - if (scanout->cursor.resource_id) { - update_cursor(g, &scanout->cursor); - } -diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c -index 4709a24597..f737ae617a 100644 ---- a/ui/gtk-egl.c -+++ b/ui/gtk-egl.c -@@ -184,62 +184,57 @@ void gd_egl_refresh(DisplayChangeListener *dcl) - vc->gfx.new_cursor = true; - } - -- cursor_updated = vc->gfx.cursor_image && -- (vc->gfx.cursor_moved || vc->gfx.new_cursor); -- - #ifdef CONFIG_GBM - gd_gl_count_frame(&vc->gfx.dcl, false, false); -- if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) && -- qemu_dmabuf_get_draw_submitted(dmabuf) && -- qemu_dmabuf_get_render_sync(dmabuf)) { -- gd_egl_draw(vc); -- return; -- } -- -- if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0) -- && !qemu_dmabuf_get_draw_submitted(dmabuf) -- && cursor_updated) { -- -- if (vc->gfx.recently_updated) { -- vc->gfx.recently_updated = 0; -- return; -- } -- -- if (vc->gfx.cursor_x > 0 && -- vc->gfx.cursor_x < vc->gfx.win_fb.width - 1 && -- vc->gfx.cursor_y > 0 && -- vc->gfx.cursor_y < vc->gfx.win_fb.height - 1) { - -- eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -- vc->gfx.esurface, vc->gfx.ectx); -- -- if (vc->gfx.new_cursor) { -- gd_egl_cursor_texture(vc); -- vc->gfx.new_cursor = false; -+ if (dmabuf && (qemu_dmabuf_get_fd(dmabuf) > 0)) { -+ cursor_updated = vc->gfx.cursor_image && -+ (vc->gfx.cursor_moved || vc->gfx.new_cursor); -+ if (qemu_dmabuf_get_draw_submitted(dmabuf) && -+ qemu_dmabuf_get_render_sync(dmabuf)) { -+ gd_egl_draw(vc); -+ } else if (!qemu_dmabuf_get_draw_submitted(dmabuf) && -+ cursor_updated) { -+ if (vc->gfx.recently_updated) { -+ vc->gfx.recently_updated = 0; -+ return; - } - -- egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); -- egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, -- &vc->gfx.cursor_fb, vc->gfx.y0_top, -- vc->gfx.cursor_x, vc->gfx.cursor_y, -- vc->gfx.scale_x, vc->gfx.scale_y); -- -- eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -- gd_gl_count_frame(&vc->gfx.dcl, false, true); -- vc->gfx.cursor_moved = false; -- vc->gfx.cursor_prev_drawn = true; -- } else if (vc->gfx.cursor_prev_drawn) { -- /* Cursor moved outside the window, so we need to redraw the -- * window without the cursor */ -- eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -- vc->gfx.esurface, vc->gfx.ectx); -- -- egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); -- eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -- gd_gl_count_frame(&vc->gfx.dcl, false, true); -- vc->gfx.cursor_prev_drawn = false; -- } -- -+ if (vc->gfx.cursor_x > 0 && -+ vc->gfx.cursor_x < vc->gfx.win_fb.width - 1 && -+ vc->gfx.cursor_y > 0 && -+ vc->gfx.cursor_y < vc->gfx.win_fb.height - 1) { -+ -+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -+ vc->gfx.esurface, vc->gfx.ectx); -+ -+ if (vc->gfx.new_cursor) { -+ gd_egl_cursor_texture(vc); -+ vc->gfx.new_cursor = false; -+ } -+ -+ egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); -+ egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, -+ &vc->gfx.cursor_fb, vc->gfx.y0_top, -+ vc->gfx.cursor_x, vc->gfx.cursor_y, -+ vc->gfx.scale_x, vc->gfx.scale_y); -+ -+ eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -+ gd_gl_count_frame(&vc->gfx.dcl, false, true); -+ vc->gfx.cursor_moved = false; -+ vc->gfx.cursor_prev_drawn = true; -+ } else if (vc->gfx.cursor_prev_drawn) { -+ /* Cursor moved outside the window, so we need to redraw the -+ * window without the cursor */ -+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, -+ vc->gfx.esurface, vc->gfx.ectx); -+ -+ egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top); -+ eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); -+ gd_gl_count_frame(&vc->gfx.dcl, false, true); -+ vc->gfx.cursor_prev_drawn = false; -+ } -+ } - return; - } - #endif --- -2.34.1 - diff --git a/SPECS/qemu/0056-hw-display-virtio-gpu-Properly-free-current_cursor.patch b/SPECS/qemu/0056-hw-display-virtio-gpu-Properly-free-current_cursor.patch deleted file mode 100644 index aa36aad1af..0000000000 --- a/SPECS/qemu/0056-hw-display-virtio-gpu-Properly-free-current_cursor.patch +++ /dev/null @@ -1,30 +0,0 @@ -From f3b07985b09cdea3a37fdd7cd826ae0a05486816 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 4 Sep 2025 12:55:29 -0700 -Subject: [PATCH 2/3] hw/display/virtio-gpu: Properly free current_cursor - -s->current_cursor should be freed properly instead of -brutally freeing the structure without considering ref -count. - -Signed-off-by: Dongwon Kim ---- - hw/display/virtio-gpu.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c -index c90e242e12..11f33daed5 100644 ---- a/hw/display/virtio-gpu.c -+++ b/hw/display/virtio-gpu.c -@@ -64,7 +64,7 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g, - * The assumption is the cursor image is square. - */ - int width = sqrt(res->blob_size / 4); -- g_free(s->current_cursor); -+ cursor_unref(s->current_cursor); - s->current_cursor = cursor_alloc(width, width); - } - data = res->blob; --- -2.34.1 - diff --git a/SPECS/qemu/0057-ui-gtk-Re-grabbing-PTR-KBD-individually.patch b/SPECS/qemu/0057-ui-gtk-Re-grabbing-PTR-KBD-individually.patch deleted file mode 100644 index a15f4e7144..0000000000 --- a/SPECS/qemu/0057-ui-gtk-Re-grabbing-PTR-KBD-individually.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 2a166768b9bd385e517bfa47605cb6b51edafec9 Mon Sep 17 00:00:00 2001 -From: Dongwon Kim -Date: Thu, 18 Sep 2025 23:46:06 +0530 -Subject: [PATCH 3/3] ui/gtk: Re-grabbing PTR/KBD individually - -Re-grabbing any of PTR and KBD is done only if both were grabbed before. -There are cases where only one of them is grabbed so it should be -checked and regrabbed separtely. - -Signed-off-by: Dongwon Kim ---- - ui/gtk.c | 38 +++++++++++++++++--------------------- - 1 file changed, 17 insertions(+), 21 deletions(-) - -diff --git a/ui/gtk.c b/ui/gtk.c -index fce6fd1f99..1442507b45 100644 ---- a/ui/gtk.c -+++ b/ui/gtk.c -@@ -1574,17 +1574,16 @@ static gboolean gd_window_state_event(GtkWidget *widget, GdkEvent *event, - } - - if (event->window_state.new_window_state & GDK_WINDOW_STATE_FOCUSED) { -- if (s->ptr_owner == vc && s->kbd_owner == vc) { -- if (gd_is_grab_active(s)) { -- s->ptr_owner = NULL; -- s->kbd_owner = NULL; -- gd_grab_keyboard(vc, "windows-focused"); -- gd_grab_pointer(vc, "windows-focused"); -- } else { -- gd_ungrab_keyboard(s); -- gd_ungrab_pointer(s); -- } -+ if (s->ptr_owner == vc) { -+ s->ptr_owner = NULL; -+ gd_grab_pointer(vc, "windows-focused"); -+ } -+ -+ if (s->kbd_owner == vc) { -+ s->kbd_owner = NULL; -+ gd_grab_keyboard(vc, "windows-focused"); - } -+ - } - - /* WA to fullscreen window if it's forcefully un-fullscreened by -@@ -1710,17 +1709,14 @@ static void gd_window_show_on_monitor(GdkDisplay *dpy, VirtualConsole *vc, - info.height = gdk_window_get_height(window); - dpy_set_ui_info(vc->gfx.dcl.con, &info, false); - -- if (s->ptr_owner && s->kbd_owner && -- s->ptr_owner == vc && s->kbd_owner == vc) { -- if (gd_is_grab_active(s)) { -- s->ptr_owner = NULL; -- s->kbd_owner = NULL; -- gd_grab_keyboard(vc, "user-request-main-window"); -- gd_grab_pointer(vc, "user-request-main-window"); -- } else { -- gd_ungrab_keyboard(s); -- gd_ungrab_pointer(s); -- } -+ if (s->ptr_owner == vc) { -+ s->ptr_owner = NULL; -+ gd_grab_pointer(vc, "user-request-main-window"); -+ } -+ -+ if (s->kbd_owner == vc) { -+ s->kbd_owner = NULL; -+ gd_grab_keyboard(vc, "user-request-main-window"); - } - - gd_update_cursor(vc); --- -2.34.1 - diff --git a/SPECS/qemu/0058-hw-usb-host-libusb-Do-not-assert-when-detects-invali.patch b/SPECS/qemu/0058-hw-usb-host-libusb-Do-not-assert-when-detects-invali.patch deleted file mode 100644 index 9f360d99f6..0000000000 --- a/SPECS/qemu/0058-hw-usb-host-libusb-Do-not-assert-when-detects-invali.patch +++ /dev/null @@ -1,63 +0,0 @@ -From b5e4fa8886c09c676a28279369d9ea334bdb77bb Mon Sep 17 00:00:00 2001 -From: Liang1 Yang -Date: Thu, 30 Oct 2025 20:07:41 +0800 -Subject: [PATCH 1/1] hw/usb/host-libusb: Do not assert when detects invalid - alt - -Log warning and skip the interface instead of asserting in qemu -host-libusb when there is invalid altsetting index during fast -USB device hotplug/unplug. -This is to prevent guest vm from crashing which is caused by -QEMU task abort. - -Signed-off-by: Liang1 Yang ---- - hw/usb/host-libusb.c | 25 ++++++++++++++++++++++++- - 1 file changed, 24 insertions(+), 1 deletion(-) - -diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c -index 691bc881fb..3a08caafa5 100644 ---- a/hw/usb/host-libusb.c -+++ b/hw/usb/host-libusb.c -@@ -885,6 +885,15 @@ static void usb_host_ep_update(USBHostDevice *s) - trace_usb_host_parse_config(s->bus_num, s->addr, - conf->bConfigurationValue, true); - -+ /* Log and skip if configuration is NULL or has no interfaces */ -+ if (!conf || conf->bNumInterfaces == 0) { -+ warn_report("usb-host: ignoring invalid configuration " -+ "for device %s (bus=%03d, addr=%03d)", -+ udev->product_desc ? udev->product_desc : "unknown", -+ s->bus_num, s->addr); -+ return; -+ } -+ - for (i = 0; i < conf->bNumInterfaces; i++) { - /* - * The udev->altsetting array indexes alternate settings -@@ -896,7 +905,21 @@ static void usb_host_ep_update(USBHostDevice *s) - alt = udev->altsetting[intf->bInterfaceNumber]; - - if (alt != 0) { -- assert(alt < conf->interface[i].num_altsetting); -+ if (alt >= conf->interface[i].num_altsetting) { -+ /* -+ * Recommend fix: sometimes libusb reports a temporary -+ * invalid altsetting index during fast hotplug/unplug. -+ * Instead of aborting, log a warning and skip the interface. -+ */ -+ warn_report("usb-host: ignoring invalid altsetting=%d (max=%d) " -+ "for interface=%d on %s (bus=%03d, addr=%03d)", -+ alt, -+ conf->interface[i].num_altsetting ? conf->interface[i].num_altsetting - 1 : -1, -+ i, -+ udev->product_desc ? udev->product_desc : "unknown", -+ s->bus_num, s->addr); -+ continue; -+ } - intf = &conf->interface[i].altsetting[alt]; - } - --- -2.35.3 - diff --git a/SPECS/qemu/CVE-2021-20255.patch b/SPECS/qemu/CVE-2021-20255.patch deleted file mode 100644 index 4aa03e7b8b..0000000000 --- a/SPECS/qemu/CVE-2021-20255.patch +++ /dev/null @@ -1,60 +0,0 @@ -From: Stefan Weil -Date: Fri, 19 Feb 2021 09:08 -Am 19.02.21 um 09:08 schrieb Stefan Weil : - -> Okay, I can confirm the infinite recursion now. - -> The test case triggers memory writes by the hardware which cause new actions -> of the same hardware and so on. - -> I don't know how the real hardware would handle that case. - -> For QEMU we can extend the current code which tries to prevent endless loops: -> the device status EEPRO100State can be extended by a recursion counter to -> limit the number of recursions, or maybe a boolean flag could be used to stop -> any recursion of action_command(). I prefer the second variant (no recursion -> at all) and suggest to add a diagnostic message as well like it is done for -> the endless loop case. - - -If there are no recursions in normal use, the following patch should work: - -Link: https://lists.gnu.org/archive/html/qemu-devel/2021-02/msg06098.html ---- -diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c -index 16e95ef9cc..2474cf3dc2 100644 ---- a/hw/net/eepro100.c -+++ b/hw/net/eepro100.c -@@ -279,6 +279,9 @@ typedef struct { - /* Quasi static device properties (no need to save them). */ - uint16_t stats_size; - bool has_extended_tcb_support; -+ -+ /* Flag to avoid recursions. */ -+ bool busy; - } EEPRO100State; - - /* Word indices in EEPROM. */ -@@ -837,6 +840,14 @@ static void action_command(EEPRO100State *s) - Therefore we limit the number of iterations. */ - unsigned max_loop_count = 16; - -+ if (s->busy) { -+ /* Prevent recursions. */ -+ logout("recursion in %s:%u\n", __FILE__, __LINE__); -+ return; -+ } -+ -+ s->busy = true; -+ - for (;;) { - bool bit_el; - bool bit_s; -@@ -933,6 +944,7 @@ static void action_command(EEPRO100State *s) - } - TRACE(OTHER, logout("CU list empty\n")); - /* List is empty. Now CU is idle or suspended. */ -+ s->busy = false; - } - - static void eepro100_cu_command(EEPRO100State * s, uint8_t val) diff --git a/SPECS/qemu/CVE-2023-6683.patch b/SPECS/qemu/CVE-2023-6683.patch deleted file mode 100644 index a57c8f15c0..0000000000 --- a/SPECS/qemu/CVE-2023-6683.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 405484b29f6548c7b86549b0f961b906337aa68a Mon Sep 17 00:00:00 2001 -From: Fiona Ebner -Date: Wed, 24 Jan 2024 11:57:48 +0100 -Subject: [PATCH] ui/clipboard: mark type as not available when there is no - data -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -With VNC, a client can send a non-extended VNC_MSG_CLIENT_CUT_TEXT -message with len=0. In qemu_clipboard_set_data(), the clipboard info -will be updated setting data to NULL (because g_memdup(data, size) -returns NULL when size is 0). If the client does not set the -VNC_ENCODING_CLIPBOARD_EXT feature when setting up the encodings, then -the 'request' callback for the clipboard peer is not initialized. -Later, because data is NULL, qemu_clipboard_request() can be reached -via vdagent_chr_write() and vdagent_clipboard_recv_request() and -there, the clipboard owner's 'request' callback will be attempted to -be called, but that is a NULL pointer. - -In particular, this can happen when using the KRDC (22.12.3) VNC -client. - -Another scenario leading to the same issue is with two clients (say -noVNC and KRDC): - -The noVNC client sets the extension VNC_FEATURE_CLIPBOARD_EXT and -initializes its cbpeer. - -The KRDC client does not, but triggers a vnc_client_cut_text() (note -it's not the _ext variant)). There, a new clipboard info with it as -the 'owner' is created and via qemu_clipboard_set_data() is called, -which in turn calls qemu_clipboard_update() with that info. - -In qemu_clipboard_update(), the notifier for the noVNC client will be -called, i.e. vnc_clipboard_notify() and also set vs->cbinfo for the -noVNC client. The 'owner' in that clipboard info is the clipboard peer -for the KRDC client, which did not initialize the 'request' function. -That sounds correct to me, it is the owner of that clipboard info. - -Then when noVNC sends a VNC_MSG_CLIENT_CUT_TEXT message (it did set -the VNC_FEATURE_CLIPBOARD_EXT feature correctly, so a check for it -passes), that clipboard info is passed to qemu_clipboard_request() and -the original segfault still happens. - -Fix the issue by handling updates with size 0 differently. In -particular, mark in the clipboard info that the type is not available. - -While at it, switch to g_memdup2(), because g_memdup() is deprecated. - -Cc: qemu-stable@nongnu.org -Fixes: CVE-2023-6683 -Reported-by: Markus Frank -Suggested-by: Marc-André Lureau -Signed-off-by: Fiona Ebner -Reviewed-by: Marc-André Lureau -Tested-by: Markus Frank -Message-ID: <20240124105749.204610-1-f.ebner@proxmox.com> -Link: https://gitlab.com/qemu-project/qemu/-/commit/405484b29f6548c7b86549b0f961b906337aa68a.patch ---- - ui/clipboard.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/ui/clipboard.c b/ui/clipboard.c -index 3d14bffaf80..b3f6fa3c9e1 100644 ---- a/ui/clipboard.c -+++ b/ui/clipboard.c -@@ -163,9 +163,15 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer, - } - - g_free(info->types[type].data); -- info->types[type].data = g_memdup(data, size); -- info->types[type].size = size; -- info->types[type].available = true; -+ if (size) { -+ info->types[type].data = g_memdup2(data, size); -+ info->types[type].size = size; -+ info->types[type].available = true; -+ } else { -+ info->types[type].data = NULL; -+ info->types[type].size = 0; -+ info->types[type].available = false; -+ } - - if (update) { - qemu_clipboard_update(info); --- -GitLab - diff --git a/SPECS/qemu/CVE-2023-6693.patch b/SPECS/qemu/CVE-2023-6693.patch deleted file mode 100644 index f241bd0194..0000000000 --- a/SPECS/qemu/CVE-2023-6693.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 2220e8189fb94068dbad333228659fbac819abb0 Mon Sep 17 00:00:00 2001 -From: Jason Wang -Date: Tue, 2 Jan 2024 11:29:01 +0800 -Subject: [PATCH] virtio-net: correctly copy vnet header when flushing TX - -When HASH_REPORT is negotiated, the guest_hdr_len might be larger than -the size of the mergeable rx buffer header. Using -virtio_net_hdr_mrg_rxbuf during the header swap might lead a stack -overflow in this case. Fixing this by using virtio_net_hdr_v1_hash -instead. - -Reported-by: Xiao Lei -Cc: Yuri Benditovich -Cc: qemu-stable@nongnu.org -Cc: Mauro Matteo Cascella -Fixes: CVE-2023-6693 -Fixes: e22f0603fb2f ("virtio-net: reference implementation of hash report") -Reviewed-by: Michael Tokarev -Signed-off-by: Jason Wang -Link: https://gitlab.com/qemu-project/qemu/-/commit/2220e8189fb94068dbad333228659fbac819abb0.patch ---- - hw/net/virtio-net.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c -index 7a2846fa1c7..5a79bc3a3a0 100644 ---- a/hw/net/virtio-net.c -+++ b/hw/net/virtio-net.c -@@ -674,6 +674,11 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs, - - n->mergeable_rx_bufs = mergeable_rx_bufs; - -+ /* -+ * Note: when extending the vnet header, please make sure to -+ * change the vnet header copying logic in virtio_net_flush_tx() -+ * as well. -+ */ - if (version_1) { - n->guest_hdr_len = hash_report ? - sizeof(struct virtio_net_hdr_v1_hash) : -@@ -2693,7 +2698,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) - ssize_t ret; - unsigned int out_num; - struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg; -- struct virtio_net_hdr_mrg_rxbuf mhdr; -+ struct virtio_net_hdr_v1_hash vhdr; - - elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement)); - if (!elem) { -@@ -2710,7 +2715,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) - } - - if (n->has_vnet_hdr) { -- if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) < -+ if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) < - n->guest_hdr_len) { - virtio_error(vdev, "virtio-net header incorrect"); - virtqueue_detach_element(q->tx_vq, elem, 0); -@@ -2718,8 +2723,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) - return -EINVAL; - } - if (n->needs_vnet_hdr_swap) { -- virtio_net_hdr_swap(vdev, (void *) &mhdr); -- sg2[0].iov_base = &mhdr; -+ virtio_net_hdr_swap(vdev, (void *) &vhdr); -+ sg2[0].iov_base = &vhdr; - sg2[0].iov_len = n->guest_hdr_len; - out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1, - out_sg, out_num, --- -GitLab - diff --git a/SPECS/qemu/CVE-2024-26327.patch b/SPECS/qemu/CVE-2024-26327.patch deleted file mode 100644 index 39399dccce..0000000000 --- a/SPECS/qemu/CVE-2024-26327.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 313e746958967a4b941ad4bbb80726727318edfa Mon Sep 17 00:00:00 2001 -From: Akihiko Odaki -Date: Wed, 28 Feb 2024 20:33:13 +0900 -Subject: [PATCH] pcie_sriov: Validate NumVFs - -The guest may write NumVFs greater than TotalVFs and that can lead -to buffer overflow in VF implementations. - -Cc: qemu-stable@nongnu.org -Fixes: CVE-2024-26327 -Fixes: 7c0fa8dff811 ("pcie: Add support for Single Root I/O Virtualization (SR/IOV)") -Signed-off-by: Akihiko Odaki -Message-Id: <20240228-reuse-v8-2-282660281e60@daynix.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: Sriram Yagnaraman -(cherry picked from commit 6081b4243cd64dff1b2cf5b0c215c71e9d7e753b) -Signed-off-by: Michael Tokarev ---- - hw/pci/pcie_sriov.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c -index a1fe65f5d80..da209b7f47f 100644 ---- a/hw/pci/pcie_sriov.c -+++ b/hw/pci/pcie_sriov.c -@@ -176,6 +176,9 @@ static void register_vfs(PCIDevice *dev) - - assert(sriov_cap > 0); - num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); -+ if (num_vfs > pci_get_word(dev->config + sriov_cap + PCI_SRIOV_TOTAL_VF)) { -+ return; -+ } - - dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs); - --- -GitLab - diff --git a/SPECS/qemu/CVE-2024-26328.patch b/SPECS/qemu/CVE-2024-26328.patch deleted file mode 100644 index 389f7801d2..0000000000 --- a/SPECS/qemu/CVE-2024-26328.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 98f3488c1b6090024299f8d6362aa6aac03fe26d Mon Sep 17 00:00:00 2001 -From: Akihiko Odaki -Date: Wed, 28 Feb 2024 20:33:12 +0900 -Subject: [PATCH] hw/nvme: Use pcie_sriov_num_vfs() - -nvme_sriov_pre_write_ctrl() used to directly inspect SR-IOV -configurations to know the number of VFs being disabled due to SR-IOV -configuration writes, but the logic was flawed and resulted in -out-of-bound memory access. - -It assumed PCI_SRIOV_NUM_VF always has the number of currently enabled -VFs, but it actually doesn't in the following cases: -- PCI_SRIOV_NUM_VF has been set but PCI_SRIOV_CTRL_VFE has never been. -- PCI_SRIOV_NUM_VF was written after PCI_SRIOV_CTRL_VFE was set. -- VFs were only partially enabled because of realization failure. - -It is a responsibility of pcie_sriov to interpret SR-IOV configurations -and pcie_sriov does it correctly, so use pcie_sriov_num_vfs(), which it -provides, to get the number of enabled VFs before and after SR-IOV -configuration writes. - -Cc: qemu-stable@nongnu.org -Fixes: CVE-2024-26328 -Fixes: 11871f53ef8e ("hw/nvme: Add support for the Virtualization Management command") -Suggested-by: Michael S. Tsirkin -Signed-off-by: Akihiko Odaki -Message-Id: <20240228-reuse-v8-1-282660281e60@daynix.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit 91bb64a8d2014fda33a81fcf0fce37340f0d3b0c) -Signed-off-by: Michael Tokarev ---- - hw/nvme/ctrl.c | 26 ++++++++------------------ - 1 file changed, 8 insertions(+), 18 deletions(-) - -diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c -index 585bd3b397d..eaa6946604d 100644 ---- a/hw/nvme/ctrl.c -+++ b/hw/nvme/ctrl.c -@@ -8497,36 +8497,26 @@ static void nvme_pci_reset(DeviceState *qdev) - nvme_ctrl_reset(n, NVME_RESET_FUNCTION); - } - --static void nvme_sriov_pre_write_ctrl(PCIDevice *dev, uint32_t address, -- uint32_t val, int len) -+static void nvme_sriov_post_write_config(PCIDevice *dev, uint16_t old_num_vfs) - { - NvmeCtrl *n = NVME(dev); - NvmeSecCtrlEntry *sctrl; -- uint16_t sriov_cap = dev->exp.sriov_cap; -- uint32_t off = address - sriov_cap; -- int i, num_vfs; -+ int i; - -- if (!sriov_cap) { -- return; -- } -- -- if (range_covers_byte(off, len, PCI_SRIOV_CTRL)) { -- if (!(val & PCI_SRIOV_CTRL_VFE)) { -- num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); -- for (i = 0; i < num_vfs; i++) { -- sctrl = &n->sec_ctrl_list.sec[i]; -- nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false); -- } -- } -+ for (i = pcie_sriov_num_vfs(dev); i < old_num_vfs; i++) { -+ sctrl = &n->sec_ctrl_list.sec[i]; -+ nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false); - } - } - - static void nvme_pci_write_config(PCIDevice *dev, uint32_t address, - uint32_t val, int len) - { -- nvme_sriov_pre_write_ctrl(dev, address, val, len); -+ uint16_t old_num_vfs = pcie_sriov_num_vfs(dev); -+ - pci_default_write_config(dev, address, val, len); - pcie_cap_flr_write_config(dev, address, val, len); -+ nvme_sriov_post_write_config(dev, old_num_vfs); - } - - static const VMStateDescription nvme_vmstate = { --- -GitLab - diff --git a/SPECS/qemu/CVE-2024-3447.patch b/SPECS/qemu/CVE-2024-3447.patch deleted file mode 100644 index cb14edbe15..0000000000 --- a/SPECS/qemu/CVE-2024-3447.patch +++ /dev/null @@ -1,140 +0,0 @@ -From b84c0a4b6103796312e7dd8c7288eaad1fb87aa7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Tue, 9 Apr 2024 16:19:27 +0200 -Subject: [PATCH 1/6] hw/sd/sdhci: Do not update TRNMOD when Command Inhibit - (DAT) is set -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Per "SD Host Controller Standard Specification Version 3.00": - - * 2.2.5 Transfer Mode Register (Offset 00Ch) - - Writes to this register shall be ignored when the Command - Inhibit (DAT) in the Present State register is 1. - -Do not update the TRNMOD register when Command Inhibit (DAT) -bit is set to avoid the present-status register going out of -sync, leading to malicious guest using DMA mode and overflowing -the FIFO buffer: - - $ cat << EOF | qemu-system-i386 \ - -display none -nographic -nodefaults \ - -machine accel=qtest -m 512M \ - -device sdhci-pci,sd-spec-version=3 \ - -device sd-card,drive=mydrive \ - -drive if=none,index=0,file=null-co://,format=raw,id=mydrive \ - -qtest stdio - outl 0xcf8 0x80001013 - outl 0xcfc 0x91 - outl 0xcf8 0x80001001 - outl 0xcfc 0x06000000 - write 0x9100002c 0x1 0x05 - write 0x91000058 0x1 0x16 - write 0x91000005 0x1 0x04 - write 0x91000028 0x1 0x08 - write 0x16 0x1 0x21 - write 0x19 0x1 0x20 - write 0x9100000c 0x1 0x01 - write 0x9100000e 0x1 0x20 - write 0x9100000f 0x1 0x00 - write 0x9100000c 0x1 0x00 - write 0x91000020 0x1 0x00 - EOF - -Stack trace (part): -================================================================= -==89993==ERROR: AddressSanitizer: heap-buffer-overflow on address -0x615000029900 at pc 0x55d5f885700d bp 0x7ffc1e1e9470 sp 0x7ffc1e1e9468 -WRITE of size 1 at 0x615000029900 thread T0 - #0 0x55d5f885700c in sdhci_write_dataport hw/sd/sdhci.c:564:39 - #1 0x55d5f8849150 in sdhci_write hw/sd/sdhci.c:1223:13 - #2 0x55d5fa01db63 in memory_region_write_accessor system/memory.c:497:5 - #3 0x55d5fa01d245 in access_with_adjusted_size system/memory.c:573:18 - #4 0x55d5fa01b1a9 in memory_region_dispatch_write system/memory.c:1521:16 - #5 0x55d5fa09f5c9 in flatview_write_continue system/physmem.c:2711:23 - #6 0x55d5fa08f78b in flatview_write system/physmem.c:2753:12 - #7 0x55d5fa08f258 in address_space_write system/physmem.c:2860:18 - ... -0x615000029900 is located 0 bytes to the right of 512-byte region -[0x615000029700,0x615000029900) allocated by thread T0 here: - #0 0x55d5f7237b27 in __interceptor_calloc - #1 0x7f9e36dd4c50 in g_malloc0 - #2 0x55d5f88672f7 in sdhci_pci_realize hw/sd/sdhci-pci.c:36:5 - #3 0x55d5f844b582 in pci_qdev_realize hw/pci/pci.c:2092:9 - #4 0x55d5fa2ee74b in device_set_realized hw/core/qdev.c:510:13 - #5 0x55d5fa325bfb in property_set_bool qom/object.c:2358:5 - #6 0x55d5fa31ea45 in object_property_set qom/object.c:1472:5 - #7 0x55d5fa332509 in object_property_set_qobject om/qom-qobject.c:28:10 - #8 0x55d5fa31f6ed in object_property_set_bool qom/object.c:1541:15 - #9 0x55d5fa2e2948 in qdev_realize hw/core/qdev.c:292:12 - #10 0x55d5f8eed3f1 in qdev_device_add_from_qdict system/qdev-monitor.c:719:10 - #11 0x55d5f8eef7ff in qdev_device_add system/qdev-monitor.c:738:11 - #12 0x55d5f8f211f0 in device_init_func system/vl.c:1200:11 - #13 0x55d5fad0877d in qemu_opts_foreach util/qemu-option.c:1135:14 - #14 0x55d5f8f0df9c in qemu_create_cli_devices system/vl.c:2638:5 - #15 0x55d5f8f0db24 in qmp_x_exit_preconfig system/vl.c:2706:5 - #16 0x55d5f8f14dc0 in qemu_init system/vl.c:3737:9 - ... -SUMMARY: AddressSanitizer: heap-buffer-overflow hw/sd/sdhci.c:564:39 -in sdhci_write_dataport - -Add assertions to ensure the fifo_buffer[] is not overflowed by -malicious accesses to the Buffer Data Port register. - -Fixes: CVE-2024-3447 -Cc: qemu-stable@nongnu.org -Fixes: d7dfca0807 ("hw/sdhci: introduce standard SD host controller") -Buglink: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=58813 -Reported-by: Alexander Bulekov -Reported-by: Chuhong Yuan -Signed-off-by: Peter Maydell -Message-Id: -Signed-off-by: Philippe Mathieu-Daudé -Message-Id: <20240409145524.27913-1-philmd@linaro.org> -(cherry picked from commit 9e4b27ca6bf4974f169bbca7f3dca117b1208b6f) -Signed-off-by: Michael Tokarev - -Upstream Reference: -https://gitlab.com/qemu-project/qemu/-/commit/35a67d2aa8caf8eb0bee7d38515924c95417047e ---- - hw/sd/sdhci.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c -index 40473b0..e95ea34 100644 ---- a/hw/sd/sdhci.c -+++ b/hw/sd/sdhci.c -@@ -473,6 +473,7 @@ static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size) - } - - for (i = 0; i < size; i++) { -+ assert(s->data_count < s->buf_maxsz); - value |= s->fifo_buffer[s->data_count] << i * 8; - s->data_count++; - /* check if we've read all valid data (blksize bytes) from buffer */ -@@ -561,6 +562,7 @@ static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size) - } - - for (i = 0; i < size; i++) { -+ assert(s->data_count < s->buf_maxsz); - s->fifo_buffer[s->data_count] = value & 0xFF; - s->data_count++; - value >>= 8; -@@ -1208,6 +1210,12 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) - if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) { - value &= ~SDHC_TRNS_DMA; - } -+ -+ /* TRNMOD writes are inhibited while Command Inhibit (DAT) is true */ -+ if (s->prnsts & SDHC_DATA_INHIBIT) { -+ mask |= 0xffff; -+ } -+ - MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK); - MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16); - --- -2.45.3 - diff --git a/SPECS/qemu/CVE-2024-3567.patch b/SPECS/qemu/CVE-2024-3567.patch deleted file mode 100644 index c68bd7d037..0000000000 --- a/SPECS/qemu/CVE-2024-3567.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 941f533e8191a08f5b0964333a9a534de2733093 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Tue, 9 Apr 2024 19:54:05 +0200 -Subject: [PATCH 6/6] hw/net/net_tx_pkt: Fix overrun in update_sctp_checksum() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If a fragmented packet size is too short, do not try to -calculate its checksum. - -Reproduced using: - - $ cat << EOF | qemu-system-i386 -display none -nodefaults \ - -machine q35,accel=qtest -m 32M \ - -device igb,netdev=net0 \ - -netdev user,id=net0 \ - -qtest stdio - outl 0xcf8 0x80000810 - outl 0xcfc 0xe0000000 - outl 0xcf8 0x80000804 - outw 0xcfc 0x06 - write 0xe0000403 0x1 0x02 - writel 0xe0003808 0xffffffff - write 0xe000381a 0x1 0x5b - write 0xe000381b 0x1 0x00 - EOF - Assertion failed: (offset == 0), function iov_from_buf_full, file util/iov.c, line 39. - #1 0x5575e81e952a in iov_from_buf_full qemu/util/iov.c:39:5 - #2 0x5575e6500768 in net_tx_pkt_update_sctp_checksum qemu/hw/net/net_tx_pkt.c:144:9 - #3 0x5575e659f3e1 in igb_setup_tx_offloads qemu/hw/net/igb_core.c:478:11 - #4 0x5575e659f3e1 in igb_tx_pkt_send qemu/hw/net/igb_core.c:552:10 - #5 0x5575e659f3e1 in igb_process_tx_desc qemu/hw/net/igb_core.c:671:17 - #6 0x5575e659f3e1 in igb_start_xmit qemu/hw/net/igb_core.c:903:9 - #7 0x5575e659f3e1 in igb_set_tdt qemu/hw/net/igb_core.c:2812:5 - #8 0x5575e657d6a4 in igb_core_write qemu/hw/net/igb_core.c:4248:9 - -Fixes: CVE-2024-3567 -Cc: qemu-stable@nongnu.org -Reported-by: Zheyu Ma -Fixes: f199b13bc1 ("igb: Implement Tx SCTP CSO") -Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2273 -Signed-off-by: Philippe Mathieu-Daudé -Reviewed-by: Akihiko Odaki -Acked-by: Jason Wang -Message-Id: <20240410070459.49112-1-philmd@linaro.org> -(cherry picked from commit 83ddb3dbba2ee0f1767442ae6ee665058aeb1093) -Signed-off-by: Michael Tokarev - -Upstream reference: -https://gitlab.com/qemu-project/qemu/-/commit/1cfe45956e03070f894e91b304e233b4d5b99719 ---- - hw/net/net_tx_pkt.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c -index 2e5f58b..d40d508 100644 ---- a/hw/net/net_tx_pkt.c -+++ b/hw/net/net_tx_pkt.c -@@ -141,6 +141,10 @@ bool net_tx_pkt_update_sctp_checksum(struct NetTxPkt *pkt) - uint32_t csum = 0; - struct iovec *pl_start_frag = pkt->vec + NET_TX_PKT_PL_START_FRAG; - -+ if (iov_size(pl_start_frag, pkt->payload_frags) < 8 + sizeof(csum)) { -+ return false; -+ } -+ - if (iov_from_buf(pl_start_frag, pkt->payload_frags, 8, &csum, sizeof(csum)) < sizeof(csum)) { - return false; - } --- -2.45.3 - diff --git a/SPECS/qemu/CVE-2024-4467.patch b/SPECS/qemu/CVE-2024-4467.patch deleted file mode 100644 index f39dd6cc73..0000000000 --- a/SPECS/qemu/CVE-2024-4467.patch +++ /dev/null @@ -1,111 +0,0 @@ -From cd7055d9d5ade0e9ccf468da8742f7f1ace0fb88 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Thu, 11 Apr 2024 15:06:01 +0200 -Subject: [PATCH 2/6] qcow2: Don't open data_file with BDRV_O_NO_IO - -One use case for 'qemu-img info' is verifying that untrusted images -don't reference an unwanted external file, be it as a backing file or an -external data file. To make sure that calling 'qemu-img info' can't -already have undesired side effects with a malicious image, just don't -open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do -I/O, we don't need to have it open. - -This changes the output of iotests case 061, which used 'qemu-img info' -to show that opening an image with an invalid data file fails. After -this patch, it succeeds. Replace this part of the test with a qemu-io -call, but keep the final 'qemu-img info' to show that the invalid data -file is correctly displayed in the output. - -Fixes: CVE-2024-4467 -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Hanna Czenczek - -Upstream reference: -https://gitlab.com/qemu-project/qemu/-/commit/bd385a5298d7062668e804d73944d52aec9549f1 ---- - block/qcow2.c | 17 ++++++++++++++++- - tests/qemu-iotests/061 | 6 ++++-- - tests/qemu-iotests/061.out | 8 ++++++-- - 3 files changed, 26 insertions(+), 5 deletions(-) - -diff --git a/block/qcow2.c b/block/qcow2.c -index 13e032b..7af7c0b 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -1636,7 +1636,22 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, - goto fail; - } - -- if (open_data_file) { -+ if (open_data_file && (flags & BDRV_O_NO_IO)) { -+ /* -+ * Don't open the data file for 'qemu-img info' so that it can be used -+ * to verify that an untrusted qcow2 image doesn't refer to external -+ * files. -+ * -+ * Note: This still makes has_data_file() return true. -+ */ -+ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { -+ s->data_file = NULL; -+ } else { -+ s->data_file = bs->file; -+ } -+ qdict_extract_subqdict(options, NULL, "data-file."); -+ qdict_del(options, "data-file"); -+ } else if (open_data_file) { - /* Open external data file */ - bdrv_graph_co_rdunlock(); - s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs, -diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 -index 53c7d42..b71ac09 100755 ---- a/tests/qemu-iotests/061 -+++ b/tests/qemu-iotests/061 -@@ -326,12 +326,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" - echo - _make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M - $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" --_img_info --format-specific -+$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt -+$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io - TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts - - echo - $QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" --_img_info --format-specific -+$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt -+$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io - TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts - - echo -diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out -index 139fc68..24c33ad 100644 ---- a/tests/qemu-iotests/061.out -+++ b/tests/qemu-iotests/061.out -@@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 - qemu-img: data-file can only be set for images that use an external data file - - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data --qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory -+qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory -+read 4096/4096 bytes at offset 0 -+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) - image: TEST_DIR/t.IMGFMT - file format: IMGFMT - virtual size: 64 MiB (67108864 bytes) -@@ -560,7 +562,9 @@ Format specific information: - corrupt: false - extended l2: false - --qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image -+qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image -+read 4096/4096 bytes at offset 0 -+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) - image: TEST_DIR/t.IMGFMT - file format: IMGFMT - virtual size: 64 MiB (67108864 bytes) --- -2.45.3 - diff --git a/SPECS/qemu/CVE-2024-4693.patch b/SPECS/qemu/CVE-2024-4693.patch deleted file mode 100644 index 6f711d638c..0000000000 --- a/SPECS/qemu/CVE-2024-4693.patch +++ /dev/null @@ -1,249 +0,0 @@ -From e8bea549850dc9d9583ebb01c91bc2ba456318ac Mon Sep 17 00:00:00 2001 -From: Cindy Lu -Date: Fri, 12 Apr 2024 14:26:55 +0800 -Subject: [PATCH 1/2] virtio-pci: fix use of a released vector -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -During the booting process of the non-standard image, the behavior of the -called function in qemu is as follows: - -1. vhost_net_stop() was triggered by guest image. This will call the function -virtio_pci_set_guest_notifiers() with assgin= false, -virtio_pci_set_guest_notifiers() will release the irqfd for vector 0 - -2. virtio_reset() was triggered, this will set configure vector to VIRTIO_NO_VECTOR - -3.vhost_net_start() was called (at this time, the configure vector is -still VIRTIO_NO_VECTOR) and then call virtio_pci_set_guest_notifiers() with -assgin=true, so the irqfd for vector 0 is still not "init" during this process - -4. The system continues to boot and sets the vector back to 0. After that -msix_fire_vector_notifier() was triggered to unmask the vector 0 and meet the crash - -To fix the issue, we need to support changing the vector after VIRTIO_CONFIG_S_DRIVER_OK is set. - -(gdb) bt -0 __pthread_kill_implementation (threadid=, signo=signo@entry=6, no_tid=no_tid@entry=0) - at pthread_kill.c:44 -1 0x00007fc87148ec53 in __pthread_kill_internal (signo=6, threadid=) at pthread_kill.c:78 -2 0x00007fc87143e956 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 -3 0x00007fc8714287f4 in __GI_abort () at abort.c:79 -4 0x00007fc87142871b in __assert_fail_base - (fmt=0x7fc8715bbde0 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5606413efd53 "ret == 0", file=0x5606413ef87d "../accel/kvm/kvm-all.c", line=1837, function=) at assert.c:92 -5 0x00007fc871437536 in __GI___assert_fail - (assertion=0x5606413efd53 "ret == 0", file=0x5606413ef87d "../accel/kvm/kvm-all.c", line=1837, function=0x5606413f06f0 <__PRETTY_FUNCTION__.19> "kvm_irqchip_commit_routes") at assert.c:101 -6 0x0000560640f884b5 in kvm_irqchip_commit_routes (s=0x560642cae1f0) at ../accel/kvm/kvm-all.c:1837 -7 0x0000560640c98f8e in virtio_pci_one_vector_unmask - (proxy=0x560643c65f00, queue_no=4294967295, vector=0, msg=..., n=0x560643c6e4c8) - at ../hw/virtio/virtio-pci.c:1005 -8 0x0000560640c99201 in virtio_pci_vector_unmask (dev=0x560643c65f00, vector=0, msg=...) - at ../hw/virtio/virtio-pci.c:1070 -9 0x0000560640bc402e in msix_fire_vector_notifier (dev=0x560643c65f00, vector=0, is_masked=false) - at ../hw/pci/msix.c:120 -10 0x0000560640bc40f1 in msix_handle_mask_update (dev=0x560643c65f00, vector=0, was_masked=true) - at ../hw/pci/msix.c:140 -11 0x0000560640bc4503 in msix_table_mmio_write (opaque=0x560643c65f00, addr=12, val=0, size=4) - at ../hw/pci/msix.c:231 -12 0x0000560640f26d83 in memory_region_write_accessor - (mr=0x560643c66540, addr=12, value=0x7fc86b7bc628, size=4, shift=0, mask=4294967295, attrs=...) - at ../system/memory.c:497 -13 0x0000560640f270a6 in access_with_adjusted_size - - (addr=12, value=0x7fc86b7bc628, size=4, access_size_min=1, access_size_max=4, access_fn=0x560640f26c8d , mr=0x560643c66540, attrs=...) at ../system/memory.c:573 -14 0x0000560640f2a2b5 in memory_region_dispatch_write (mr=0x560643c66540, addr=12, data=0, op=MO_32, attrs=...) - at ../system/memory.c:1521 -15 0x0000560640f37bac in flatview_write_continue - (fv=0x7fc65805e0b0, addr=4273803276, attrs=..., ptr=0x7fc871e9c028, len=4, addr1=12, l=4, mr=0x560643c66540) - at ../system/physmem.c:2714 -16 0x0000560640f37d0f in flatview_write - (fv=0x7fc65805e0b0, addr=4273803276, attrs=..., buf=0x7fc871e9c028, len=4) at ../system/physmem.c:2756 -17 0x0000560640f380bf in address_space_write - (as=0x560642161ae0 , addr=4273803276, attrs=..., buf=0x7fc871e9c028, len=4) - at ../system/physmem.c:2863 -18 0x0000560640f3812c in address_space_rw - (as=0x560642161ae0 , addr=4273803276, attrs=..., buf=0x7fc871e9c028, len=4, is_write=true) at ../system/physmem.c:2873 ---Type for more, q to quit, c to continue without paging-- -19 0x0000560640f8aa55 in kvm_cpu_exec (cpu=0x560642f205e0) at ../accel/kvm/kvm-all.c:2915 -20 0x0000560640f8d731 in kvm_vcpu_thread_fn (arg=0x560642f205e0) at ../accel/kvm/kvm-accel-ops.c:51 -21 0x00005606411949f4 in qemu_thread_start (args=0x560642f292b0) at ../util/qemu-thread-posix.c:541 -22 0x00007fc87148cdcd in start_thread (arg=) at pthread_create.c:442 -23 0x00007fc871512630 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81 -(gdb) - -MST: coding style and typo fixups - -Fixes: f9a09ca3ea ("vhost: add support for configure interrupt") -Cc: qemu-stable@nongnu.org -Signed-off-by: Cindy Lu -Message-ID: <2321ade5f601367efe7380c04e3f61379c59b48f.1713173550.git.mst@redhat.com> -Cc: Lei Yang -Cc: Jason Wang -Signed-off-by: Michael S. Tsirkin -Tested-by: Cindy Lu -(cherry picked from commit 2ce6cff94df2650c460f809e5ad263f1d22507c0) -Signed-off-by: Michael Tokarev - -Upstream reference: -https://gitlab.com/qemu-project/qemu/-/commit/fcbb086ae590e910614fe5b8bf76e264f71ef304 ---- - hw/virtio/virtio-pci.c | 37 +++++++++++++++++++++++++++++++++++-- - 1 file changed, 35 insertions(+), 2 deletions(-) - -diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c -index e433879..08faefe 100644 ---- a/hw/virtio/virtio-pci.c -+++ b/hw/virtio/virtio-pci.c -@@ -1424,6 +1424,38 @@ static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, - return offset; - } - -+static void virtio_pci_set_vector(VirtIODevice *vdev, -+ VirtIOPCIProxy *proxy, -+ int queue_no, uint16_t old_vector, -+ uint16_t new_vector) -+{ -+ bool kvm_irqfd = (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) && -+ msix_enabled(&proxy->pci_dev) && kvm_msi_via_irqfd_enabled(); -+ -+ if (new_vector == old_vector) { -+ return; -+ } -+ -+ /* -+ * If the device uses irqfd and the vector changes after DRIVER_OK is -+ * set, we need to release the old vector and set up the new one. -+ * Otherwise just need to set the new vector on the device. -+ */ -+ if (kvm_irqfd && old_vector != VIRTIO_NO_VECTOR) { -+ kvm_virtio_pci_vector_release_one(proxy, queue_no); -+ } -+ /* Set the new vector on the device. */ -+ if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { -+ vdev->config_vector = new_vector; -+ } else { -+ virtio_queue_set_vector(vdev, queue_no, new_vector); -+ } -+ /* If the new vector changed need to set it up. */ -+ if (kvm_irqfd && new_vector != VIRTIO_NO_VECTOR) { -+ kvm_virtio_pci_vector_use_one(proxy, queue_no); -+ } -+} -+ - int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy, - uint8_t bar, uint64_t offset, uint64_t length, - uint8_t id) -@@ -1570,7 +1602,8 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr, - } else { - val = VIRTIO_NO_VECTOR; - } -- vdev->config_vector = val; -+ virtio_pci_set_vector(vdev, proxy, VIRTIO_CONFIG_IRQ_IDX, -+ vdev->config_vector, val); - break; - case VIRTIO_PCI_COMMON_STATUS: - if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) { -@@ -1610,7 +1643,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr, - } else { - val = VIRTIO_NO_VECTOR; - } -- virtio_queue_set_vector(vdev, vdev->queue_sel, val); -+ virtio_pci_set_vector(vdev, proxy, vdev->queue_sel, vector, val); - break; - case VIRTIO_PCI_COMMON_Q_ENABLE: - if (val == 1) { --- -2.45.3 - - -From 352e1d101fa3cfb161ee951af754bff791ff2241 Mon Sep 17 00:00:00 2001 -From: Cindy Lu -Date: Wed, 22 May 2024 13:10:24 +0800 -Subject: [PATCH 2/2] virtio-pci: Fix the use of an uninitialized irqfd. - -The crash was reported in MAC OS and NixOS, here is the link for this bug -https://gitlab.com/qemu-project/qemu/-/issues/2334 -https://gitlab.com/qemu-project/qemu/-/issues/2321 - -The root cause is that the function virtio_pci_set_guest_notifiers() only -initializes the irqfd when the use_guest_notifier_mask and guest_notifier_mask -are set. -However, this check is missing in virtio_pci_set_vector(). -So the fix is to add this check. - -This fix is verified in vyatta,MacOS,NixOS,fedora system. - -The bt tree for this bug is: -Thread 6 "CPU 0/KVM" received signal SIGSEGV, Segmentation fault. -[Switching to Thread 0x7c817be006c0 (LWP 1269146)] -kvm_virtio_pci_vq_vector_use () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:817 -817 if (irqfd->users == 0) { -(gdb) thread apply all bt -... -Thread 6 (Thread 0x7c817be006c0 (LWP 1269146) "CPU 0/KVM"): -0 kvm_virtio_pci_vq_vector_use () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:817 -1 kvm_virtio_pci_vector_use_one () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:893 -2 0x00005983657045e2 in memory_region_write_accessor () at ../qemu-9.0.0/system/memory.c:497 -3 0x0000598365704ba6 in access_with_adjusted_size () at ../qemu-9.0.0/system/memory.c:573 -4 0x0000598365705059 in memory_region_dispatch_write () at ../qemu-9.0.0/system/memory.c:1528 -5 0x00005983659b8e1f in flatview_write_continue_step.isra.0 () at ../qemu-9.0.0/system/physmem.c:2713 -6 0x000059836570ba7d in flatview_write_continue () at ../qemu-9.0.0/system/physmem.c:2743 -7 flatview_write () at ../qemu-9.0.0/system/physmem.c:2774 -8 0x000059836570bb76 in address_space_write () at ../qemu-9.0.0/system/physmem.c:2894 -9 0x0000598365763afe in address_space_rw () at ../qemu-9.0.0/system/physmem.c:2904 -10 kvm_cpu_exec () at ../qemu-9.0.0/accel/kvm/kvm-all.c:2917 -11 0x000059836576656e in kvm_vcpu_thread_fn () at ../qemu-9.0.0/accel/kvm/kvm-accel-ops.c:50 -12 0x0000598365926ca8 in qemu_thread_start () at ../qemu-9.0.0/util/qemu-thread-posix.c:541 -13 0x00007c8185bcd1cf in ??? () at /usr/lib/libc.so.6 -14 0x00007c8185c4e504 in clone () at /usr/lib/libc.so.6 - -Fixes: 2ce6cff94d ("virtio-pci: fix use of a released vector") -Cc: qemu-stable@nongnu.org -Signed-off-by: Cindy Lu -Message-Id: <20240522051042.985825-1-lulu@redhat.com> -Acked-by: Jason Wang -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin - -Upstream reference: -https://gitlab.com/qemu-project/qemu/-/commit/7eeb62b0ce3a8f64647bf53f93903abd1fbb0b94 ---- - hw/virtio/virtio-pci.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c -index 08faefe..c10913c 100644 ---- a/hw/virtio/virtio-pci.c -+++ b/hw/virtio/virtio-pci.c -@@ -1431,6 +1431,7 @@ static void virtio_pci_set_vector(VirtIODevice *vdev, - { - bool kvm_irqfd = (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) && - msix_enabled(&proxy->pci_dev) && kvm_msi_via_irqfd_enabled(); -+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - - if (new_vector == old_vector) { - return; -@@ -1441,7 +1442,8 @@ static void virtio_pci_set_vector(VirtIODevice *vdev, - * set, we need to release the old vector and set up the new one. - * Otherwise just need to set the new vector on the device. - */ -- if (kvm_irqfd && old_vector != VIRTIO_NO_VECTOR) { -+ if (kvm_irqfd && old_vector != VIRTIO_NO_VECTOR && -+ vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - kvm_virtio_pci_vector_release_one(proxy, queue_no); - } - /* Set the new vector on the device. */ -@@ -1451,7 +1453,8 @@ static void virtio_pci_set_vector(VirtIODevice *vdev, - virtio_queue_set_vector(vdev, queue_no, new_vector); - } - /* If the new vector changed need to set it up. */ -- if (kvm_irqfd && new_vector != VIRTIO_NO_VECTOR) { -+ if (kvm_irqfd && new_vector != VIRTIO_NO_VECTOR && -+ vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - kvm_virtio_pci_vector_use_one(proxy, queue_no); - } - } --- -2.45.3 - diff --git a/SPECS/qemu/CVE-2024-6505.patch b/SPECS/qemu/CVE-2024-6505.patch deleted file mode 100644 index 1944375d94..0000000000 --- a/SPECS/qemu/CVE-2024-6505.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 7f8df6696a32c8a4aeafd1940b6cabc6c9edbe6b Mon Sep 17 00:00:00 2001 -From: Akihiko Odaki -Date: Mon, 1 Jul 2024 20:58:04 +0900 -Subject: [PATCH 3/6] virtio-net: Ensure queue index fits with RSS - -Ensure the queue index points to a valid queue when software RSS -enabled. The new calculation matches with the behavior of Linux's TAP -device with the RSS eBPF program. - -Fixes: 4474e37a5b3a ("virtio-net: implement RX RSS processing") -Reported-by: Zhibin Hu -Cc: qemu-stable@nongnu.org -Signed-off-by: Akihiko Odaki -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Jason Wang - -Upstream reference: -https://gitlab.com/qemu-project/qemu/-/commit/f1595ceb ---- - hw/net/virtio-net.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c -index 73024ba..08b69e8 100644 ---- a/hw/net/virtio-net.c -+++ b/hw/net/virtio-net.c -@@ -1909,7 +1909,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, - if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) { - int index = virtio_net_process_rss(nc, buf, size); - if (index >= 0) { -- NetClientState *nc2 = qemu_get_subqueue(n->nic, index); -+ NetClientState *nc2 = -+ qemu_get_subqueue(n->nic, index % n->curr_queue_pairs); - return virtio_net_receive_rcu(nc2, buf, size, true); - } - } --- -2.45.3 - diff --git a/SPECS/qemu/CVE-2024-7409.patch b/SPECS/qemu/CVE-2024-7409.patch deleted file mode 100644 index 3ad31cdc32..0000000000 --- a/SPECS/qemu/CVE-2024-7409.patch +++ /dev/null @@ -1,731 +0,0 @@ -From 896f944edb1bf6548183268d0711477fd67b4f02 Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Wed, 7 Aug 2024 08:50:01 -0500 -Subject: [PATCH 1/5] nbd/server: Plumb in new args to nbd_client_add() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Upcoming patches to fix a CVE need to track an opaque pointer passed -in by the owner of a client object, as well as request for a time -limit on how fast negotiation must complete. Prepare for that by -changing the signature of nbd_client_new() and adding an accessor to -get at the opaque pointer, although for now the two servers -(qemu-nbd.c and blockdev-nbd.c) do not change behavior even though -they pass in a new default timeout value. - -Suggested-by: Vladimir Sementsov-Ogievskiy -Signed-off-by: Eric Blake -Message-ID: <20240807174943.771624-11-eblake@redhat.com> -Reviewed-by: Daniel P. Berrangé -[eblake: s/LIMIT/MAX_SECS/ as suggested by Dan] -Signed-off-by: Eric Blake -(cherry picked from commit fb1c2aaa981e0a2fa6362c9985f1296b74f055ac) -Signed-off-by: Michael Tokarev -Signed-off-by: Kshitiz Godara -Upstream-reference: https://gitlab.com/qemu-project/qemu/-/commit/96ed1baeebb329426972e5a32239e0f88bd87f73 ---- - blockdev-nbd.c | 6 ++++-- - include/block/nbd.h | 11 ++++++++++- - nbd/server.c | 20 +++++++++++++++++--- - qemu-nbd.c | 4 +++- - 4 files changed, 34 insertions(+), 7 deletions(-) - -diff --git a/blockdev-nbd.c b/blockdev-nbd.c -index 2130124..267a1de 100644 ---- a/blockdev-nbd.c -+++ b/blockdev-nbd.c -@@ -64,8 +64,10 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, - nbd_update_server_watch(nbd_server); - - qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); -- nbd_client_new(cioc, nbd_server->tlscreds, nbd_server->tlsauthz, -- nbd_blockdev_client_closed); -+ /* TODO - expose handshake timeout as QMP option */ -+ nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, -+ nbd_server->tlscreds, nbd_server->tlsauthz, -+ nbd_blockdev_client_closed, NULL); - } - - static void nbd_update_server_watch(NBDServerData *s) -diff --git a/include/block/nbd.h b/include/block/nbd.h -index 4e7bd63..1d4d659 100644 ---- a/include/block/nbd.h -+++ b/include/block/nbd.h -@@ -33,6 +33,12 @@ typedef struct NBDMetaContexts NBDMetaContexts; - - extern const BlockExportDriver blk_exp_nbd; - -+/* -+ * NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must -+ * succeed at NBD_OPT_GO before being forcefully dropped as too slow. -+ */ -+#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10 -+ - /* Handshake phase structs - this struct is passed on the wire */ - - typedef struct NBDOption { -@@ -403,9 +409,12 @@ AioContext *nbd_export_aio_context(NBDExport *exp); - NBDExport *nbd_export_find(const char *name); - - void nbd_client_new(QIOChannelSocket *sioc, -+ uint32_t handshake_max_secs, - QCryptoTLSCreds *tlscreds, - const char *tlsauthz, -- void (*close_fn)(NBDClient *, bool)); -+ void (*close_fn)(NBDClient *, bool), -+ void *owner); -+void *nbd_client_owner(NBDClient *client); - void nbd_client_get(NBDClient *client); - void nbd_client_put(NBDClient *client); - -diff --git a/nbd/server.c b/nbd/server.c -index 895cf0a..b99a080 100644 ---- a/nbd/server.c -+++ b/nbd/server.c -@@ -124,10 +124,12 @@ struct NBDMetaContexts { - struct NBDClient { - int refcount; - void (*close_fn)(NBDClient *client, bool negotiated); -+ void *owner; - - NBDExport *exp; - QCryptoTLSCreds *tlscreds; - char *tlsauthz; -+ uint32_t handshake_max_secs; - QIOChannelSocket *sioc; /* The underlying data channel */ - QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */ - -@@ -3045,6 +3047,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque) - - qemu_co_mutex_init(&client->send_lock); - -+ /* TODO - utilize client->handshake_max_secs */ - if (nbd_negotiate(client, &local_err)) { - if (local_err) { - error_report_err(local_err); -@@ -3057,14 +3060,17 @@ static coroutine_fn void nbd_co_client_start(void *opaque) - } - - /* -- * Create a new client listener using the given channel @sioc. -+ * Create a new client listener using the given channel @sioc and @owner. - * Begin servicing it in a coroutine. When the connection closes, call -- * @close_fn with an indication of whether the client completed negotiation. -+ * @close_fn with an indication of whether the client completed negotiation -+ * within @handshake_max_secs seconds (0 for unbounded). - */ - void nbd_client_new(QIOChannelSocket *sioc, -+ uint32_t handshake_max_secs, - QCryptoTLSCreds *tlscreds, - const char *tlsauthz, -- void (*close_fn)(NBDClient *, bool)) -+ void (*close_fn)(NBDClient *, bool), -+ void *owner) - { - NBDClient *client; - Coroutine *co; -@@ -3076,13 +3082,21 @@ void nbd_client_new(QIOChannelSocket *sioc, - object_ref(OBJECT(client->tlscreds)); - } - client->tlsauthz = g_strdup(tlsauthz); -+ client->handshake_max_secs = handshake_max_secs; - client->sioc = sioc; - qio_channel_set_delay(QIO_CHANNEL(sioc), false); - object_ref(OBJECT(client->sioc)); - client->ioc = QIO_CHANNEL(sioc); - object_ref(OBJECT(client->ioc)); - client->close_fn = close_fn; -+ client->owner = owner; - - co = qemu_coroutine_create(nbd_co_client_start, client); - qemu_coroutine_enter(co); - } -+ -+void * -+nbd_client_owner(NBDClient *client) -+{ -+ return client->owner; -+} -diff --git a/qemu-nbd.c b/qemu-nbd.c -index 186e646..5fa399c 100644 ---- a/qemu-nbd.c -+++ b/qemu-nbd.c -@@ -389,7 +389,9 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, - - nb_fds++; - nbd_update_server_watch(); -- nbd_client_new(cioc, tlscreds, tlsauthz, nbd_client_closed); -+ /* TODO - expose handshake timeout as command line option */ -+ nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, -+ tlscreds, tlsauthz, nbd_client_closed, NULL); - } - - static void nbd_update_server_watch(void) --- -2.45.4 - - -From 5b6c93134e69cedd84f7dbc60568caa3ee8227c5 Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Wed, 7 Aug 2024 12:23:13 -0500 -Subject: [PATCH 2/5] nbd/server: CVE-2024-7409: Close stray clients at - server-stop -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -A malicious client can attempt to connect to an NBD server, and then -intentionally delay progress in the handshake, including if it does -not know the TLS secrets. Although the previous two patches reduce -this behavior by capping the default max-connections parameter and -killing slow clients, they did not eliminate the possibility of a -client waiting to close the socket until after the QMP nbd-server-stop -command is executed, at which point qemu would SEGV when trying to -dereference the NULL nbd_server global which is no longer present. -This amounts to a denial of service attack. Worse, if another NBD -server is started before the malicious client disconnects, I cannot -rule out additional adverse effects when the old client interferes -with the connection count of the new server (although the most likely -is a crash due to an assertion failure when checking -nbd_server->connections > 0). - -For environments without this patch, the CVE can be mitigated by -ensuring (such as via a firewall) that only trusted clients can -connect to an NBD server. Note that using frameworks like libvirt -that ensure that TLS is used and that nbd-server-stop is not executed -while any trusted clients are still connected will only help if there -is also no possibility for an untrusted client to open a connection -but then stall on the NBD handshake. - -Given the previous patches, it would be possible to guarantee that no -clients remain connected by having nbd-server-stop sleep for longer -than the default handshake deadline before finally freeing the global -nbd_server object, but that could make QMP non-responsive for a long -time. So intead, this patch fixes the problem by tracking all client -sockets opened while the server is running, and forcefully closing any -such sockets remaining without a completed handshake at the time of -nbd-server-stop, then waiting until the coroutines servicing those -sockets notice the state change. nbd-server-stop now has a second -AIO_WAIT_WHILE_UNLOCKED (the first is indirectly through the -blk_exp_close_all_type() that disconnects all clients that completed -handshakes), but forced socket shutdown is enough to progress the -coroutines and quickly tear down all clients before the server is -freed, thus finally fixing the CVE. - -This patch relies heavily on the fact that nbd/server.c guarantees -that it only calls nbd_blockdev_client_closed() from the main loop -(see the assertion in nbd_client_put() and the hoops used in -nbd_client_put_nonzero() to achieve that); if we did not have that -guarantee, we would also need a mutex protecting our accesses of the -list of connections to survive re-entrancy from independent iothreads. - -Although I did not actually try to test old builds, it looks like this -problem has existed since at least commit 862172f45c (v2.12.0, 2017) - -even back when that patch started using a QIONetListener to handle -listening on multiple sockets, nbd_server_free() was already unaware -that the nbd_blockdev_client_closed callback can be reached later by a -client thread that has not completed handshakes (and therefore the -client's socket never got added to the list closed in -nbd_export_close_all), despite that patch intentionally tearing down -the QIONetListener to prevent new clients. - -Reported-by: Alexander Ivanov -Fixes: CVE-2024-7409 -CC: qemu-stable@nongnu.org -Signed-off-by: Eric Blake -Message-ID: <20240807174943.771624-14-eblake@redhat.com> -Reviewed-by: Daniel P. Berrangé -Signed-off-by: Kshitiz Godara -Upstream-reference: https://gitlab.com/qemu-project/qemu/-/commit/3e7ef738c8462c45043a1d39f702a0990406a3b3 ---- - blockdev-nbd.c | 35 ++++++++++++++++++++++++++++++++++- - 1 file changed, 34 insertions(+), 1 deletion(-) - -diff --git a/blockdev-nbd.c b/blockdev-nbd.c -index 267a1de..9cbdacc 100644 ---- a/blockdev-nbd.c -+++ b/blockdev-nbd.c -@@ -21,12 +21,18 @@ - #include "io/channel-socket.h" - #include "io/net-listener.h" - -+typedef struct NBDConn { -+ QIOChannelSocket *cioc; -+ QLIST_ENTRY(NBDConn) next; -+} NBDConn; -+ - typedef struct NBDServerData { - QIONetListener *listener; - QCryptoTLSCreds *tlscreds; - char *tlsauthz; - uint32_t max_connections; - uint32_t connections; -+ QLIST_HEAD(, NBDConn) conns; - } NBDServerData; - - static NBDServerData *nbd_server; -@@ -51,6 +57,14 @@ int nbd_server_max_connections(void) - - static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) - { -+ NBDConn *conn = nbd_client_owner(client); -+ -+ assert(qemu_in_main_thread() && nbd_server); -+ -+ object_unref(OBJECT(conn->cioc)); -+ QLIST_REMOVE(conn, next); -+ g_free(conn); -+ - nbd_client_put(client); - assert(nbd_server->connections > 0); - nbd_server->connections--; -@@ -60,14 +74,20 @@ static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) - static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, - gpointer opaque) - { -+ NBDConn *conn = g_new0(NBDConn, 1); -+ -+ assert(qemu_in_main_thread() && nbd_server); - nbd_server->connections++; -+ object_ref(OBJECT(cioc)); -+ conn->cioc = cioc; -+ QLIST_INSERT_HEAD(&nbd_server->conns, conn, next); - nbd_update_server_watch(nbd_server); - - qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); - /* TODO - expose handshake timeout as QMP option */ - nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, - nbd_server->tlscreds, nbd_server->tlsauthz, -- nbd_blockdev_client_closed, NULL); -+ nbd_blockdev_client_closed, conn); - } - - static void nbd_update_server_watch(NBDServerData *s) -@@ -81,12 +101,25 @@ static void nbd_update_server_watch(NBDServerData *s) - - static void nbd_server_free(NBDServerData *server) - { -+ NBDConn *conn, *tmp; -+ - if (!server) { - return; - } - -+ /* -+ * Forcefully close the listener socket, and any clients that have -+ * not yet disconnected on their own. -+ */ - qio_net_listener_disconnect(server->listener); - object_unref(OBJECT(server->listener)); -+ QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) { -+ qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH, -+ NULL); -+ } -+ -+ AIO_WAIT_WHILE_UNLOCKED(NULL, server->connections > 0); -+ - if (server->tlscreds) { - object_unref(OBJECT(server->tlscreds)); - } --- -2.45.4 - - -From 5ce6ede06b9378bc4877f26866d7028632e60004 Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Tue, 6 Aug 2024 13:53:00 -0500 -Subject: [PATCH 3/5] nbd/server: CVE-2024-7409: Cap default max-connections to - 100 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Allowing an unlimited number of clients to any web service is a recipe -for a rudimentary denial of service attack: the client merely needs to -open lots of sockets without closing them, until qemu no longer has -any more fds available to allocate. - -For qemu-nbd, we default to allowing only 1 connection unless more are -explicitly asked for (-e or --shared); this was historically picked as -a nice default (without an explicit -t, a non-persistent qemu-nbd goes -away after a client disconnects, without needing any additional -follow-up commands), and we are not going to change that interface now -(besides, someday we want to point people towards qemu-storage-daemon -instead of qemu-nbd). - -But for qemu proper, and the newer qemu-storage-daemon, the QMP -nbd-server-start command has historically had a default of unlimited -number of connections, in part because unlike qemu-nbd it is -inherently persistent until nbd-server-stop. Allowing multiple client -sockets is particularly useful for clients that can take advantage of -MULTI_CONN (creating parallel sockets to increase throughput), -although known clients that do so (such as libnbd's nbdcopy) typically -use only 8 or 16 connections (the benefits of scaling diminish once -more sockets are competing for kernel attention). Picking a number -large enough for typical use cases, but not unlimited, makes it -slightly harder for a malicious client to perform a denial of service -merely by opening lots of connections withot progressing through the -handshake. - -This change does not eliminate CVE-2024-7409 on its own, but reduces -the chance for fd exhaustion or unlimited memory usage as an attack -surface. On the other hand, by itself, it makes it more obvious that -with a finite limit, we have the problem of an unauthenticated client -holding 100 fds opened as a way to block out a legitimate client from -being able to connect; thus, later patches will further add timeouts -to reject clients that are not making progress. - -This is an INTENTIONAL change in behavior, and will break any client -of nbd-server-start that was not passing an explicit max-connections -parameter, yet expects more than 100 simultaneous connections. We are -not aware of any such client (as stated above, most clients aware of -MULTI_CONN get by just fine on 8 or 16 connections, and probably cope -with later connections failing by relying on the earlier connections; -libvirt has not yet been passing max-connections, but generally -creates NBD servers with the intent for a single client for the sake -of live storage migration; meanwhile, the KubeSAN project anticipates -a large cluster sharing multiple clients [up to 8 per node, and up to -100 nodes in a cluster], but it currently uses qemu-nbd with an -explicit --shared=0 rather than qemu-storage-daemon with -nbd-server-start). - -We considered using a deprecation period (declare that omitting -max-parameters is deprecated, and make it mandatory in 3 releases - -then we don't need to pick an arbitrary default); that has zero risk -of breaking any apps that accidentally depended on more than 100 -connections, and where such breakage might not be noticed under unit -testing but only under the larger loads of production usage. But it -does not close the denial-of-service hole until far into the future, -and requires all apps to change to add the parameter even if 100 was -good enough. It also has a drawback that any app (like libvirt) that -is accidentally relying on an unlimited default should seriously -consider their own CVE now, at which point they are going to change to -pass explicit max-connections sooner than waiting for 3 qemu releases. -Finally, if our changed default breaks an app, that app can always -pass in an explicit max-parameters with a larger value. - -It is also intentional that the HMP interface to nbd-server-start is -not changed to expose max-connections (any client needing to fine-tune -things should be using QMP). - -Suggested-by: Daniel P. Berrangé -Signed-off-by: Eric Blake -Message-ID: <20240807174943.771624-12-eblake@redhat.com> -Reviewed-by: Daniel P. Berrangé -[ericb: Expand commit message to summarize Dan's argument for why we -break corner-case back-compat behavior without a deprecation period] -Signed-off-by: Eric Blake -Signed-off-by: Kshitiz Godara -Upstream-reference: https://gitlab.com/qemu-project/qemu/-/commit/c8a76dbd90c2f48df89b75bef74917f90a59b623 ---- - block/monitor/block-hmp-cmds.c | 3 ++- - blockdev-nbd.c | 8 ++++++++ - include/block/nbd.h | 7 +++++++ - qapi/block-export.json | 4 ++-- - 4 files changed, 19 insertions(+), 3 deletions(-) - -diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c -index c729cbf..78a6975 100644 ---- a/block/monitor/block-hmp-cmds.c -+++ b/block/monitor/block-hmp-cmds.c -@@ -415,7 +415,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) - goto exit; - } - -- nbd_server_start(addr, NULL, NULL, 0, &local_err); -+ nbd_server_start(addr, NULL, NULL, NBD_DEFAULT_MAX_CONNECTIONS, -+ &local_err); - qapi_free_SocketAddress(addr); - if (local_err != NULL) { - goto exit; -diff --git a/blockdev-nbd.c b/blockdev-nbd.c -index 9cbdacc..f73409a 100644 ---- a/blockdev-nbd.c -+++ b/blockdev-nbd.c -@@ -203,6 +203,10 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds, - - void nbd_server_start_options(NbdServerOptions *arg, Error **errp) - { -+ if (!arg->has_max_connections) { -+ arg->max_connections = NBD_DEFAULT_MAX_CONNECTIONS; -+ } -+ - nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, - arg->max_connections, errp); - } -@@ -215,6 +219,10 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr, - { - SocketAddress *addr_flat = socket_address_flatten(addr); - -+ if (!has_max_connections) { -+ max_connections = NBD_DEFAULT_MAX_CONNECTIONS; -+ } -+ - nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections, errp); - qapi_free_SocketAddress(addr_flat); - } -diff --git a/include/block/nbd.h b/include/block/nbd.h -index 1d4d659..d4f8b21 100644 ---- a/include/block/nbd.h -+++ b/include/block/nbd.h -@@ -39,6 +39,13 @@ extern const BlockExportDriver blk_exp_nbd; - */ - #define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10 - -+/* -+ * NBD_DEFAULT_MAX_CONNECTIONS: Number of client sockets to allow at -+ * once; must be large enough to allow a MULTI_CONN-aware client like -+ * nbdcopy to create its typical number of 8-16 sockets. -+ */ -+#define NBD_DEFAULT_MAX_CONNECTIONS 100 -+ - /* Handshake phase structs - this struct is passed on the wire */ - - typedef struct NBDOption { -diff --git a/qapi/block-export.json b/qapi/block-export.json -index 7874a49..1d255d7 100644 ---- a/qapi/block-export.json -+++ b/qapi/block-export.json -@@ -28,7 +28,7 @@ - # @max-connections: The maximum number of connections to allow at the - # same time, 0 for unlimited. Setting this to 1 also stops the - # server from advertising multiple client support (since 5.2; --# default: 0) -+# default: 100) - # - # Since: 4.2 - ## -@@ -63,7 +63,7 @@ - # @max-connections: The maximum number of connections to allow at the - # same time, 0 for unlimited. Setting this to 1 also stops the - # server from advertising multiple client support (since 5.2; --# default: 0). -+# default: 100). - # - # Returns: error if the server is already running. - # --- -2.45.4 - - -From a61bd1bdaad59cbaa7b5efcffc06d2f2a4eeeba1 Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Thu, 8 Aug 2024 16:05:08 -0500 -Subject: [PATCH 4/5] nbd/server: CVE-2024-7409: Drop non-negotiating clients -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -A client that opens a socket but does not negotiate is merely hogging -qemu's resources (an open fd and a small amount of memory); and a -malicious client that can access the port where NBD is listening can -attempt a denial of service attack by intentionally opening and -abandoning lots of unfinished connections. The previous patch put a -default bound on the number of such ongoing connections, but once that -limit is hit, no more clients can connect (including legitimate ones). -The solution is to insist that clients complete handshake within a -reasonable time limit, defaulting to 10 seconds. A client that has -not successfully completed NBD_OPT_GO by then (including the case of -where the client didn't know TLS credentials to even reach the point -of NBD_OPT_GO) is wasting our time and does not deserve to stay -connected. Later patches will allow fine-tuning the limit away from -the default value (including disabling it for doing integration -testing of the handshake process itself). - -Note that this patch in isolation actually makes it more likely to see -qemu SEGV after nbd-server-stop, as any client socket still connected -when the server shuts down will now be closed after 10 seconds rather -than at the client's whims. That will be addressed in the next patch. - -For a demo of this patch in action: -$ qemu-nbd -f raw -r -t -e 10 file & -$ nbdsh --opt-mode -c ' -H = list() -for i in range(20): - print(i) - H.insert(i, nbd.NBD()) - H[i].set_opt_mode(True) - H[i].connect_uri("nbd://localhost") -' -$ kill $! - -where later connections get to start progressing once earlier ones are -forcefully dropped for taking too long, rather than hanging. - -Suggested-by: Daniel P. Berrangé -Signed-off-by: Eric Blake -Message-ID: <20240807174943.771624-13-eblake@redhat.com> -Reviewed-by: Daniel P. Berrangé -[eblake: rebase to changes earlier in series, reduce scope of timer] -Signed-off-by: Eric Blake -Signed-off-by: Kshitiz Godara -Upstream-reference: https://gitlab.com/qemu-project/qemu/-/commit/b9b72cb3ce15b693148bd09cef7e50110566d8a0 ---- - nbd/server.c | 28 +++++++++++++++++++++++++++- - nbd/trace-events | 1 + - 2 files changed, 28 insertions(+), 1 deletion(-) - -diff --git a/nbd/server.c b/nbd/server.c -index b99a080..51a9b7a 100644 ---- a/nbd/server.c -+++ b/nbd/server.c -@@ -3040,21 +3040,47 @@ static void nbd_client_receive_next_request(NBDClient *client) - } - } - -+static void nbd_handshake_timer_cb(void *opaque) -+{ -+ QIOChannel *ioc = opaque; -+ -+ trace_nbd_handshake_timer_cb(); -+ qio_channel_shutdown(ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); -+} -+ - static coroutine_fn void nbd_co_client_start(void *opaque) - { - NBDClient *client = opaque; - Error *local_err = NULL; -+ QEMUTimer *handshake_timer = NULL; - - qemu_co_mutex_init(&client->send_lock); - -- /* TODO - utilize client->handshake_max_secs */ -+ /* -+ * Create a timer to bound the time spent in negotiation. If the -+ * timer expires, it is likely nbd_negotiate will fail because the -+ * socket was shutdown. -+ */ -+ if (client->handshake_max_secs > 0) { -+ handshake_timer = aio_timer_new(qemu_get_aio_context(), -+ QEMU_CLOCK_REALTIME, -+ SCALE_NS, -+ nbd_handshake_timer_cb, -+ client->sioc); -+ timer_mod(handshake_timer, -+ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + -+ client->handshake_max_secs * NANOSECONDS_PER_SECOND); -+ } -+ - if (nbd_negotiate(client, &local_err)) { - if (local_err) { - error_report_err(local_err); - } -+ timer_free(handshake_timer); - client_close(client, false); - return; - } -+ timer_free(handshake_timer); - - nbd_client_receive_next_request(client); - } -diff --git a/nbd/trace-events b/nbd/trace-events -index 00ae321..cbd0a4a 100644 ---- a/nbd/trace-events -+++ b/nbd/trace-events -@@ -76,6 +76,7 @@ nbd_co_receive_request_payload_received(uint64_t cookie, uint64_t len) "Payload - nbd_co_receive_ext_payload_compliance(uint64_t from, uint64_t len) "client sent non-compliant write without payload flag: from=0x%" PRIx64 ", len=0x%" PRIx64 - nbd_co_receive_align_compliance(const char *op, uint64_t from, uint64_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx64 ", align=0x%" PRIx32 - nbd_trip(void) "Reading request" -+nbd_handshake_timer_cb(void) "client took too long to negotiate" - - # client-connection.c - nbd_connect_thread_sleep(uint64_t timeout) "timeout %" PRIu64 --- -2.45.4 - - -From 64ca5b3bee44bda9e8723f324f2b703229d85b90 Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Thu, 22 Aug 2024 09:35:29 -0500 -Subject: [PATCH 5/5] nbd/server: CVE-2024-7409: Avoid use-after-free when - closing server - -Commit 3e7ef738 plugged the use-after-free of the global nbd_server -object, but overlooked a use-after-free of nbd_server->listener. -Although this race is harder to hit, notice that our shutdown path -first drops the reference count of nbd_server->listener, then triggers -actions that can result in a pending client reaching the -nbd_blockdev_client_closed() callback, which in turn calls -qio_net_listener_set_client_func on a potentially stale object. - -If we know we don't want any more clients to connect, and have already -told the listener socket to shut down, then we should not be trying to -update the listener socket's associated function. - -Reproducer: - -> #!/usr/bin/python3 -> -> import os -> from threading import Thread -> -> def start_stop(): -> while 1: -> os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-start", -+"arguments":{"addr":{"type":"unix","data":{"path":"/tmp/nbd-sock"}}}}\'') -> os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-stop"}\'') -> -> def nbd_list(): -> while 1: -> os.system('/path/to/build/qemu-nbd -L -k /tmp/nbd-sock') -> -> def test(): -> sst = Thread(target=start_stop) -> sst.start() -> nlt = Thread(target=nbd_list) -> nlt.start() -> -> sst.join() -> nlt.join() -> -> test() - -Fixes: CVE-2024-7409 -Fixes: 3e7ef738c8 ("nbd/server: CVE-2024-7409: Close stray clients at server-stop") -CC: qemu-stable@nongnu.org -Reported-by: Andrey Drobyshev -Signed-off-by: Eric Blake -Message-ID: <20240822143617.800419-2-eblake@redhat.com> -Reviewed-by: Stefan Hajnoczi -(cherry picked from commit 3874f5f73c441c52f1c699c848d463b0eda01e4c) -Signed-off-by: Michael Tokarev -Signed-off-by: Kshitiz Godara -Upstream-reference: https://gitlab.com/qemu-project/qemu/-/commit/0fe466df932d23fd8881bba1ab2c1798c09884c1 ---- - blockdev-nbd.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/blockdev-nbd.c b/blockdev-nbd.c -index f73409a..b36f41b 100644 ---- a/blockdev-nbd.c -+++ b/blockdev-nbd.c -@@ -92,10 +92,13 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, - - static void nbd_update_server_watch(NBDServerData *s) - { -- if (!s->max_connections || s->connections < s->max_connections) { -- qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, NULL); -- } else { -- qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL); -+ if (s->listener) { -+ if (!s->max_connections || s->connections < s->max_connections) { -+ qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, -+ NULL); -+ } else { -+ qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL); -+ } - } - } - -@@ -113,6 +116,7 @@ static void nbd_server_free(NBDServerData *server) - */ - qio_net_listener_disconnect(server->listener); - object_unref(OBJECT(server->listener)); -+ server->listener = NULL; - QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) { - qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH, - NULL); --- -2.45.4 - diff --git a/SPECS/qemu/CVE-2024-7730.patch b/SPECS/qemu/CVE-2024-7730.patch deleted file mode 100644 index f854c279fa..0000000000 --- a/SPECS/qemu/CVE-2024-7730.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 3396278a67b18a8e417c595cd5377ce187ad5cfd Mon Sep 17 00:00:00 2001 -From: Manos Pitsidianakis -Date: Mon, 8 Jul 2024 10:09:49 +0300 -Subject: [PATCH 5/6] virtio-snd: add max size bounds check in input cb -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When reading input audio in the virtio-snd input callback, -virtio_snd_pcm_in_cb(), we do not check whether the iov can actually fit -the data buffer. This is because we use the buffer->size field as a -total-so-far accumulator instead of byte-size-left like in TX buffers. - -This triggers an out of bounds write if the size of the virtio queue -element is equal to virtio_snd_pcm_status, which makes the available -space for audio data zero. This commit adds a check for reaching the -maximum buffer size before attempting any writes. - -Reported-by: Zheyu Ma -Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2427 -Signed-off-by: Manos Pitsidianakis -Message-Id: -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin - -Upstream reference: -https://gitlab.com/qemu-project/qemu/-/commit/98e77e3dd8dd6e7aa9a7dffa60f49c8c8a49d4e3 ---- - hw/audio/virtio-snd.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c -index 137fa77..15986af 100644 ---- a/hw/audio/virtio-snd.c -+++ b/hw/audio/virtio-snd.c -@@ -1274,7 +1274,7 @@ static void virtio_snd_pcm_in_cb(void *data, int available) - { - VirtIOSoundPCMStream *stream = data; - VirtIOSoundPCMBuffer *buffer; -- size_t size; -+ size_t size, max_size; - - WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { - while (!QSIMPLEQ_EMPTY(&stream->queue)) { -@@ -1288,7 +1288,12 @@ static void virtio_snd_pcm_in_cb(void *data, int available) - continue; - } - -+ max_size = iov_size(buffer->elem->in_sg, buffer->elem->in_num); - for (;;) { -+ if (buffer->size >= max_size) { -+ return_rx_buffer(stream, buffer); -+ break; -+ } - size = AUD_read(stream->voice.in, - buffer->data + buffer->size, - MIN(available, (stream->params.period_bytes - --- -2.45.3 - diff --git a/SPECS/qemu/qemu.signatures.json b/SPECS/qemu/qemu.signatures.json index 7e4c68f912..153079e6f0 100644 --- a/SPECS/qemu/qemu.signatures.json +++ b/SPECS/qemu/qemu.signatures.json @@ -10,6 +10,6 @@ "qemu-ga.sysconfig": "d0c126093fb7bd26d255bd7b692ac59f0559394b7feef792651e6208127fd1ee", "qemu-guest-agent.service": "7eb1547eeae0887bd58680e0c41a6f7bfe47babd356a98b91b4d39a5ade31501", "vhost.conf": "a523b6e2082ab5b913c9541295424ce7f3ff7f8161e6f21c7a8f64d23dd22313", - "qemu-9.1.0.tar.xz": "816b7022a8ba7c2ac30e2e0cf973e826f6bcc8505339603212c5ede8e94d7834" + "qemu-10.0.4.tar.xz": "4a6883388e1eea38fae422e205332b90746a4b2b48d50445f7bff3b9c39ee5c4" } } diff --git a/SPECS/qemu/qemu.spec b/SPECS/qemu/qemu.spec index cf9b6279fe..7e58e9bd48 100644 --- a/SPECS/qemu/qemu.spec +++ b/SPECS/qemu/qemu.spec @@ -305,6 +305,7 @@ Distribution: Edge Microvisor Toolkit %else %define requires_char_baum %{nil} %endif +%define requires_device_uefi_vars Requires: %{name}-device-uefi-vars = %{evr} %define requires_device_usb_host Requires: %{name}-device-usb-host = %{evr} %define requires_device_usb_redirect Requires: %{name}-device-usb-redirect = %{evr} %define requires_ui_curses Requires: %{name}-ui-curses = %{evr} @@ -445,8 +446,8 @@ Obsoletes: sgabios-bin <= 1:0.20180715git-10.fc38 Summary: QEMU is a FAST! processor emulator Name: qemu -Version: 9.1.0 -Release: 5%{?dist} +Version: 10.0.4 +Release: 1%{?dist} License: Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND FSFAP AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-2.0-or-later WITH GCC-exception-2.0 AND LGPL-2.0-only AND LGPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND MIT AND LicenseRef-Fedora-Public-Domain AND CC-BY-3.0 URL: http://www.qemu.org/ @@ -474,72 +475,13 @@ Source36: README.tests # Skip failing test in copr # https://gitlab.com/qemu-project/qemu/-/issues/2541 -Patch1: 0001-Disable-9p-local-tests-that-fail-on-copr-aarch64.patch - -# https://patchwork.kernel.org/project/qemu-devel/patch/20231128143647.847668-1-crobinso@redhat.com/ -# Fix pvh.img ld build failure on fedora rawhide -Patch2: 0001-pc-bios-optionrom-Fix-pvh.img-ld-build-failure-on-fe.patch -#Patch3: 0002-Disable-failing-tests-on-azl.patch - -# SRIOV patches -Patch4: 0001-ui-gtk-Attach-fullscreen-toggling-cb-to-all-detached.patch -Patch5: 0002-ui-egl-helpers-Consolidates-create-sync-and-create-f.patch -Patch6: 0003-ui-dmabuf-Remove-sync-from-QemuDmaBuf-struct.patch -Patch7: 0004-hw-display-virtio-gpu-Introducing-render_sync-param.patch -Patch8: 0005-ui-gtk-Start-rendering-of-guest-blob-scandout-if-ren.patch -Patch9: 0006-ui-gtk-Factor-out-tab-window-creation-into-a-separat.patch -Patch10: 0007-ui-gtk-Add-a-new-parameter-to-assign-connectors-moni.patch -Patch11: 0008-ui-gtk-Page-number-of-1-is-not-a-valid-page-number.patch -Patch12: 0009-ui-gtk-move-guest-mouse-cursor-after-host-cursor-hit.patch -Patch13: 0010-ui-gtk-Register-shortcut-key-for-grab_input-to-accel.patch -Patch14: 0011-audio-Switch-audio-status-with-Guest-VM-switch-from-.patch -Patch15: 0012-usb-hid-added-new-type-for-touch-stylus.patch -Patch16: 0013-ui-gtk-Adds-status-bar-and-display-guest-ups-and-dra.patch -Patch17: 0014-ui-gtk-Refresh-grabbing-status-when-the-window-is-fo.patch -Patch18: 0015-ui-gtk-untabifying-even-the-primary-window.patch -Patch19: 0016-ui-gtk-Forcefully-full-screening-window.patch -Patch20: 0017-ui-spice-Add-an-option-for-users-to-provide-a-prefer.patch -Patch21: 0018-ui-spice-Enable-gl-on-option-for-non-local-or-remote.patch -Patch22: 0019-ui-spice-Submit-the-gl_draw-requests-at-60-FPS-for-r.patch -Patch23: 0020-ui-console-gl-Add-a-helper-to-create-a-texture-with-.patch -Patch24: 0021-ui-spice-Create-another-texture-with-linear-layout-w.patch -Patch25: 0022-ui-spice-Blit-the-scanout-texture-if-its-memory-layo.patch -Patch26: 0023-ui-gtk-Enables-HW-cursor.patch -Patch27: 0024-ui-gtk-Hardcode-default-size-of-new-tab-window-to-96.patch -Patch28: 0025-ui-gtk-Added-an-input-mode.patch -Patch29: 0026-ui-gtk-Scanout-flush-only-if-guest-framebuffer-exist.patch -Patch30: 0027-virtio-gpu-Replace-the-surface-with-null-surface-onl.patch -Patch31: 0028-virtio-gpu-Recreate-the-resource-s-dmabuf-if-new-bac.patch -Patch32: 0029-virtio-gpu-Find-the-host-addr-given-gpa-associated-w.patch -Patch33: 0030-virtio-gpu-udmabuf-Create-dmabuf-from-mr-associated-.patch -Patch34: 0031-gtk-Skip-to-configure-the-size-only-in-HPD-case.patch -Patch35: 0032-ui-spice-unblock-the-console-when-the-scanout-is-bei.patch -Patch36: 0033-virtio-gpu-Update-cursor-data-only-if-it-is-valid.patch -Patch37: 0034-virtio-gpu-Freeing-udmabuf-and-make-dmabuf-NULL-when.patch -Patch38: 0035-Revert-ui-gtk-Fix-mouse-motion-event-scaling-issue-w.patch -Patch39: 0036-virtio-gpu-udmabuf-gtk-Set-dmabuf_fd-1-to-prevent-fu.patch -Patch40: 0037-ui-gtk-egl-Skip-refreshing-frame-and-hw-cursor-if-th.patch -Patch41: 0038-ui-gtk-Refreshing-is-also-counted-when-calculating-F.patch -Patch42: 0039-ui-gtk-FPS-and-UPS-are-updated-every-1-sec-instead-o.patch -Patch43: 0040-ui-gtk-fps-param-for-gd_gl_count_frame.patch -Patch44: 0041-hw-virtio-gpu-udmabuf-g-dmabuf.primary-i-shouldn-t-b.patch -Patch45: 0042-ui-gtk-Unblock-zero-copy-display-pipeline-before-sav.patch -Patch46: 0043-ui-gtk-show-fps-works-on-GFX-consoles.patch -Patch47: 0044-ui-gtk-egl-Skipping-frame-drawing-if-not-necessary.patch -Patch48: 0045-ui-gtk-HPD-handling-disconnection-immediately.patch -Patch49: 0046-ui-gtk-egl-Cursor-image-texture-filtering-using-GL_N.patch -Patch50: 0047-ui-gtk-Covering-render_sync-false-case-when-dealing-.patch -Patch51: 0048-ui-gtk-egl-Cursor-texture-needs-to-be-re-created-whe.patch -Patch52: 0049-Adding-default-docs.patch -Patch53: 0050-gtk-Abort-if-there-is-no-connector-set-for-primary-w.patch -Patch54: 0051-hw-display-virtio-gpu-Initialize-dmabuf_fd-for-the-b.patch -Patch55: 0052-gtk-Adding-funcs-for-destroying-textures-in-gtk-egl-.patch -Patch56: 0053-hw-virtio-gpu-Cursor-size-can-be-changed.patch -Patch57: 0054-hw-display-virtio-gpu-Redundant-call-of-dpy_gfx_repl.patch -Patch58: 0055-hw-display-virtio-gpu-Manual-res-flush-to-redraw-sav.patch -Patch59: 0056-hw-display-virtio-gpu-Properly-free-current_cursor.patch -Patch60: 0057-ui-gtk-Re-grabbing-PTR-KBD-individually.patch -Patch61: 0058-hw-usb-host-libusb-Do-not-assert-when-detects-invali.patch +Patch: 0001-Disable-9p-local-tests-that-fail-on-copr-aarch64.patch +# https://lists.nongnu.org/archive/html/qemu-block/2025-01/msg00480.html +Patch: 0002-nfs-Add-support-for-libnfs-v2-api.patch +Patch: 0008-Revert-meson.build-Disallow-libnfs-v6-to-fix-the-bro.patch +# Increase test-replication timeout +# NOT upstream, but see https://gitlab.com/qemu-project/qemu/-/issues/3035 +Patch: 0002-TEMPORARY-increase-test-timeout.patch BuildRequires: gnupg2 BuildRequires: meson >= %{meson_version} @@ -745,7 +687,6 @@ Requires: %{name}-system-aarch64 = %{version}-%{release} Requires: %{name}-system-alpha = %{version}-%{release} Requires: %{name}-system-arm = %{version}-%{release} Requires: %{name}-system-avr = %{version}-%{release} -Requires: %{name}-system-cris = %{version}-%{release} Requires: %{name}-system-loongarch64 = %{version}-%{release} Requires: %{name}-system-m68k = %{version}-%{release} Requires: %{name}-system-microblaze = %{version}-%{release} @@ -1144,6 +1085,11 @@ Requires: %{name}-device-display-virtio-vga%{?_isa} = %{version}-%{release} This package provides the virtio-vga-rutabaga display device for QEMU. %endif +%package device-uefi-vars +Summary: QEMU UEFI variable service +Requires: %{name}-common%{?_isa} = %{evr} +%description device-uefi-vars +This package provides the UEFI variable service for QEMU. %package device-usb-host Summary: QEMU usb host device @@ -1314,12 +1260,6 @@ Summary: QEMU user mode emulation of arm qemu targets static build This package provides the arm user mode emulation of qemu targets built as static binaries -%package user-static-cris -Summary: QEMU user mode emulation of cris qemu targets static build -%description user-static-cris -This package provides the cris user mode emulation of qemu targets built as -static binaries - %package user-static-hexagon Summary: QEMU user mode emulation of hexagon qemu targets static build %description user-static-hexagon @@ -1469,21 +1409,6 @@ Requires: %{name}-common = %{version}-%{release} %description system-avr-core This package provides the QEMU system emulator for AVR systems. - -%package system-cris -Summary: QEMU system emulator for CRIS -Requires: %{name}-system-cris-core = %{version}-%{release} -%{requires_all_modules} -%description system-cris -This package provides the system emulator for CRIS systems. - -%package system-cris-core -Summary: QEMU system emulator for CRIS -Requires: %{name}-common = %{version}-%{release} -%description system-cris-core -This package provides the system emulator for CRIS boards. - - %package system-hppa Summary: QEMU system emulator for HPPA Requires: %{name}-system-hppa-core = %{version}-%{release} @@ -1735,6 +1660,7 @@ mkdir -p %{static_builddir} --audio-drv-list= \\\ --disable-af-xdp \\\ --disable-alsa \\\ + --disable-asan \\\ --disable-attr \\\ --disable-auth-pam \\\ --disable-avx2 \\\ @@ -1830,7 +1756,6 @@ mkdir -p %{static_builddir} --disable-rutabaga-gfx \\\ --disable-rng-none \\\ --disable-safe-stack \\\ - --disable-sanitizers \\\ --disable-sdl \\\ --disable-sdl-image \\\ --disable-seccomp \\\ @@ -1851,6 +1776,7 @@ mkdir -p %{static_builddir} --disable-tsan \\\ --disable-uadk \\\ --disable-u2f \\\ + --disable-ubsan \\\ --disable-usb-redir \\\ --disable-user \\\ --disable-vpc \\\ @@ -2091,7 +2017,6 @@ run_configure \ %endif --enable-vhdx \ --enable-virtfs \ - --enable-virtfs-proxy-helper \ --enable-vpc \ --enable-vnc-jpeg \ --enable-vte \ @@ -2361,8 +2286,6 @@ ln -sf qemu-system-x86_64 %{buildroot}%{_bindir}/qemu-kvm # Needed until CBL-Mariner starts cross-compiling 'ipxe', 'seabios' and 'sgabios' for other architectures. rm -rf %{buildroot}%{_bindir}/qemu-system-i386 rm -rf %{buildroot}%{_bindir}/qemu-system-x86_64 -rm -rf %{buildroot}%{_libdir}/%{name}/accel-tcg-i386.so -rm -rf %{buildroot}%{_libdir}/%{name}/accel-tcg-x86_64.so rm -rf %{buildroot}%{_datadir}/systemtap/tapset/qemu-system-i386*.stp rm -rf %{buildroot}%{_datadir}/systemtap/tapset/qemu-system-x86_64*.stp %if ! %{emt} @@ -2491,11 +2414,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %postun user-static-arm /bin/systemctl --system try-restart systemd-binfmt.service &>/dev/null || : -%post user-static-cris -/bin/systemctl --system try-restart systemd-binfmt.service &>/dev/null || : -%postun user-static-cris -/bin/systemctl --system try-restart systemd-binfmt.service &>/dev/null || : - %post user-static-hexagon /bin/systemctl --system try-restart systemd-binfmt.service &>/dev/null || : %postun user-static-hexagon @@ -2655,6 +2573,7 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %{_datadir}/icons/* %{_datadir}/%{name}/keymaps/ %{_datadir}/%{name}/linuxboot_dma.bin +%{_datadir}/%{name}/pnv-pnor.bin %attr(4755, -, -) %{_libexecdir}/qemu-bridge-helper %dir %{_libdir}/%{name}/ %if ! %{emt} @@ -2676,10 +2595,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ # Fedora specific %{_datadir}/applications/qemu.desktop %exclude %{_datadir}/%{name}/qemu-nsis.bmp -%{_libexecdir}/virtfs-proxy-helper -%if ! %{emt} -%{_mandir}/man1/virtfs-proxy-helper.1* -%endif %files tests @@ -2808,6 +2723,8 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %files device-display-virtio-vga-rutabaga %{_libdir}/%{name}/hw-display-virtio-vga-rutabaga.so %endif +%files device-uefi-vars +%{_libdir}/%{name}/hw-uefi-vars.so %files device-usb-host %{_libdir}/%{name}/hw-usb-host.so %files device-usb-redirect @@ -2855,7 +2772,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %{_bindir}/qemu-alpha %{_bindir}/qemu-arm %{_bindir}/qemu-armeb -%{_bindir}/qemu-cris %{_bindir}/qemu-hppa %{_bindir}/qemu-hexagon %{_bindir}/qemu-loongarch64 @@ -2902,9 +2818,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %{_datadir}/systemtap/tapset/qemu-arm.stp %{_datadir}/systemtap/tapset/qemu-arm-log.stp %{_datadir}/systemtap/tapset/qemu-arm-simpletrace.stp -%{_datadir}/systemtap/tapset/qemu-cris.stp -%{_datadir}/systemtap/tapset/qemu-cris-log.stp -%{_datadir}/systemtap/tapset/qemu-cris-simpletrace.stp %{_datadir}/systemtap/tapset/qemu-hexagon.stp %{_datadir}/systemtap/tapset/qemu-hexagon-log.stp %{_datadir}/systemtap/tapset/qemu-hexagon-simpletrace.stp @@ -3037,12 +2950,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %endif %{_exec_prefix}/lib/binfmt.d/qemu-armeb-static.conf -%files user-static-cris -%{_bindir}/qemu-cris-static -%{_datadir}/systemtap/tapset/qemu-cris-log-static.stp -%{_datadir}/systemtap/tapset/qemu-cris-simpletrace-static.stp -%{_datadir}/systemtap/tapset/qemu-cris-static.stp - %files user-static-hexagon %{_bindir}/qemu-hexagon-static %{_datadir}/systemtap/tapset/qemu-hexagon-log-static.stp @@ -3250,6 +3157,7 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %files system-arm-core %{_bindir}/qemu-system-arm %{_datadir}/%{name}/npcm7xx_bootrom.bin +%{_datadir}/%{name}/npcm8xx_bootrom.bin %{_datadir}/systemtap/tapset/qemu-system-arm.stp %{_datadir}/systemtap/tapset/qemu-system-arm-log.stp %{_datadir}/systemtap/tapset/qemu-system-arm-simpletrace.stp @@ -3268,18 +3176,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %{_mandir}/man1/qemu-system-avr.1* %endif - -%files system-cris -%files system-cris-core -%{_bindir}/qemu-system-cris -%{_datadir}/systemtap/tapset/qemu-system-cris.stp -%{_datadir}/systemtap/tapset/qemu-system-cris-log.stp -%{_datadir}/systemtap/tapset/qemu-system-cris-simpletrace.stp -%if ! %{emt} -%{_mandir}/man1/qemu-system-cris.1* -%endif - - %files system-hppa %files system-hppa-core %{_bindir}/qemu-system-hppa @@ -3430,7 +3326,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %{_mandir}/man1/qemu-system-s390x.1* %endif %{_datadir}/%{name}/s390-ccw.img -%{_datadir}/%{name}/s390-netboot.img %files system-sh4 @@ -3483,7 +3378,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %files system-x86 %files system-x86-core %{_bindir}/qemu-system-x86_64 -%{_libdir}/%{name}/accel-tcg-x86_64.so %{_datadir}/systemtap/tapset/qemu-system-x86_64.stp %{_datadir}/systemtap/tapset/qemu-system-x86_64-log.stp %{_datadir}/systemtap/tapset/qemu-system-x86_64-simpletrace.stp @@ -3509,7 +3403,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %endif %files system-i386 %{_bindir}/qemu-system-i386 -%{_libdir}/%{name}/accel-tcg-i386.so %{_datadir}/systemtap/tapset/qemu-system-i386.stp %{_datadir}/systemtap/tapset/qemu-system-i386-log.stp %{_datadir}/systemtap/tapset/qemu-system-i386-simpletrace.stp @@ -3538,6 +3431,9 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog +* Thu Jan 08 2026 Rajesh Shanmugam - 10.0.4-1 +- Upgrade to 10.0.4 for CVE-2025-54566 and CVE-2025-54567 + * Thu Oct 30 2025 Liang Yang - 9.1.0-5 - Added 1 patch from Intel Distribution Qemu Commit 3fbf5c5 - Fix assert in qemu host-libusb when altsetting invalid diff --git a/cgmanifest.json b/cgmanifest.json index 3e1468a1ab..20adec3010 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -26303,8 +26303,8 @@ "type": "other", "other": { "name": "qemu", - "version": "9.1.0", - "downloadUrl": "https://download.qemu.org/qemu-9.1.0.tar.xz" + "version": "10.0.4", + "downloadUrl": "https://download.qemu.org/qemu-10.0.4.tar.xz" } } },