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