qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC PATCH] accel/tcg/translator: add tb_enter TCG trac


From: Alex Bennée
Subject: Re: [Qemu-devel] [RFC PATCH] accel/tcg/translator: add tb_enter TCG trace
Date: Fri, 28 Jun 2019 17:33:05 +0100
User-agent: mu4e 1.3.2; emacs 26.1

Luc Michel <address@hidden> writes:

> Add a TCG trace at the begining of a translation block recording the
> first and last (past-the-end) PC values.
>
> Signed-off-by: Luc Michel <address@hidden>
> ---
> This can be used to trace the execution of the guest quite efficiently.
> It will report each time a TB is entered (using the tb_enter_exec
> trace). The traces arguments give the PC start and past-the-end values.
> It has very little to no performance impact since the trace is actually
> emitted in the generated code only when it is enabled at run time.
>
> It works already quite well on its own to trace guest execution.

You could just remove the disable from:

disable exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR

And call qemu with -d nochain,trace:exec_tb

> However
> it does not handle the case where a TB is exited in the middle of
> execution. I'm not sure how to properly trace that. A trace could be
> added when `cpu_loop_exit()' is called to report the current PC, but in
> most cases the interesting value (the PC of the instruction that
> caused the exit) is already lost at this stage.
>
> I'm not sure there is a generic (i.e. not target specific) way of
> recovering the last PC executed when cpu_loop_exit() is called. Do you
> think of a better way?
>
> Thanks to the Xilinx's QEMU team who sponsored this work.
> ---
>  accel/tcg/translator.c | 24 ++++++++++++++++++++++++
>  trace-events           |  3 +++
>  2 files changed, 27 insertions(+)
>
> diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
> index 9226a348a3..c55377aa18 100644
> --- a/accel/tcg/translator.c
> +++ b/accel/tcg/translator.c
> @@ -14,10 +14,11 @@
>  #include "tcg/tcg-op.h"
>  #include "exec/exec-all.h"
>  #include "exec/gen-icount.h"
>  #include "exec/log.h"
>  #include "exec/translator.h"
> +#include "trace-tcg.h"
>
>  /* Pairs with tcg_clear_temp_count.
>     To be called by #TranslatorOps.{translate_insn,tb_stop} if
>     (1) the target is sufficiently clean to support reporting,
>     (2) as and when all temporaries are known to be consumed.
> @@ -28,14 +29,31 @@ void translator_loop_temp_check(DisasContextBase *db)
>          qemu_log("warning: TCG temporary leaks before "
>                   TARGET_FMT_lx "\n", db->pc_next);
>      }
>  }
>
> +static TCGOp *gen_trace_tb_enter(TranslationBlock *tb)
> +{
> +    TCGOp *last_pc_op;
> +
> +    TCGv pc_end = tcg_temp_new();
> +
> +    /* The last PC value is not known yet */
> +    tcg_gen_movi_tl(pc_end, 0xdeadbeef);
> +    last_pc_op = tcg_last_op();
> +
> +    trace_tb_enter_tcg(tcg_ctx->cpu, cpu_env, tb->pc, pc_end);
> +    tcg_temp_free(pc_end);
> +
> +    return last_pc_op;
> +}
> +
>  void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
>                       CPUState *cpu, TranslationBlock *tb, int max_insns)
>  {
>      int bp_insn = 0;
> +    TCGOp *trace_pc_end;
>
>      /* Initialize DisasContext */
>      db->tb = tb;
>      db->pc_first = tb->pc;
>      db->pc_next = db->pc_first;
> @@ -50,10 +68,13 @@ void translator_loop(const TranslatorOps *ops, 
> DisasContextBase *db,
>      /* Reset the temp count so that we can identify leaks */
>      tcg_clear_temp_count();
>
>      /* Start translating.  */
>      gen_tb_start(db->tb);
> +
> +    trace_pc_end = gen_trace_tb_enter(tb);
> +
>      ops->tb_start(db, cpu);
>      tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
>
>      while (true) {
>          db->num_insns++;
> @@ -110,10 +131,13 @@ void translator_loop(const TranslatorOps *ops, 
> DisasContextBase *db,
>
>      /* Emit code to exit the TB, as indicated by db->is_jmp.  */
>      ops->tb_stop(db, cpu);
>      gen_tb_end(db->tb, db->num_insns - bp_insn);
>
> +    /* Fixup the last PC value in the tb_enter trace now that we know it */
> +    tcg_set_insn_param(trace_pc_end, 1, db->pc_next);
> +
>      /* The disas_log hook may use these values rather than recompute.  */
>      db->tb->size = db->pc_next - db->pc_first;
>      db->tb->icount = db->num_insns;
>
>  #ifdef DEBUG_DISAS
> diff --git a/trace-events b/trace-events
> index aeea3c2bdb..e37fa12ef0 100644
> --- a/trace-events
> +++ b/trace-events
> @@ -157,10 +157,13 @@ vcpu guest_cpu_reset(void)
>  #
>  # Mode: user, softmmu
>  # Targets: TCG(all)
>  vcpu tcg guest_mem_before(TCGv vaddr, uint8_t info) "info=%d", 
> "vaddr=0x%016"PRIx64" info=%d"
>
> +# translator.c
> +vcpu tcg tb_enter(uint64_t pc_start, TCGv pc_end) "pc_start:0x%"PRIx64, 
> "pc:0x%"PRIx64" pc_end:0x%"PRIx64
> +
>  # linux-user/syscall.c
>  # bsd-user/syscall.c
>
>  # @num: System call number.
>  # @arg*: System call argument value.


--
Alex Bennée



reply via email to

[Prev in Thread] Current Thread [Next in Thread]