diff options
-rw-r--r-- | cpu-all.h | 3 | ||||
-rw-r--r-- | darwin-user/signal.c | 2 | ||||
-rw-r--r-- | exec.c | 56 | ||||
-rw-r--r-- | gdbstub.c | 2 | ||||
-rw-r--r-- | hw/dma.c | 2 | ||||
-rw-r--r-- | hw/mac_dbdma.c | 2 | ||||
-rw-r--r-- | linux-user/main.c | 2 | ||||
-rw-r--r-- | linux-user/signal.c | 2 | ||||
-rw-r--r-- | vl.c | 14 |
9 files changed, 47 insertions, 38 deletions
@@ -760,7 +760,6 @@ extern CPUState *cpu_single_env; extern int64_t qemu_icount; extern int use_icount; -#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */ #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ #define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */ #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */ @@ -774,6 +773,8 @@ extern int use_icount; void cpu_interrupt(CPUState *s, int mask); void cpu_reset_interrupt(CPUState *env, int mask); +void cpu_exit(CPUState *s); + /* Breakpoint/watchpoint flags */ #define BP_MEM_READ 0x01 #define BP_MEM_WRITE 0x02 diff --git a/darwin-user/signal.c b/darwin-user/signal.c index ba41c2e61a..851e85b60f 100644 --- a/darwin-user/signal.c +++ b/darwin-user/signal.c @@ -215,7 +215,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, #endif if (queue_signal(sig, &tinfo) == 1) { /* interrupt the virtual CPU as soon as possible */ - cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); + cpu_exit(global_env); } } @@ -523,7 +523,9 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be32s(f, &env->halted); qemu_get_be32s(f, &env->interrupt_request); - env->interrupt_request &= ~CPU_INTERRUPT_EXIT; + /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the + version_id is increased. */ + env->interrupt_request &= ~0x01; tlb_flush(env, 1); return 0; @@ -1499,28 +1501,36 @@ void cpu_set_log_filename(const char *filename) cpu_set_log(loglevel); } -/* mask must never be zero, except for A20 change call */ -void cpu_interrupt(CPUState *env, int mask) +static void cpu_unlink_tb(CPUState *env) { -#if !defined(USE_NPTL) +#if defined(USE_NPTL) + /* FIXME: TB unchaining isn't SMP safe. For now just ignore the + problem and hope the cpu will stop of its own accord. For userspace + emulation this often isn't actually as bad as it sounds. Often + signals are used primarily to interrupt blocking syscalls. */ +#else TranslationBlock *tb; static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; -#endif - int old_mask; - if (mask & CPU_INTERRUPT_EXIT) { - env->exit_request = 1; - mask &= ~CPU_INTERRUPT_EXIT; + tb = env->current_tb; + /* if the cpu is currently executing code, we must unlink it and + all the potentially executing TB */ + if (tb && !testandset(&interrupt_lock)) { + env->current_tb = NULL; + tb_reset_jump_recursive(tb); + resetlock(&interrupt_lock); } +#endif +} + +/* mask must never be zero, except for A20 change call */ +void cpu_interrupt(CPUState *env, int mask) +{ + int old_mask; old_mask = env->interrupt_request; env->interrupt_request |= mask; -#if defined(USE_NPTL) - /* FIXME: TB unchaining isn't SMP safe. For now just ignore the - problem and hope the cpu will stop of its own accord. For userspace - emulation this often isn't actually as bad as it sounds. Often - signals are used primarily to interrupt blocking syscalls. */ -#else + if (use_icount) { env->icount_decr.u16.high = 0xffff; #ifndef CONFIG_USER_ONLY @@ -1530,16 +1540,8 @@ void cpu_interrupt(CPUState *env, int mask) } #endif } else { - tb = env->current_tb; - /* if the cpu is currently executing code, we must unlink it and - all the potentially executing TB */ - if (tb && !testandset(&interrupt_lock)) { - env->current_tb = NULL; - tb_reset_jump_recursive(tb); - resetlock(&interrupt_lock); - } + cpu_unlink_tb(env); } -#endif } void cpu_reset_interrupt(CPUState *env, int mask) @@ -1547,6 +1549,12 @@ void cpu_reset_interrupt(CPUState *env, int mask) env->interrupt_request &= ~mask; } +void cpu_exit(CPUState *env) +{ + env->exit_request = 1; + cpu_unlink_tb(env); +} + const CPULogItem cpu_log_items[] = { { CPU_LOG_TB_OUT_ASM, "out_asm", "show generated host assembly code for each compiled TB" }, @@ -2012,7 +2012,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) #ifdef CONFIG_USER_ONLY gdb_handlesig(s->c_cpu, 0); #else - cpu_interrupt(s->c_cpu, CPU_INTERRUPT_EXIT); + cpu_exit(s->c_cpu); #endif } @@ -449,7 +449,7 @@ void DMA_schedule(int nchan) { CPUState *env = cpu_single_env; if (env) - cpu_interrupt(env, CPU_INTERRUPT_EXIT); + cpu_exit(env); } static void dma_reset(void *opaque) diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c index 8e82a2356c..b8e4b128d4 100644 --- a/hw/mac_dbdma.c +++ b/hw/mac_dbdma.c @@ -653,7 +653,7 @@ void DBDMA_schedule(void) { CPUState *env = cpu_single_env; if (env) - cpu_interrupt(env, CPU_INTERRUPT_EXIT); + cpu_exit(env); } static void diff --git a/linux-user/main.c b/linux-user/main.c index 2c1e4df6e5..feb3036170 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -200,7 +200,7 @@ static inline void start_exclusive(void) for (other = first_cpu; other; other = other->next_cpu) { if (other->running) { pending_cpus++; - cpu_interrupt(other, CPU_INTERRUPT_EXIT); + cpu_exit(other); } } if (pending_cpus > 1) { diff --git a/linux-user/signal.c b/linux-user/signal.c index 48640ec835..fc37dc11ff 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -460,7 +460,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, host_to_target_siginfo_noswap(&tinfo, info); if (queue_signal(thread_env, sig, &tinfo) == 1) { /* interrupt the virtual CPU as soon as possible */ - cpu_interrupt(thread_env, CPU_INTERRUPT_EXIT); + cpu_exit(thread_env); } } @@ -1181,7 +1181,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) } /* Interrupt execution to force deadline recalculation. */ if (use_icount && cpu_single_env) { - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); + cpu_exit(cpu_single_env); } } } @@ -1348,7 +1348,7 @@ static void host_alarm_handler(int host_signum) if (env) { /* stop the currently executing cpu because a timer occured */ - cpu_interrupt(env, CPU_INTERRUPT_EXIT); + cpu_exit(env); #ifdef USE_KQEMU if (env->kqemu_enabled) { kqemu_cpu_interrupt(env); @@ -3326,7 +3326,7 @@ void qemu_service_io(void) { CPUState *env = cpu_single_env; if (env) { - cpu_interrupt(env, CPU_INTERRUPT_EXIT); + cpu_exit(env); #ifdef USE_KQEMU if (env->kqemu_enabled) { kqemu_cpu_interrupt(env); @@ -3407,7 +3407,7 @@ void qemu_bh_schedule(QEMUBH *bh) bh->idle = 0; /* stop the currently executing CPU to execute the BH ASAP */ if (env) { - cpu_interrupt(env, CPU_INTERRUPT_EXIT); + cpu_exit(env); } } @@ -3618,21 +3618,21 @@ void qemu_system_reset_request(void) reset_requested = 1; } if (cpu_single_env) - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); + cpu_exit(cpu_single_env); } void qemu_system_shutdown_request(void) { shutdown_requested = 1; if (cpu_single_env) - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); + cpu_exit(cpu_single_env); } void qemu_system_powerdown_request(void) { powerdown_requested = 1; if (cpu_single_env) - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); + cpu_exit(cpu_single_env); } #ifdef _WIN32 |