From: Paolo Bonzini <pbonzini@redhat.com>
When icount is active, tb_add_jump is surprisingly called with an
out of bounds basic block index. I have no idea how that can work,
but it does not seem like a good idea. Clear *last_tb for all
TB_EXIT_ICOUNT_EXPIRED cases, even when all you have to do is
refill icount_extra.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 43d70ddf9f96b3ad037abe4d5f9f2768196b8c92)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
cpu-exec.c | 7 ++++---
include/exec/exec-all.h | 1 +
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index 4188fed..c081a7a 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -542,7 +542,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
trace_exec_tb(tb, tb->pc);
ret = cpu_tb_exec(cpu, tb);
- *last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
+ tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
*tb_exit = ret & TB_EXIT_MASK;
switch (*tb_exit) {
case TB_EXIT_REQUESTED:
@@ -566,6 +566,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
abort();
#else
int insns_left = cpu->icount_decr.u32;
+ *last_tb = NULL;
if (cpu->icount_extra && insns_left >= 0) {
/* Refill decrementer and continue execution. */
cpu->icount_extra += insns_left;
@@ -575,17 +576,17 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
} else {
if (insns_left > 0) {
/* Execute remaining instructions. */
- cpu_exec_nocache(cpu, insns_left, *last_tb, false);
+ cpu_exec_nocache(cpu, insns_left, tb, false);
align_clocks(sc, cpu);
}
cpu->exception_index = EXCP_INTERRUPT;
- *last_tb = NULL;
cpu_loop_exit(cpu);
}
break;
#endif
}
default:
+ *last_tb = tb;
break;
}
}
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index a8c13ce..e596ff7 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -320,6 +320,7 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
{
+ assert(n < ARRAY_SIZE(tb->jmp_list_next));
if (tb->jmp_list_next[n]) {
/* Another thread has already done this while we were
* outside of the lock; nothing to do in this case */
--
2.7.4