|
|
9ae3a8 |
From 4fb30d2478b2d030262bcd1699a683973e481cfd Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
Message-Id: <4fb30d2478b2d030262bcd1699a683973e481cfd.1387298827.git.minovotn@redhat.com>
|
|
|
9ae3a8 |
In-Reply-To: <3ed0fb61a3dc912ef036d7ef450bed192090709e.1387298827.git.minovotn@redhat.com>
|
|
|
9ae3a8 |
References: <3ed0fb61a3dc912ef036d7ef450bed192090709e.1387298827.git.minovotn@redhat.com>
|
|
|
9ae3a8 |
From: "Michael S. Tsirkin" <mst@redhat.com>
|
|
|
9ae3a8 |
Date: Tue, 17 Dec 2013 15:17:19 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 12/56] loader: store FW CFG ROM files in RAM
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Michael S. Tsirkin <mst@redhat.com>
|
|
|
9ae3a8 |
Message-id: <1387293161-4085-13-git-send-email-mst@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 56317
|
|
|
9ae3a8 |
O-Subject: [PATCH qemu-kvm RHEL7.0 v2 12/57] loader: store FW CFG ROM files in RAM
|
|
|
9ae3a8 |
Bugzilla: 1034876
|
|
|
9ae3a8 |
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Marcel Apfelbaum <marcel.a@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
ROM files that are put in FW CFG are copied to guest ram, by BIOS, but
|
|
|
9ae3a8 |
they are not backed by RAM so they don't get migrated.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Each time we change two bytes in such a ROM this breaks cross-version
|
|
|
9ae3a8 |
migration: since we can migrate after BIOS has read the first byte but
|
|
|
9ae3a8 |
before it has read the second one, getting an inconsistent state.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Future-proof this by creating, for each such ROM,
|
|
|
9ae3a8 |
an MR serving as the backing store.
|
|
|
9ae3a8 |
This MR is never mapped into guest memory, but it's registered
|
|
|
9ae3a8 |
as RAM so it's migrated with the guest.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Naturally, this only helps for -M 1.7 and up, older machine types
|
|
|
9ae3a8 |
will still have the cross-version migration bug.
|
|
|
9ae3a8 |
Luckily the race window for the problem to trigger is very small,
|
|
|
9ae3a8 |
which is also likely why we didn't notice the cross-version
|
|
|
9ae3a8 |
migration bug in testing yet.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
9ae3a8 |
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
9ae3a8 |
(cherry picked from commit 04920fc0faa4760f9c4fc0e73b992b768099be70)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Conflicts:
|
|
|
9ae3a8 |
hw/i386/pc_piix.c
|
|
|
9ae3a8 |
hw/i386/pc_q35.c
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
include/hw/loader.h | 1 +
|
|
|
9ae3a8 |
hw/core/loader.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
|
|
|
9ae3a8 |
hw/i386/pc_piix.c | 2 ++
|
|
|
9ae3a8 |
hw/i386/pc_q35.c | 1 +
|
|
|
9ae3a8 |
4 files changed, 50 insertions(+), 3 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Michal Novotny <minovotn@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
hw/core/loader.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
|
|
|
9ae3a8 |
hw/i386/pc_piix.c | 2 ++
|
|
|
9ae3a8 |
hw/i386/pc_q35.c | 1 +
|
|
|
9ae3a8 |
include/hw/loader.h | 1 +
|
|
|
9ae3a8 |
4 files changed, 50 insertions(+), 3 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/hw/core/loader.c b/hw/core/loader.c
|
|
|
9ae3a8 |
index 7d61537..6bdbd15 100644
|
|
|
9ae3a8 |
--- a/hw/core/loader.c
|
|
|
9ae3a8 |
+++ b/hw/core/loader.c
|
|
|
9ae3a8 |
@@ -54,6 +54,8 @@
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
#include <zlib.h>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+bool rom_file_in_ram = true;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
static int roms_loaded;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
/* return the size or -1 if error */
|
|
|
9ae3a8 |
@@ -542,6 +544,7 @@ struct Rom {
|
|
|
9ae3a8 |
size_t datasize;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
uint8_t *data;
|
|
|
9ae3a8 |
+ MemoryRegion *mr;
|
|
|
9ae3a8 |
int isrom;
|
|
|
9ae3a8 |
char *fw_dir;
|
|
|
9ae3a8 |
char *fw_file;
|
|
|
9ae3a8 |
@@ -571,6 +574,21 @@ static void rom_insert(Rom *rom)
|
|
|
9ae3a8 |
QTAILQ_INSERT_TAIL(&roms, rom, next);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+static void *rom_set_mr(Rom *rom, const char *name)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ void *data;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ rom->mr = g_malloc(sizeof(*rom->mr));
|
|
|
9ae3a8 |
+ memory_region_init_ram(rom->mr, name, rom->datasize);
|
|
|
9ae3a8 |
+ memory_region_set_readonly(rom->mr, true);
|
|
|
9ae3a8 |
+ vmstate_register_ram_global(rom->mr);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ data = memory_region_get_ram_ptr(rom->mr);
|
|
|
9ae3a8 |
+ memcpy(data, rom->data, rom->datasize);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ return data;
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
int rom_add_file(const char *file, const char *fw_dir,
|
|
|
9ae3a8 |
hwaddr addr, int32_t bootindex)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
@@ -612,6 +630,7 @@ int rom_add_file(const char *file, const char *fw_dir,
|
|
|
9ae3a8 |
if (rom->fw_file && fw_cfg) {
|
|
|
9ae3a8 |
const char *basename;
|
|
|
9ae3a8 |
char fw_file_name[56];
|
|
|
9ae3a8 |
+ void *data;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
basename = strrchr(rom->fw_file, '/');
|
|
|
9ae3a8 |
if (basename) {
|
|
|
9ae3a8 |
@@ -621,8 +640,15 @@ int rom_add_file(const char *file, const char *fw_dir,
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
snprintf(fw_file_name, sizeof(fw_file_name), "%s/%s", rom->fw_dir,
|
|
|
9ae3a8 |
basename);
|
|
|
9ae3a8 |
- fw_cfg_add_file(fw_cfg, fw_file_name, rom->data, rom->romsize);
|
|
|
9ae3a8 |
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ if (rom_file_in_ram) {
|
|
|
9ae3a8 |
+ data = rom_set_mr(rom, devpath);
|
|
|
9ae3a8 |
+ } else {
|
|
|
9ae3a8 |
+ data = rom->data;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ fw_cfg_add_file(fw_cfg, fw_file_name, data, rom->romsize);
|
|
|
9ae3a8 |
} else {
|
|
|
9ae3a8 |
snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
@@ -697,7 +723,12 @@ static void rom_reset(void *unused)
|
|
|
9ae3a8 |
if (rom->data == NULL) {
|
|
|
9ae3a8 |
continue;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
- cpu_physical_memory_write_rom(rom->addr, rom->data, rom->datasize);
|
|
|
9ae3a8 |
+ if (rom->mr) {
|
|
|
9ae3a8 |
+ void *host = memory_region_get_ram_ptr(rom->mr);
|
|
|
9ae3a8 |
+ memcpy(host, rom->data, rom->datasize);
|
|
|
9ae3a8 |
+ } else {
|
|
|
9ae3a8 |
+ cpu_physical_memory_write_rom(rom->addr, rom->data, rom->datasize);
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
if (rom->isrom) {
|
|
|
9ae3a8 |
/* rom needs to be written only once */
|
|
|
9ae3a8 |
g_free(rom->data);
|
|
|
9ae3a8 |
@@ -746,6 +777,9 @@ static Rom *find_rom(hwaddr addr)
|
|
|
9ae3a8 |
if (rom->fw_file) {
|
|
|
9ae3a8 |
continue;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ if (rom->mr) {
|
|
|
9ae3a8 |
+ continue;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
if (rom->addr > addr) {
|
|
|
9ae3a8 |
continue;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
@@ -773,6 +807,9 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size)
|
|
|
9ae3a8 |
if (rom->fw_file) {
|
|
|
9ae3a8 |
continue;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ if (rom->mr) {
|
|
|
9ae3a8 |
+ continue;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
if (rom->addr + rom->romsize < addr) {
|
|
|
9ae3a8 |
continue;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
@@ -831,7 +868,13 @@ void do_info_roms(Monitor *mon, const QDict *qdict)
|
|
|
9ae3a8 |
Rom *rom;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
QTAILQ_FOREACH(rom, &roms, next) {
|
|
|
9ae3a8 |
- if (!rom->fw_file) {
|
|
|
9ae3a8 |
+ if (rom->mr) {
|
|
|
9ae3a8 |
+ monitor_printf(mon, "%s"
|
|
|
9ae3a8 |
+ " size=0x%06zx name=\"%s\"\n",
|
|
|
9ae3a8 |
+ rom->mr->name,
|
|
|
9ae3a8 |
+ rom->romsize,
|
|
|
9ae3a8 |
+ rom->name);
|
|
|
9ae3a8 |
+ } else if (!rom->fw_file) {
|
|
|
9ae3a8 |
monitor_printf(mon, "addr=" TARGET_FMT_plx
|
|
|
9ae3a8 |
" size=0x%06zx mem=%s name=\"%s\"\n",
|
|
|
9ae3a8 |
rom->addr, rom->romsize,
|
|
|
9ae3a8 |
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
index b6f9288..07848c1 100644
|
|
|
9ae3a8 |
--- a/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
+++ b/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
@@ -25,6 +25,7 @@
|
|
|
9ae3a8 |
#include <glib.h>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
#include "hw/hw.h"
|
|
|
9ae3a8 |
+#include "hw/loader.h"
|
|
|
9ae3a8 |
#include "hw/i386/pc.h"
|
|
|
9ae3a8 |
#include "hw/i386/apic.h"
|
|
|
9ae3a8 |
#include "hw/i386/smbios.h"
|
|
|
9ae3a8 |
@@ -883,6 +884,7 @@ static void pc_init_rhel650(QEMUMachineInitArgs *args)
|
|
|
9ae3a8 |
x86_cpu_compat_set_features("Opteron_G3", FEAT_8000_0001_EDX,
|
|
|
9ae3a8 |
0, CPUID_EXT2_RDTSCP);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+ rom_file_in_ram = false;
|
|
|
9ae3a8 |
pc_init_rhel700(args);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
|
|
9ae3a8 |
index f308098..8fa6793 100644
|
|
|
9ae3a8 |
--- a/hw/i386/pc_q35.c
|
|
|
9ae3a8 |
+++ b/hw/i386/pc_q35.c
|
|
|
9ae3a8 |
@@ -28,6 +28,7 @@
|
|
|
9ae3a8 |
* THE SOFTWARE.
|
|
|
9ae3a8 |
*/
|
|
|
9ae3a8 |
#include "hw/hw.h"
|
|
|
9ae3a8 |
+#include "hw/loader.h"
|
|
|
9ae3a8 |
#include "sysemu/arch_init.h"
|
|
|
9ae3a8 |
#include "hw/i2c/smbus.h"
|
|
|
9ae3a8 |
#include "hw/boards.h"
|
|
|
9ae3a8 |
diff --git a/include/hw/loader.h b/include/hw/loader.h
|
|
|
9ae3a8 |
index 15d4cc9..19e11ea 100644
|
|
|
9ae3a8 |
--- a/include/hw/loader.h
|
|
|
9ae3a8 |
+++ b/include/hw/loader.h
|
|
|
9ae3a8 |
@@ -23,6 +23,7 @@ void pstrcpy_targphys(const char *name,
|
|
|
9ae3a8 |
hwaddr dest, int buf_size,
|
|
|
9ae3a8 |
const char *source);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+extern bool rom_file_in_ram;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
int rom_add_file(const char *file, const char *fw_dir,
|
|
|
9ae3a8 |
hwaddr addr, int32_t bootindex);
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.11.7
|
|
|
9ae3a8 |
|