qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [RFC PATCH v2 4/7] tcg: add instrumenting module


From: Alex Bennée
Subject: Re: [Qemu-devel] [RFC PATCH v2 4/7] tcg: add instrumenting module
Date: Fri, 07 Sep 2018 14:36:36 +0100
User-agent: mu4e 1.1.0; emacs 26.1.50

Pavel Dovgalyuk <address@hidden> writes:

> From: Pavel Dovgalyuk <address@hidden>
>
> This is a samples of the instrumenting interface and implementation
> of some instruction tracing tasks.
>
> Signed-off-by: Pavel Dovgalyuk <address@hidden>
> ---
>  accel/tcg/translator.c    |    5 +++++
>  include/qemu/instrument.h |    7 +++++++
>  plugins/helper.h          |    1 +
>  plugins/plugins.c         |   41 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 54 insertions(+)
>  create mode 100644 include/qemu/instrument.h
>  create mode 100644 plugins/helper.h
>
> diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
> index 0f9dca9..48773ac 100644
> --- a/accel/tcg/translator.c
> +++ b/accel/tcg/translator.c
> @@ -17,6 +17,7 @@
>  #include "exec/gen-icount.h"
>  #include "exec/log.h"
>  #include "exec/translator.h"
> +#include "qemu/instrument.h"
>
>  /* Pairs with tcg_clear_temp_count.
>     To be called by #TranslatorOps.{translate_insn,tb_stop} if
> @@ -89,6 +90,10 @@ void translator_loop(const TranslatorOps *ops, 
> DisasContextBase *db,
>              }
>          }
>
> +        if (plugins_need_before_insn(db->pc_next, cpu)) {
> +            plugins_instrument_before_insn(db->pc_next, cpu);
> +        }
> +

I don't really see the need for a plugin_need_foo call here. Can't we
just iterate over all plugins that provide a before_insn binding and
leave it at that?

If the plugin decides it doesn't want to do anything with this
particular instruction it can always bail early.

>          /* Disassemble one instruction.  The translate_insn hook should
>             update db->pc_next and db->is_jmp to indicate what should be
>             done next -- either exiting this loop or locate the start of
> diff --git a/include/qemu/instrument.h b/include/qemu/instrument.h
> new file mode 100644
> index 0000000..e8f279f
> --- /dev/null
> +++ b/include/qemu/instrument.h
> @@ -0,0 +1,7 @@
> +#ifndef INSTRUMENT_H
> +#define INSTRUMENT_H
> +
> +bool plugins_need_before_insn(target_ulong pc, CPUState *cpu);
> +void plugins_instrument_before_insn(target_ulong pc, CPUState *cpu);

Need empty inline cases for #ifndef CONFIG_PLUGINS

> +
> +#endif /* INSTRUMENT_H */
> diff --git a/plugins/helper.h b/plugins/helper.h
> new file mode 100644
> index 0000000..007b395
> --- /dev/null
> +++ b/plugins/helper.h
> @@ -0,0 +1 @@
> +DEF_HELPER_2(before_insn, void, tl, ptr)

I wonder if we should have an explicit DEF_HELPER_FLAGS_2. Looking at
the flags though:

  /* call flags */
  /* Helper does not read globals (either directly or through an exception). It
     implies TCG_CALL_NO_WRITE_GLOBALS. */
  #define TCG_CALL_NO_READ_GLOBALS    0x0010
  /* Helper does not write globals */
  #define TCG_CALL_NO_WRITE_GLOBALS   0x0020
  /* Helper can be safely suppressed if the return value is not used. */
  #define TCG_CALL_NO_SIDE_EFFECTS    0x0040

  /* convenience version of most used call flags */
  #define TCG_CALL_NO_RWG         TCG_CALL_NO_READ_GLOBALS
  #define TCG_CALL_NO_WG          TCG_CALL_NO_WRITE_GLOBALS
  #define TCG_CALL_NO_SE          TCG_CALL_NO_SIDE_EFFECTS
  #define TCG_CALL_NO_RWG_SE      (TCG_CALL_NO_RWG | TCG_CALL_NO_SE)
  #define TCG_CALL_NO_WG_SE       (TCG_CALL_NO_WG | TCG_CALL_NO_SE)

I guess no flags means machine state is fully consistent before we make
the helper call?

> diff --git a/plugins/plugins.c b/plugins/plugins.c
> index eabc931..5a08e71 100644
> --- a/plugins/plugins.c
> +++ b/plugins/plugins.c
> @@ -1,8 +1,13 @@
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "cpu.h"
>  #include "qemu/error-report.h"
>  #include "qemu/plugins.h"
> +#include "qemu/instrument.h"
> +#include "tcg/tcg.h"
> +#include "tcg/tcg-op.h"
>  #include "qemu/queue.h"
> +#include "qemu/option.h"
>  #include <gmodule.h>
>
>  typedef bool (*PluginInitFunc)(const char *);
> @@ -80,6 +85,40 @@ void qemu_plugin_load(const char *filename, const char 
> *args)
>      return;
>  }
>
> +bool plugins_need_before_insn(target_ulong pc, CPUState *cpu)
> +{
> +    QemuPluginInfo *info;
> +    QLIST_FOREACH(info, &qemu_plugins, next) {
> +        if (info->needs_before_insn && info->needs_before_insn(pc, cpu)) {
> +            return true;
> +        }
> +    }
> +
> +    return false;
> +}
> +
> +void plugins_instrument_before_insn(target_ulong pc, CPUState *cpu)
> +{
> +    TCGv t_pc = tcg_const_tl(pc);
> +    TCGv_ptr t_cpu = tcg_const_ptr(cpu);
> +    /* We will dispatch plugins' callbacks in our own helper below */
> +    gen_helper_before_insn(t_pc, t_cpu);
> +    tcg_temp_free(t_pc);
> +    tcg_temp_free_ptr(t_cpu);
> +}

OK I see what is happening here - but I worry about pushing off all
plugins into a single helper call with a fairly fixed amount of
information.

Would it be better to expose the generate helper API and maybe a few TCG
constants to the plugin function itself. It could then either emit
additional TCG operations or call to the helper - and deal with the
logic about if it should or shouldn't in a single call rather than doing
the need_foo call first.

Richard,

Will the TCG be smart enough to drop the pc/t_cpu variables if they are
ultimately not used by the instrument in this particular iteration?

> +
> +void helper_before_insn(target_ulong pc, void *cpu)
> +{
> +    QemuPluginInfo *info;
> +    QLIST_FOREACH(info, &qemu_plugins, next) {
> +        if (info->needs_before_insn && info->needs_before_insn(pc, cpu)) {
> +            if (info->before_insn) {
> +                info->before_insn(pc, cpu);
> +            }
> +        }
> +    }
> +}
> +
>  void qemu_plugins_init(void)
>  {
>      QemuPluginInfo *info;
> @@ -88,4 +127,6 @@ void qemu_plugins_init(void)
>              info->init(info->args);
>          }
>      }
> +
> +#include "exec/helper-register.h"
>  }


--
Alex Bennée



reply via email to

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