qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] roms: Flush icache when writing roms to guest memor


From: Alexander Graf
Subject: [Qemu-devel] [PATCH] roms: Flush icache when writing roms to guest memory
Date: Wed, 11 Dec 2013 14:23:36 +0100

We use the rom infrastructure to write firmware and/or initial kernel
blobs into guest address space. So we're essentially the layer before
the first code that gets executed inside the guest.

The guest expects that its data and instruction cache view of the world
is 100% consistent when it initially boots. This works just fine on
initial rom population for the first boot.

However, when we reboot and then repopulate the rom region there could
be old code still stuck in the instruction cache, giving the guest an
inconsistent view of the world when we're using kvm.

So we need to invalidate the icache every time we write a rom into guest
address space. We do not need to do this for every DMA since the guest
expects it has to flush the icache manually in that case.

This fixes random reboot issues on e5500 (booke ppc) for me.

Signed-off-by: Alexander Graf <address@hidden>
---
 exec.c           |  8 ++++++++
 hw/core/loader.c | 10 ++++++++++
 2 files changed, 18 insertions(+)

diff --git a/exec.c b/exec.c
index f4b9ef2..cc63eb6 100644
--- a/exec.c
+++ b/exec.c
@@ -50,6 +50,7 @@
 #include "translate-all.h"
 
 #include "exec/memory-internal.h"
+#include "qemu/cache-utils.h"
 
 //#define DEBUG_SUBPAGE
 
@@ -2033,6 +2034,13 @@ void cpu_physical_memory_write_rom(hwaddr addr,
             ptr = qemu_get_ram_ptr(addr1);
             memcpy(ptr, buf, l);
             invalidate_and_set_dirty(addr1, l);
+            if (kvm_enabled()) {
+                /*
+                 * The guest may want to directly execute from the rom region,
+                 * so we better invalidate its icache
+                 */
+                flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
+            }
         }
         len -= l;
         buf += l;
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 60d2ebd..4f809f3 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -51,6 +51,7 @@
 #include "hw/nvram/fw_cfg.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
+#include "qemu/cache-utils.h"
 
 #include <zlib.h>
 
@@ -619,6 +620,7 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char 
*name)
 
     data = memory_region_get_ram_ptr(rom->mr);
     memcpy(data, rom->data, rom->datasize);
+    flush_icache_range((uintptr_t)data, (uintptr_t)data + rom->datasize);
 
     return data;
 }
@@ -777,6 +779,14 @@ static void rom_reset(void *unused)
         if (rom->mr) {
             void *host = memory_region_get_ram_ptr(rom->mr);
             memcpy(host, rom->data, rom->datasize);
+            if (kvm_enabled()) {
+                /*
+                 * The guest may want to directly execute from the rom region,
+                 * so we better invalidate its icache
+                 */
+                flush_icache_range((uintptr_t)host,
+                                   (uintptr_t)host + rom->datasize);
+            }
         } else {
             cpu_physical_memory_write_rom(rom->addr, rom->data, rom->datasize);
         }
-- 
1.8.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]