Skip to content

Commit 8ffe062

Browse files
Steve SistareFabiano Rosas
authored andcommitted
hw/qxl: fix cpr
During normal migration, new QEMU creates and initializes memory regions, then loads the preserved contents of the region from vmstate. During CPR, memory regions are preserved in place, then the realize method initializes the regions contents, losing the old contents. To fix, skip writes to the qxl memory regions during CPR load. Reported-by: [email protected] Tested-by: [email protected] Signed-off-by: Steve Sistare <[email protected]> Reviewed-by: Fabiano Rosas <[email protected]> Message-ID: <[email protected]> Signed-off-by: Fabiano Rosas <[email protected]>
1 parent b42f281 commit 8ffe062

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

hw/display/qxl.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "qemu/module.h"
3131
#include "hw/qdev-properties.h"
3232
#include "system/runstate.h"
33+
#include "migration/cpr.h"
3334
#include "migration/vmstate.h"
3435
#include "trace.h"
3536

@@ -333,6 +334,10 @@ static void init_qxl_rom(PCIQXLDevice *d)
333334
uint32_t fb;
334335
int i, n;
335336

337+
if (cpr_is_incoming()) {
338+
goto skip_init;
339+
}
340+
336341
memset(rom, 0, d->rom_size);
337342

338343
rom->magic = cpu_to_le32(QXL_ROM_MAGIC);
@@ -390,6 +395,7 @@ static void init_qxl_rom(PCIQXLDevice *d)
390395
sizeof(rom->client_monitors_config));
391396
}
392397

398+
skip_init:
393399
d->shadow_rom = *rom;
394400
d->rom = rom;
395401
d->modes = modes;
@@ -403,6 +409,9 @@ static void init_qxl_ram(PCIQXLDevice *d)
403409

404410
buf = d->vga.vram_ptr;
405411
d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset));
412+
if (cpr_is_incoming()) {
413+
return;
414+
}
406415
d->ram->magic = cpu_to_le32(QXL_RAM_MAGIC);
407416
d->ram->int_pending = cpu_to_le32(0);
408417
d->ram->int_mask = cpu_to_le32(0);
@@ -539,6 +548,10 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
539548

540549
trace_qxl_interface_set_compression_level(qxl->id, level);
541550
qxl->shadow_rom.compression_level = cpu_to_le32(level);
551+
if (cpr_is_incoming()) {
552+
assert(qxl->rom->compression_level == cpu_to_le32(level));
553+
return;
554+
}
542555
qxl->rom->compression_level = cpu_to_le32(level);
543556
qxl_rom_set_dirty(qxl);
544557
}
@@ -997,7 +1010,8 @@ static void interface_set_client_capabilities(QXLInstance *sin,
9971010
}
9981011

9991012
if (runstate_check(RUN_STATE_INMIGRATE) ||
1000-
runstate_check(RUN_STATE_POSTMIGRATE)) {
1013+
runstate_check(RUN_STATE_POSTMIGRATE) ||
1014+
cpr_is_incoming()) {
10011015
return;
10021016
}
10031017

@@ -1200,6 +1214,10 @@ static void qxl_reset_state(PCIQXLDevice *d)
12001214
{
12011215
QXLRom *rom = d->rom;
12021216

1217+
if (cpr_is_incoming()) {
1218+
return;
1219+
}
1220+
12031221
qxl_check_state(d);
12041222
d->shadow_rom.update_id = cpu_to_le32(0);
12051223
*rom = d->shadow_rom;
@@ -1370,8 +1388,11 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
13701388
memslot.virt_start = virt_start + (guest_start - pci_start);
13711389
memslot.virt_end = virt_start + (guest_end - pci_start);
13721390
memslot.addr_delta = memslot.virt_start - delta;
1373-
memslot.generation = d->rom->slot_generation = 0;
1374-
qxl_rom_set_dirty(d);
1391+
if (!cpr_is_incoming()) {
1392+
d->rom->slot_generation = 0;
1393+
qxl_rom_set_dirty(d);
1394+
}
1395+
memslot.generation = d->rom->slot_generation;
13751396

13761397
qemu_spice_add_memslot(&d->ssd, &memslot, async);
13771398
d->guest_slots[slot_id].mr = mr;

0 commit comments

Comments
 (0)