|
@@ -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" },
|