Blob Blame History Raw
From: Cole Robinson <crobinso@redhat.com>
Date: Fri, 16 Aug 2013 12:14:51 -0400
Subject: [PATCH] Fix migration from qemu-kvm

Details are in the code comments for each change. Just lumped this together
to ease patch maintenance.

Everything except the video memory bits can likely be dropped by Fedora 21
time frame. Need to figure out if there's anything to upstream for the
video memory bits.
---
 hw/acpi/piix4.c         |  8 ++++++-
 hw/display/qxl.c        |  9 ++++----
 hw/i386/pc_piix.c       | 61 +++++++++++++++++++++++++++++++++++++++++++++----
 hw/timer/i8254_common.c |  7 +++++-
 4 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 3aaf18c..6fbe57c 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -289,7 +289,13 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
 static const VMStateDescription vmstate_acpi = {
     .name = "piix4_pm",
     .version_id = 3,
-    .minimum_version_id = 3,
+    /*
+     * qemu-kvm 1.2 uses qemu.git version 3 format, but advertised as 2.
+     * This allows incoming migration from qemu-kvm, but breaks incoming
+     * migration from qemu < 1.3.
+     */
+    //minimum_version_id = 3,
+    .minimum_version_id = 2,
     .minimum_version_id_old = 1,
     .load_state_old = acpi_load_old,
     .post_load = vmstate_acpi_post_load,
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index c537057..7ef3eff 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -307,16 +307,14 @@ static inline uint32_t msb_mask(uint32_t val)
     return mask;
 }
 
-static ram_addr_t qxl_rom_size(void)
+static void check_qxl_rom_size(PCIQXLDevice *d)
 {
     uint32_t required_rom_size = sizeof(QXLRom) + sizeof(QXLModes) +
                                  sizeof(qxl_modes);
-    uint32_t rom_size = 8192; /* two pages */
 
     required_rom_size = MAX(required_rom_size, TARGET_PAGE_SIZE);
     required_rom_size = msb_mask(required_rom_size * 2 - 1);
-    assert(required_rom_size <= rom_size);
-    return rom_size;
+    assert(required_rom_size <= d->rom_size);
 }
 
 static void init_qxl_rom(PCIQXLDevice *d)
@@ -1981,7 +1979,7 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
     pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
 
-    qxl->rom_size = qxl_rom_size();
+    check_qxl_rom_size(qxl);
     memory_region_init_ram(&qxl->rom_bar, OBJECT(qxl), "qxl.vrom",
                            qxl->rom_size);
     vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev);
@@ -2309,6 +2307,7 @@ static Property qxl_properties[] = {
         DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
         DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16),
         DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024),
+        DEFINE_PROP_UINT32("rom_size", PCIQXLDevice, rom_size, 8192),
         DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 3df2ff9..28216ee 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -377,6 +377,24 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
     DEFAULT_MACHINE_OPTIONS,
 };
 
+/*
+ * Commit 038c1879a00153b14bce113315b693e8c2944fa9 changed the qxl rom
+ * size to 8192, which fixes incoming migration from qemu 1.0. However
+ * from qemu 1.2 and 1.3 had rom size 16384, so incoming migration
+ * from those versions is now broken.
+ *
+ * Add a rom_size compat property. 1.2 and 1.3 get 16384, everything
+ * else is 8192.
+ *
+ * This isn't actually fool proof, since rom_size can be dependent on
+ * the version of spice qemu is built against:
+ *
+ * https://lists.gnu.org/archive/html/qemu-devel/2013-02/msg03154.html
+ *
+ * However these sizes match what native Fedora packages get, so it's
+ * good enough for now.
+ */
+
 #define PC_COMPAT_1_3 \
 	PC_COMPAT_1_4, \
         {\
@@ -395,8 +413,17 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
             .driver   = "e1000",\
             .property = "autonegotiation",\
             .value    = "off",\
+        },{ \
+            .driver   = "qxl", \
+            .property = "rom_size", \
+            .value    = stringify(16384), \
+        },{\
+            .driver   = "qxl-vga", \
+            .property = "rom_size", \
+            .value    = stringify(16384), \
         }
 
+
 static QEMUMachine pc_machine_v1_3 = {
     .name = "pc-1.3",
     .desc = "Standard PC",
@@ -409,6 +436,19 @@ static QEMUMachine pc_machine_v1_3 = {
     DEFAULT_MACHINE_OPTIONS,
 };
 
+
+/*
+ * https://lists.gnu.org/archive/html/qemu-devel/2013-01/msg02540.html
+ *
+ * qemu-kvm defaulted to vgamem=16MB since at least 0.15, while qemu used
+ * 8MB. For qemu 1.2, the default was changed to 16MB for all devices
+ * except cirrus.
+ *
+ * Make sure cirrus uses 16MB for <= pc-1.2 (the qemu-kvm merge),
+ * and 16MB always for all others. This will break incoming qemu
+ * migration for qemu < 1.3.
+ */
+
 #define PC_COMPAT_1_2 \
         PC_COMPAT_1_3,\
         {\
@@ -432,6 +472,10 @@ static QEMUMachine pc_machine_v1_3 = {
             .property = "revision",\
             .value    = stringify(3),\
         },{\
+            .driver   = "cirrus-vga",\
+            .property = "vgamem_mb",\
+            .value    = stringify(16),\
+        },{\
             .driver   = "VGA",\
             .property = "mmio",\
             .value    = "off",\
@@ -462,25 +506,34 @@ static QEMUMachine pc_machine_v1_2 = {
         },{\
             .driver   = "VGA",\
             .property = "vgamem_mb",\
-            .value    = stringify(8),\
+            .value    = stringify(16),\
         },{\
             .driver   = "vmware-svga",\
             .property = "vgamem_mb",\
-            .value    = stringify(8),\
+            .value    = stringify(16),\
         },{\
             .driver   = "qxl-vga",\
             .property = "vgamem_mb",\
-            .value    = stringify(8),\
+            .value    = stringify(16),\
         },{\
             .driver   = "qxl",\
             .property = "vgamem_mb",\
-            .value    = stringify(8),\
+            .value    = stringify(16),\
         },{\
             .driver   = "virtio-blk-pci",\
             .property = "config-wce",\
             .value    = "off",\
+        },{ \
+            .driver   = "qxl", \
+            .property = "rom_size", \
+            .value    = stringify(8192), \
+        },{\
+            .driver   = "qxl-vga", \
+            .property = "rom_size", \
+            .value    = stringify(8192), \
         }
 
+
 static QEMUMachine pc_machine_v1_1 = {
     .name = "pc-1.1",
     .desc = "Standard PC",
diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c
index 4e5bf0b..cbc00a0 100644
--- a/hw/timer/i8254_common.c
+++ b/hw/timer/i8254_common.c
@@ -267,7 +267,12 @@ static const VMStateDescription vmstate_pit_common = {
     .pre_save = pit_dispatch_pre_save,
     .post_load = pit_dispatch_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3),
+        /* qemu-kvm version_id=2 had 'flags' here which is equivalent
+         * This fixes incoming migration from qemu-kvm 1.0, but breaks
+         * incoming migration from qemu < 1.1
+         */
+        //VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3),
+        VMSTATE_UINT32(channels[0].irq_disabled, PITCommonState),
         VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2,
                              vmstate_pit_channel, PITChannelState),
         VMSTATE_INT64(channels[0].next_transition_time,