virtio-gpu: Ensure BHs are invoked only from main-loop thread

QEMU's display GL core is tied to main-loop thread and virtio-gpu
interacts with display while processing GPU commands. Virtio-gpu BHs
work in generic AIO context that can be invoked on vCPU thread, while
GL and UI toolkits are bound to the main-loop thread.

Make virtio-gpu BHs use iohandler AIO context that is handled in a
main-loop thread only.

 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: qemu-stable@nongnu.org
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Message-ID: <20260303151422.977399-8-dmitry.osipenko@collabora.com>
Message-ID: <20260304165043.1437519-10-alex.bennee@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
(cherry picked from commit 235f9b3638)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
This commit is contained in:
Dmitry Osipenko
2026-03-04 16:50:31 +00:00
committed by Michael Tokarev
parent deb60fe8f5
commit 0f58b60bdb
4 changed files with 26 additions and 6 deletions

View File

@@ -1199,9 +1199,9 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
}
#if VIRGL_VERSION_MAJOR >= 1
gl->cmdq_resume_bh = aio_bh_new(qemu_get_aio_context(),
virtio_gpu_virgl_resume_cmdq_bh,
g);
gl->cmdq_resume_bh = virtio_bh_io_new_guarded(DEVICE(g),
virtio_gpu_virgl_resume_cmdq_bh,
g);
#endif
return 0;

View File

@@ -1514,9 +1514,9 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
g->ctrl_vq = virtio_get_queue(vdev, 0);
g->cursor_vq = virtio_get_queue(vdev, 1);
g->ctrl_bh = virtio_bh_new_guarded(qdev, virtio_gpu_ctrl_bh, g);
g->cursor_bh = virtio_bh_new_guarded(qdev, virtio_gpu_cursor_bh, g);
g->reset_bh = qemu_bh_new(virtio_gpu_reset_bh, g);
g->ctrl_bh = virtio_bh_io_new_guarded(qdev, virtio_gpu_ctrl_bh, g);
g->cursor_bh = virtio_bh_io_new_guarded(qdev, virtio_gpu_cursor_bh, g);
g->reset_bh = virtio_bh_io_new_guarded(qdev, virtio_gpu_reset_bh, g);
qemu_cond_init(&g->reset_cond);
QTAILQ_INIT(&g->reslist);
QTAILQ_INIT(&g->cmdq);

View File

@@ -4403,3 +4403,13 @@ QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
return qemu_bh_new_full(cb, opaque, name,
&transport->mem_reentrancy_guard);
}
QEMUBH *virtio_bh_io_new_guarded_full(DeviceState *dev,
QEMUBHFunc *cb, void *opaque,
const char *name)
{
DeviceState *transport = qdev_get_parent_bus(dev)->parent;
return aio_bh_new_full(iohandler_get_aio_context(), cb, opaque, name,
&transport->mem_reentrancy_guard);
}

View File

@@ -543,4 +543,14 @@ QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
#define virtio_bh_new_guarded(dev, cb, opaque) \
virtio_bh_new_guarded_full((dev), (cb), (opaque), (stringify(cb)))
/*
* The "_io" variant runs BH only on a main-loop thread, while generic BH
* may run on a vCPU thread.
*/
QEMUBH *virtio_bh_io_new_guarded_full(DeviceState *dev,
QEMUBHFunc *cb, void *opaque,
const char *name);
#define virtio_bh_io_new_guarded(dev, cb, opaque) \
virtio_bh_io_new_guarded_full((dev), (cb), (opaque), (stringify(cb)))
#endif