From e55e5fd43113a5b266efa6d17e44f0e9231a98ed Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 25 Aug 2010 16:08:37 +0000
Subject: [PATCH 31/39] qxl: savevm fixes
---
hw/qxl.c | 125 +++++++++++++++++++++++++++++++++++++++++++++----------------
hw/qxl.h | 6 +++
2 files changed, 98 insertions(+), 33 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c
index 86c0e03..4a15200 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1087,6 +1087,14 @@ static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
{
PCIQXLDevice *qxl = opaque;
qemu_spice_vm_change_state_handler(&qxl->ssd, running, reason);
+
+ if (!running && qxl->mode == QXL_MODE_NATIVE) {
+ /* dirty all vram (which holds surfaces) to make sure it is saved */
+ /* FIXME #1: should go out during "live" stage */
+ /* FIXME #2: we only need to save the areas which are actually used */
+ ram_addr_t addr = qxl->vram_offset;
+ qxl_set_dirty(addr, addr + qxl->vram_size);
+ }
}
/* display change listener */
@@ -1134,6 +1142,8 @@ static int qxl_init(PCIDevice *dev)
qxl->id = device_id;
qxl->mode = QXL_MODE_UNDEFINED;
qxl->generation = 1;
+ qxl->num_memslots = NUM_MEMSLOTS;
+ qxl->num_surfaces = NUM_SURFACES;
switch (qxl->revision) {
case 1: /* spice 0.4 -- qxl-1 */
@@ -1183,7 +1193,8 @@ static int qxl_init(PCIDevice *dev)
if (ram_size < 16 * 1024 * 1024)
ram_size = 16 * 1024 * 1024;
qxl->vga.vram_size = ram_size;
- qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar0", qxl->vga.vram_size);
+ qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vgavram",
+ qxl->vga.vram_size);
qxl->vga.vram_ptr = qemu_get_ram_ptr(qxl->vga.vram_offset);
pci_config_set_class(config, PCI_CLASS_DISPLAY_OTHER);
@@ -1195,14 +1206,14 @@ static int qxl_init(PCIDevice *dev)
pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
qxl->rom_size = qxl_rom_size();
- qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar2", qxl->rom_size);
+ qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vrom", qxl->rom_size);
init_qxl_rom(qxl);
init_qxl_ram(qxl);
if (qxl->vram_size < 16 * 1024 * 1024)
qxl->vram_size = 16 * 1024 * 1024;
qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
- qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar1", qxl->vram_size);
+ qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vram", qxl->vram_size);
pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
msb_mask(QXL_IO_RANGE_SIZE * 2 - 1),
@@ -1237,14 +1248,12 @@ static void qxl_pre_save(void *opaque)
uint8_t *ram_start = d->vga.vram_ptr;
dprintf(d, 1, "%s:\n", __FUNCTION__);
-#if 1 /* wanna zap this */
if (d->last_release == NULL) {
d->last_release_offset = 0;
} else {
d->last_release_offset = (uint8_t *)d->last_release - ram_start;
}
assert(d->last_release_offset < d->vga.vram_size);
-#endif
}
static int qxl_pre_load(void *opaque)
@@ -1306,29 +1315,55 @@ static int qxl_post_load(void *opaque, int version)
}
dprintf(d, 1, "%s: done\n", __FUNCTION__);
-#if 1 /* wanna zap this */
- if (d->last_release_offset >= d->vga.vram_size) {
- dprintf(d, 1, "%s: invalid last_release_offset %u, ram_size %u\n",
- __FUNCTION__, d->last_release_offset, d->vga.vram_size);
- exit(-1);
- }
-
+ assert(d->last_release_offset < d->vga.vram_size);
if (d->last_release_offset == 0) {
d->last_release = NULL;
} else {
d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset);
}
-#endif
+
+ /* spice 0.4 compatibility -- accept but ignore */
+ free(d->worker_data);
+ d->worker_data = NULL;
+ d->worker_data_size = 0;
return 0;
}
-#define QXL_VER 1
+#define QXL_SAVE_VERSION 20
+
+static bool qxl_test_worker_data(void *opaque, int version_id)
+{
+ PCIQXLDevice* d = opaque;
+
+ if (d->revision != 1) {
+ return false;
+ }
+ if (!d->worker_data_size) {
+ return false;
+ }
+ if (!d->worker_data) {
+ d->worker_data = qemu_malloc(d->worker_data_size);
+ }
+ return true;
+}
+
+static bool qxl_test_spice04(void *opaque, int version_id)
+{
+ PCIQXLDevice* d = opaque;
+ return d->revision == 1;
+}
+
+static bool qxl_test_spice06(void *opaque)
+{
+ PCIQXLDevice* d = opaque;
+ return d->revision > 1;
+}
static VMStateDescription qxl_memslot = {
.name = "qxl-memslot",
- .version_id = QXL_VER,
- .minimum_version_id = QXL_VER,
+ .version_id = QXL_SAVE_VERSION,
+ .minimum_version_id = QXL_SAVE_VERSION,
.fields = (VMStateField[]) {
VMSTATE_UINT64(slot.mem_start, struct guest_slots),
VMSTATE_UINT64(slot.mem_end, struct guest_slots),
@@ -1339,8 +1374,8 @@ static VMStateDescription qxl_memslot = {
static VMStateDescription qxl_surface = {
.name = "qxl-surface",
- .version_id = QXL_VER,
- .minimum_version_id = QXL_VER,
+ .version_id = QXL_SAVE_VERSION,
+ .minimum_version_id = QXL_SAVE_VERSION,
.fields = (VMStateField[]) {
VMSTATE_UINT32(width, QXLSurfaceCreate),
VMSTATE_UINT32(height, QXLSurfaceCreate),
@@ -1355,34 +1390,58 @@ static VMStateDescription qxl_surface = {
}
};
+static VMStateDescription qxl_vmstate_spice06 = {
+ .name = "qxl/spice06",
+ .version_id = QXL_SAVE_VERSION,
+ .minimum_version_id = QXL_SAVE_VERSION,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
+ VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
+ qxl_memslot, struct guest_slots),
+ VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
+ qxl_surface, QXLSurfaceCreate),
+ VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
+ VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
+ vmstate_info_uint64, uint64_t),
+ VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static VMStateDescription qxl_vmstate = {
.name = "qxl",
- .version_id = QXL_VER,
- .minimum_version_id = QXL_VER,
+ .version_id = QXL_SAVE_VERSION,
+ .minimum_version_id = QXL_SAVE_VERSION,
.pre_save = qxl_pre_save,
.pre_load = qxl_pre_load,
.post_load = qxl_post_load,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
- VMSTATE_STRUCT(vga, PCIQXLDevice, QXL_VER, vmstate_vga_common, VGACommonState),
+ VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
-#if 1 /* wanna zap this */
VMSTATE_UINT32(num_free_res, PCIQXLDevice),
VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
-#endif
VMSTATE_UINT32(mode, PCIQXLDevice),
VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
-#if 1 /* new stuff */
- VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, QXL_VER,
- qxl_memslot, struct guest_slots),
- VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, QXL_VER,
- qxl_surface, QXLSurfaceCreate),
- VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, QXL_VER,
- vmstate_info_uint64, uint64_t),
- VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
-#endif
+
+ /* spice 0.4 sends/expects them */
+ VMSTATE_VBUFFER_UINT32(vga.vram_ptr, PCIQXLDevice, 0, qxl_test_spice04, 0,
+ vga.vram_size),
+ VMSTATE_UINT32_TEST(worker_data_size, PCIQXLDevice, qxl_test_spice04),
+ VMSTATE_VBUFFER_UINT32(worker_data, PCIQXLDevice, 0, qxl_test_worker_data, 0,
+ worker_data_size),
+
VMSTATE_END_OF_LIST()
- }
+ },
+ .subsections = (VMStateSubsection[]) {
+ {
+ /* additional spice 0.6 state */
+ .vmsd = &qxl_vmstate_spice06,
+ .needed = qxl_test_spice06,
+ },{
+ /* end of list */
+ },
+ },
};
static PCIDeviceInfo qxl_info = {
diff --git a/hw/qxl.h b/hw/qxl.h
index 1216405..caf3684 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -24,6 +24,9 @@ typedef struct PCIQXLDevice {
int generation;
uint32_t revision;
+ int32_t num_memslots;
+ int32_t num_surfaces;
+
struct guest_slots {
QXLMemSlot slot;
void *ptr;
@@ -74,6 +77,9 @@ typedef struct PCIQXLDevice {
/* io bar */
uint32_t io_base;
+ /* spice 0.4 loadvm compatibility */
+ void *worker_data;
+ uint32_t worker_data_size;
} PCIQXLDevice;
#define PANIC_ON(x) if ((x)) { \
--
1.7.2.3