@samitouri / QOSamiQemu / commits / d7189d4009

hw/display/vga-isa: Fix migration of the isa-vga device

QEMU currently crashes when migrating a guest that uses the isa-vga device as display. This happens because vga_isa_class_initfn() registers a vmsd for vmstate_vga_common that operates on VGACommonState. But the isa-vga device is derived from ISADevice, not from VGACommonState, so the migration code tries to fill in the data for VGACommonState to the memory that is a ISADevice instead, which is of cause causing trouble. We need an indirection here as it's also e.g. done in vga-pci.c, so that the migration data gets filled into the right location. While we're at it, also drop the "global_vmstate = true" here. Since migration was broken for this device during the last 15 years (!) anyway, we don't have to worry about maintaining backward compatibility with this switch for older versions of QEMU anymore. Fixes: 7435b791ca9 ("vga-isa: convert to qdev") Reviewed-by: Fabiano Rosas <farosas@suse.de> Signed-off-by: Thomas Huth <thuth@redhat.com> Message-ID: <20260326113457.159065-1-thuth@redhat.com>

Thomas Huth committed Mar 26, 2026 at 12:34 UTC d7189d40099b3c669368026fcdb156996e79b038
1 file changed +11 -2
hw/display/vga-isa.c
+11 -2
@@ -32,6 +32,7 @@
32 #include "qemu/timer.h"
33 #include "hw/core/loader.h"
34 #include "hw/core/qdev-properties.h"
35 +#include "migration/vmstate.h"
36 #include "ui/console.h"
37 #include "qom/object.h"
38
@@ -62,7 +63,6 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
63 MemoryRegion *vga_io_memory;
64 const MemoryRegionPortio *vga_ports, *vbe_ports;
65
65 - s->global_vmstate = true;
66 if (!vga_common_init(s, OBJECT(dev), errp)) {
67 return;
68 }
@@ -88,6 +88,15 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
88 rom_add_vga(VGABIOS_FILENAME);
89 }
90
91 +static const VMStateDescription vmstate_vga_isa = {
92 + .name = "vga-isa",
93 + .version_id = 1,
94 + .fields = (const VMStateField[]) {
95 + VMSTATE_STRUCT(state, ISAVGAState, 0, vmstate_vga_common, VGACommonState),
96 + VMSTATE_END_OF_LIST()
97 + }
98 +};
99 +
100 static const Property vga_isa_properties[] = {
101 DEFINE_PROP_UINT32("vgamem_mb", ISAVGAState, state.vram_size_mb, 8),
102 };
@@ -98,7 +107,7 @@ static void vga_isa_class_initfn(ObjectClass *klass, const void *data)
107
108 dc->realize = vga_isa_realizefn;
109 device_class_set_legacy_reset(dc, vga_isa_reset);
101 - dc->vmsd = &vmstate_vga_common;
110 + dc->vmsd = &vmstate_vga_isa;
111 device_class_set_props(dc, vga_isa_properties);
112 set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
113 }