From patchwork Sun Jul 3 09:42:06 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Blue Swirl X-Patchwork-Id: 103003 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0E9E6B6EDF for ; Sun, 3 Jul 2011 19:45:27 +1000 (EST) Received: from localhost ([::1]:51244 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QdJEw-0006bE-Sn for incoming@patchwork.ozlabs.org; Sun, 03 Jul 2011 05:45:23 -0400 Received: from eggs.gnu.org ([140.186.70.92]:43240) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QdJCB-0006aX-KJ for qemu-devel@nongnu.org; Sun, 03 Jul 2011 05:42:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QdJC7-0002Uu-Vv for qemu-devel@nongnu.org; Sun, 03 Jul 2011 05:42:31 -0400 Received: from mail-qy0-f180.google.com ([209.85.216.180]:57269) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QdJC7-0002Sx-58 for qemu-devel@nongnu.org; Sun, 03 Jul 2011 05:42:27 -0400 Received: by qyk30 with SMTP id 30so2670182qyk.4 for ; Sun, 03 Jul 2011 02:42:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:from:date:message-id:subject:to:content-type; bh=I3qCS2kZ1ky4u48M0pQBabjVuvo5uExWGQIf7gxX9nQ=; b=s9q/yOzYJH7zen4CrmT/OEqIO/4nvhwrGno+tzQBrH1v3B2Q1Z9Ka3GfM6YK2ODpm9 opILcUKlOGdFRTR/EVyoWasyTOXhKTgwTD9SE4cdhUcLEmuAewXjMTwrDKVZkZ/SpMUL DZK72u+7Z2gNOErgpzJ2gi/levkmYAtk7Uo0M= Received: by 10.224.190.136 with SMTP id di8mr3727446qab.255.1309686146178; Sun, 03 Jul 2011 02:42:26 -0700 (PDT) MIME-Version: 1.0 Received: by 10.224.73.129 with HTTP; Sun, 3 Jul 2011 02:42:06 -0700 (PDT) From: Blue Swirl Date: Sun, 3 Jul 2011 12:42:06 +0300 Message-ID: To: qemu-devel , Richard Henderson , "Edgar E. Iglesias" , Aurelien Jarno , =?UTF-8?Q?Herv=C3=A9_Poussineau?= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.216.180 Subject: [Qemu-devel] [PATCH] Fix unassigned memory access handling 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 cea5f9a28faa528b6b1b117c9ab2d8828f473fef exposed bugs in unassigned memory access handling. Fix them by always passing CPUState to the handlers. Reported-by: Hervé Poussineau Signed-off-by: Blue Swirl --- exec-all.h | 2 +- exec.c | 12 ++++++------ target-alpha/cpu.h | 5 +++-- target-alpha/op_helper.c | 10 ++++++++-- target-microblaze/cpu.h | 4 ++-- target-microblaze/op_helper.c | 14 ++++---------- target-mips/cpu.h | 4 ++-- target-mips/op_helper.c | 10 ++++++++-- target-sparc/cpu.h | 4 ++-- target-sparc/op_helper.c | 31 ++++++++++++++++++++++++------- 10 files changed, 60 insertions(+), 36 deletions(-) int fault_type; @@ -4272,8 +4277,8 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, static void do_unassigned_access(target_ulong addr, int is_write, int is_exec, int is_asi, int size) #else -void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, - int is_asi, int size) +static void do_unassigned_access(target_phys_addr_t addr, int is_write, + int is_exec, int is_asi, int size) #endif { CPUState *saved_env; @@ -4297,7 +4302,6 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, } #endif - #ifdef TARGET_SPARC64 void helper_tick_set_count(void *opaque, uint64_t count) { @@ -4322,3 +4326,16 @@ void helper_tick_set_limit(void *opaque, uint64_t limit) #endif } #endif + +#if !defined(CONFIG_USER_ONLY) +void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr, + int is_write, int is_exec, int is_asi, int size) +{ + CPUState *saved_env; + + saved_env = env; + env = env1; + do_unassigned_access(addr, is_write, is_exec, is_asi, size); + env = saved_env; +} +#endif From c6a67abaf0a0851ef5723115f6670d061a61adac Mon Sep 17 00:00:00 2001 Message-Id: From: Blue Swirl Date: Sun, 3 Jul 2011 08:53:46 +0000 Subject: [PATCH] Fix unassigned memory access handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cea5f9a28faa528b6b1b117c9ab2d8828f473fef exposed bugs in unassigned memory access handling. Fix them by always passing CPUState to the handlers. Reported-by: Hervé Poussineau Signed-off-by: Blue Swirl --- exec-all.h | 2 +- exec.c | 12 ++++++------ target-alpha/cpu.h | 5 +++-- target-alpha/op_helper.c | 10 ++++++++-- target-microblaze/cpu.h | 4 ++-- target-microblaze/op_helper.c | 14 ++++---------- target-mips/cpu.h | 4 ++-- target-mips/op_helper.c | 10 ++++++++-- target-sparc/cpu.h | 4 ++-- target-sparc/op_helper.c | 31 ++++++++++++++++++++++++------- 10 files changed, 60 insertions(+), 36 deletions(-) diff --git a/exec-all.h b/exec-all.h index 21a69d6..c24518e 100644 --- a/exec-all.h +++ b/exec-all.h @@ -327,7 +327,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK; if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC) - do_unassigned_access(addr, 0, 1, 0, 4); + cpu_unassigned_access(env1, addr, 0, 1, 0, 4); #else cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); #endif diff --git a/exec.c b/exec.c index 4c45299..4d9d92b 100644 --- a/exec.c +++ b/exec.c @@ -3236,7 +3236,7 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); #endif #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - do_unassigned_access(addr, 0, 0, 0, 1); + cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 1); #endif return 0; } @@ -3247,7 +3247,7 @@ static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr) printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); #endif #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - do_unassigned_access(addr, 0, 0, 0, 2); + cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 2); #endif return 0; } @@ -3258,7 +3258,7 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); #endif #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - do_unassigned_access(addr, 0, 0, 0, 4); + cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 4); #endif return 0; } @@ -3269,7 +3269,7 @@ static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_ printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); #endif #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - do_unassigned_access(addr, 1, 0, 0, 1); + cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 1); #endif } @@ -3279,7 +3279,7 @@ static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_ printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); #endif #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - do_unassigned_access(addr, 1, 0, 0, 2); + cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 2); #endif } @@ -3289,7 +3289,7 @@ static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_ printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); #endif #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - do_unassigned_access(addr, 1, 0, 0, 4); + cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 4); #endif } diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 411bd55..ccdcd1b 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -436,8 +436,9 @@ uint64_t cpu_alpha_load_fpcr (CPUState *env); void cpu_alpha_store_fpcr (CPUState *env, uint64_t val); #ifndef CONFIG_USER_ONLY void swap_shadow_regs(CPUState *env); -extern QEMU_NORETURN void do_unassigned_access(target_phys_addr_t addr, - int, int, int, int); +QEMU_NORETURN void cpu_unassigned_access(CPUState *env1, + target_phys_addr_t addr, int is_write, + int is_exec, int unused, int size); #endif /* Bits in TB->FLAGS that control how translation is processed. */ diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c index 51d1bd7..90f3c75 100644 --- a/target-alpha/op_helper.c +++ b/target-alpha/op_helper.c @@ -1301,12 +1301,18 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write, helper_excp(EXCP_UNALIGN, 0); } -void QEMU_NORETURN do_unassigned_access(target_phys_addr_t addr, int is_write, - int is_exec, int unused, int size) +void QEMU_NORETURN cpu_unassigned_access(CPUState *env1, + target_phys_addr_t addr, int is_write, + int is_exec, int unused, int size) { + CPUState *saved_env; + + saved_env = env; + env = env1; env->trap_arg0 = addr; env->trap_arg1 = is_write; dynamic_excp(EXCP_MCHK, 0); + env = saved_env; } #define MMUSUFFIX _mmu diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 51a13e3..76f4fc4 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -347,8 +347,8 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, } #if !defined(CONFIG_USER_ONLY) -void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, - int is_asi, int size); +void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr, + int is_write, int is_exec, int is_asi, int size); #endif static inline bool cpu_has_work(CPUState *env) diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c index 1a0a476..664ffe5 100644 --- a/target-microblaze/op_helper.c +++ b/target-microblaze/op_helper.c @@ -488,20 +488,14 @@ void helper_mmu_write(uint32_t rn, uint32_t v) mmu_write(env, rn, v); } -void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, - int is_asi, int size) +void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr, + int is_write, int is_exec, int is_asi, int size) { CPUState *saved_env; - if (!cpu_single_env) { - /* XXX: ??? */ - return; - } - - /* XXX: hack to restore env in all cases, even if not called from - generated code */ saved_env = env; - env = cpu_single_env; + env = env1; + qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n", addr, is_write, is_exec); if (!(env->sregs[SR_MSR] & MSR_EE)) { diff --git a/target-mips/cpu.h b/target-mips/cpu.h index b0ac4da..33be296 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -493,8 +493,8 @@ void r4k_helper_tlbwr (void); void r4k_helper_tlbp (void); void r4k_helper_tlbr (void); -void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, - int unused, int size); +void cpu_unassigned_access(CPUState *env, target_phys_addr_t addr, + int is_write, int is_exec, int unused, int size); #endif void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf); diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 6b966b1..f47f052 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1980,13 +1980,19 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) env = saved_env; } -void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, - int unused, int size) +void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr, + int is_write, int is_exec, int unused, int size) { + CPUState *saved_env; + + saved_env = env; + env = env1; + if (is_exec) helper_raise_exception(EXCP_IBE); else helper_raise_exception(EXCP_DBE); + env = saved_env; } #endif /* !CONFIG_USER_ONLY */ diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 4edae78..f6cb300 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -510,8 +510,8 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb, /* cpu-exec.c */ #if !defined(CONFIG_USER_ONLY) -void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, - int is_asi, int size); +void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr, + int is_write, int is_exec, int is_asi, int size); target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr, int mmu_idx); diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index fd0cfbd..fc1e5da 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -79,9 +79,14 @@ #define CACHE_CTRL_FD (1 << 22) /* Flush Data cache (Write only) */ #define CACHE_CTRL_DS (1 << 23) /* Data cache snoop enable */ -#if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64) +#if !defined(CONFIG_USER_ONLY) +static void do_unassigned_access(target_phys_addr_t addr, int is_write, + int is_exec, int is_asi, int size); +#else +#ifdef TARGET_SPARC64 static void do_unassigned_access(target_ulong addr, int is_write, int is_exec, - int is_asi, int size); + int is_asi, int size); +#endif #endif #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) @@ -4206,8 +4211,8 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) #ifndef TARGET_SPARC64 #if !defined(CONFIG_USER_ONLY) -void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, - int is_asi, int size) +static void do_unassigned_access(target_phys_addr_t addr, int is_write, + int is_exec, int is_asi, int size) { CPUState *saved_env; int fault_type; @@ -4272,8 +4277,8 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, static void do_unassigned_access(target_ulong addr, int is_write, int is_exec, int is_asi, int size) #else -void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, - int is_asi, int size) +static void do_unassigned_access(target_phys_addr_t addr, int is_write, + int is_exec, int is_asi, int size) #endif { CPUState *saved_env; @@ -4297,7 +4302,6 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, } #endif - #ifdef TARGET_SPARC64 void helper_tick_set_count(void *opaque, uint64_t count) { @@ -4322,3 +4326,16 @@ void helper_tick_set_limit(void *opaque, uint64_t limit) #endif } #endif + +#if !defined(CONFIG_USER_ONLY) +void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr, + int is_write, int is_exec, int is_asi, int size) +{ + CPUState *saved_env; + + saved_env = env; + env = env1; + do_unassigned_access(addr, is_write, is_exec, is_asi, size); + env = saved_env; +} +#endif -- 1.7.2.5