QEMU's display GL core is tied to main-loop thread and virtio-gpu interacts with display while processing GPU commands. virtio_gpu_ctrl_bh() works in generic AIO context that can be processed from vCPU thread, while GL and UI toolkits are bound to the main-loop thread. Bounce the ctrl-bh execution if running from a thread other than main to fix the problem.
0 SDL_GL_MakeCurrent() (libSDL3) 1 SDL_GL_MakeCurrent_REAL() (libSDL2) 2 sdl2_gl_make_context_current() (ui/sdl2-gl.c:201) 3 make_current() (virglrenderer.c:639) 4 vrend_finish_context_switch() (vrend_renderer.c:11630) 5 vrend_hw_switch_context() (vrend_renderer.c:11613) 6 vrend_renderer_force_ctx_0() (vrend_renderer.c:12986) 7 virgl_renderer_force_ctx_0() (virglrenderer.c:460) 8 virtio_gpu_virgl_process_cmd() (virtio-gpu-virgl.c:1013) 9 virtio_gpu_process_cmdq() (virtio-gpu.c:1050) 10 virtio_gpu_gl_handle_ctrl() (virtio-gpu-gl.c:86) 11 aio_bh_poll() (util/async.c) 12 aio_poll() (util/aio-posix.c) 13 blk_pwrite() (block/block-gen.c:1985) 14 pflash_update() (pflash_cfi01.c:396) 15 pflash_write() (pflash_cfi01.c:541) 16 memory_region_dispatch_write() (system/memory.c:1554) 17 flatview_write() (system/physmem.c:3333) 18 address_space_write() (system/physmem.c:3453) 19 kvm_cpu_exec() (accel/kvm/kall-all.c:3248) 20 kvm_vcpu_thread_fn() (accel/kvm/kaccel-ops.c:53) Cc: [email protected] Signed-off-by: Dmitry Osipenko <[email protected]> --- hw/display/virtio-gpu.c | 12 +++++++++++- include/hw/virtio/virtio-gpu.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 643e91ca2a7a..d0737cbba8a2 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1126,7 +1126,16 @@ static void virtio_gpu_ctrl_bh(void *opaque) VirtIOGPU *g = opaque; VirtIOGPUClass *vgc = VIRTIO_GPU_GET_CLASS(g); - vgc->handle_ctrl(VIRTIO_DEVICE(g), g->ctrl_vq); + /* + * Bounce handling to main-loop thread as display UI toolkit + * and GL context are bounded there. + */ + if (qemu_get_thread_id() == g->thread_id) { + vgc->handle_ctrl(VIRTIO_DEVICE(g), g->ctrl_vq); + } else { + aio_bh_schedule_oneshot(qemu_get_aio_context(), + virtio_gpu_ctrl_bh, g); + } } static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq) @@ -1533,6 +1542,7 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) QTAILQ_INIT(&g->reslist); QTAILQ_INIT(&g->cmdq); QTAILQ_INIT(&g->fenceq); + g->thread_id = qemu_get_thread_id(); } static void virtio_gpu_device_unrealize(DeviceState *qdev) diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 58e0f91fda65..d3bd8ed0d28a 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -218,6 +218,8 @@ struct VirtIOGPU { } dmabuf; GArray *capset_ids; + + int thread_id; }; struct VirtIOGPUClass { -- 2.52.0
