qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH for-1.4 2/2] pc_sysfw: fix migration for versions <=


From: Michael Roth
Subject: [Qemu-devel] [PATCH for-1.4 2/2] pc_sysfw: fix migration for versions <= 1.3 via resizable ROM regions
Date: Tue, 5 Feb 2013 18:48:26 -0600

SeaBIOS recently changed in tree from 128KB to 256KB. This causes
migration from versions prior to 1.4 to fail due to the corresponding
RAMBlock sizes not matching. Relaxing this check is insufficient since
it results in a partially overwritten BIOS region that leads to a KVM
exception on post-migration reboot.

Instead, use a VMStateRAMResizeHandler to re-initialize the RAMBlock and
relevant MemoryRegions in cases where the migrated ROM size is
different than the current one.

relevant 'info mtree' for 1.3:

  pci
  0000000000000000-7ffffffffffffffe (prio 0, RW): pci
    00000000000c0000-00000000000dffff (prio 1, RW): pc.rom
    00000000000e0000-00000000000fffff (prio 1, R-): alias isa-bios \
        @pc.bios 0000000000000000-000000000001ffff
    00000000fffe0000-00000000ffffffff (prio 0, R-): pc.bios

relevant 'info mtree' for 1.4 pre-migration:

  pci
  0000000000000000-7ffffffffffffffe (prio 0, RW): pci
    00000000000c0000-00000000000dffff (prio 1, RW): pc.rom
    00000000000e0000-00000000000fffff (prio 1, R-): alias isa-bios \
        @pc.bios 0000000000020000-000000000003ffff
    00000000fffc0000-00000000ffffffff (prio 0, R-): pc.bios

relevant 'info mtree' for 1.4 after the resize handler is called:

  pci
  0000000000000000-7ffffffffffffffe (prio 0, RW): pci
    00000000000c0000-00000000000dffff (prio 1, RW): pc.rom
    00000000000e0000-00000000000fffff (prio 1, R-): alias isa-bios \
        @pc.bios 0000000000000000-000000000001ffff
    00000000fffe0000-00000000ffffffff (prio 0, R-): pc.bios

Tested post-migration (from 1.3) functionality with qemu-jeos,
Ubuntu 12.10, and Windows 7.

Cc: address@hidden
Signed-off-by: Michael Roth <address@hidden>
---
 hw/pc_sysfw.c |  104 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 78 insertions(+), 26 deletions(-)

diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index 7f6c12c..3053de4 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -138,12 +138,84 @@ static void pc_system_flash_init(MemoryRegion *rom_memory,
     pc_isa_bios_init(rom_memory, flash_mem, size);
 }
 
+typedef struct SystemRomResizeState {
+    MemoryRegion *rom_memory;
+    MemoryRegion *isa_bios;
+} SystemRomResizeState;
+
+static void system_rom_memory_init(MemoryRegion *rom_memory,
+                                   int bios_size, bool resizable);
+
+static int system_rom_memory_resize(MemoryRegion *bios, uint64_t size,
+                                    void *opaque)
+{
+    SystemRomResizeState *resize_state = opaque;
+
+    memory_region_del_subregion(resize_state->rom_memory, bios);
+    memory_region_del_subregion(resize_state->rom_memory,
+                                resize_state->isa_bios);
+    memory_region_destroy(resize_state->isa_bios);
+    memory_region_destroy(bios);
+    g_free(bios);
+    g_free(resize_state->isa_bios);
+
+    system_rom_memory_init(resize_state->rom_memory, size, false);
+
+    return 0;
+}
+
+static void system_rom_memory_resize_cleanup(void *opaque)
+{
+    SystemRomResizeState *resize_state = opaque;
+
+    g_free(resize_state);
+}
+
+static void system_rom_memory_init(MemoryRegion *rom_memory,
+                                   int bios_size, bool resizable)
+{
+    MemoryRegion *bios, *isa_bios;
+    int isa_bios_size;
+    SystemRomResizeState *resize_state;
+
+    bios = g_malloc(sizeof(*bios));
+    memory_region_init_ram(bios, "pc.bios", bios_size);
+    vmstate_register_ram_global(bios);
+    memory_region_set_readonly(bios, true);
+
+    /* map the last 128KB of the BIOS in ISA space */
+    isa_bios_size = bios_size;
+    if (isa_bios_size > (128 * 1024)) {
+        isa_bios_size = 128 * 1024;
+    }
+    isa_bios = g_malloc(sizeof(*isa_bios));
+    memory_region_init_alias(isa_bios, "isa-bios", bios,
+                             bios_size - isa_bios_size, isa_bios_size);
+    memory_region_add_subregion_overlap(rom_memory,
+                                        0x100000 - isa_bios_size,
+                                        isa_bios,
+                                        1);
+    memory_region_set_readonly(isa_bios, true);
+
+    /* map all the bios at the top of memory */
+    memory_region_add_subregion(rom_memory,
+                                (uint32_t)(-bios_size),
+                                bios);
+
+    if (resizable) {
+        resize_state = g_malloc0(sizeof(SystemRomResizeState));
+        resize_state->rom_memory = rom_memory;
+        resize_state->isa_bios = isa_bios;
+        vmstate_register_ram_resizable(bios, system_rom_memory_resize,
+                                       system_rom_memory_resize_cleanup,
+                                       resize_state);
+    }
+}
+
 static void old_pc_system_rom_init(MemoryRegion *rom_memory)
 {
     char *filename;
-    MemoryRegion *bios, *isa_bios;
-    int bios_size, isa_bios_size;
-    int ret;
+    int ret, bios_size;
 
     /* BIOS load */
     if (bios_name == NULL) {
@@ -159,10 +231,9 @@ static void old_pc_system_rom_init(MemoryRegion 
*rom_memory)
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
-    bios = g_malloc(sizeof(*bios));
-    memory_region_init_ram(bios, "pc.bios", bios_size);
-    vmstate_register_ram_global(bios);
-    memory_region_set_readonly(bios, true);
+
+    system_rom_memory_init(rom_memory, bios_size, true);
+
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
     if (ret != 0) {
     bios_error:
@@ -172,25 +243,6 @@ static void old_pc_system_rom_init(MemoryRegion 
*rom_memory)
     if (filename) {
         g_free(filename);
     }
-
-    /* map the last 128KB of the BIOS in ISA space */
-    isa_bios_size = bios_size;
-    if (isa_bios_size > (128 * 1024)) {
-        isa_bios_size = 128 * 1024;
-    }
-    isa_bios = g_malloc(sizeof(*isa_bios));
-    memory_region_init_alias(isa_bios, "isa-bios", bios,
-                             bios_size - isa_bios_size, isa_bios_size);
-    memory_region_add_subregion_overlap(rom_memory,
-                                        0x100000 - isa_bios_size,
-                                        isa_bios,
-                                        1);
-    memory_region_set_readonly(isa_bios, true);
-
-    /* map all the bios at the top of memory */
-    memory_region_add_subregion(rom_memory,
-                                (uint32_t)(-bios_size),
-                                bios);
 }
 
 void pc_system_firmware_init(MemoryRegion *rom_memory)
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]