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