From patchwork Wed Dec 11 13:23:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 300058 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id BE9C82C00A2 for ; Thu, 12 Dec 2013 00:24:08 +1100 (EST) Received: from localhost ([::1]:56962 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vqjll-00018e-FH for incoming@patchwork.ozlabs.org; Wed, 11 Dec 2013 08:24:05 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55845) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VqjlS-00018V-5A for qemu-devel@nongnu.org; Wed, 11 Dec 2013 08:23:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VqjlM-0001aG-4z for qemu-devel@nongnu.org; Wed, 11 Dec 2013 08:23:46 -0500 Received: from cantor2.suse.de ([195.135.220.15]:49422 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VqjlL-0001aC-S1; Wed, 11 Dec 2013 08:23:40 -0500 Received: from relay1.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 4BA5AA7D86; Wed, 11 Dec 2013 14:23:38 +0100 (CET) From: Alexander Graf To: QEMU Developers Date: Wed, 11 Dec 2013 14:23:36 +0100 Message-Id: <1386768216-33686-1-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.8.1.4 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x X-Received-From: 195.135.220.15 Cc: "Bogdan.Vlad@freescale.com" , "mihai.caraman@freescale.com" , "qemu-ppc@nongnu.org" , Scott Wood , "Varun.Sethi@freescale.com" Subject: [Qemu-devel] [PATCH] roms: Flush icache when writing roms to guest memory X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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 @@ -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); }