mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
vfio/pci: close display console during unrealize, not finalize
The QemuGraphicConsole holds a strong QOM link back to the device via its "device" property (OBJ_PROP_LINK_STRONG). When graphic_console_close() is only called from vfio_display_finalize() during object finalize, this creates a ref-cycle deadlock: the device can't reach refcount 0 because the console holds a strong ref, but the console's ref is only dropped by graphic_console_close() which runs inside finalize. Split the display teardown into two phases: - vfio_display_exit(): called during unrealize (vfio_exitfn), closes the graphic console to break the ref cycle, and removes display region subregions while the parent memory regions are still alive. - vfio_display_finalize(): remains in finalize (vfio_pci_put_device), frees display region memory, dmabuf, and edid resources. The region memory contains QOM child objects (MemoryRegions) that must stay alive until QOM finalization has processed them. Acked-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20260623-b4-ui-v4-5-4656aec3398d@redhat.com>
This commit is contained in:
@@ -2347,6 +2347,7 @@ S: Supported
|
||||
F: hw/vfio/*
|
||||
F: util/vfio-helpers.c
|
||||
F: include/hw/vfio/
|
||||
F: docs/devel/vfio-mdpy.rst
|
||||
F: docs/devel/migration/vfio.rst
|
||||
F: qapi/vfio.json
|
||||
F: migration/vfio-stub.c
|
||||
|
||||
@@ -505,15 +505,6 @@ static bool vfio_display_region_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vfio_display_region_exit(VFIODisplay *dpy)
|
||||
{
|
||||
if (!dpy->region.buffer.size) {
|
||||
return;
|
||||
}
|
||||
|
||||
vfio_region_exit(&dpy->region.buffer);
|
||||
vfio_region_finalize(&dpy->region.buffer);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@@ -547,17 +538,31 @@ bool vfio_display_probe(VFIOPCIDevice *vdev, Error **errp)
|
||||
return false;
|
||||
}
|
||||
|
||||
void vfio_display_exit(VFIOPCIDevice *vdev)
|
||||
{
|
||||
if (!vdev->dpy) {
|
||||
return;
|
||||
}
|
||||
|
||||
vfio_display_dmabuf_exit(vdev->dpy);
|
||||
qemu_graphic_console_close(vdev->dpy->con);
|
||||
if (vdev->dpy->region.buffer.size) {
|
||||
vfio_region_exit(&vdev->dpy->region.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void vfio_display_finalize(VFIOPCIDevice *vdev)
|
||||
{
|
||||
if (!vdev->dpy) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_graphic_console_close(vdev->dpy->con);
|
||||
vfio_display_dmabuf_exit(vdev->dpy);
|
||||
vfio_display_region_exit(vdev->dpy);
|
||||
if (vdev->dpy->region.buffer.size) {
|
||||
vfio_region_finalize(&vdev->dpy->region.buffer);
|
||||
}
|
||||
vfio_display_edid_exit(vdev->dpy);
|
||||
g_free(vdev->dpy);
|
||||
vdev->dpy = NULL;
|
||||
}
|
||||
|
||||
static bool migrate_needed(void *opaque)
|
||||
|
||||
@@ -3591,6 +3591,7 @@ static void vfio_pci_realize(PCIDevice *pdev, Error **errp)
|
||||
return;
|
||||
|
||||
out_deregister:
|
||||
vfio_display_exit(vdev);
|
||||
if (vdev->interrupt == VFIO_INT_INTx) {
|
||||
vfio_intx_disable(vdev);
|
||||
}
|
||||
@@ -3624,6 +3625,7 @@ static void vfio_exitfn(PCIDevice *pdev)
|
||||
VFIOPCIDevice *vdev = VFIO_PCI_DEVICE(pdev);
|
||||
VFIODevice *vbasedev = &vdev->vbasedev;
|
||||
|
||||
vfio_display_exit(vdev);
|
||||
vfio_unregister_req_notifier(vdev);
|
||||
vfio_unregister_err_notifier(vdev);
|
||||
pci_device_set_intx_routing_notifier(pdev, NULL);
|
||||
|
||||
@@ -270,6 +270,7 @@ bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp);
|
||||
|
||||
void vfio_display_reset(VFIOPCIDevice *vdev);
|
||||
bool vfio_display_probe(VFIOPCIDevice *vdev, Error **errp);
|
||||
void vfio_display_exit(VFIOPCIDevice *vdev);
|
||||
void vfio_display_finalize(VFIOPCIDevice *vdev);
|
||||
|
||||
extern const VMStateDescription vfio_display_vmstate;
|
||||
|
||||
Reference in New Issue
Block a user