Instead of invalidating an original TB in cpu_exec_nocache() prematurely, just save a link to it in the temporary generated TB. If cpu_io_recompile() is raised subsequently from the temporary TB, invalidate the original one as well. That allows reusing the original TB each time cpu_exec_nocache() is called to handle expired instruction counter in icount mode.
Signed-off-by: Sergey Fedorov <serge.f...@gmail.com> --- cpu-exec.c | 8 ++------ include/exec/exec-all.h | 2 ++ translate-all.c | 6 ++++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 2ffeb6e..2b7537c 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -231,19 +231,15 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles, { CPUState *cpu = ENV_GET_CPU(env); TranslationBlock *tb; - target_ulong pc = orig_tb->pc; - target_ulong cs_base = orig_tb->cs_base; - uint64_t flags = orig_tb->flags; /* Should never happen. We only end up here when an existing TB is too long. */ if (max_cycles > CF_COUNT_MASK) max_cycles = CF_COUNT_MASK; - /* tb_gen_code can flush our orig_tb, invalidate it now */ - tb_phys_invalidate(orig_tb, -1); - tb = tb_gen_code(cpu, pc, cs_base, flags, + tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, max_cycles | CF_NOCACHE); + tb->orig_tb = orig_tb; cpu->current_tb = tb; /* execute the generated code */ trace_exec_tb_nocache(tb, tb->pc); diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 2573e8c..2aab8c3 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -155,6 +155,8 @@ struct TranslationBlock { void *tc_ptr; /* pointer to the translated code */ /* next matching tb for physical address. */ struct TranslationBlock *phys_hash_next; + /* original tb when cflags has CF_NOCACHE */ + struct TranslationBlock *orig_tb; /* first and second physical page containing code. The lower bit of the pointer tells the index in page_next[] */ struct TranslationBlock *page_next[2]; diff --git a/translate-all.c b/translate-all.c index b6b0e1c..3fe65c7 100644 --- a/translate-all.c +++ b/translate-all.c @@ -1532,6 +1532,12 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) cs_base = tb->cs_base; flags = tb->flags; tb_phys_invalidate(tb, -1); + if (tb->cflags & CF_NOCACHE) { + /* Invalidate original TB if this TB was generated in + * cpu_exec_nocache() */ + tb_phys_invalidate(tb->orig_tb, -1); + tb_free(tb); + } /* FIXME: In theory this could raise an exception. In practice we have already translated the block once so it's probably ok. */ tb_gen_code(cpu, pc, cs_base, flags, cflags); -- 1.9.1