From 10e2b13650c36df8085d1b9a3c9c85dc9c1e91b2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 7 Jun 2018 11:56:25 -0400 Subject: [PATCH] tcg: Pass tb and index to tcg_gen_exit_tb separately Do the cast to uintptr_t within the helper, so that the compiler can type check the pointer argument. We can also do some more sanity checking of the index argument. Backports commit 07ea28b41830f946de3841b0ac61a3413679feb9 from qemu --- qemu/include/exec/gen-icount.h | 2 +- qemu/target/arm/translate-a64.c | 6 +++--- qemu/target/arm/translate.c | 8 ++++---- qemu/target/i386/translate.c | 8 ++++---- qemu/target/m68k/translate.c | 6 +++--- qemu/target/mips/translate.c | 4 ++-- qemu/target/sparc/translate.c | 16 ++++++++-------- qemu/tcg/tcg-op.c | 24 ++++++++++++++++++++++-- qemu/tcg/tcg-op.h | 17 +++++++++++++---- qemu/tcg/tcg.h | 7 ++++--- 10 files changed, 64 insertions(+), 34 deletions(-) diff --git a/qemu/include/exec/gen-icount.h b/qemu/include/exec/gen-icount.h index 076dc70e..81396c83 100644 --- a/qemu/include/exec/gen-icount.h +++ b/qemu/include/exec/gen-icount.h @@ -50,7 +50,7 @@ static inline void gen_tb_start(TCGContext *tcg_ctx, TranslationBlock *tb) static inline void gen_tb_end(TCGContext *tcg_ctx, TranslationBlock *tb, int num_insns) { gen_set_label(tcg_ctx, tcg_ctx->exitreq_label); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)tb + TB_EXIT_REQUESTED); + tcg_gen_exit_tb(tcg_ctx, tb, TB_EXIT_REQUESTED); #if 0 if (tb->cflags & CF_USE_ICOUNT) { diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 45459c7c..3c12d9f9 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -404,7 +404,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest) if (use_goto_tb(s, n, dest)) { tcg_gen_goto_tb(tcg_ctx, n); gen_a64_set_pc_im(s, dest); - tcg_gen_exit_tb(tcg_ctx, (intptr_t)tb + n); + tcg_gen_exit_tb(tcg_ctx, tb, n); s->base.is_jmp = DISAS_NORETURN; } else { gen_a64_set_pc_im(s, dest); @@ -14070,7 +14070,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_a64_set_pc_im(dc, dc->pc); /* fall through */ case DISAS_EXIT: - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; case DISAS_JUMP: tcg_gen_lookup_and_goto_ptr(tcg_ctx); @@ -14099,7 +14099,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) /* The helper doesn't necessarily throw an exception, but we * must go back to the main loop to check for interrupts anyway. */ - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; } } diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 90930c99..b3fe03c5 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -1028,7 +1028,7 @@ static inline void gen_bx_excret_final_code(DisasContext *s) if (is_singlestepping(s)) { gen_singlestep_exception(s); } else { - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } gen_set_label(tcg_ctx, excret_label); /* Yes: this is an exception return. @@ -4376,7 +4376,7 @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest) if (use_goto_tb(s, dest)) { tcg_gen_goto_tb(tcg_ctx, n); gen_set_pc_im(s, dest); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + n); + tcg_gen_exit_tb(tcg_ctx, s->base.tb, n); } else { gen_set_pc_im(s, dest); gen_goto_ptr(s); @@ -12907,7 +12907,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) /* fall through */ default: /* indicate that the hash table must be used to find the next TB */ - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; case DISAS_NORETURN: /* nothing more to generate */ @@ -12922,7 +12922,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) /* The helper doesn't necessarily throw an exception, but we * must go back to the main loop to check for interrupts anyway. */ - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; } case DISAS_WFE: diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index 7b99e63d..ecb98c64 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -2464,7 +2464,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) /* jump to same page: we can use a direct jump */ tcg_gen_goto_tb(tcg_ctx, tb_num); gen_jmp_im(s, eip); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + tb_num); + tcg_gen_exit_tb(tcg_ctx, s->base.tb, tb_num); s->base.is_jmp = DISAS_NORETURN; } else { /* jump to another page */ @@ -2904,13 +2904,13 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr) gen_helper_debug(tcg_ctx, tcg_ctx->cpu_env); } else if (recheck_tf) { gen_helper_rechecking_single_step(tcg_ctx, tcg_ctx->cpu_env); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } else if (s->tf) { gen_helper_single_step(tcg_ctx, tcg_ctx->cpu_env); } else if (jr) { tcg_gen_lookup_and_goto_ptr(tcg_ctx); } else { - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } s->base.is_jmp = DISAS_NORETURN; } @@ -8030,7 +8030,7 @@ case 0x101: gen_helper_vmrun(tcg_ctx, cpu_env, tcg_const_i32(tcg_ctx, s->aflag - 1), tcg_const_i32(tcg_ctx, s->pc - pc_start)); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); s->base.is_jmp = DISAS_NORETURN; break; diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index 09f0ee5e..e3d56e85 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -1528,10 +1528,10 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest) } else if (use_goto_tb(s, dest)) { tcg_gen_goto_tb(tcg_ctx, n); tcg_gen_movi_i32(tcg_ctx, tcg_ctx->QREG_PC, dest); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->tb + n); + tcg_gen_exit_tb(tcg_ctx, s->tb, n); } else { gen_jmp_im(s, dest); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } s->is_jmp = DISAS_TB_JUMP; } @@ -6416,7 +6416,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) case DISAS_UPDATE: update_cc_op(dc); /* indicate that the hash table must be used to find the next TB */ - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; case DISAS_TB_JUMP: /* nothing more to generate */ diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index a7b124bc..8d18e28b 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -4350,7 +4350,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) if (use_goto_tb(ctx, dest)) { tcg_gen_goto_tb(tcg_ctx, n); gen_save_pc(ctx, dest); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)ctx->base.tb + n); + tcg_gen_exit_tb(tcg_ctx, ctx->base.tb, n); } else { gen_save_pc(ctx, dest); if (ctx->base.singlestep_enabled) { @@ -20534,7 +20534,7 @@ static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) gen_goto_tb(ctx, 0, ctx->base.pc_next); break; case DISAS_EXIT: - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); break; case DISAS_NORETURN: break; diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index 58dc1bb3..07820f9f 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -359,12 +359,12 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, tcg_gen_goto_tb(tcg_ctx, tb_num); tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, pc); tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_npc, npc); - tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + tb_num); + tcg_gen_exit_tb(tcg_ctx, s->base.tb, tb_num); } else { /* jump to another page: currently not optimized */ tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, pc); tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_npc, npc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } } @@ -4510,7 +4510,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins /* End TB to notice changed ASI. */ save_state(dc); gen_op_next_insn(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; break; case 0x6: /* V9 wrfprs */ @@ -4519,7 +4519,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins dc->fprs_dirty = 0; save_state(dc); gen_op_next_insn(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; break; case 0xf: /* V9 sir, nop if user */ @@ -4647,7 +4647,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins dc->cc_op = CC_OP_FLAGS; save_state(dc); gen_op_next_insn(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; #endif } @@ -4803,7 +4803,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins hpstate)); save_state(dc); gen_op_next_insn(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; break; case 1: // htstate @@ -5979,7 +5979,7 @@ static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, save_state(dc); } gen_helper_debug(tcg_ctx, tcg_ctx->cpu_env); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); dc->base.is_jmp = DISAS_NORETURN; /* update pc_next so that the current instruction is included in tb->size */ dc->base.pc_next += 4; @@ -6026,7 +6026,7 @@ static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, dc->pc); } save_npc(dc); - tcg_gen_exit_tb(tcg_ctx, 0); + tcg_gen_exit_tb(tcg_ctx, NULL, 0); } } } diff --git a/qemu/tcg/tcg-op.c b/qemu/tcg/tcg-op.c index 9f4c0f02..e32fe7a6 100644 --- a/qemu/tcg/tcg-op.c +++ b/qemu/tcg/tcg-op.c @@ -2588,10 +2588,30 @@ void tcg_gen_extr32_i64(TCGContext *s, TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg) /* QEMU specific operations. */ +void tcg_gen_exit_tb(TCGContext *s, TranslationBlock *tb, unsigned idx) +{ + uintptr_t val = (uintptr_t)tb + idx; + + if (tb == NULL) { + tcg_debug_assert(idx == 0); + } else if (idx <= TB_EXIT_IDXMAX) { +#ifdef CONFIG_DEBUG_TCG + /* This is an exit following a goto_tb. Verify that we have + seen this numbered exit before, via tcg_gen_goto_tb. */ + tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx)); +#endif + } else { + /* This is an exit via the exitreq label. */ + tcg_debug_assert(idx == TB_EXIT_REQUESTED); + } + + tcg_gen_op1i(s, INDEX_op_exit_tb, val); +} + void tcg_gen_goto_tb(TCGContext *s, unsigned idx) { /* We only support two chained exits. */ - tcg_debug_assert(idx <= 1); + tcg_debug_assert(idx <= TB_EXIT_IDXMAX); #ifdef CONFIG_DEBUG_TCG /* Verify that we havn't seen this numbered exit before. */ tcg_debug_assert((s->goto_tb_issue_mask & (1 << idx)) == 0); @@ -2608,7 +2628,7 @@ void tcg_gen_lookup_and_goto_ptr(TCGContext *s) tcg_gen_op1i(s, INDEX_op_goto_ptr, tcgv_ptr_arg(s, ptr)); tcg_temp_free_ptr(s, ptr); } else { - tcg_gen_exit_tb(s, 0); + tcg_gen_exit_tb(s, NULL, 0); } } diff --git a/qemu/tcg/tcg-op.h b/qemu/tcg/tcg-op.h index 327718a6..0fa9f443 100644 --- a/qemu/tcg/tcg-op.h +++ b/qemu/tcg/tcg-op.h @@ -789,10 +789,19 @@ static inline void tcg_gen_insn_start(TCGContext *tcg_ctx, target_ulong pc, targ # error "Unhandled number of operands to insn_start" #endif -static inline void tcg_gen_exit_tb(TCGContext *s, uintptr_t val) -{ - tcg_gen_op1i(s, INDEX_op_exit_tb, val); -} +/** + * tcg_gen_exit_tb() - output exit_tb TCG operation + * @tb: The TranslationBlock from which we are exiting + * @idx: Direct jump slot index, or exit request + * + * See tcg/README for more info about this TCG operation. + * See also tcg.h and the block comment above TB_EXIT_MASK. + * + * For a normal exit from the TB, back to the main loop, @tb should + * be NULL and @idx should be 0. Otherwise, @tb should be valid and + * @idx should be one of the TB_EXIT_ values. + */ +void tcg_gen_exit_tb(TCGContext *s, TranslationBlock *tb, unsigned idx); /** * tcg_gen_goto_tb() - output goto_tb TCG operation diff --git a/qemu/tcg/tcg.h b/qemu/tcg/tcg.h index 21bd9946..8355fd5b 100644 --- a/qemu/tcg/tcg.h +++ b/qemu/tcg/tcg.h @@ -1373,9 +1373,10 @@ static inline unsigned get_mmuidx(TCGMemOpIdx oi) * to this default (which just calls the prologue.code emitted by * tcg_target_qemu_prologue()). */ -#define TB_EXIT_MASK 3 -#define TB_EXIT_IDX0 0 -#define TB_EXIT_IDX1 1 +#define TB_EXIT_MASK 3 +#define TB_EXIT_IDX0 0 +#define TB_EXIT_IDX1 1 +#define TB_EXIT_IDXMAX 1 #define TB_EXIT_ICOUNT_EXPIRED 2 #define TB_EXIT_REQUESTED 3