Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 394

kvm-83-270.el5_11.src.rpm

From 347f66fb58d1ae83f49200f89af80a930246dcaf Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 29 Jul 2010 17:04:52 -0300
Subject: [PATCH 1/4] introduce __rhel5 marker into the migration/save data (to be used by crash)

RH-Author: Paolo Bonzini <pbonzini@redhat.com>
Message-id: <1280423092-10210-1-git-send-email-pbonzini@redhat.com>
Patchwork-id: 11094
O-Subject: [RHEL5 KVM PATCH v2] introduce __rhel5 marker into the migration/save
	data (to be used by crash)
Bugzilla: 603026
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Juan Quintela <quintela@redhat.com>

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=603026

Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2626091

RHEL5 KVM uses version 9 for its CPU state save data, but the format is
very different from the version 9 of upstream QEMU.  This causes problems
in crash, which uses QEMU's savefiles as kvm core dumps.

Until now, the differences did nothing problematic (crash missed the
states for all but the first CPU, but it doesn't use those anyway).
However, for version 9 upstream does this:

        int32_t pending_irq = (int32_t) get_be32 (fp);
        if (pending_irq >= 0)
                dx86->kvm.int_bitmap[pending_irq / 64] |=

instead of this which is still done in RHEL5:

        for (i = 0; i < 4; i++)
                dx86->kvm.int_bitmap[i] = get_be64 (fp);

(note that the above source code comes from crash, not QEMU).  In other
words, when reading a RHEL5.5+ dump the first 32 bits of the bitmap are
treated as an index, causing an out-of-bounds access.

Of course, adding a "<= 255" check is easily done, but it's only a matter
of time until RHEL5's version will hit 12 and we'll have serious problems
handling both RHEL5 and RHEL6 dumps.

For RHEL6, we'll hopefully fix the problem with Juan's subsection support
(and teach crash about those).

For RHEL5, what to do depends on the -M value.  rhel5.4.0 and rhel5.4.4
are safe; rhel5.5.0 isn't, but we cannot change it; for RHEL5.6 and later
we add a new __rhel5 marker that crash looks at to distinguish the two
version number "namespaces".  This of course requires adding a new
machine type, and upgrading rhel5.5.0 machines to it.

Registering the marker before the cpu ensures that old crash will fail
to load the dump gracefully instead of accessing random memory, so
the only problematic machine type will be rhel5.5.0.  We might consider
adding heuristics to crash later.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Cc: Juan Quintela <quintela@redhat.com>
---
	v1->v2: commit message editing, override default version for
	    RHEL < 5.6.0 rather than the other way round

 qemu/exec.c                |   15 +++++++++++++++
 qemu/hw/boards.h           |    1 +
 qemu/hw/pc.c               |   14 ++++++++++++++
 qemu/target-i386/machine.c |    1 +
 4 files changed, 31 insertions(+), 0 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 qemu/exec.c                |   15 +++++++++++++++
 qemu/hw/boards.h           |    1 +
 qemu/hw/pc.c               |   14 ++++++++++++++
 qemu/target-i386/machine.c |    1 +
 4 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/qemu/exec.c b/qemu/exec.c
index 6943e56..cf5a859 100644
--- a/qemu/exec.c
+++ b/qemu/exec.c
@@ -540,6 +540,15 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
 
     return 0;
 }
+
+static void do_nothing_save(QEMUFile *f, void *opaque, int version_id)
+{
+}
+
+static int do_nothing_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return 0;
+}
 #endif
 
 void cpu_exec_init(CPUState *env)
@@ -564,6 +573,12 @@ void cpu_exec_init(CPUState *env)
 #endif
     *penv = env;
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
+    if (cpu_index == 0) {
+        int version_id = machine_device_version("__rhel5", 0);
+        if (version_id != SAVEVM_DISABLED)
+            register_savevm("__rhel5", 0, version_id, do_nothing_save,
+                            do_nothing_load, env);
+    }
     register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
                     cpu_common_save, cpu_common_load, env);
     register_savevm("cpu", cpu_index,
diff --git a/qemu/hw/boards.h b/qemu/hw/boards.h
index 0fe63b1..ecd8ae2 100644
--- a/qemu/hw/boards.h
+++ b/qemu/hw/boards.h
@@ -42,6 +42,7 @@ extern QEMUMachine axisdev88_machine;
 extern QEMUMachine rhel540_machine;
 extern QEMUMachine rhel544_machine;
 extern QEMUMachine rhel550_machine;
+extern QEMUMachine rhel560_machine;
 extern QEMUMachine isapc_machine;
 
 /* ppc.c */
diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c
index 9f8a50a..d4eac21 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -1290,6 +1290,7 @@ QEMUMachine rhel540_machine = {
 		{ .name = "ide", .version_id =  3},
 		{ .name = "virtio-blk", .version_id =  2},
 		{ .name = "qxl", .version_id =  3},
+		{ .name = "__rhel5", .version_id =  SAVEVM_DISABLED},
 		{ /* Empty */ }
     },
 };
@@ -1305,6 +1306,7 @@ QEMUMachine rhel544_machine = {
 		{ .name = "ide", .version_id =  3},
 		{ .name = "virtio-blk", .version_id =  2},
 		{ .name = "qxl", .version_id =  3},
+		{ .name = "__rhel5", .version_id =  SAVEVM_DISABLED},
 		{ /* Empty */ }
     },
 };
@@ -1316,6 +1318,18 @@ QEMUMachine rhel550_machine = {
     .ram_require = VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,
     .max_cpus = 255,
     .devices = (DeviceVersion []) {
+		{ .name = "__rhel5", .version_id =  SAVEVM_DISABLED},
+		{ /* Empty */ }
+    },
+};
+
+QEMUMachine rhel560_machine = {
+    .name = "rhel5.6.0",
+    .desc = "RHEL 5.6.0 PC",
+    .init = pc_init_pci,
+    .ram_require = VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,
+    .max_cpus = 255,
+    .devices = (DeviceVersion []) {
 		{ /* Empty */ }
     },
 };
diff --git a/qemu/target-i386/machine.c b/qemu/target-i386/machine.c
index a65b55d..3d9b043 100644
--- a/qemu/target-i386/machine.c
+++ b/qemu/target-i386/machine.c
@@ -11,6 +11,7 @@ void register_machines(void)
     qemu_register_machine(&rhel540_machine);
     qemu_register_machine(&rhel544_machine);
     qemu_register_machine(&rhel550_machine);
+    qemu_register_machine(&rhel560_machine);
 #ifdef CONFIG_ISAPC
     qemu_register_machine(&isapc_machine);
 #endif
-- 
1.6.5.5