qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v2] Fix unassigned memory access handling


From: Blue Swirl
Subject: [Qemu-devel] [PATCH v2] Fix unassigned memory access handling
Date: Wed, 13 Jul 2011 23:09:57 +0300

cea5f9a28faa528b6b1b117c9ab2d8828f473fef exposed bugs in unassigned memory
access handling. Fix them by always passing CPUState to the handlers.

Reported-by: Hervé Poussineau <address@hidden>
Signed-off-by: Blue Swirl <address@hidden>
---
v2: don't try to restore env since all targets eventually always call
cpu_loop_exit() which will not return.

 exec-all.h                    |    2 +-
 exec.c                        |   12 ++++++------
 target-alpha/cpu.h            |    5 +++--
 target-alpha/op_helper.c      |    6 ++++--
 target-microblaze/cpu.h       |    4 ++--
 target-microblaze/op_helper.c |   14 ++++----------
 target-mips/cpu.h             |    4 ++--
 target-mips/op_helper.c       |    6 ++++--
 target-sparc/cpu.h            |    4 ++--
 target-sparc/op_helper.c      |   26 ++++++++++++++++++++------
 10 files changed, 48 insertions(+), 35 deletions(-)

diff --git a/exec-all.h b/exec-all.h
index 69acf3b..9b8d62c 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -323,7 +323,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 f1777e6..16e16f3 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 78caa79..919be12 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -434,8 +434,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..8f39154 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1301,9 +1301,11 @@ 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)
 {
+    env = env1;
     env->trap_arg0 = addr;
     env->trap_arg1 = is_write;
     dynamic_excp(EXCP_MCHK, 0);
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..01315ef 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1980,9 +1980,11 @@ 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)
 {
+    env = env1;
+
     if (is_exec)
         helper_raise_exception(EXCP_IBE);
     else
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..101edfb 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;
@@ -4322,3 +4327,12 @@ 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)
+{
+    env = env1;
+    do_unassigned_access(addr, is_write, is_exec, is_asi, size);
+}
+#endif
-- 
1.6.2.4

Attachment: 0001-Fix-unassigned-memory-access-handling.patch
Description: Text Data


reply via email to

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