diff options
author | Blue Swirl <blauwirbel@gmail.com> | 2011-08-01 21:26:03 +0000 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2011-08-01 21:26:03 +0000 |
commit | 67494323f2c782fe3e65c60529fe9dfa613fc500 (patch) | |
tree | 1e99ed4562eb475214f3923f8e5263acb04bf4ef /target-sparc/op_helper.c | |
parent | 927d721777e73339f73719f36eaf400ab641366c (diff) | |
download | qemu-67494323f2c782fe3e65c60529fe9dfa613fc500.zip |
Sparc: fix non-faulting unassigned memory accesses
Commit b14ef7c9ab41ea824c3ccadb070ad95567cca84e
introduced cpu_unassigned_access() function. On Sparc,
the function does not restore AREG0 used for global CPUState
on function exit, causing bugs with non-faulting unassigned
memory accesses. Alpha, Microblaze and MIPS are not affected.
Fix by restoring AREG0 on exit. Remove excess saving by
do_unassigned_access() functions.
Also ignore unassigned accesses outside of CPU context.
Reported-by: Bob Breuer <breuerr@mc.net>
Tested-by: Bob Breuer <breuerr@mc.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-sparc/op_helper.c')
-rw-r--r-- | target-sparc/op_helper.c | 25 |
1 files changed, 8 insertions, 17 deletions
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index c1c4d4b07e..5aeca2b06d 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -4252,13 +4252,8 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) 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; - /* XXX: hack to restore env in all cases, even if not called from - generated code */ - saved_env = env; - env = cpu_single_env; #ifdef DEBUG_UNASSIGNED if (is_asi) printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx @@ -4306,8 +4301,6 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write, if (env->mmuregs[0] & MMU_NF) { tlb_flush(env, 1); } - - env = saved_env; } #endif #else @@ -4319,13 +4312,6 @@ 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; - - /* XXX: hack to restore env in all cases, even if not called from - generated code */ - saved_env = env; - env = cpu_single_env; - #ifdef DEBUG_UNASSIGNED printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n", addr, env->pc); @@ -4335,8 +4321,6 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write, raise_exception(TT_CODE_ACCESS); else raise_exception(TT_DATA_ACCESS); - - env = saved_env; } #endif @@ -4370,7 +4354,14 @@ void helper_tick_set_limit(void *opaque, uint64_t limit) 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); + /* Ignore unassigned accesses outside of CPU context */ + if (env1) { + do_unassigned_access(addr, is_write, is_exec, is_asi, size); + } + env = saved_env; } #endif |