From 81cd34a359a36656d2f6542226235bd318ff8873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 10 May 2023 11:25:31 +0400 Subject: [PATCH 1/6] chardev: report the handshake error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This can help to debug connection issues. Related to: https://bugzilla.redhat.com/show_bug.cgi?id=2196182 Signed-off-by: Marc-André Lureau Reviewed-by: Daniel P. Berrangé Message-Id: <20230510072531.3937189-1-marcandre.lureau@redhat.com> --- chardev/char-socket.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/chardev/char-socket.c b/chardev/char-socket.c index 8c58532171..e8e3a743d5 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -742,8 +742,12 @@ static void tcp_chr_websock_handshake(QIOTask *task, gpointer user_data) { Chardev *chr = user_data; SocketChardev *s = user_data; + Error *err = NULL; - if (qio_task_propagate_error(task, NULL)) { + if (qio_task_propagate_error(task, &err)) { + error_reportf_err(err, + "websock handshake of character device %s failed: ", + chr->label); tcp_chr_disconnect(chr); } else { if (s->do_telnetopt) { @@ -778,8 +782,12 @@ static void tcp_chr_tls_handshake(QIOTask *task, { Chardev *chr = user_data; SocketChardev *s = user_data; + Error *err = NULL; - if (qio_task_propagate_error(task, NULL)) { + if (qio_task_propagate_error(task, &err)) { + error_reportf_err(err, + "TLS handshake of character device %s failed: ", + chr->label); tcp_chr_disconnect(chr); } else { if (s->is_websock) { From 957d77863e4564454eb97f8f371096843daf4678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 26 Jul 2023 21:39:28 +0400 Subject: [PATCH 2/6] virtio-gpu: free BHs, by implementing unrealize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Dongwon Kim Signed-off-by: Marc-André Lureau Message-Id: <20230726173929.690601-2-marcandre.lureau@redhat.com> --- hw/display/virtio-gpu-base.c | 2 +- hw/display/virtio-gpu.c | 10 ++++++++++ include/hw/virtio/virtio-gpu.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index 7ab7d08d0a..ca1fb7b16f 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -244,7 +244,7 @@ virtio_gpu_base_set_features(VirtIODevice *vdev, uint64_t features) trace_virtio_gpu_features(((features & virgl) == virgl)); } -static void +void virtio_gpu_base_device_unrealize(DeviceState *qdev) { VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev); diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index e8603d78ca..b1f5d392bb 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1392,6 +1392,15 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) QTAILQ_INIT(&g->fenceq); } +static void virtio_gpu_device_unrealize(DeviceState *qdev) +{ + VirtIOGPU *g = VIRTIO_GPU(qdev); + + g_clear_pointer(&g->ctrl_bh, qemu_bh_delete); + g_clear_pointer(&g->cursor_bh, qemu_bh_delete); + virtio_gpu_base_device_unrealize(qdev); +} + void virtio_gpu_reset(VirtIODevice *vdev) { VirtIOGPU *g = VIRTIO_GPU(vdev); @@ -1492,6 +1501,7 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data) vgbc->gl_flushed = virtio_gpu_handle_gl_flushed; vdc->realize = virtio_gpu_device_realize; + vdc->unrealize = virtio_gpu_device_unrealize; vdc->reset = virtio_gpu_reset; vdc->get_config = virtio_gpu_get_config; vdc->set_config = virtio_gpu_set_config; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 7ea8ae2bee..05bee09e1a 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -238,6 +238,7 @@ bool virtio_gpu_base_device_realize(DeviceState *qdev, VirtIOHandleOutput ctrl_cb, VirtIOHandleOutput cursor_cb, Error **errp); +void virtio_gpu_base_device_unrealize(DeviceState *qdev); void virtio_gpu_base_reset(VirtIOGPUBase *g); void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g, struct virtio_gpu_resp_display_info *dpy_info); From a41e2d97f92b48552988b3cc62dce79d62f60dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 26 Jul 2023 21:39:29 +0400 Subject: [PATCH 3/6] virtio-gpu: reset gfx resources in main thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling OpenGL from different threads can have bad consequences if not carefully reviewed. It's not generally supported. In my case, I was debugging a crash in glDeleteTextures from OPENGL32.DLL, where I asked qemu for gl=es, and thus ANGLE implementation was expected. libepoxy did resolution of the global pointer for glGenTexture to the GLES version from the main thread. But it resolved glDeleteTextures to the GL version, because it was done from a different thread without correct context. Oops. Let's stick to the main thread for GL calls by using a BH. Note: I didn't use atomics for reset_finished check, assuming the BQL will provide enough of sync, but I might be wrong. Acked-by: Dongwon Kim Signed-off-by: Marc-André Lureau Message-Id: <20230726173929.690601-3-marcandre.lureau@redhat.com> --- hw/display/virtio-gpu.c | 40 +++++++++++++++++++++++++++------- include/hw/virtio/virtio-gpu.h | 3 +++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index b1f5d392bb..bbd5c6561a 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu/iov.h" +#include "sysemu/cpus.h" #include "ui/console.h" #include "trace.h" #include "sysemu/dma.h" @@ -41,6 +42,7 @@ virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id, static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, struct virtio_gpu_simple_resource *res); +static void virtio_gpu_reset_bh(void *opaque); void virtio_gpu_update_cursor_data(VirtIOGPU *g, struct virtio_gpu_scanout *s, @@ -1387,6 +1389,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) &qdev->mem_reentrancy_guard); g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g, &qdev->mem_reentrancy_guard); + g->reset_bh = qemu_bh_new(virtio_gpu_reset_bh, g); + qemu_cond_init(&g->reset_cond); QTAILQ_INIT(&g->reslist); QTAILQ_INIT(&g->cmdq); QTAILQ_INIT(&g->fenceq); @@ -1398,18 +1402,42 @@ static void virtio_gpu_device_unrealize(DeviceState *qdev) g_clear_pointer(&g->ctrl_bh, qemu_bh_delete); g_clear_pointer(&g->cursor_bh, qemu_bh_delete); + g_clear_pointer(&g->reset_bh, qemu_bh_delete); + qemu_cond_destroy(&g->reset_cond); virtio_gpu_base_device_unrealize(qdev); } +static void virtio_gpu_reset_bh(void *opaque) +{ + VirtIOGPU *g = VIRTIO_GPU(opaque); + struct virtio_gpu_simple_resource *res, *tmp; + int i = 0; + + QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) { + virtio_gpu_resource_destroy(g, res); + } + + for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { + dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL); + } + + g->reset_finished = true; + qemu_cond_signal(&g->reset_cond); +} + void virtio_gpu_reset(VirtIODevice *vdev) { VirtIOGPU *g = VIRTIO_GPU(vdev); - struct virtio_gpu_simple_resource *res, *tmp; struct virtio_gpu_ctrl_command *cmd; - int i = 0; - QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) { - virtio_gpu_resource_destroy(g, res); + if (qemu_in_vcpu_thread()) { + g->reset_finished = false; + qemu_bh_schedule(g->reset_bh); + while (!g->reset_finished) { + qemu_cond_wait_iothread(&g->reset_cond); + } + } else { + virtio_gpu_reset_bh(g); } while (!QTAILQ_EMPTY(&g->cmdq)) { @@ -1425,10 +1453,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)); } diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 05bee09e1a..390c4642b8 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,6 +169,9 @@ struct VirtIOGPU { QEMUBH *ctrl_bh; QEMUBH *cursor_bh; + QEMUBH *reset_bh; + QemuCond reset_cond; + bool reset_finished; QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq; From 8a64609eea8cb2bac015968c4b62da5bce266e22 Mon Sep 17 00:00:00 2001 From: Dongli Zhang Date: Wed, 12 Jul 2023 22:58:19 -0700 Subject: [PATCH 4/6] dump: kdump-zlib data pages not dumped with pvtime/aarch64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kdump-zlib data pages are not dumped from aarch64 host when the 'pvtime' is involved, that is, when the block->target_end is not aligned to page_size. In the below example, it is expected to dump two blocks. (qemu) info mtree -f ... ... 00000000090a0000-00000000090a0fff (prio 0, ram): pvtime KVM ... ... 0000000040000000-00000001bfffffff (prio 0, ram): mach-virt.ram KVM ... ... However, there is an issue with get_next_page() so that the pages for "mach-virt.ram" will not be dumped. At line 1296, although we have reached at the end of the 'pvtime' block, since it is not aligned to the page_size (e.g., 0x10000), it will not break at line 1298. 1255 static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr, 1256 uint8_t **bufptr, DumpState *s) ... ... 1294 memcpy(buf + addr % page_size, hbuf, n); 1295 addr += n; 1296 if (addr % page_size == 0) { 1297 /* we filled up the page */ 1298 break; 1299 } As a result, get_next_page() will continue to the next block ("mach-virt.ram"). Finally, when get_next_page() returns to the caller: - 'pfnptr' is referring to the 'pvtime' - but 'blockptr' is referring to the "mach-virt.ram" When get_next_page() is called the next time, "*pfnptr += 1" still refers to the prior 'pvtime'. It will exit immediately because it is out of the range of the current "mach-virt.ram". The fix is to break when it is time to come to the next block, so that both 'pfnptr' and 'blockptr' refer to the same block. Fixes: 94d788408d2d ("dump: fix kdump to work over non-aligned blocks") Cc: Joe Jin Signed-off-by: Dongli Zhang Reviewed-by: Marc-André Lureau Message-ID: <20230713055819.30497-1-dongli.zhang@oracle.com> --- dump/dump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index 1f1a6edcab..d4ef713cd0 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -1293,8 +1293,8 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr, memcpy(buf + addr % page_size, hbuf, n); addr += n; - if (addr % page_size == 0) { - /* we filled up the page */ + if (addr % page_size == 0 || addr >= block->target_end) { + /* we filled up the page or the current block is finished */ break; } } else { From fdd649538e6c6c9ef99082cb74cc36dbb6b9f953 Mon Sep 17 00:00:00 2001 From: Zongmin Zhou Date: Thu, 13 Apr 2023 16:15:26 +0800 Subject: [PATCH 5/6] hw/i386/vmmouse:add relative packet flag for button status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The buttons value use macros instead of direct numbers. If request relative mode, have to add this for guest vmmouse driver to judge this is a relative packet. otherwise,vmmouse driver will not match the condition 'status & VMMOUSE_RELATIVE_PACKET', and can't report events on the correct(relative) input device, result to relative mode unuseful. Signed-off-by: Zongmin Zhou Message-ID: <20230413081526.2229916-1-zhouzongmin@kylinos.cn> Reviewed-by: Marc-André Lureau --- hw/i386/vmmouse.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c index a56c185f15..6cd624bd09 100644 --- a/hw/i386/vmmouse.c +++ b/hw/i386/vmmouse.c @@ -44,6 +44,12 @@ #define VMMOUSE_VERSION 0x3442554a +#define VMMOUSE_RELATIVE_PACKET 0x00010000 + +#define VMMOUSE_LEFT_BUTTON 0x20 +#define VMMOUSE_RIGHT_BUTTON 0x10 +#define VMMOUSE_MIDDLE_BUTTON 0x08 + #ifdef DEBUG_VMMOUSE #define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else @@ -103,15 +109,18 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_ x, y, dz, buttons_state); if ((buttons_state & MOUSE_EVENT_LBUTTON)) - buttons |= 0x20; + buttons |= VMMOUSE_LEFT_BUTTON; if ((buttons_state & MOUSE_EVENT_RBUTTON)) - buttons |= 0x10; + buttons |= VMMOUSE_RIGHT_BUTTON; if ((buttons_state & MOUSE_EVENT_MBUTTON)) - buttons |= 0x08; + buttons |= VMMOUSE_MIDDLE_BUTTON; if (s->absolute) { x <<= 1; y <<= 1; + } else{ + /* add for guest vmmouse driver to judge this is a relative packet. */ + buttons |= VMMOUSE_RELATIVE_PACKET; } s->queue[s->nb_queue++] = buttons; From 58ea90f8032912b41e753a95089ba764fcc6446a Mon Sep 17 00:00:00 2001 From: Dongwon Kim Date: Mon, 24 Jul 2023 17:11:31 -0700 Subject: [PATCH 6/6] ui/gtk: set scanout mode in gd_egl/gd_gl_area_scanout_texture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing a regression (black screen) caused by a commit 92b58156e7 ("ui/gtk: set scanout-mode right before scheduling draw"). The commit 92b58156e7 was made with an assumption that the scanout mode needs to be set only if the guest scanout is a dmabuf but there are cases (e.g. virtio-gpu-virgl) where the scanout is still processed in a form of a texture but is not backed by dmabuf. So it is needed to put back the line that sets scanout mode in gd_egl_scanout_texture and gd_gl_area_scanout_texture. Fixes: 92b58156e7 ("ui/gtk: set scanout-mode right before scheduling draw) Reported-by: Volker Rümelin Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim Reviewed-by: Marc-André Lureau Message-ID: <20230725001131.24017-1-dongwon.kim@intel.com> --- ui/gtk-egl.c | 1 + ui/gtk-gl-area.c | 1 + 2 files changed, 2 insertions(+) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 4c29ac10d0..a1060fd80f 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -246,6 +246,7 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl, eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, vc->gfx.esurface, vc->gfx.ectx); + gtk_egl_set_scanout_mode(vc, true); egl_fb_setup_for_tex(&vc->gfx.guest_fb, backing_width, backing_height, backing_id, false); } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 1ce34a249e..52dcac161e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -268,6 +268,7 @@ void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, return; } + gtk_gl_area_set_scanout_mode(vc, true); egl_fb_setup_for_tex(&vc->gfx.guest_fb, backing_width, backing_height, backing_id, false); }