From a94b36ddd6af28593c8a5171b5100e6c3dfc063e Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 12 Dec 2013 10:29:19 +0100 Subject: roms: Flush icache when writing roms to guest memory 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 Signed-off-by: Paolo Bonzini --- exec.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'exec.c') 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; -- cgit v1.1 From 2ba82852894c762299b7d05e9a2be184116b80f0 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 18 Dec 2013 16:42:17 -0200 Subject: mempath prefault: fix off-by-one error Fix off-by-one error (noticed by Andrea Arcangeli). Reviewed-by: Paolo Bonzini Signed-off-by: Marcelo Tosatti --- exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'exec.c') diff --git a/exec.c b/exec.c index 896f7b8..52d451b 100644 --- a/exec.c +++ b/exec.c @@ -1001,7 +1001,7 @@ static void *file_ram_alloc(RAMBlock *block, } /* MAP_POPULATE silently ignores failures */ - for (i = 0; i < (memory/hpagesize)-1; i++) { + for (i = 0; i < (memory/hpagesize); i++) { memset(area + (hpagesize*i), 0, 1); } -- cgit v1.1