qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Akihiko Odaki <akihiko.odaki@daynix.com>
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
	"Thomas Huth" <thuth@redhat.com>,
	"Alexandre Iooss" <erdnaxe@crans.org>,
	"Mahmoud Mandour" <ma.mandourr@gmail.com>,
	"Eduardo Habkost" <eduardo@habkost.net>,
	"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>,
	"Yanan Wang" <wangyanan55@huawei.com>,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Daniel P. Berrangé" <berrange@redhat.com>,
	"John Snow" <jsnow@redhat.com>, "Cleber Rosa" <crosa@redhat.com>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	"Michael Rolnik" <mrolnik@gmail.com>,
	"Edgar E. Iglesias" <edgar.iglesias@gmail.com>,
	"Brian Cain" <bcain@quicinc.com>,
	"Song Gao" <gaosong@loongson.cn>,
	"Xiaojuan Yang" <yangxiaojuan@loongson.cn>,
	"Laurent Vivier" <laurent@vivier.eu>,
	"Aurelien Jarno" <aurelien@aurel32.net>,
	"Jiaxun Yang" <jiaxun.yang@flygoat.com>,
	"Aleksandar Rikalo" <aleksandar.rikalo@syrmia.com>,
	"Chris Wulff" <crwulff@gmail.com>, "Marek Vasut" <marex@denx.de>,
	"Stafford Horne" <shorne@gmail.com>,
	"Daniel Henrique Barboza" <danielhb413@gmail.com>,
	"Cédric Le Goater" <clg@kaod.org>,
	"David Gibson" <david@gibson.dropbear.id.au>,
	"Greg Kurz" <groug@kaod.org>,
	"Nicholas Piggin" <npiggin@gmail.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Alistair Francis" <alistair.francis@wdc.com>,
	"Bin Meng" <bin.meng@windriver.com>,
	"Weiwei Li" <liweiwei@iscas.ac.cn>,
	"Liu Zhiwei" <zhiwei_liu@linux.alibaba.com>,
	"Yoshinori Sato" <ysato@users.sourceforge.jp>,
	"David Hildenbrand" <david@redhat.com>,
	"Ilya Leoshkevich" <iii@linux.ibm.com>,
	"Mark Cave-Ayland" <mark.cave-ayland@ilande.co.uk>,
	"Artyom Tarasenko" <atar4qemu@gmail.com>,
	"Bastian Koppelmann" <kbastian@mail.uni-paderborn.de>,
	"Max Filippov" <jcmvbkbc@gmail.com>,
	qemu-devel@nongnu.org, qemu-arm@nongnu.org, qemu-ppc@nongnu.org,
	qemu-riscv@nongnu.org, qemu-s390x@nongnu.org
Subject: Re: [RFC PATCH 22/24] contrib/plugins: Allow to log registers
Date: Mon, 14 Aug 2023 16:21:15 +0100	[thread overview]
Message-ID: <87ttt1ps02.fsf@linaro.org> (raw)
In-Reply-To: <20230731084354.115015-23-akihiko.odaki@daynix.com>


Akihiko Odaki <akihiko.odaki@daynix.com> writes:

> This demonstrates how a register can be read from a plugin.

I think it would be a little more useful as a demo if it tracked changes
to the register state rather than dumping it for every line executed.

>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  docs/devel/tcg-plugins.rst |  10 ++-
>  contrib/plugins/execlog.c  | 130 ++++++++++++++++++++++++++++---------
>  2 files changed, 108 insertions(+), 32 deletions(-)
>
> diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst
> index 81dcd43a61..c9f8b27590 100644
> --- a/docs/devel/tcg-plugins.rst
> +++ b/docs/devel/tcg-plugins.rst
> @@ -497,6 +497,15 @@ arguments if required::
>    $ qemu-system-arm $(QEMU_ARGS) \
>      -plugin ./contrib/plugins/libexeclog.so,ifilter=st1w,afilter=0x40001808 -d plugin
>  
> +This plugin can also dump a specified register. The specification of register
> +follows `GDB standard target features <https://sourceware.org/gdb/onlinedocs/gdb/Standard-Target-Features.html>`__.
> +
> +Specify the name of the feature that contains the register and the name of the
> +register with ``rfile`` and ``reg`` options, respectively::
> +
> +  $ qemu-system-arm $(QEMU_ARGS) \
> +    -plugin ./contrib/plugins/libexeclog.so,rfile=org.gnu.gdb.arm.core,reg=sp -d plugin
> +
>  - contrib/plugins/cache.c
>  
>  Cache modelling plugin that measures the performance of a given L1 cache
> @@ -583,4 +592,3 @@ The following API is generated from the inline documentation in
>  include the full kernel-doc annotations.
>  
>  .. kernel-doc:: include/qemu/qemu-plugin.h
> -
> diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c
> index ce67acf145..031ad67fbb 100644
> --- a/contrib/plugins/execlog.c
> +++ b/contrib/plugins/execlog.c
> @@ -15,27 +15,42 @@
>  
>  #include <qemu-plugin.h>
>  
> +typedef struct CPU {
> +    /* Store last executed instruction on each vCPU as a GString */
> +    GString *last_exec;
> +    GByteArray *reg_buf;
> +
> +    int reg;
> +} CPU;
> +
>  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
>  
> -/* Store last executed instruction on each vCPU as a GString */
> -static GPtrArray *last_exec;
> +static CPU *cpus;
> +static int num_cpus;
>  static GRWLock expand_array_lock;
>  
>  static GPtrArray *imatches;
>  static GArray *amatches;
>  
> +static char *rfile_name;
> +static char *reg_name;
> +
>  /*
> - * Expand last_exec array.
> + * Expand cpu array.
>   *
>   * As we could have multiple threads trying to do this we need to
>   * serialise the expansion under a lock.
>   */
> -static void expand_last_exec(int cpu_index)
> +static void expand_cpu(int cpu_index)
>  {
> -    g_rw_lock_writer_unlock(&expand_array_lock);
> -    while (cpu_index >= last_exec->len) {
> -        GString *s = g_string_new(NULL);
> -        g_ptr_array_add(last_exec, s);
> +    g_rw_lock_writer_lock(&expand_array_lock);
> +    if (cpu_index >= num_cpus) {
> +        cpus = g_realloc_n(cpus, cpu_index + 1, sizeof(*cpus));
> +        while (cpu_index >= num_cpus) {
> +            cpus[num_cpus].last_exec = g_string_new(NULL);
> +            cpus[num_cpus].reg_buf = g_byte_array_new();
> +            num_cpus++;
> +        }
>      }
>      g_rw_lock_writer_unlock(&expand_array_lock);
>  }
> @@ -50,8 +65,8 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info,
>  
>      /* Find vCPU in array */
>      g_rw_lock_reader_lock(&expand_array_lock);
> -    g_assert(cpu_index < last_exec->len);
> -    s = g_ptr_array_index(last_exec, cpu_index);
> +    g_assert(cpu_index < num_cpus);
> +    s = cpus[cpu_index].last_exec;
>      g_rw_lock_reader_unlock(&expand_array_lock);
>  
>      /* Indicate type of memory access */
> @@ -77,28 +92,35 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info,
>   */
>  static void vcpu_insn_exec(unsigned int cpu_index, void *udata)
>  {
> -    GString *s;
> +    CPU cpu;
> +    int n;
> +    int i;
>  
>      /* Find or create vCPU in array */
>      g_rw_lock_reader_lock(&expand_array_lock);
> -    if (cpu_index >= last_exec->len) {
> -        g_rw_lock_reader_unlock(&expand_array_lock);
> -        expand_last_exec(cpu_index);
> -        g_rw_lock_reader_lock(&expand_array_lock);
> -    }
> -    s = g_ptr_array_index(last_exec, cpu_index);
> +    cpu = cpus[cpu_index];
>      g_rw_lock_reader_unlock(&expand_array_lock);
>  
>      /* Print previous instruction in cache */
> -    if (s->len) {
> -        qemu_plugin_outs(s->str);
> +    if (cpu.last_exec->len) {
> +        qemu_plugin_outs(cpu.last_exec->str);
>          qemu_plugin_outs("\n");
>      }
>  
>      /* Store new instruction in cache */
>      /* vcpu_mem will add memory access information to last_exec */
> -    g_string_printf(s, "%u, ", cpu_index);
> -    g_string_append(s, (char *)udata);
> +    g_string_printf(cpu.last_exec, "%u, ", cpu_index);
> +    g_string_append(cpu.last_exec, (char *)udata);
> +
> +    if (cpu.reg >= 0) {
> +        g_string_append(cpu.last_exec, ", reg,");
> +        n = qemu_plugin_read_register(cpu.reg_buf, cpu.reg);
> +        for (i = 0; i < n; i++) {
> +            g_string_append_printf(cpu.last_exec, " 0x%02X",
> +                                   cpu.reg_buf->data[i]);
> +        }

so instead of:

  0, 0x4001b4, 0xd10043ff, "sub sp, sp, #0x10", reg, 0x70 0xFF 0x7F 0x00 0x00 0x40 0x00 0x00

we could aim for something like:

  0, 0x4001b4, 0xd10043ff, "sub sp, sp, #0x10", sp => 0x70ff7f0000400000


> +        g_byte_array_set_size(cpu.reg_buf, 0);
> +    }
>  }
>  
>  /**
> @@ -167,8 +189,10 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
>                                               QEMU_PLUGIN_MEM_RW, NULL);
>  
>              /* Register callback on instruction */
> -            qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec,
> -                                                   QEMU_PLUGIN_CB_NO_REGS, output);
> +            qemu_plugin_register_vcpu_insn_exec_cb(
> +                insn, vcpu_insn_exec,
> +                rfile_name ? QEMU_PLUGIN_CB_R_REGS : QEMU_PLUGIN_CB_NO_REGS,
> +                output);
>  
>              /* reset skip */
>              skip = (imatches || amatches);
> @@ -177,17 +201,53 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
>      }
>  }
>  
> +static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index)
> +{
> +    int reg = 0;
> +    bool found = false;
> +
> +    expand_cpu(vcpu_index);
> +
> +    if (rfile_name) {
> +        int i;
> +        int j;
> +        int n;
> +
> +        qemu_plugin_register_file_t *rfiles =
> +            qemu_plugin_get_register_files(vcpu_index, &n);
> +
> +        for (i = 0; i < n; i++) {
> +            if (g_strcmp0(rfiles[i].name, rfile_name) == 0) {
> +                for (j = 0; j < rfiles[i].num_regs; j++) {
> +                    if (g_strcmp0(rfiles[i].regs[j], reg_name) == 0) {
> +                        reg += j;
> +                        found = true;
> +                        break;
> +                    }
> +                }
> +                break;
> +            }
> +
> +            reg += rfiles[i].num_regs;
> +        }
> +
> +        g_free(rfiles);
> +    }
> +
> +    g_rw_lock_writer_lock(&expand_array_lock);
> +    cpus[vcpu_index].reg = found ? reg : -1;
> +    g_rw_lock_writer_unlock(&expand_array_lock);
> +}
> +
>  /**
>   * On plugin exit, print last instruction in cache
>   */
>  static void plugin_exit(qemu_plugin_id_t id, void *p)
>  {
>      guint i;
> -    GString *s;
> -    for (i = 0; i < last_exec->len; i++) {
> -        s = g_ptr_array_index(last_exec, i);
> -        if (s->str) {
> -            qemu_plugin_outs(s->str);
> +    for (i = 0; i < num_cpus; i++) {
> +        if (cpus[i].last_exec->str) {
> +            qemu_plugin_outs(cpus[i].last_exec->str);
>              qemu_plugin_outs("\n");
>          }
>      }
> @@ -224,9 +284,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
>       * we don't know the size before emulation.
>       */
>      if (info->system_emulation) {
> -        last_exec = g_ptr_array_sized_new(info->system.max_vcpus);
> -    } else {
> -        last_exec = g_ptr_array_new();
> +        cpus = g_new(CPU, info->system.max_vcpus);
>      }
>  
>      for (int i = 0; i < argc; i++) {
> @@ -236,13 +294,23 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
>              parse_insn_match(tokens[1]);
>          } else if (g_strcmp0(tokens[0], "afilter") == 0) {
>              parse_vaddr_match(tokens[1]);
> +        } else if (g_strcmp0(tokens[0], "rfile") == 0) {
> +            rfile_name = g_strdup(tokens[1]);
> +        } else if (g_strcmp0(tokens[0], "reg") == 0) {
> +            reg_name = g_strdup(tokens[1]);
>          } else {
>              fprintf(stderr, "option parsing failed: %s\n", opt);
>              return -1;
>          }
>      }
>  
> +    if ((!rfile_name) != (!reg_name)) {
> +        fputs("file and reg need to be set at the same time\n", stderr);
> +        return -1;
> +    }
> +
>      /* Register translation block and exit callbacks */
> +    qemu_plugin_register_vcpu_init_cb(id, vcpu_init);
>      qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
>      qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


  reply	other threads:[~2023-08-14 15:25 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 01/24] contrib/plugins: Use GRWLock in execlog Akihiko Odaki
2023-08-14 10:48   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 02/24] gdbstub: Introduce GDBFeature structure Akihiko Odaki
2023-07-31 13:34   ` Philippe Mathieu-Daudé
2023-07-31 13:51   ` Philippe Mathieu-Daudé
2023-08-14 11:33   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 03/24] gdbstub: Add num_regs member to GDBFeature Akihiko Odaki
2023-07-31 13:35   ` Philippe Mathieu-Daudé
2023-08-14 11:44   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 04/24] gdbstub: Introduce gdb_find_static_feature() Akihiko Odaki
2023-07-31 13:52   ` Philippe Mathieu-Daudé
2023-08-14 11:56   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 05/24] target/arm: Move the reference to arm-core.xml Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature Akihiko Odaki
2023-07-31 13:27   ` Philippe Mathieu-Daudé
2023-07-31 13:37     ` Akihiko Odaki
2023-08-14 11:59   ` Alex Bennée
2023-08-16 13:47     ` Akihiko Odaki
2023-08-16 15:00       ` Alex Bennée
2023-08-16 15:10         ` Akihiko Odaki
2023-08-14 13:19   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 07/24] target/arm: Use GDBFeature for dynamic XML Akihiko Odaki
2023-07-31 13:44   ` Philippe Mathieu-Daudé
2023-07-31 14:00     ` Akihiko Odaki
2023-08-14 13:01   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 08/24] target/ppc: " Akihiko Odaki
2023-07-31 13:45   ` Philippe Mathieu-Daudé
2023-07-31  8:43 ` [RFC PATCH 09/24] target/riscv: " Akihiko Odaki
2023-07-31 13:46   ` Philippe Mathieu-Daudé
2023-07-31  8:43 ` [RFC PATCH 10/24] gdbstub: Use GDBFeature for gdb_register_coprocessor Akihiko Odaki
2023-08-14 13:13   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 11/24] gdbstub: Use GDBFeature for GDBRegisterState Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 12/24] gdbstub: Simplify XML lookup Akihiko Odaki
2023-08-14 13:27   ` Alex Bennée
2023-08-16 13:51     ` Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 13/24] hw/core/cpu: Remove gdb_get_dynamic_xml member Akihiko Odaki
2023-08-14 13:29   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 14/24] gdbstub: Add members to identify registers to GDBFeature Akihiko Odaki
2023-08-14 13:30   ` Alex Bennée
2023-07-31  8:43 ` [RFC PATCH 15/24] target/arm: Fill new members of GDBFeature Akihiko Odaki
2023-08-14 14:56   ` Alex Bennée
2023-08-16 14:23     ` Akihiko Odaki
2023-08-16 15:03       ` Alex Bennée
2023-08-16 15:11         ` Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 16/24] target/ppc: " Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 17/24] target/riscv: " Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 18/24] hw/core/cpu: Add a parameter to gdb_read_register/gdb_write_register Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 19/24] gdbstub: Hide gdb_has_xml Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 20/24] gdbstub: Expose functions to read registers Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 21/24] plugins: Allow " Akihiko Odaki
2023-08-14 15:05   ` Alex Bennée
2023-08-16 14:38     ` Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 22/24] contrib/plugins: Allow to log registers Akihiko Odaki
2023-08-14 15:21   ` Alex Bennée [this message]
2023-08-16 14:59     ` Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 23/24] plugins: Support C++ Akihiko Odaki
2023-07-31  8:43 ` [RFC PATCH 24/24] contrib/plugins: Add cc plugin Akihiko Odaki
2023-08-14 15:23   ` Alex Bennée
2023-08-16 15:04     ` Akihiko Odaki
2023-08-14 15:27 ` [RFC PATCH 00/24] plugins: Allow to read registers Alex Bennée

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ttt1ps02.fsf@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=akihiko.odaki@daynix.com \
    --cc=aleksandar.rikalo@syrmia.com \
    --cc=alistair.francis@wdc.com \
    --cc=atar4qemu@gmail.com \
    --cc=aurelien@aurel32.net \
    --cc=bcain@quicinc.com \
    --cc=berrange@redhat.com \
    --cc=bin.meng@windriver.com \
    --cc=clg@kaod.org \
    --cc=crosa@redhat.com \
    --cc=crwulff@gmail.com \
    --cc=danielhb413@gmail.com \
    --cc=david@gibson.dropbear.id.au \
    --cc=david@redhat.com \
    --cc=edgar.iglesias@gmail.com \
    --cc=eduardo@habkost.net \
    --cc=erdnaxe@crans.org \
    --cc=gaosong@loongson.cn \
    --cc=groug@kaod.org \
    --cc=iii@linux.ibm.com \
    --cc=jcmvbkbc@gmail.com \
    --cc=jiaxun.yang@flygoat.com \
    --cc=jsnow@redhat.com \
    --cc=kbastian@mail.uni-paderborn.de \
    --cc=laurent@vivier.eu \
    --cc=liweiwei@iscas.ac.cn \
    --cc=ma.mandourr@gmail.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=marex@denx.de \
    --cc=mark.cave-ayland@ilande.co.uk \
    --cc=mrolnik@gmail.com \
    --cc=npiggin@gmail.com \
    --cc=palmer@dabbelt.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=philmd@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=qemu-s390x@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=shorne@gmail.com \
    --cc=thuth@redhat.com \
    --cc=wangyanan55@huawei.com \
    --cc=yangxiaojuan@loongson.cn \
    --cc=ysato@users.sourceforge.jp \
    --cc=zhiwei_liu@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).