version 1.1.1.9, 2018/04/24 17:20:28
|
version 1.1.1.10, 2018/04/24 17:34:02
|
Line 38
|
Line 38
|
#endif |
#endif |
#endif |
#endif |
|
|
#if defined(__sparc__) && !defined(HOST_SOLARIS) |
#if defined(__sparc__) && !defined(CONFIG_SOLARIS) |
// Work around ugly bugs in glibc that mangle global register contents |
// Work around ugly bugs in glibc that mangle global register contents |
#undef env |
#undef env |
#define env cpu_single_env |
#define env cpu_single_env |
Line 46
|
Line 46
|
|
|
int tb_invalidated_flag; |
int tb_invalidated_flag; |
|
|
//#define DEBUG_EXEC |
//#define CONFIG_DEBUG_EXEC |
//#define DEBUG_SIGNAL |
//#define DEBUG_SIGNAL |
|
|
int qemu_cpu_has_work(CPUState *env) |
int qemu_cpu_has_work(CPUState *env) |
Line 202 static void cpu_handle_debug_exception(C
|
Line 202 static void cpu_handle_debug_exception(C
|
CPUWatchpoint *wp; |
CPUWatchpoint *wp; |
|
|
if (!env->watchpoint_hit) |
if (!env->watchpoint_hit) |
TAILQ_FOREACH(wp, &env->watchpoints, entry) |
QTAILQ_FOREACH(wp, &env->watchpoints, entry) |
wp->flags &= ~BP_WATCHPOINT_HIT; |
wp->flags &= ~BP_WATCHPOINT_HIT; |
|
|
if (debug_excp_handler) |
if (debug_excp_handler) |
Line 249 int cpu_exec(CPUState *env1)
|
Line 249 int cpu_exec(CPUState *env1)
|
#elif defined(TARGET_MIPS) |
#elif defined(TARGET_MIPS) |
#elif defined(TARGET_SH4) |
#elif defined(TARGET_SH4) |
#elif defined(TARGET_CRIS) |
#elif defined(TARGET_CRIS) |
|
#elif defined(TARGET_S390X) |
/* XXXXX */ |
/* XXXXX */ |
#else |
#else |
#error unsupported target CPU |
#error unsupported target CPU |
Line 258 int cpu_exec(CPUState *env1)
|
Line 259 int cpu_exec(CPUState *env1)
|
/* prepare setjmp context for exception handling */ |
/* prepare setjmp context for exception handling */ |
for(;;) { |
for(;;) { |
if (setjmp(env->jmp_env) == 0) { |
if (setjmp(env->jmp_env) == 0) { |
#if defined(__sparc__) && !defined(HOST_SOLARIS) |
#if defined(__sparc__) && !defined(CONFIG_SOLARIS) |
#undef env |
#undef env |
env = cpu_single_env; |
env = cpu_single_env; |
#define env cpu_single_env |
#define env cpu_single_env |
Line 321 int cpu_exec(CPUState *env1)
|
Line 322 int cpu_exec(CPUState *env1)
|
} |
} |
env->exception_index = -1; |
env->exception_index = -1; |
} |
} |
#ifdef CONFIG_KQEMU |
|
if (kqemu_is_ok(env) && env->interrupt_request == 0 && env->exit_request == 0) { |
|
int ret; |
|
env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK); |
|
ret = kqemu_cpu_exec(env); |
|
/* put eflags in CPU temporary format */ |
|
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
|
DF = 1 - (2 * ((env->eflags >> 10) & 1)); |
|
CC_OP = CC_OP_EFLAGS; |
|
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
|
if (ret == 1) { |
|
/* exception */ |
|
longjmp(env->jmp_env, 1); |
|
} else if (ret == 2) { |
|
/* softmmu execution needed */ |
|
} else { |
|
if (env->interrupt_request != 0 || env->exit_request != 0) { |
|
/* hardware interrupt will be executed just after */ |
|
} else { |
|
/* otherwise, we restart */ |
|
longjmp(env->jmp_env, 1); |
|
} |
|
} |
|
} |
|
#endif |
|
|
|
if (kvm_enabled()) { |
if (kvm_enabled()) { |
kvm_cpu_exec(env); |
kvm_cpu_exec(env); |
Line 414 int cpu_exec(CPUState *env1)
|
Line 390 int cpu_exec(CPUState *env1)
|
env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); |
env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); |
intno = cpu_get_pic_interrupt(env); |
intno = cpu_get_pic_interrupt(env); |
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno); |
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno); |
#if defined(__sparc__) && !defined(HOST_SOLARIS) |
#if defined(__sparc__) && !defined(CONFIG_SOLARIS) |
#undef env |
#undef env |
env = cpu_single_env; |
env = cpu_single_env; |
#define env cpu_single_env |
#define env cpu_single_env |
Line 441 int cpu_exec(CPUState *env1)
|
Line 417 int cpu_exec(CPUState *env1)
|
#elif defined(TARGET_PPC) |
#elif defined(TARGET_PPC) |
#if 0 |
#if 0 |
if ((interrupt_request & CPU_INTERRUPT_RESET)) { |
if ((interrupt_request & CPU_INTERRUPT_RESET)) { |
cpu_ppc_reset(env); |
cpu_reset(env); |
} |
} |
#endif |
#endif |
if (interrupt_request & CPU_INTERRUPT_HARD) { |
if (interrupt_request & CPU_INTERRUPT_HARD) { |
Line 485 int cpu_exec(CPUState *env1)
|
Line 461 int cpu_exec(CPUState *env1)
|
env->exception_index = env->interrupt_index; |
env->exception_index = env->interrupt_index; |
do_interrupt(env); |
do_interrupt(env); |
env->interrupt_index = 0; |
env->interrupt_index = 0; |
#if !defined(CONFIG_USER_ONLY) |
|
cpu_check_irqs(env); |
|
#endif |
|
next_tb = 0; |
next_tb = 0; |
} |
} |
} else if (interrupt_request & CPU_INTERRUPT_TIMER) { |
} else if (interrupt_request & CPU_INTERRUPT_TIMER) { |
Line 568 int cpu_exec(CPUState *env1)
|
Line 541 int cpu_exec(CPUState *env1)
|
env->exception_index = EXCP_INTERRUPT; |
env->exception_index = EXCP_INTERRUPT; |
cpu_loop_exit(); |
cpu_loop_exit(); |
} |
} |
#ifdef DEBUG_EXEC |
#ifdef CONFIG_DEBUG_EXEC |
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) { |
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) { |
/* restore flags in standard format */ |
/* restore flags in standard format */ |
regs_to_env(); |
regs_to_env(); |
Line 614 int cpu_exec(CPUState *env1)
|
Line 587 int cpu_exec(CPUState *env1)
|
next_tb = 0; |
next_tb = 0; |
tb_invalidated_flag = 0; |
tb_invalidated_flag = 0; |
} |
} |
#ifdef DEBUG_EXEC |
#ifdef CONFIG_DEBUG_EXEC |
qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n", |
qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n", |
(long)tb->tc_ptr, tb->pc, |
(long)tb->tc_ptr, tb->pc, |
lookup_symbol(tb->pc)); |
lookup_symbol(tb->pc)); |
Line 623 int cpu_exec(CPUState *env1)
|
Line 596 int cpu_exec(CPUState *env1)
|
spans two pages, we cannot safely do a direct |
spans two pages, we cannot safely do a direct |
jump. */ |
jump. */ |
{ |
{ |
if (next_tb != 0 && |
if (next_tb != 0 && tb->page_addr[1] == -1) { |
#ifdef CONFIG_KQEMU |
|
(env->kqemu_enabled != 2) && |
|
#endif |
|
tb->page_addr[1] == -1) { |
|
tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb); |
tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb); |
} |
} |
} |
} |
Line 644 int cpu_exec(CPUState *env1)
|
Line 613 int cpu_exec(CPUState *env1)
|
while (env->current_tb) { |
while (env->current_tb) { |
tc_ptr = tb->tc_ptr; |
tc_ptr = tb->tc_ptr; |
/* execute the generated code */ |
/* execute the generated code */ |
#if defined(__sparc__) && !defined(HOST_SOLARIS) |
#if defined(__sparc__) && !defined(CONFIG_SOLARIS) |
#undef env |
#undef env |
env = cpu_single_env; |
env = cpu_single_env; |
#define env cpu_single_env |
#define env cpu_single_env |
Line 681 int cpu_exec(CPUState *env1)
|
Line 650 int cpu_exec(CPUState *env1)
|
} |
} |
/* reset soft MMU for next block (it can currently |
/* reset soft MMU for next block (it can currently |
only be set by a memory fault) */ |
only be set by a memory fault) */ |
#if defined(CONFIG_KQEMU) |
|
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000) |
|
if (kqemu_is_ok(env) && |
|
(cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) { |
|
cpu_loop_exit(); |
|
} |
|
#endif |
|
} /* for(;;) */ |
} /* for(;;) */ |
} else { |
} else { |
env_to_regs(); |
env_to_regs(); |
Line 712 int cpu_exec(CPUState *env1)
|
Line 674 int cpu_exec(CPUState *env1)
|
#elif defined(TARGET_SH4) |
#elif defined(TARGET_SH4) |
#elif defined(TARGET_ALPHA) |
#elif defined(TARGET_ALPHA) |
#elif defined(TARGET_CRIS) |
#elif defined(TARGET_CRIS) |
|
#elif defined(TARGET_S390X) |
/* XXXXX */ |
/* XXXXX */ |
#else |
#else |
#error unsupported target CPU |
#error unsupported target CPU |
Line 785 void cpu_x86_frstor(CPUX86State *s, targ
|
Line 748 void cpu_x86_frstor(CPUX86State *s, targ
|
#if !defined(CONFIG_SOFTMMU) |
#if !defined(CONFIG_SOFTMMU) |
|
|
#if defined(TARGET_I386) |
#if defined(TARGET_I386) |
|
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code) |
|
#else |
|
#define EXCEPTION_ACTION cpu_loop_exit() |
|
#endif |
|
|
/* 'pc' is the host PC at which the exception was raised. 'address' is |
/* 'pc' is the host PC at which the exception was raised. 'address' is |
the effective address of the memory exception. 'is_write' is 1 if a |
the effective address of the memory exception. 'is_write' is 1 if a |
Line 809 static inline int handle_cpu_signal(unsi
|
Line 776 static inline int handle_cpu_signal(unsi
|
} |
} |
|
|
/* see if it is an MMU fault */ |
/* see if it is an MMU fault */ |
ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
if (ret < 0) |
if (ret < 0) |
return 0; /* not an MMU fault */ |
return 0; /* not an MMU fault */ |
if (ret == 0) |
if (ret == 0) |
Line 821 static inline int handle_cpu_signal(unsi
|
Line 788 static inline int handle_cpu_signal(unsi
|
a virtual CPU fault */ |
a virtual CPU fault */ |
cpu_restore_state(tb, env, pc, puc); |
cpu_restore_state(tb, env, pc, puc); |
} |
} |
if (ret == 1) { |
|
#if 0 |
|
printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", |
|
env->eip, env->cr[2], env->error_code); |
|
#endif |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
raise_exception_err(env->exception_index, env->error_code); |
|
} else { |
|
/* activate soft MMU for this block */ |
|
env->hflags |= HF_SOFTMMU_MASK; |
|
cpu_resume_from_signal(env, puc); |
|
} |
|
/* never comes here */ |
|
return 1; |
|
} |
|
|
|
#elif defined(TARGET_ARM) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(h2g(address), pc, puc)) { |
|
return 1; |
|
} |
|
/* see if it is an MMU fault */ |
|
ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
cpu_loop_exit(); |
|
/* never comes here */ |
|
return 1; |
|
} |
|
#elif defined(TARGET_SPARC) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(h2g(address), pc, puc)) { |
|
return 1; |
|
} |
|
/* see if it is an MMU fault */ |
|
ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
/* we restore the process signal mask as the sigreturn should |
/* we restore the process signal mask as the sigreturn should |
do it (XXX: use sigsetjmp) */ |
do it (XXX: use sigsetjmp) */ |
sigprocmask(SIG_SETMASK, old_set, NULL); |
sigprocmask(SIG_SETMASK, old_set, NULL); |
cpu_loop_exit(); |
EXCEPTION_ACTION; |
/* never comes here */ |
|
return 1; |
|
} |
|
#elif defined (TARGET_PPC) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(h2g(address), pc, puc)) { |
|
return 1; |
|
} |
|
|
|
/* see if it is an MMU fault */ |
|
ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
|
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
if (ret == 1) { |
|
#if 0 |
|
printf("PF exception: NIP=0x%08x error=0x%x %p\n", |
|
env->nip, env->error_code, tb); |
|
#endif |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
cpu_loop_exit(); |
|
} else { |
|
/* activate soft MMU for this block */ |
|
cpu_resume_from_signal(env, puc); |
|
} |
|
/* never comes here */ |
/* never comes here */ |
return 1; |
return 1; |
} |
} |
|
|
#elif defined(TARGET_M68K) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(address, pc, puc)) { |
|
return 1; |
|
} |
|
/* see if it is an MMU fault */ |
|
ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
cpu_loop_exit(); |
|
/* never comes here */ |
|
return 1; |
|
} |
|
|
|
#elif defined (TARGET_MIPS) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(h2g(address), pc, puc)) { |
|
return 1; |
|
} |
|
|
|
/* see if it is an MMU fault */ |
|
ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
|
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
if (ret == 1) { |
|
#if 0 |
|
printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n", |
|
env->PC, env->error_code, tb); |
|
#endif |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
cpu_loop_exit(); |
|
} else { |
|
/* activate soft MMU for this block */ |
|
cpu_resume_from_signal(env, puc); |
|
} |
|
/* never comes here */ |
|
return 1; |
|
} |
|
|
|
#elif defined (TARGET_MICROBLAZE) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(h2g(address), pc, puc)) { |
|
return 1; |
|
} |
|
|
|
/* see if it is an MMU fault */ |
|
ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
|
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
if (ret == 1) { |
|
#if 0 |
|
printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n", |
|
env->PC, env->error_code, tb); |
|
#endif |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
cpu_loop_exit(); |
|
} else { |
|
/* activate soft MMU for this block */ |
|
cpu_resume_from_signal(env, puc); |
|
} |
|
/* never comes here */ |
|
return 1; |
|
} |
|
|
|
#elif defined (TARGET_SH4) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(h2g(address), pc, puc)) { |
|
return 1; |
|
} |
|
|
|
/* see if it is an MMU fault */ |
|
ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
|
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
#if 0 |
|
printf("PF exception: NIP=0x%08x error=0x%x %p\n", |
|
env->nip, env->error_code, tb); |
|
#endif |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
cpu_loop_exit(); |
|
/* never comes here */ |
|
return 1; |
|
} |
|
|
|
#elif defined (TARGET_ALPHA) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(h2g(address), pc, puc)) { |
|
return 1; |
|
} |
|
|
|
/* see if it is an MMU fault */ |
|
ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
|
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
#if 0 |
|
printf("PF exception: NIP=0x%08x error=0x%x %p\n", |
|
env->nip, env->error_code, tb); |
|
#endif |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
cpu_loop_exit(); |
|
/* never comes here */ |
|
return 1; |
|
} |
|
#elif defined (TARGET_CRIS) |
|
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
|
int is_write, sigset_t *old_set, |
|
void *puc) |
|
{ |
|
TranslationBlock *tb; |
|
int ret; |
|
|
|
if (cpu_single_env) |
|
env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
|
#if defined(DEBUG_SIGNAL) |
|
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", |
|
pc, address, is_write, *(unsigned long *)old_set); |
|
#endif |
|
/* XXX: locking issue */ |
|
if (is_write && page_unprotect(h2g(address), pc, puc)) { |
|
return 1; |
|
} |
|
|
|
/* see if it is an MMU fault */ |
|
ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); |
|
if (ret < 0) |
|
return 0; /* not an MMU fault */ |
|
if (ret == 0) |
|
return 1; /* the MMU fault was handled without causing real CPU fault */ |
|
|
|
/* now we have a real cpu fault */ |
|
tb = tb_find_pc(pc); |
|
if (tb) { |
|
/* the PC is inside the translated code. It means that we have |
|
a virtual CPU fault */ |
|
cpu_restore_state(tb, env, pc, puc); |
|
} |
|
/* we restore the process signal mask as the sigreturn should |
|
do it (XXX: use sigsetjmp) */ |
|
sigprocmask(SIG_SETMASK, old_set, NULL); |
|
cpu_loop_exit(); |
|
/* never comes here */ |
|
return 1; |
|
} |
|
|
|
#else |
|
#error unsupported target CPU |
|
#endif |
|
|
|
#if defined(__i386__) |
#if defined(__i386__) |
|
|
#if defined(__APPLE__) |
#if defined(__APPLE__) |
Line 1247 static inline int handle_cpu_signal(unsi
|
Line 807 static inline int handle_cpu_signal(unsi
|
# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno) |
# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno) |
# define ERROR_sig(context) ((context)->uc_mcontext->es.err) |
# define ERROR_sig(context) ((context)->uc_mcontext->es.err) |
# define MASK_sig(context) ((context)->uc_sigmask) |
# define MASK_sig(context) ((context)->uc_sigmask) |
|
#elif defined (__NetBSD__) |
|
# include <ucontext.h> |
|
|
|
# define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP]) |
|
# define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO]) |
|
# define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR]) |
|
# define MASK_sig(context) ((context)->uc_sigmask) |
|
#elif defined (__FreeBSD__) || defined(__DragonFly__) |
|
# include <ucontext.h> |
|
|
|
# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_eip)) |
|
# define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno) |
|
# define ERROR_sig(context) ((context)->uc_mcontext.mc_err) |
|
# define MASK_sig(context) ((context)->uc_sigmask) |
#elif defined(__OpenBSD__) |
#elif defined(__OpenBSD__) |
# define EIP_sig(context) ((context)->sc_eip) |
# define EIP_sig(context) ((context)->sc_eip) |
# define TRAP_sig(context) ((context)->sc_trapno) |
# define TRAP_sig(context) ((context)->sc_trapno) |
Line 1263 int cpu_signal_handler(int host_signum,
|
Line 837 int cpu_signal_handler(int host_signum,
|
void *puc) |
void *puc) |
{ |
{ |
siginfo_t *info = pinfo; |
siginfo_t *info = pinfo; |
#if defined(__OpenBSD__) |
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__) |
|
ucontext_t *uc = puc; |
|
#elif defined(__OpenBSD__) |
struct sigcontext *uc = puc; |
struct sigcontext *uc = puc; |
#else |
#else |
struct ucontext *uc = puc; |
struct ucontext *uc = puc; |
Line 1297 int cpu_signal_handler(int host_signum,
|
Line 873 int cpu_signal_handler(int host_signum,
|
#define TRAP_sig(context) ((context)->sc_trapno) |
#define TRAP_sig(context) ((context)->sc_trapno) |
#define ERROR_sig(context) ((context)->sc_err) |
#define ERROR_sig(context) ((context)->sc_err) |
#define MASK_sig(context) ((context)->sc_mask) |
#define MASK_sig(context) ((context)->sc_mask) |
|
#elif defined (__FreeBSD__) || defined(__DragonFly__) |
|
#include <ucontext.h> |
|
|
|
#define PC_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_rip)) |
|
#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno) |
|
#define ERROR_sig(context) ((context)->uc_mcontext.mc_err) |
|
#define MASK_sig(context) ((context)->uc_sigmask) |
#else |
#else |
#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP]) |
#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP]) |
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO]) |
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO]) |
Line 1309 int cpu_signal_handler(int host_signum,
|
Line 892 int cpu_signal_handler(int host_signum,
|
{ |
{ |
siginfo_t *info = pinfo; |
siginfo_t *info = pinfo; |
unsigned long pc; |
unsigned long pc; |
#ifdef __NetBSD__ |
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__) |
ucontext_t *uc = puc; |
ucontext_t *uc = puc; |
#elif defined(__OpenBSD__) |
#elif defined(__OpenBSD__) |
struct sigcontext *uc = puc; |
struct sigcontext *uc = puc; |
Line 1435 int cpu_signal_handler(int host_signum,
|
Line 1018 int cpu_signal_handler(int host_signum,
|
siginfo_t *info = pinfo; |
siginfo_t *info = pinfo; |
int is_write; |
int is_write; |
uint32_t insn; |
uint32_t insn; |
#if !defined(__arch64__) || defined(HOST_SOLARIS) |
#if !defined(__arch64__) || defined(CONFIG_SOLARIS) |
uint32_t *regs = (uint32_t *)(info + 1); |
uint32_t *regs = (uint32_t *)(info + 1); |
void *sigmask = (regs + 20); |
void *sigmask = (regs + 20); |
/* XXX: is there a standard glibc define ? */ |
/* XXX: is there a standard glibc define ? */ |