qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: gleb@kernel.org, mtosatti@redhat.com, Alexander Graf <agraf@suse.de>
Subject: [Qemu-devel] [PULL 4/9] roms: Flush icache when writing roms to guest memory
Date: Mon, 20 Jan 2014 15:44:06 +0100	[thread overview]
Message-ID: <1390229051-28635-5-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1390229051-28635-1-git-send-email-pbonzini@redhat.com>

From: Alexander Graf <agraf@suse.de>

We use the rom infrastructure to write firmware and/or initial kernel
blobs into guest address space. So we're basically emulating the cache
off phase on very early system bootup.

That phase is usually responsible for clearing the instruction cache for
anything it writes into cachable memory, to ensure that after reboot we
don't happen to execute stale bits from the instruction cache.

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 <agraf@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                    | 44 +++++++++++++++++++++++++++++++++++++++-----
 hw/core/loader.c          |  7 +++++++
 include/exec/cpu-common.h |  1 +
 3 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/exec.c b/exec.c
index f4b9ef2..896f7b8 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
 
@@ -2010,9 +2011,13 @@ void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
     address_space_rw(&address_space_memory, addr, buf, len, is_write);
 }
 
-/* used for ROM loading : can write in RAM and ROM */
-void cpu_physical_memory_write_rom(hwaddr addr,
-                                   const uint8_t *buf, int len)
+enum write_rom_type {
+    WRITE_DATA,
+    FLUSH_CACHE,
+};
+
+static inline void cpu_physical_memory_write_rom_internal(
+    hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type)
 {
     hwaddr l;
     uint8_t *ptr;
@@ -2031,8 +2036,15 @@ void cpu_physical_memory_write_rom(hwaddr addr,
             addr1 += memory_region_get_ram_addr(mr);
             /* ROM/RAM case */
             ptr = qemu_get_ram_ptr(addr1);
-            memcpy(ptr, buf, l);
-            invalidate_and_set_dirty(addr1, l);
+            switch (type) {
+            case WRITE_DATA:
+                memcpy(ptr, buf, l);
+                invalidate_and_set_dirty(addr1, l);
+                break;
+            case FLUSH_CACHE:
+                flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
+                break;
+            }
         }
         len -= l;
         buf += l;
@@ -2040,6 +2052,28 @@ void cpu_physical_memory_write_rom(hwaddr addr,
     }
 }
 
+/* used for ROM loading : can write in RAM and ROM */
+void cpu_physical_memory_write_rom(hwaddr addr,
+                                   const uint8_t *buf, int len)
+{
+    cpu_physical_memory_write_rom_internal(addr, buf, len, WRITE_DATA);
+}
+
+void cpu_flush_icache_range(hwaddr start, int len)
+{
+    /*
+     * This function should do the same thing as an icache flush that was
+     * triggered from within the guest. For TCG we are always cache coherent,
+     * so there is no need to flush anything. For KVM / Xen we need to flush
+     * the host's instruction cache at least.
+     */
+    if (tcg_enabled()) {
+        return;
+    }
+
+    cpu_physical_memory_write_rom_internal(start, NULL, len, FLUSH_CACHE);
+}
+
 typedef struct {
     MemoryRegion *mr;
     void *buffer;
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 60d2ebd..0634bee 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -785,6 +785,13 @@ static void rom_reset(void *unused)
             g_free(rom->data);
             rom->data = NULL;
         }
+        /*
+         * The rom loader is really on the same level as firmware in the guest
+         * shadowing a ROM into RAM. Such a shadowing mechanism needs to ensure
+         * that the instruction cache for that new region is clear, so that the
+         * CPU definitely fetches its instructions from the just written data.
+         */
+        cpu_flush_icache_range(rom->addr, rom->datasize);
     }
 }
 
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index e4996e1..8f33122 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -110,6 +110,7 @@ void stq_phys(hwaddr addr, uint64_t val);
 
 void cpu_physical_memory_write_rom(hwaddr addr,
                                    const uint8_t *buf, int len);
+void cpu_flush_icache_range(hwaddr start, int len);
 
 extern struct MemoryRegion io_mem_rom;
 extern struct MemoryRegion io_mem_notdirty;
-- 
1.8.3.1

  parent reply	other threads:[~2014-01-20 14:44 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-20 14:44 [Qemu-devel] [PULL 0/8] KVM uq/master changes for 2014-01-20 Paolo Bonzini
2014-01-20 14:44 ` [Qemu-devel] [PULL 1/9] target-i386: Intel MPX Paolo Bonzini
2014-01-20 14:44 ` [Qemu-devel] [PULL 2/9] target-i386: do not special case TSC writeback Paolo Bonzini
2014-01-20 14:44 ` [Qemu-devel] [PULL 3/9] target-i386: clear guest TSC on reset Paolo Bonzini
2014-01-20 14:44 ` Paolo Bonzini [this message]
2014-01-20 14:44 ` [Qemu-devel] [PULL 5/9] kvm: x86: Separately write feature control MSR " Paolo Bonzini
2014-01-20 14:44 ` [Qemu-devel] [PULL 6/9] mempath prefault: fix off-by-one error Paolo Bonzini
2014-01-20 14:44 ` [Qemu-devel] [PULL 7/9] KVM: Retry KVM_CREATE_VM on EINTR Paolo Bonzini
2014-01-27 13:44   ` Alexander Graf
2014-01-27 13:53     ` Paolo Bonzini
2014-01-20 14:44 ` [Qemu-devel] [PULL 8/9] KVM: fix addr type for KVM_IOEVENTFD Paolo Bonzini
2014-01-20 14:44 ` [Qemu-devel] [PULL 9/9] kvm: always update the MPX model specific register Paolo Bonzini
2014-01-22  4:48   ` Liu, Jinsong
2014-01-20 14:47 ` [Qemu-devel] [PULL 0/8] KVM uq/master changes for 2014-01-20 Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1390229051-28635-5-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=agraf@suse.de \
    --cc=gleb@kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).