aboutsummaryrefslogtreecommitdiff
path: root/cpu-exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu-exec.c')
-rw-r--r--cpu-exec.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/cpu-exec.c b/cpu-exec.c
index f9ea080e31..9092145d0b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -64,6 +64,12 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
cpu_pc_from_tb(env, tb);
}
+ if ((next_tb & TB_EXIT_MASK) == TB_EXIT_REQUESTED) {
+ /* We were asked to stop executing TBs (probably a pending
+ * interrupt. We've now stopped, so clear the flag.
+ */
+ cpu->tcg_exit_req = 0;
+ }
return next_tb;
}
@@ -608,7 +614,20 @@ int cpu_exec(CPUArchState *env)
tc_ptr = tb->tc_ptr;
/* execute the generated code */
next_tb = cpu_tb_exec(cpu, tc_ptr);
- if ((next_tb & TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) {
+ switch (next_tb & TB_EXIT_MASK) {
+ case TB_EXIT_REQUESTED:
+ /* Something asked us to stop executing
+ * chained TBs; just continue round the main
+ * loop. Whatever requested the exit will also
+ * have set something else (eg exit_request or
+ * interrupt_request) which we will handle
+ * next time around the loop.
+ */
+ tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
+ next_tb = 0;
+ break;
+ case TB_EXIT_ICOUNT_EXPIRED:
+ {
/* Instruction counter expired. */
int insns_left;
tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
@@ -632,6 +651,10 @@ int cpu_exec(CPUArchState *env)
next_tb = 0;
cpu_loop_exit(env);
}
+ break;
+ }
+ default:
+ break;
}
}
cpu->current_tb = NULL;