carlwgeorge / rpms / qemu

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