|
|
9ae3a8 |
From 9f136b4ed4ecd83a2de6ffa52775286b106bb5f5 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Laszlo Ersek <lersek@redhat.com>
|
|
|
9ae3a8 |
Date: Thu, 17 Apr 2014 11:13:59 +0200
|
|
|
9ae3a8 |
Subject: [PATCH 10/12] qemu_loadvm_state(): shadow SeaBIOS for VM incoming from RHEL-6 host
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Laszlo Ersek <lersek@redhat.com>
|
|
|
9ae3a8 |
Message-id: <1397733239-8835-1-git-send-email-lersek@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 58498
|
|
|
9ae3a8 |
O-Subject: [RHEL-7.0 0day qemu-kvm PATCH v2] qemu_loadvm_state(): shadow SeaBIOS for VM incoming from RHEL-6 host
|
|
|
9ae3a8 |
Bugzilla: 1027565
|
|
|
9ae3a8 |
RH-Acked-by: Dr. David Alan Gilbert (git) <dgilbert@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Marcel Apfelbaum <marcel.a@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1027565
|
|
|
9ae3a8 |
Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=7352678
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RHEL-only patch.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
SeaBIOS's shadowing logic has no effect on "pc.ram" (only on "pc.bios" and
|
|
|
9ae3a8 |
"pc.rom") when it runs on the RHEL-6 emulator. When such a guest is
|
|
|
9ae3a8 |
migrated to the RHEL-7 emulator, where the PAM registers actually work,
|
|
|
9ae3a8 |
these two UMBs under 1MB simply disappear from the guest's view, breaking
|
|
|
9ae3a8 |
reboot and S3 resume.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Tested extensively by QE.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Notes:
|
|
|
9ae3a8 |
Changes in v2:
|
|
|
9ae3a8 |
- print message to stderr when we shadow the UMBs manually [Dave]
|
|
|
9ae3a8 |
- also copy C and D segments from pc.rom to pc.ram
|
|
|
9ae3a8 |
- move to qemu_loadvm_state() from ram_load() -- we must shadow only
|
|
|
9ae3a8 |
when all RAMBlocks have been loaded [Dave]
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
include/sysemu/sysemu.h | 1 +
|
|
|
9ae3a8 |
hw/i386/pc_piix.c | 1 +
|
|
|
9ae3a8 |
savevm.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
9ae3a8 |
3 files changed, 68 insertions(+)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
hw/i386/pc_piix.c | 1 +
|
|
|
9ae3a8 |
include/sysemu/sysemu.h | 1 +
|
|
|
9ae3a8 |
savevm.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
9ae3a8 |
3 files changed, 68 insertions(+), 0 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
index 940816f..fea98b6 100644
|
|
|
9ae3a8 |
--- a/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
+++ b/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
@@ -954,6 +954,7 @@ static void pc_compat_rhel650(QEMUMachineInitArgs *args)
|
|
|
9ae3a8 |
rom_file_has_mr = false;
|
|
|
9ae3a8 |
has_acpi_build = false;
|
|
|
9ae3a8 |
gigabyte_align = false;
|
|
|
9ae3a8 |
+ shadow_bios_after_incoming = true;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
static void pc_init_rhel650(QEMUMachineInitArgs *args)
|
|
|
9ae3a8 |
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
|
|
|
9ae3a8 |
index 8dc0a4c..07181ac 100644
|
|
|
9ae3a8 |
--- a/include/sysemu/sysemu.h
|
|
|
9ae3a8 |
+++ b/include/sysemu/sysemu.h
|
|
|
9ae3a8 |
@@ -84,6 +84,7 @@ void qemu_savevm_state_complete(QEMUFile *f);
|
|
|
9ae3a8 |
void qemu_savevm_state_cancel(void);
|
|
|
9ae3a8 |
uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
|
|
|
9ae3a8 |
int qemu_loadvm_state(QEMUFile *f);
|
|
|
9ae3a8 |
+extern bool shadow_bios_after_incoming;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
/* SLIRP */
|
|
|
9ae3a8 |
void do_info_slirp(Monitor *mon);
|
|
|
9ae3a8 |
diff --git a/savevm.c b/savevm.c
|
|
|
9ae3a8 |
index 4d92a7b..6efbb75 100644
|
|
|
9ae3a8 |
--- a/savevm.c
|
|
|
9ae3a8 |
+++ b/savevm.c
|
|
|
9ae3a8 |
@@ -52,6 +52,8 @@
|
|
|
9ae3a8 |
#define ARP_PTYPE_IP 0x0800
|
|
|
9ae3a8 |
#define ARP_OP_REQUEST_REV 0x3
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+bool shadow_bios_after_incoming;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
static int announce_self_create(uint8_t *buf,
|
|
|
9ae3a8 |
uint8_t *mac_addr)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
@@ -2195,6 +2197,63 @@ typedef struct LoadStateEntry {
|
|
|
9ae3a8 |
int version_id;
|
|
|
9ae3a8 |
} LoadStateEntry;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+static void shadow_bios(void)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ RAMBlock *block, *ram, *oprom, *bios;
|
|
|
9ae3a8 |
+ size_t one_meg, oprom_size, bios_size;
|
|
|
9ae3a8 |
+ uint8_t *cd_seg_host, *ef_seg_host;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ ram = NULL;
|
|
|
9ae3a8 |
+ oprom = NULL;
|
|
|
9ae3a8 |
+ bios = NULL;
|
|
|
9ae3a8 |
+ QTAILQ_FOREACH(block, &ram_list.blocks, next) {
|
|
|
9ae3a8 |
+ if (strcmp("pc.ram", block->idstr) == 0) {
|
|
|
9ae3a8 |
+ assert(ram == NULL);
|
|
|
9ae3a8 |
+ ram = block;
|
|
|
9ae3a8 |
+ } else if (strcmp("pc.rom", block->idstr) == 0) {
|
|
|
9ae3a8 |
+ assert(oprom == NULL);
|
|
|
9ae3a8 |
+ oprom = block;
|
|
|
9ae3a8 |
+ } else if (strcmp("pc.bios", block->idstr) == 0) {
|
|
|
9ae3a8 |
+ assert(bios == NULL);
|
|
|
9ae3a8 |
+ bios = block;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+ assert(ram != NULL);
|
|
|
9ae3a8 |
+ assert(oprom != NULL);
|
|
|
9ae3a8 |
+ assert(bios != NULL);
|
|
|
9ae3a8 |
+ assert(memory_region_is_ram(ram->mr));
|
|
|
9ae3a8 |
+ assert(memory_region_is_ram(oprom->mr));
|
|
|
9ae3a8 |
+ assert(memory_region_is_ram(bios->mr));
|
|
|
9ae3a8 |
+ assert(int128_eq(ram->mr->size, int128_make64(ram->length)));
|
|
|
9ae3a8 |
+ assert(int128_eq(oprom->mr->size, int128_make64(oprom->length)));
|
|
|
9ae3a8 |
+ assert(int128_eq(bios->mr->size, int128_make64(bios->length)));
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ one_meg = 1024 * 1024;
|
|
|
9ae3a8 |
+ oprom_size = 128 * 1024;
|
|
|
9ae3a8 |
+ bios_size = 128 * 1024;
|
|
|
9ae3a8 |
+ assert(ram->length >= one_meg);
|
|
|
9ae3a8 |
+ assert(oprom->length == oprom_size);
|
|
|
9ae3a8 |
+ assert(bios->length == bios_size);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ ef_seg_host = memory_region_get_ram_ptr(ram->mr) + (one_meg - bios_size);
|
|
|
9ae3a8 |
+ cd_seg_host = ef_seg_host - oprom_size;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ /* This is a crude hack, but we must distinguish a rhel6.x.0 machtype guest
|
|
|
9ae3a8 |
+ * coming in from a RHEL-6 emulator (where shadowing has had no effect on
|
|
|
9ae3a8 |
+ * "pc.ram") from a similar guest coming in from a RHEL-7 emulator (where
|
|
|
9ae3a8 |
+ * shadowing has worked). In the latter case we must not trample the live
|
|
|
9ae3a8 |
+ * SeaBIOS variables in "pc.ram".
|
|
|
9ae3a8 |
+ */
|
|
|
9ae3a8 |
+ if (buffer_is_zero(ef_seg_host, bios_size)) {
|
|
|
9ae3a8 |
+ fprintf(stderr, "copying E and F segments from pc.bios to pc.ram\n");
|
|
|
9ae3a8 |
+ memcpy(ef_seg_host, memory_region_get_ram_ptr(bios->mr), bios_size);
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+ if (buffer_is_zero(cd_seg_host, oprom_size)) {
|
|
|
9ae3a8 |
+ fprintf(stderr, "copying C and D segments from pc.rom to pc.ram\n");
|
|
|
9ae3a8 |
+ memcpy(cd_seg_host, memory_region_get_ram_ptr(oprom->mr), oprom_size);
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
int qemu_loadvm_state(QEMUFile *f)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
QLIST_HEAD(, LoadStateEntry) loadvm_handlers =
|
|
|
9ae3a8 |
@@ -2297,6 +2356,13 @@ int qemu_loadvm_state(QEMUFile *f)
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+ /* Supplement SeaBIOS's shadowing now, because it was useless when the
|
|
|
9ae3a8 |
+ * incoming VM started on the RHEL-6 emulator.
|
|
|
9ae3a8 |
+ */
|
|
|
9ae3a8 |
+ if (shadow_bios_after_incoming) {
|
|
|
9ae3a8 |
+ shadow_bios();
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
cpu_synchronize_all_post_init();
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
ret = 0;
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|