diff options
-rw-r--r-- | cpu-all.h | 4 | ||||
-rw-r--r-- | cpu-exec.c | 43 | ||||
-rw-r--r-- | cpu-i386.h | 6 | ||||
-rw-r--r-- | exec.c | 7 | ||||
-rw-r--r-- | linux-user/signal.c | 2 | ||||
-rw-r--r-- | translate-i386.c | 2 |
6 files changed, 35 insertions, 29 deletions
@@ -309,6 +309,10 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size); void cpu_abort(CPUState *env, const char *fmt, ...); extern CPUState *cpu_single_env; +#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */ +#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ +void cpu_interrupt(CPUX86State *s, int mask); + /* gdb stub API */ extern int gdbstub_fd; CPUState *cpu_gdbstub_get_env(void *opaque); diff --git a/cpu-exec.c b/cpu-exec.c index aa2ee3a9e3..4da3641e6f 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -71,7 +71,7 @@ int cpu_exec(CPUState *env1) #ifdef __sparc__ int saved_i7, tmp_T0; #endif - int code_gen_size, ret; + int code_gen_size, ret, interrupt_request; void (*gen_func)(void); TranslationBlock *tb, **ptb; uint8_t *tc_ptr, *cs_base, *pc; @@ -139,7 +139,6 @@ int cpu_exec(CPUState *env1) #else #error unsupported target CPU #endif - env->interrupt_request = 0; env->exception_index = -1; /* prepare setjmp context for exception handling */ @@ -176,28 +175,32 @@ int cpu_exec(CPUState *env1) } env->exception_index = -1; } -#if defined(TARGET_I386) - /* if hardware interrupt pending, we execute it */ - if (env->hard_interrupt_request && - (env->eflags & IF_MASK)) { - int intno; - intno = cpu_x86_get_pic_interrupt(env); - if (loglevel) { - fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); - } - do_interrupt(intno, 0, 0, 0); - env->hard_interrupt_request = 0; - } -#endif T0 = 0; /* force lookup of first TB */ for(;;) { #ifdef __sparc__ /* g1 can be modified by some libc? functions */ tmp_T0 = T0; #endif - if (env->interrupt_request) { - env->exception_index = EXCP_INTERRUPT; - cpu_loop_exit(); + interrupt_request = env->interrupt_request; + if (interrupt_request) { +#if defined(TARGET_I386) + /* if hardware interrupt pending, we execute it */ + if ((interrupt_request & CPU_INTERRUPT_HARD) && + (env->eflags & IF_MASK)) { + int intno; + intno = cpu_x86_get_pic_interrupt(env); + if (loglevel) { + fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); + } + do_interrupt(intno, 0, 0, 0); + env->interrupt_request &= ~CPU_INTERRUPT_HARD; + } +#endif + if (interrupt_request & CPU_INTERRUPT_EXIT) { + env->interrupt_request &= ~CPU_INTERRUPT_EXIT; + env->exception_index = EXCP_INTERRUPT; + cpu_loop_exit(); + } } #ifdef DEBUG_EXEC if (loglevel) { @@ -212,7 +215,7 @@ int cpu_exec(CPUState *env1) env->regs[R_EBP] = EBP; env->regs[R_ESP] = ESP; env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); - cpu_x86_dump_state(env, logfile, 0); + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); #elif defined(TARGET_ARM) cpu_arm_dump_state(env, logfile, 0); @@ -454,7 +457,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, { TranslationBlock *tb; int ret; - + if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ #if defined(DEBUG_SIGNAL) diff --git a/cpu-i386.h b/cpu-i386.h index 6c7afbf6e2..4029746c80 100644 --- a/cpu-i386.h +++ b/cpu-i386.h @@ -254,10 +254,7 @@ typedef struct CPUX86State { struct TranslationBlock *current_tb; /* currently executing TB */ uint32_t cr[5]; /* NOTE: cr1 is unused */ uint32_t dr[8]; /* debug registers */ - int interrupt_request; /* if true, will exit from cpu_exec() ASAP */ - /* if true, will call cpu_x86_get_pic_interrupt() ASAP to get the - request interrupt number */ - int hard_interrupt_request; + int interrupt_request; int user_mode_only; /* user mode only simulation */ /* user data */ @@ -275,7 +272,6 @@ int cpu_x86_inl(CPUX86State *env, int addr); CPUX86State *cpu_x86_init(void); int cpu_x86_exec(CPUX86State *s); -void cpu_x86_interrupt(CPUX86State *s); void cpu_x86_close(CPUX86State *s); int cpu_x86_get_pic_interrupt(CPUX86State *s); @@ -617,11 +617,12 @@ static void tb_reset_jump_recursive(TranslationBlock *tb) tb_reset_jump_recursive2(tb, 1); } -void cpu_interrupt(CPUState *env) +/* mask must never be zero */ +void cpu_interrupt(CPUState *env, int mask) { TranslationBlock *tb; - - env->interrupt_request = 1; + + env->interrupt_request |= mask; /* if the cpu is currently executing code, we must unlink it and all the potentially executing TB */ tb = env->current_tb; diff --git a/linux-user/signal.c b/linux-user/signal.c index 8c757dd4a1..74aaeea681 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -333,7 +333,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, host_to_target_siginfo_noswap(&tinfo, info); if (queue_signal(sig, &tinfo) == 1) { /* interrupt the virtual CPU as soon as possible */ - cpu_interrupt(global_env); + cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); } } diff --git a/translate-i386.c b/translate-i386.c index b477ac4adb..8a7147c556 100644 --- a/translate-i386.c +++ b/translate-i386.c @@ -3331,12 +3331,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) if (!s->vm86) { if (s->cpl <= s->iopl) { gen_op_sti(); + s->is_jmp = 2; /* give a chance to handle pending irqs */ } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } } else { if (s->iopl == 3) { gen_op_sti(); + s->is_jmp = 2; /* give a chance to handle pending irqs */ } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } |