qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/24] plugins: Allow to read registers
@ 2023-07-31  8:43 Akihiko Odaki
  2023-07-31  8:43 ` [RFC PATCH 01/24] contrib/plugins: Use GRWLock in execlog Akihiko Odaki
                   ` (24 more replies)
  0 siblings, 25 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

I and other people in the University of Tokyo, where I research processor
design, found TCG plugins are very useful for processor design exploration.

The feature we find missing is the capability to read registers from
plugins. In this series, I propose to add such a capability by reusing
gdbstub code.

The reuse of gdbstub code ensures the long-term stability of the TCG plugin
interface for register access without incurring a burden to maintain yet
another interface for register access.

This process to add TCG plugin involves four major changes. The first one
is to add GDBFeature structure that represents a GDB feature, which usually
includes registers. GDBFeature can be generated from static XML files or
dynamically generated by architecture-specific code. In fact, this is a
refactoring independent of the feature this series adds, and potentially
it's benefitial even without the plugin feature. The plugin feature will
utilize this new structure to describe registers exposed to plugins.

The second one is to make gdb_read_register/gdb_write_register usable
outside of gdbstub context.

The third one is to actually make registers readable for plugins.

The last one is to allow to implement a QEMU plugin in C++. A plugin that
I'll describe later is written in C++.

The below is a summary of patches:
Patch 01 fixes a bug in execlog plugin.
Patch [02, 13] introduces GDBFeature.
Patch [14, 17] adds information useful for plugins to GDBFeature.
Patch [18, 20] makes registers readable outside of gdbstub context.
Patch [21, 22] adds the feature to read registers from plugins.
Patch [23, 24] makes it possible to write plugins in C++.

The execlog plugin will have new options to demonstrate the new feature.
I also have a plugin that uses this new feature to generate execution traces for
Sniper processor simulator, which is available at:
https://github.com/shioya-lab/sniper/tree/akihikodaki/bb

Akihiko Odaki (24):
  contrib/plugins: Use GRWLock in execlog
  gdbstub: Introduce GDBFeature structure
  gdbstub: Add num_regs member to GDBFeature
  gdbstub: Introduce gdb_find_static_feature()
  target/arm: Move the reference to arm-core.xml
  hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  target/arm: Use GDBFeature for dynamic XML
  target/ppc: Use GDBFeature for dynamic XML
  target/riscv: Use GDBFeature for dynamic XML
  gdbstub: Use GDBFeature for gdb_register_coprocessor
  gdbstub: Use GDBFeature for GDBRegisterState
  gdbstub: Simplify XML lookup
  hw/core/cpu: Remove gdb_get_dynamic_xml member
  gdbstub: Add members to identify registers to GDBFeature
  target/arm: Fill new members of GDBFeature
  target/ppc: Fill new members of GDBFeature
  target/riscv: Fill new members of GDBFeature
  hw/core/cpu: Add a parameter to gdb_read_register/gdb_write_register
  gdbstub: Hide gdb_has_xml
  gdbstub: Expose functions to read registers
  plugins: Allow to read registers
  contrib/plugins: Allow to log registers
  plugins: Support C++
  contrib/plugins: Add cc plugin

 MAINTAINERS                   |   2 +-
 docs/devel/tcg-plugins.rst    |  18 +++-
 configure                     |  15 ++-
 meson.build                   |   2 +-
 gdbstub/internals.h           |   8 ++
 include/exec/gdbstub.h        |  30 +++---
 include/hw/core/cpu.h         |  15 ++-
 include/qemu/qemu-plugin.h    |  69 +++++++++++++-
 target/alpha/cpu.h            |   6 +-
 target/arm/cpu.h              |  37 ++++----
 target/arm/internals.h        |   2 +-
 target/avr/cpu.h              |   6 +-
 target/cris/cpu.h             |   9 +-
 target/hexagon/internal.h     |   6 +-
 target/hppa/cpu.h             |   6 +-
 target/i386/cpu.h             |   6 +-
 target/loongarch/internals.h  |   6 +-
 target/m68k/cpu.h             |   6 +-
 target/microblaze/cpu.h       |   6 +-
 target/mips/internal.h        |   6 +-
 target/openrisc/cpu.h         |   6 +-
 target/ppc/cpu-qom.h          |   3 +-
 target/ppc/cpu.h              |  15 +--
 target/riscv/cpu.h            |  10 +-
 target/rx/cpu.h               |   6 +-
 target/s390x/cpu.h            |   2 -
 target/s390x/s390x-internal.h |   6 +-
 target/sh4/cpu.h              |   6 +-
 target/sparc/cpu.h            |   6 +-
 target/tricore/cpu.h          |   6 +-
 target/xtensa/cpu.h           |   6 +-
 contrib/plugins/execlog.c     | 140 ++++++++++++++++++++-------
 cpu.c                         |  11 ---
 gdbstub/gdbstub.c             | 100 ++++++++++++--------
 hw/core/cpu-common.c          |  16 +++-
 plugins/api.c                 |  40 ++++++++
 stubs/gdbstub.c               |   6 +-
 target/alpha/gdbstub.c        |   6 +-
 target/arm/cpu.c              |   6 +-
 target/arm/cpu64.c            |   4 +-
 target/arm/gdbstub.c          | 172 ++++++++++++++++++----------------
 target/arm/gdbstub64.c        |  55 +++++++----
 target/arm/tcg/cpu32.c        |   3 +-
 target/avr/cpu.c              |   4 +-
 target/avr/gdbstub.c          |   6 +-
 target/cris/gdbstub.c         |   9 +-
 target/hexagon/cpu.c          |   5 +-
 target/hexagon/gdbstub.c      |   6 +-
 target/hppa/gdbstub.c         |   6 +-
 target/i386/cpu.c             |   7 +-
 target/i386/gdbstub.c         |  10 +-
 target/loongarch/cpu.c        |   4 +-
 target/loongarch/gdbstub.c    |   8 +-
 target/m68k/cpu.c             |   7 +-
 target/m68k/gdbstub.c         |   6 +-
 target/m68k/helper.c          |   6 +-
 target/microblaze/cpu.c       |   9 +-
 target/microblaze/gdbstub.c   |   6 +-
 target/mips/gdbstub.c         |   6 +-
 target/nios2/cpu.c            |   6 +-
 target/openrisc/gdbstub.c     |   6 +-
 target/ppc/cpu_init.c         |   9 +-
 target/ppc/gdbstub.c          |  62 ++++++------
 target/riscv/cpu.c            |  21 +----
 target/riscv/gdbstub.c        |  68 +++++++++-----
 target/rx/cpu.c               |   4 +-
 target/rx/gdbstub.c           |   6 +-
 target/s390x/cpu.c            |   4 +-
 target/s390x/gdbstub.c        |  34 +++----
 target/sh4/gdbstub.c          |   6 +-
 target/sparc/gdbstub.c        |   6 +-
 target/tricore/gdbstub.c      |   6 +-
 target/xtensa/gdbstub.c       |   6 +-
 contrib/plugins/Makefile      |   5 +
 contrib/plugins/cc.cc         |  15 +++
 plugins/qemu-plugins.symbols  |   2 +
 scripts/feature_to_c.py       |  98 +++++++++++++++++++
 scripts/feature_to_c.sh       |  69 --------------
 tests/tcg/Makefile.target     |   3 +
 79 files changed, 904 insertions(+), 529 deletions(-)
 create mode 100644 contrib/plugins/cc.cc
 create mode 100755 scripts/feature_to_c.py
 delete mode 100644 scripts/feature_to_c.sh

-- 
2.41.0



^ permalink raw reply	[flat|nested] 61+ messages in thread

* [RFC PATCH 01/24] contrib/plugins: Use GRWLock in execlog
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (23 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

execlog had the following comment:
> As we could have multiple threads trying to do this we need to
> serialise the expansion under a lock. Threads accessing already
> created entries can continue without issue even if the ptr array
> gets reallocated during resize.

However, when the ptr array gets reallocated, the other threads may have
a stale reference to the old buffer. This results in use-after-free.

Use GRWLock to properly fix this issue.

Fixes: 3d7caf145e ("contrib/plugins: add execlog to log instruction execution and memory access")
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 contrib/plugins/execlog.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c
index 7129d526f8..ce67acf145 100644
--- a/contrib/plugins/execlog.c
+++ b/contrib/plugins/execlog.c
@@ -19,7 +19,7 @@ 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 GMutex expand_array_lock;
+static GRWLock expand_array_lock;
 
 static GPtrArray *imatches;
 static GArray *amatches;
@@ -28,18 +28,16 @@ static GArray *amatches;
  * Expand last_exec array.
  *
  * As we could have multiple threads trying to do this we need to
- * serialise the expansion under a lock. Threads accessing already
- * created entries can continue without issue even if the ptr array
- * gets reallocated during resize.
+ * serialise the expansion under a lock.
  */
 static void expand_last_exec(int cpu_index)
 {
-    g_mutex_lock(&expand_array_lock);
+    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_mutex_unlock(&expand_array_lock);
+    g_rw_lock_writer_unlock(&expand_array_lock);
 }
 
 /**
@@ -51,8 +49,10 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info,
     GString *s;
 
     /* 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_rw_lock_reader_unlock(&expand_array_lock);
 
     /* Indicate type of memory access */
     if (qemu_plugin_mem_is_store(info)) {
@@ -80,10 +80,14 @@ static void vcpu_insn_exec(unsigned int cpu_index, void *udata)
     GString *s;
 
     /* 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);
+    g_rw_lock_reader_unlock(&expand_array_lock);
 
     /* Print previous instruction in cache */
     if (s->len) {
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 02/24] gdbstub: Introduce GDBFeature structure
  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-07-31  8:43 ` Akihiko Odaki
  2023-07-31 13:34   ` Philippe Mathieu-Daudé
                     ` (2 more replies)
  2023-07-31  8:43 ` [RFC PATCH 03/24] gdbstub: Add num_regs member to GDBFeature Akihiko Odaki
                   ` (22 subsequent siblings)
  24 siblings, 3 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

Before this change, the information from a XML file was stored in an
array that is not descriptive. Introduce a dedicated structure type to
make it easier to understand and to extend with more fields.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 MAINTAINERS             |  2 +-
 meson.build             |  2 +-
 include/exec/gdbstub.h  |  9 ++++--
 gdbstub/gdbstub.c       |  4 +--
 stubs/gdbstub.c         |  6 ++--
 scripts/feature_to_c.py | 44 ++++++++++++++++++++++++++
 scripts/feature_to_c.sh | 69 -----------------------------------------
 7 files changed, 58 insertions(+), 78 deletions(-)
 create mode 100755 scripts/feature_to_c.py
 delete mode 100644 scripts/feature_to_c.sh

diff --git a/MAINTAINERS b/MAINTAINERS
index 12e59b6b27..514ac74101 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2826,7 +2826,7 @@ F: include/exec/gdbstub.h
 F: include/gdbstub/*
 F: gdb-xml/
 F: tests/tcg/multiarch/gdbstub/
-F: scripts/feature_to_c.sh
+F: scripts/feature_to_c.py
 F: scripts/probe-gdb-support.py
 
 Memory API
diff --git a/meson.build b/meson.build
index 98e68ef0b1..5c633f7e01 100644
--- a/meson.build
+++ b/meson.build
@@ -3683,7 +3683,7 @@ common_all = static_library('common',
                             dependencies: common_all.dependencies(),
                             name_suffix: 'fa')
 
-feature_to_c = find_program('scripts/feature_to_c.sh')
+feature_to_c = find_program('scripts/feature_to_c.py')
 
 if targetos == 'darwin'
   entitlement = find_program('scripts/entitlement.sh')
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 7d743fe1e9..bd5bc91dda 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -10,6 +10,11 @@
 #define GDB_WATCHPOINT_READ      3
 #define GDB_WATCHPOINT_ACCESS    4
 
+typedef struct GDBFeature {
+    const char *xmlname;
+    const char *xml;
+} GDBFeature;
+
 
 /* Get or set a register.  Returns the size of the register.  */
 typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
@@ -38,7 +43,7 @@ void gdb_set_stop_cpu(CPUState *cpu);
  */
 extern bool gdb_has_xml;
 
-/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
-extern const char *const xml_builtin[][2];
+/* in gdbstub-xml.c, generated by scripts/feature_to_c.py */
+extern const GDBFeature gdb_features[];
 
 #endif
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 6911b73c07..fad70200d8 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -407,11 +407,11 @@ static const char *get_feature_xml(const char *p, const char **newp,
         }
     }
     for (i = 0; ; i++) {
-        name = xml_builtin[i][0];
+        name = gdb_features[i].xmlname;
         if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len))
             break;
     }
-    return name ? xml_builtin[i][1] : NULL;
+    return name ? gdb_features[i].xml : NULL;
 }
 
 static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
diff --git a/stubs/gdbstub.c b/stubs/gdbstub.c
index 2b7aee50d3..324d17f045 100644
--- a/stubs/gdbstub.c
+++ b/stubs/gdbstub.c
@@ -1,6 +1,6 @@
 #include "qemu/osdep.h"
-#include "exec/gdbstub.h"       /* xml_builtin */
+#include "exec/gdbstub.h"       /* gdb_features */
 
-const char *const xml_builtin[][2] = {
-  { NULL, NULL }
+const GDBFeature gdb_features[] = {
+  { NULL }
 };
diff --git a/scripts/feature_to_c.py b/scripts/feature_to_c.py
new file mode 100755
index 0000000000..5a5b49367b
--- /dev/null
+++ b/scripts/feature_to_c.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+import os, sys
+
+def writeliteral(indent, bytes):
+    sys.stdout.write(' ' * indent)
+    sys.stdout.write('"')
+    quoted = True
+
+    for c in bytes:
+        if not quoted:
+            sys.stdout.write('\n')
+            sys.stdout.write(' ' * indent)
+            sys.stdout.write('"')
+            quoted = True
+
+        if c == b'"'[0]:
+            sys.stdout.write('\\"')
+        elif c == b'\\'[0]:
+            sys.stdout.write('\\\\')
+        elif c == b'\n'[0]:
+            sys.stdout.write('\\n"')
+            quoted = False
+        elif c >= 32 and c < 127:
+            sys.stdout.write(c.to_bytes(1, 'big').decode())
+        else:
+            sys.stdout.write(f'\{c:03o}')
+
+    if quoted:
+        sys.stdout.write('"')
+
+sys.stdout.write('#include "qemu/osdep.h"\n#include "exec/gdbstub.h"\n\nconst GDBFeature gdb_features[] = {\n')
+
+for input in sys.argv[1:]:
+    with open(input, 'rb') as file:
+        read = file.read()
+
+    sys.stdout.write('    {\n')
+    writeliteral(8, bytes(os.path.basename(input), 'utf-8'))
+    sys.stdout.write(',\n')
+    writeliteral(8, read)
+    sys.stdout.write('\n    },\n')
+
+sys.stdout.write('    { NULL }\n};\n')
diff --git a/scripts/feature_to_c.sh b/scripts/feature_to_c.sh
deleted file mode 100644
index c1f67c8f6a..0000000000
--- a/scripts/feature_to_c.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/sh
-
-# Convert text files to compilable C arrays.
-#
-# Copyright (C) 2007 Free Software Foundation, Inc.
-#
-# This file is part of GDB.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-if test -z "$1"; then
-  echo "Usage: $0 INPUTFILE..."
-  exit 1
-fi
-
-for input; do
-  arrayname=xml_feature_$(echo $input | sed 's,.*/,,; s/[-.]/_/g')
-
-  ${AWK:-awk} 'BEGIN { n = 0
-      printf "#include \"qemu/osdep.h\"\n"
-      print "static const char '$arrayname'[] = {"
-      for (i = 0; i < 255; i++)
-        _ord_[sprintf("%c", i)] = i
-    } {
-      split($0, line, "");
-      printf "  "
-      for (i = 1; i <= length($0); i++) {
-        c = line[i]
-        if (c == "'\''") {
-          printf "'\''\\'\'''\'', "
-        } else if (c == "\\") {
-          printf "'\''\\\\'\'', "
-        } else if (_ord_[c] >= 32 && _ord_[c] < 127) {
-	  printf "'\''%s'\'', ", c
-        } else {
-          printf "'\''\\%03o'\'', ", _ord_[c]
-        }
-        if (i % 10 == 0)
-          printf "\n   "
-      }
-      printf "'\''\\n'\'', \n"
-    } END {
-      print "  0 };"
-    }' < $input
-done
-
-echo
-echo '#include "exec/gdbstub.h"'
-echo "const char *const xml_builtin[][2] = {"
-
-for input; do
-  basename=$(echo $input | sed 's,.*/,,')
-  arrayname=xml_feature_$(echo $input | sed 's,.*/,,; s/[-.]/_/g')
-  echo "  { \"$basename\", $arrayname },"
-done
-
-echo "  { (char *)0, (char *)0 }"
-echo "};"
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 03/24] gdbstub: Add num_regs member to GDBFeature
  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-07-31  8:43 ` [RFC PATCH 02/24] gdbstub: Introduce GDBFeature structure Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (21 subsequent siblings)
  24 siblings, 2 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

Currently the number of registers exposed to GDB is written as magic
numbers in code. Derive the number of registers GDB actually see from
XML files to replace the magic numbers in code later.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/exec/gdbstub.h  |  1 +
 scripts/feature_to_c.py | 46 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index bd5bc91dda..22e5add5b1 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -13,6 +13,7 @@
 typedef struct GDBFeature {
     const char *xmlname;
     const char *xml;
+    int num_regs;
 } GDBFeature;
 
 
diff --git a/scripts/feature_to_c.py b/scripts/feature_to_c.py
index 5a5b49367b..8eb8c81cf8 100755
--- a/scripts/feature_to_c.py
+++ b/scripts/feature_to_c.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 
-import os, sys
+import os, sys, xml.etree.ElementTree
 
 def writeliteral(indent, bytes):
     sys.stdout.write(' ' * indent)
@@ -35,10 +35,52 @@ def writeliteral(indent, bytes):
     with open(input, 'rb') as file:
         read = file.read()
 
+    parser = xml.etree.ElementTree.XMLPullParser(['start', 'end'])
+    parser.feed(read)
+    events = parser.read_events()
+    event, element = next(events)
+    if event != 'start':
+        sys.stderr.write(f'unexpected event: {event}\n')
+        exit(1)
+    if element.tag != 'feature':
+        sys.stderr.write(f'unexpected start tag: {element.tag}\n')
+        exit(1)
+
+    regnum = 0
+    regnums = []
+    tags = ['feature']
+    for event, element in events:
+        if event == 'end':
+            if element.tag != tags[len(tags) - 1]:
+                sys.stderr.write(f'unexpected end tag: {element.tag}\n')
+                exit(1)
+
+            tags.pop()
+            if element.tag == 'feature':
+                break
+        elif event == 'start':
+            if len(tags) < 2 and element.tag == 'reg':
+                if 'regnum' in element.attrib:
+                    regnum = int(element.attrib['regnum'])
+
+                regnums.append(regnum)
+                regnum += 1
+
+            tags.append(element.tag)
+        else:
+            raise Exception(f'unexpected event: {event}\n')
+
+    if len(tags):
+        sys.stderr.write('unterminated feature tag\n')
+        exit(1)
+
+    base_reg = min(regnums)
+    num_regs = max(regnums) - base_reg + 1 if len(regnums) else 0
+
     sys.stdout.write('    {\n')
     writeliteral(8, bytes(os.path.basename(input), 'utf-8'))
     sys.stdout.write(',\n')
     writeliteral(8, read)
-    sys.stdout.write('\n    },\n')
+    sys.stdout.write(f',\n        {num_regs},\n    }},\n')
 
 sys.stdout.write('    { NULL }\n};\n')
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 04/24] gdbstub: Introduce gdb_find_static_feature()
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (2 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 03/24] gdbstub: Add num_regs member to GDBFeature Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (20 subsequent siblings)
  24 siblings, 2 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

This function is useful to determine the number of registers exposed to
GDB from the XML name.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/exec/gdbstub.h |  2 ++
 gdbstub/gdbstub.c      | 13 +++++++++++++
 2 files changed, 15 insertions(+)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 22e5add5b1..3115dc21c0 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -34,6 +34,8 @@ void gdb_register_coprocessor(CPUState *cpu,
  */
 int gdbserver_start(const char *port_or_device);
 
+const GDBFeature *gdb_find_static_feature(const char *xmlname);
+
 void gdb_set_stop_cpu(CPUState *cpu);
 
 /**
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index fad70200d8..6d9cef5b95 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -414,6 +414,19 @@ static const char *get_feature_xml(const char *p, const char **newp,
     return name ? gdb_features[i].xml : NULL;
 }
 
+const GDBFeature *gdb_find_static_feature(const char *xmlname)
+{
+    const GDBFeature *feature;
+
+    for (feature = gdb_features; feature->xmlname; feature++) {
+        if (!strcmp(feature->xmlname, xmlname)) {
+            return feature;
+        }
+    }
+
+    return NULL;
+}
+
 static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
 {
     CPUClass *cc = CPU_GET_CLASS(cpu);
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 05/24] target/arm: Move the reference to arm-core.xml
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (3 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 04/24] gdbstub: Introduce gdb_find_static_feature() Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

Some subclasses overwrite gdb_core_xml_file member but others don't.
Always initialize the member in the subclasses for consistency.

This especially helps for AArch64; in a following change, the file
specified by gdb_core_xml_file is always looked up even if it's going to
be overwritten later. Looking up arm-core.xml results in an error as
it will not be embedded in the AArch64 build.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 target/arm/cpu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 93c28d50e5..d71a162070 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2354,7 +2354,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->sysemu_ops = &arm_sysemu_ops;
 #endif
     cc->gdb_num_core_regs = 26;
-    cc->gdb_core_xml_file = "arm-core.xml";
     cc->gdb_arch_name = arm_gdb_arch_name;
     cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
     cc->gdb_stop_before_watchpoint = true;
@@ -2376,8 +2375,10 @@ static void arm_cpu_instance_init(Object *obj)
 static void cpu_register_class_init(ObjectClass *oc, void *data)
 {
     ARMCPUClass *acc = ARM_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(acc);
 
     acc->info = data;
+    cc->gdb_core_xml_file = "arm-core.xml";
 }
 
 void arm_cpu_register(const ARMCPUInfo *info)
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (4 preceding siblings ...)
  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 ` Akihiko Odaki
  2023-07-31 13:27   ` Philippe Mathieu-Daudé
                     ` (2 more replies)
  2023-07-31  8:43 ` [RFC PATCH 07/24] target/arm: Use GDBFeature for dynamic XML Akihiko Odaki
                   ` (18 subsequent siblings)
  24 siblings, 3 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

This is a tree-wide change to replace gdb_core_xml_file, the path to
GDB XML file with gdb_core_feature, the pointer to GDBFeature. This
also replaces the values assigned to gdb_num_core_regs with the
num_regs member of GDBFeature where applicable to remove magic numbers.

A following change will utilize additional information provided by
GDBFeature to simplify XML file lookup.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/hw/core/cpu.h   | 5 +++--
 target/s390x/cpu.h      | 2 --
 gdbstub/gdbstub.c       | 6 +++---
 target/arm/cpu.c        | 4 ++--
 target/arm/cpu64.c      | 4 ++--
 target/arm/tcg/cpu32.c  | 3 ++-
 target/avr/cpu.c        | 4 ++--
 target/hexagon/cpu.c    | 2 +-
 target/i386/cpu.c       | 7 +++----
 target/loongarch/cpu.c  | 4 ++--
 target/m68k/cpu.c       | 7 ++++---
 target/microblaze/cpu.c | 4 ++--
 target/ppc/cpu_init.c   | 4 ++--
 target/riscv/cpu.c      | 7 ++++---
 target/rx/cpu.c         | 4 ++--
 target/s390x/cpu.c      | 4 ++--
 16 files changed, 36 insertions(+), 35 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index fdcbe87352..84219c1885 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -23,6 +23,7 @@
 #include "hw/qdev-core.h"
 #include "disas/dis-asm.h"
 #include "exec/cpu-common.h"
+#include "exec/gdbstub.h"
 #include "exec/hwaddr.h"
 #include "exec/memattrs.h"
 #include "qapi/qapi-types-run-state.h"
@@ -127,7 +128,7 @@ struct SysemuCPUOps;
  *       breakpoint.  Used by AVR to handle a gdb mis-feature with
  *       its Harvard architecture split code and data.
  * @gdb_num_core_regs: Number of core registers accessible to GDB.
- * @gdb_core_xml_file: File name for core registers GDB XML description.
+ * @gdb_core_feature: GDB core feature description.
  * @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
  *           before the insn which triggers a watchpoint rather than after it.
  * @gdb_arch_name: Optional callback that returns the architecture name known
@@ -163,7 +164,7 @@ struct CPUClass {
     int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
     vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
 
-    const char *gdb_core_xml_file;
+    const GDBFeature *gdb_core_feature;
     gchar * (*gdb_arch_name)(CPUState *cpu);
     const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
 
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index eb5b65b7d3..c5bac3230c 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -451,8 +451,6 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState *env, vaddr *pc,
 #define S390_R13_REGNUM 15
 #define S390_R14_REGNUM 16
 #define S390_R15_REGNUM 17
-/* Total Core Registers. */
-#define S390_NUM_CORE_REGS 18
 
 static inline void setcc(S390CPU *cpu, uint64_t cc)
 {
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 6d9cef5b95..6f2e0cb06f 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -386,7 +386,7 @@ static const char *get_feature_xml(const char *p, const char **newp,
                 g_free(arch);
             }
             pstrcat(buf, buf_sz, "<xi:include href=\"");
-            pstrcat(buf, buf_sz, cc->gdb_core_xml_file);
+            pstrcat(buf, buf_sz, cc->gdb_core_feature->xmlname);
             pstrcat(buf, buf_sz, "\"/>");
             for (r = cpu->gdb_regs; r; r = r->next) {
                 pstrcat(buf, buf_sz, "<xi:include href=\"");
@@ -1506,7 +1506,7 @@ static void handle_query_supported(GArray *params, void *user_ctx)
 
     g_string_printf(gdbserver_state.str_buf, "PacketSize=%x", MAX_PACKET_LENGTH);
     cc = CPU_GET_CLASS(first_cpu);
-    if (cc->gdb_core_xml_file) {
+    if (cc->gdb_core_feature) {
         g_string_append(gdbserver_state.str_buf, ";qXfer:features:read+");
     }
 
@@ -1548,7 +1548,7 @@ static void handle_query_xfer_features(GArray *params, void *user_ctx)
 
     process = gdb_get_cpu_process(gdbserver_state.g_cpu);
     cc = CPU_GET_CLASS(gdbserver_state.g_cpu);
-    if (!cc->gdb_core_xml_file) {
+    if (!cc->gdb_core_feature) {
         gdb_put_packet("");
         return;
     }
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d71a162070..a206ab6b1b 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2353,7 +2353,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
 #ifndef CONFIG_USER_ONLY
     cc->sysemu_ops = &arm_sysemu_ops;
 #endif
-    cc->gdb_num_core_regs = 26;
     cc->gdb_arch_name = arm_gdb_arch_name;
     cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
     cc->gdb_stop_before_watchpoint = true;
@@ -2378,7 +2377,8 @@ static void cpu_register_class_init(ObjectClass *oc, void *data)
     CPUClass *cc = CPU_CLASS(acc);
 
     acc->info = data;
-    cc->gdb_core_xml_file = "arm-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("arm-core.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
 }
 
 void arm_cpu_register(const ARMCPUInfo *info)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 96158093cc..9c2a226159 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -754,8 +754,8 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
 
     cc->gdb_read_register = aarch64_cpu_gdb_read_register;
     cc->gdb_write_register = aarch64_cpu_gdb_write_register;
-    cc->gdb_num_core_regs = 34;
-    cc->gdb_core_xml_file = "aarch64-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("aarch64-core.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
     cc->gdb_arch_name = aarch64_gdb_arch_name;
 
     object_class_property_add_bool(oc, "aarch64", aarch64_cpu_get_aarch64,
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index 47d2e8e781..49a823ad58 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -1040,7 +1040,8 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
 
     acc->info = data;
     cc->tcg_ops = &arm_v7m_tcg_ops;
-    cc->gdb_core_xml_file = "arm-m-profile.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("arm-m-profile.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
 }
 
 #ifndef TARGET_AARCH64
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index 8f741f258c..217adc64cb 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -246,8 +246,8 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
     cc->gdb_read_register = avr_cpu_gdb_read_register;
     cc->gdb_write_register = avr_cpu_gdb_write_register;
     cc->gdb_adjust_breakpoint = avr_cpu_gdb_adjust_breakpoint;
-    cc->gdb_num_core_regs = 35;
-    cc->gdb_core_xml_file = "avr-cpu.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("avr-cpu.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
     cc->tcg_ops = &avr_tcg_ops;
 }
 
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index f155936289..b54162cbeb 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -391,7 +391,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data)
     cc->gdb_write_register = hexagon_gdb_write_register;
     cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
     cc->gdb_stop_before_watchpoint = true;
-    cc->gdb_core_xml_file = "hexagon-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("hexagon-core.xml");
     cc->disas_set_info = hexagon_cpu_disas_set_info;
     cc->tcg_ops = &hexagon_tcg_ops;
 }
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 97ad229d8b..069410985f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -7963,12 +7963,11 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 
     cc->gdb_arch_name = x86_gdb_arch_name;
 #ifdef TARGET_X86_64
-    cc->gdb_core_xml_file = "i386-64bit.xml";
-    cc->gdb_num_core_regs = 66;
+    cc->gdb_core_feature = gdb_find_static_feature("i386-64bit.xml");
 #else
-    cc->gdb_core_xml_file = "i386-32bit.xml";
-    cc->gdb_num_core_regs = 50;
+    cc->gdb_core_feature = gdb_find_static_feature("i386-32bit.xml");
 #endif
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
     cc->disas_set_info = x86_disas_set_info;
 
     dc->user_creatable = true;
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ad93ecac92..b204cb279d 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -722,8 +722,8 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
     cc->gdb_read_register = loongarch_cpu_gdb_read_register;
     cc->gdb_write_register = loongarch_cpu_gdb_write_register;
     cc->disas_set_info = loongarch_cpu_disas_set_info;
-    cc->gdb_num_core_regs = 35;
-    cc->gdb_core_xml_file = "loongarch-base64.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("loongarch-base64.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
     cc->gdb_stop_before_watchpoint = true;
     cc->gdb_arch_name = loongarch_gdb_arch_name;
 
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 70d58471dc..2bd7238aa8 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -572,7 +572,6 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
 #endif
     cc->disas_set_info = m68k_cpu_disas_set_info;
 
-    cc->gdb_num_core_regs = 18;
     cc->tcg_ops = &m68k_tcg_ops;
 }
 
@@ -580,7 +579,8 @@ static void m68k_cpu_class_init_cf_core(ObjectClass *c, void *data)
 {
     CPUClass *cc = CPU_CLASS(c);
 
-    cc->gdb_core_xml_file = "cf-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("cf-core.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
 }
 
 #define DEFINE_M68K_CPU_TYPE_CF(model)               \
@@ -595,7 +595,8 @@ static void m68k_cpu_class_init_m68k_core(ObjectClass *c, void *data)
 {
     CPUClass *cc = CPU_CLASS(c);
 
-    cc->gdb_core_xml_file = "m68k-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("m68k-core.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
 }
 
 #define DEFINE_M68K_CPU_TYPE_M68K(model)             \
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 03c2c4db1f..47f37c2519 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -428,8 +428,8 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
     cc->sysemu_ops = &mb_sysemu_ops;
 #endif
     device_class_set_props(dc, mb_properties);
-    cc->gdb_num_core_regs = 32 + 25;
-    cc->gdb_core_xml_file = "microblaze-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("microblaze-core.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
 
     cc->disas_set_info = mb_disas_set_info;
     cc->tcg_ops = &mb_tcg_ops;
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 02b7aad9b0..eb56226865 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7381,9 +7381,9 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
 
     cc->gdb_arch_name = ppc_gdb_arch_name;
 #if defined(TARGET_PPC64)
-    cc->gdb_core_xml_file = "power64-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("power64-core.xml");
 #else
-    cc->gdb_core_xml_file = "power-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("power-core.xml");
 #endif
     cc->disas_set_info = ppc_disas_set_info;
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6b93b04453..36de35270d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1031,11 +1031,11 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
 #ifdef TARGET_RISCV64
     case MXL_RV64:
     case MXL_RV128:
-        cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
+        cc->gdb_core_feature = gdb_find_static_feature("riscv-64bit-cpu.xml");
         break;
 #endif
     case MXL_RV32:
-        cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
+        cc->gdb_core_feature = gdb_find_static_feature("riscv-32bit-cpu.xml");
         break;
     default:
         g_assert_not_reached();
@@ -1045,6 +1045,8 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
         error_setg(errp, "misa_mxl_max must be equal to misa_mxl");
         return;
     }
+
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
 }
 
 /*
@@ -2138,7 +2140,6 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
     cc->get_pc = riscv_cpu_get_pc;
     cc->gdb_read_register = riscv_cpu_gdb_read_register;
     cc->gdb_write_register = riscv_cpu_gdb_write_register;
-    cc->gdb_num_core_regs = 33;
     cc->gdb_stop_before_watchpoint = true;
     cc->disas_set_info = riscv_cpu_disas_set_info;
 #ifndef CONFIG_USER_ONLY
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
index 157e57da0f..b139265728 100644
--- a/target/rx/cpu.c
+++ b/target/rx/cpu.c
@@ -239,8 +239,8 @@ static void rx_cpu_class_init(ObjectClass *klass, void *data)
     cc->gdb_write_register = rx_cpu_gdb_write_register;
     cc->disas_set_info = rx_cpu_disas_set_info;
 
-    cc->gdb_num_core_regs = 26;
-    cc->gdb_core_xml_file = "rx-core.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("rx-core.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
     cc->tcg_ops = &rx_tcg_ops;
 }
 
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index df167493c3..2a2ff8cbdc 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -348,8 +348,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
     s390_cpu_class_init_sysemu(cc);
 #endif
     cc->disas_set_info = s390_cpu_disas_set_info;
-    cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
-    cc->gdb_core_xml_file = "s390x-core64.xml";
+    cc->gdb_core_feature = gdb_find_static_feature("s390x-core64.xml");
+    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
     cc->gdb_arch_name = s390_gdb_arch_name;
 
     s390_cpu_model_class_register_props(oc);
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 07/24] target/arm: Use GDBFeature for dynamic XML
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (5 preceding siblings ...)
  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  8:43 ` Akihiko Odaki
  2023-07-31 13:44   ` Philippe Mathieu-Daudé
  2023-08-14 13:01   ` Alex Bennée
  2023-07-31  8:43 ` [RFC PATCH 08/24] target/ppc: " Akihiko Odaki
                   ` (17 subsequent siblings)
  24 siblings, 2 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

In preparation for a change to use GDBFeature as a parameter of
gdb_register_coprocessor(), convert the internal representation of
dynamic feature from plain XML to GDBFeature.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 target/arm/cpu.h       | 20 +++++------
 target/arm/internals.h |  2 +-
 target/arm/gdbstub.c   | 80 +++++++++++++++++++++++-------------------
 target/arm/gdbstub64.c | 11 +++---
 4 files changed, 60 insertions(+), 53 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 88e5accda6..d6c2378d05 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -136,23 +136,21 @@ enum {
  */
 
 /**
- * DynamicGDBXMLInfo:
- * @desc: Contains the XML descriptions.
- * @num: Number of the registers in this XML seen by GDB.
+ * DynamicGDBFeatureInfo:
+ * @desc: Contains the feature descriptions.
  * @data: A union with data specific to the set of registers
  *    @cpregs_keys: Array that contains the corresponding Key of
  *                  a given cpreg with the same order of the cpreg
  *                  in the XML description.
  */
-typedef struct DynamicGDBXMLInfo {
-    char *desc;
-    int num;
+typedef struct DynamicGDBFeatureInfo {
+    GDBFeature desc;
     union {
         struct {
             uint32_t *keys;
         } cpregs;
     } data;
-} DynamicGDBXMLInfo;
+} DynamicGDBFeatureInfo;
 
 /* CPU state for each instance of a generic timer (in cp15 c14) */
 typedef struct ARMGenericTimer {
@@ -881,10 +879,10 @@ struct ArchCPU {
     uint64_t *cpreg_vmstate_values;
     int32_t cpreg_vmstate_array_len;
 
-    DynamicGDBXMLInfo dyn_sysreg_xml;
-    DynamicGDBXMLInfo dyn_svereg_xml;
-    DynamicGDBXMLInfo dyn_m_systemreg_xml;
-    DynamicGDBXMLInfo dyn_m_secextreg_xml;
+    DynamicGDBFeatureInfo dyn_sysreg_feature;
+    DynamicGDBFeatureInfo dyn_svereg_feature;
+    DynamicGDBFeatureInfo dyn_m_systemreg_feature;
+    DynamicGDBFeatureInfo dyn_m_secextreg_feature;
 
     /* Timers used by the generic (architected) timer */
     QEMUTimer *gt_timer[NUM_GTIMERS];
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 0f01bc32a8..8421a755af 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1388,7 +1388,7 @@ static inline uint64_t pmu_counter_mask(CPUARMState *env)
 }
 
 #ifdef TARGET_AARCH64
-int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
+GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cpu, int base_reg);
 int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray *buf, int reg);
 int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg);
 int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg);
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index f421c5d041..cd35bac013 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -25,11 +25,11 @@
 #include "internals.h"
 #include "cpregs.h"
 
-typedef struct RegisterSysregXmlParam {
+typedef struct RegisterSysregFeatureParam {
     CPUState *cs;
     GString *s;
     int n;
-} RegisterSysregXmlParam;
+} RegisterSysregFeatureParam;
 
 /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
    whatever the target description contains.  Due to a historical mishap
@@ -243,7 +243,7 @@ static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
     const ARMCPRegInfo *ri;
     uint32_t key;
 
-    key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
+    key = cpu->dyn_sysreg_feature.data.cpregs.keys[reg];
     ri = get_arm_cp_reginfo(cpu->cp_regs, key);
     if (ri) {
         if (cpreg_field_is_64bit(ri)) {
@@ -260,7 +260,8 @@ static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
     return 0;
 }
 
-static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
+static void arm_gen_one_feature_sysreg(GString *s,
+                                       DynamicGDBFeatureInfo *dyn_feature,
                                        ARMCPRegInfo *ri, uint32_t ri_key,
                                        int bitsize, int regnum)
 {
@@ -268,25 +269,25 @@ static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
     g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
     g_string_append_printf(s, " regnum=\"%d\"", regnum);
     g_string_append_printf(s, " group=\"cp_regs\"/>");
-    dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
-    dyn_xml->num++;
+    dyn_feature->data.cpregs.keys[dyn_feature->desc.num_regs] = ri_key;
+    dyn_feature->desc.num_regs++;
 }
 
-static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
-                                        gpointer p)
+static void arm_register_sysreg_for_feature(gpointer key, gpointer value,
+                                            gpointer p)
 {
     uint32_t ri_key = (uintptr_t)key;
     ARMCPRegInfo *ri = value;
-    RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
+    RegisterSysregFeatureParam *param = (RegisterSysregFeatureParam *)p;
     GString *s = param->s;
     ARMCPU *cpu = ARM_CPU(param->cs);
     CPUARMState *env = &cpu->env;
-    DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
+    DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
 
     if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
         if (arm_feature(env, ARM_FEATURE_AARCH64)) {
             if (ri->state == ARM_CP_STATE_AA64) {
-                arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
+                arm_gen_one_feature_sysreg(s , dyn_feature, ri, ri_key, 64,
                                            param->n++);
             }
         } else {
@@ -296,10 +297,10 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
                     return;
                 }
                 if (ri->type & ARM_CP_64BIT) {
-                    arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
+                    arm_gen_one_feature_sysreg(s , dyn_feature, ri, ri_key, 64,
                                                param->n++);
                 } else {
-                    arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
+                    arm_gen_one_feature_sysreg(s , dyn_feature, ri, ri_key, 32,
                                                param->n++);
                 }
             }
@@ -307,21 +308,24 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
     }
 }
 
-static int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
+static GDBFeature *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     GString *s = g_string_new(NULL);
-    RegisterSysregXmlParam param = {cs, s, base_reg};
+    RegisterSysregFeatureParam param = {cs, s, base_reg};
+    DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
+    gsize num_regs = g_hash_table_size(cpu->cp_regs);
 
-    cpu->dyn_sysreg_xml.num = 0;
-    cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
+    dyn_feature->desc.num_regs = 0;
+    dyn_feature->data.cpregs.keys = g_new(uint32_t, num_regs);
     g_string_printf(s, "<?xml version=\"1.0\"?>");
     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
     g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
-    g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
+    g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_feature, &param);
     g_string_append_printf(s, "</feature>");
-    cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
-    return cpu->dyn_sysreg_xml.num;
+    dyn_feature->desc.xmlname = "system-registers.xml";
+    dyn_feature->desc.xml = g_string_free(s, false);
+    return &dyn_feature->desc;
 }
 
 #ifdef CONFIG_TCG
@@ -413,7 +417,8 @@ static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg)
     return 0; /* TODO */
 }
 
-static int arm_gen_dynamic_m_systemreg_xml(CPUState *cs, int orig_base_reg)
+static GDBFeature *arm_gen_dynamic_m_systemreg_feature(CPUState *cs,
+                                                       int orig_base_reg)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -434,10 +439,11 @@ static int arm_gen_dynamic_m_systemreg_xml(CPUState *cs, int orig_base_reg)
     }
 
     g_string_append_printf(s, "</feature>");
-    cpu->dyn_m_systemreg_xml.desc = g_string_free(s, false);
-    cpu->dyn_m_systemreg_xml.num = base_reg - orig_base_reg;
+    cpu->dyn_m_systemreg_feature.desc.xmlname = "arm-m-system.xml";
+    cpu->dyn_m_systemreg_feature.desc.xml = g_string_free(s, false);
+    cpu->dyn_m_systemreg_feature.desc.num_regs = base_reg - orig_base_reg;
 
-    return cpu->dyn_m_systemreg_xml.num;
+    return &cpu->dyn_m_systemreg_feature.desc;
 }
 
 #ifndef CONFIG_USER_ONLY
@@ -455,7 +461,8 @@ static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg)
     return 0; /* TODO */
 }
 
-static int arm_gen_dynamic_m_secextreg_xml(CPUState *cs, int orig_base_reg)
+static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
+                                                       int orig_base_reg)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     GString *s = g_string_new(NULL);
@@ -476,10 +483,11 @@ static int arm_gen_dynamic_m_secextreg_xml(CPUState *cs, int orig_base_reg)
     }
 
     g_string_append_printf(s, "</feature>");
-    cpu->dyn_m_secextreg_xml.desc = g_string_free(s, false);
-    cpu->dyn_m_secextreg_xml.num = base_reg - orig_base_reg;
+    cpu->dyn_m_secextreg_feature.desc.xmlname = "arm-m-secext.xml";
+    cpu->dyn_m_secextreg_feature.desc.xml = g_string_free(s, false);
+    cpu->dyn_m_secextreg_feature.desc.num_regs = base_reg - orig_base_reg;
 
-    return cpu->dyn_m_secextreg_xml.num;
+    return &cpu->dyn_m_secextreg_feature.desc;
 }
 #endif
 #endif /* CONFIG_TCG */
@@ -489,14 +497,14 @@ const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
     ARMCPU *cpu = ARM_CPU(cs);
 
     if (strcmp(xmlname, "system-registers.xml") == 0) {
-        return cpu->dyn_sysreg_xml.desc;
+        return cpu->dyn_sysreg_feature.desc.xml;
     } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
-        return cpu->dyn_svereg_xml.desc;
+        return cpu->dyn_svereg_feature.desc.xml;
     } else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
-        return cpu->dyn_m_systemreg_xml.desc;
+        return cpu->dyn_m_systemreg_feature.desc.xml;
 #ifndef CONFIG_USER_ONLY
     } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
-        return cpu->dyn_m_secextreg_xml.desc;
+        return cpu->dyn_m_secextreg_feature.desc.xml;
 #endif
     }
     return NULL;
@@ -514,7 +522,7 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
          */
 #ifdef TARGET_AARCH64
         if (isar_feature_aa64_sve(&cpu->isar)) {
-            int nreg = arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs);
+            int nreg = arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs)->num_regs;
             gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
                                      aarch64_gdb_set_sve_reg, nreg,
                                      "sve-registers.xml", 0);
@@ -560,20 +568,20 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
                                  1, "arm-m-profile-mve.xml", 0);
     }
     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
-                             arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
+                             arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs)->num_regs,
                              "system-registers.xml", 0);
 
 #ifdef CONFIG_TCG
     if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
         gdb_register_coprocessor(cs,
             arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
-            arm_gen_dynamic_m_systemreg_xml(cs, cs->gdb_num_regs),
+            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs)->num_regs,
             "arm-m-system.xml", 0);
 #ifndef CONFIG_USER_ONLY
         if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
             gdb_register_coprocessor(cs,
                 arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
-                arm_gen_dynamic_m_secextreg_xml(cs, cs->gdb_num_regs),
+                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs)->num_regs,
                 "arm-m-secext.xml", 0);
         }
 #endif
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index d7b79a6589..20483ef9bc 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -316,11 +316,11 @@ static void output_vector_union_type(GString *s, int reg_width,
     g_string_append(s, "</union>");
 }
 
-int arm_gen_dynamic_svereg_xml(CPUState *cs, int orig_base_reg)
+GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int orig_base_reg)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     GString *s = g_string_new(NULL);
-    DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
+    DynamicGDBFeatureInfo *info = &cpu->dyn_svereg_feature;
     int reg_width = cpu->sve_max_vq * 128;
     int pred_width = cpu->sve_max_vq * 16;
     int base_reg = orig_base_reg;
@@ -375,7 +375,8 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int orig_base_reg)
 
     g_string_append_printf(s, "</feature>");
 
-    info->desc = g_string_free(s, false);
-    info->num = base_reg - orig_base_reg;
-    return info->num;
+    info->desc.xmlname = "sve-registers.xml";
+    info->desc.xml = g_string_free(s, false);
+    info->desc.num_regs = base_reg - orig_base_reg;
+    return &info->desc;
 }
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 08/24] target/ppc: Use GDBFeature for dynamic XML
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (6 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 07/24] target/arm: Use GDBFeature for dynamic XML Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-07-31 13:45   ` Philippe Mathieu-Daudé
  2023-07-31  8:43 ` [RFC PATCH 09/24] target/riscv: " Akihiko Odaki
                   ` (16 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

In preparation for a change to use GDBFeature as a parameter of
gdb_register_coprocessor(), convert the internal representation of
dynamic feature from plain XML to GDBFeature.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 target/ppc/cpu-qom.h  |  3 +--
 target/ppc/cpu.h      |  2 +-
 target/ppc/cpu_init.c |  2 +-
 target/ppc/gdbstub.c  | 13 +++++++------
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index be33786bd8..633fb402b5 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -186,8 +186,7 @@ struct PowerPCCPUClass {
     int bfd_mach;
     uint32_t l1_dcache_size, l1_icache_size;
 #ifndef CONFIG_USER_ONLY
-    unsigned int gdb_num_sprs;
-    const char *gdb_spr_xml;
+    GDBFeature gdb_spr;
 #endif
     const PPCHash64Options *hash64_opts;
     struct ppc_radix_page_info *radix_page_info;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 25fac9577a..5f251bdffe 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1381,7 +1381,7 @@ int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
 #ifndef CONFIG_USER_ONLY
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu);
+void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu);
 const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
 #endif
 int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index eb56226865..938cd2b7e1 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6673,7 +6673,7 @@ static void init_ppc_proc(PowerPCCPU *cpu)
     (*pcc->init_proc)(env);
 
 #if !defined(CONFIG_USER_ONLY)
-    ppc_gdb_gen_spr_xml(cpu);
+    ppc_gdb_gen_spr_feature(cpu);
 #endif
 
     /* MSR bits & flags consistency checks */
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index ca39efdc35..adc647a24e 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -318,7 +318,7 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
 }
 
 #ifndef CONFIG_USER_ONLY
-void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
+void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu)
 {
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     CPUPPCState *env = &cpu->env;
@@ -346,7 +346,7 @@ void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
         num_regs++;
     }
 
-    if (pcc->gdb_spr_xml) {
+    if (pcc->gdb_spr.xml) {
         return;
     }
 
@@ -371,8 +371,9 @@ void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
 
     g_string_append(xml, "</feature>");
 
-    pcc->gdb_num_sprs = num_regs;
-    pcc->gdb_spr_xml = g_string_free(xml, false);
+    pcc->gdb_spr.num_regs = num_regs;
+    pcc->gdb_spr.xmlname = "power-spr.xml";
+    pcc->gdb_spr.xml = g_string_free(xml, false);
 }
 
 const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
@@ -380,7 +381,7 @@ const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
 
     if (strcmp(xml_name, "power-spr.xml") == 0) {
-        return pcc->gdb_spr_xml;
+        return pcc->gdb_spr.xml;
     }
     return NULL;
 }
@@ -618,6 +619,6 @@ void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *pcc)
     }
 #ifndef CONFIG_USER_ONLY
     gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg,
-                             pcc->gdb_num_sprs, "power-spr.xml", 0);
+                             pcc->gdb_spr.num_regs, "power-spr.xml", 0);
 #endif
 }
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 09/24] target/riscv: Use GDBFeature for dynamic XML
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (7 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 08/24] target/ppc: " Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (15 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

In preparation for a change to use GDBFeature as a parameter of
gdb_register_coprocessor(), convert the internal representation of
dynamic feature from plain XML to GDBFeature.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 target/riscv/cpu.h     |  4 ++--
 target/riscv/cpu.c     |  4 ++--
 target/riscv/gdbstub.c | 25 ++++++++++++++-----------
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6ea22e0eea..f67751d5b7 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -391,8 +391,8 @@ struct ArchCPU {
     CPUNegativeOffsetState neg;
     CPURISCVState env;
 
-    char *dyn_csr_xml;
-    char *dyn_vreg_xml;
+    GDBFeature dyn_csr_feature;
+    GDBFeature dyn_vreg_feature;
 
     /* Configuration Settings */
     RISCVCPUConfig cfg;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 36de35270d..ceca40cdd9 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1962,9 +1962,9 @@ static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
     RISCVCPU *cpu = RISCV_CPU(cs);
 
     if (strcmp(xmlname, "riscv-csr.xml") == 0) {
-        return cpu->dyn_csr_xml;
+        return cpu->dyn_csr_feature.xml;
     } else if (strcmp(xmlname, "riscv-vector.xml") == 0) {
-        return cpu->dyn_vreg_xml;
+        return cpu->dyn_vreg_feature.xml;
     }
 
     return NULL;
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 524bede865..70c60ad8b1 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -212,7 +212,7 @@ static int riscv_gdb_set_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
+static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
@@ -252,24 +252,27 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
 
     g_string_append_printf(s, "</feature>");
 
-    cpu->dyn_csr_xml = g_string_free(s, false);
+    cpu->dyn_csr_feature.num_regs = CSR_TABLE_SIZE;
+    cpu->dyn_csr_feature.xmlname = "riscv-csr.xml";
+    cpu->dyn_csr_feature.xml = g_string_free(s, false);
 
 #if !defined(CONFIG_USER_ONLY)
     env->debugger = false;
 #endif
 
-    return CSR_TABLE_SIZE;
+    return &cpu->dyn_csr_feature;
 }
 
-static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
+static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     GString *s = g_string_new(NULL);
     g_autoptr(GString) ts = g_string_new("");
     int reg_width = cpu->cfg.vlen;
-    int num_regs = 0;
     int i;
 
+    cpu->dyn_vreg_feature.num_regs = 32;
+
     g_string_printf(s, "<?xml version=\"1.0\"?>");
     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.vector\">");
@@ -293,19 +296,19 @@ static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
     g_string_append(s, "</union>");
 
     /* Define vector registers */
-    for (i = 0; i < 32; i++) {
+    for (i = 0; i < cpu->dyn_vreg_feature.num_regs; i++) {
         g_string_append_printf(s,
                                "<reg name=\"v%d\" bitsize=\"%d\""
                                " regnum=\"%d\" group=\"vector\""
                                " type=\"riscv_vector\"/>",
                                i, reg_width, base_reg++);
-        num_regs++;
     }
 
     g_string_append_printf(s, "</feature>");
 
-    cpu->dyn_vreg_xml = g_string_free(s, false);
-    return num_regs;
+    cpu->dyn_vreg_feature.xmlname = "riscv-vector.xml";
+    cpu->dyn_vreg_feature.xml = g_string_free(s, false);
+    return &cpu->dyn_vreg_feature;
 }
 
 void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
@@ -323,7 +326,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
         int base_reg = cs->gdb_num_regs;
         gdb_register_coprocessor(cs, riscv_gdb_get_vector,
                                  riscv_gdb_set_vector,
-                                 ricsv_gen_dynamic_vector_xml(cs, base_reg),
+                                 ricsv_gen_dynamic_vector_feature(cs, base_reg)->num_regs,
                                  "riscv-vector.xml", 0);
     }
     switch (env->misa_mxl_max) {
@@ -345,7 +348,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
     if (cpu->cfg.ext_icsr) {
         int base_reg = cs->gdb_num_regs;
         gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
-                                 riscv_gen_dynamic_csr_xml(cs, base_reg),
+                                 riscv_gen_dynamic_csr_feature(cs, base_reg)->num_regs,
                                  "riscv-csr.xml", 0);
     }
 }
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 10/24] gdbstub: Use GDBFeature for gdb_register_coprocessor
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (8 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 09/24] target/riscv: " Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (14 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

This is a tree-wide change to introduce GDBFeature parameter to
gdb_register_coprocessor(). The new parameter just replaces num_regs
and xml parameters for now. GDBFeature will be utilized to simplify XML
lookup in a following change.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/exec/gdbstub.h     |  2 +-
 gdbstub/gdbstub.c          | 13 +++++++------
 target/arm/gdbstub.c       | 36 ++++++++++++++++++++----------------
 target/hexagon/cpu.c       |  3 +--
 target/loongarch/gdbstub.c |  2 +-
 target/m68k/helper.c       |  6 +++---
 target/microblaze/cpu.c    |  5 +++--
 target/ppc/gdbstub.c       | 11 ++++++-----
 target/riscv/gdbstub.c     | 20 ++++++++++++--------
 target/s390x/gdbstub.c     | 28 +++++++---------------------
 10 files changed, 61 insertions(+), 65 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 3115dc21c0..9b3da5b257 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -22,7 +22,7 @@ typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
 typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
 void gdb_register_coprocessor(CPUState *cpu,
                               gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
-                              int num_regs, const char *xml, int g_pos);
+                              const GDBFeature *feature, int g_pos);
 
 /**
  * gdbserver_start: start the gdb server
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 6f2e0cb06f..ab75f6686b 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -471,7 +471,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
 
 void gdb_register_coprocessor(CPUState *cpu,
                               gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
-                              int num_regs, const char *xml, int g_pos)
+                              const GDBFeature *feature, int g_pos)
 {
     GDBRegisterState *s;
     GDBRegisterState **p;
@@ -479,25 +479,26 @@ void gdb_register_coprocessor(CPUState *cpu,
     p = &cpu->gdb_regs;
     while (*p) {
         /* Check for duplicates.  */
-        if (strcmp((*p)->xml, xml) == 0)
+        if (strcmp((*p)->xml, feature->xmlname) == 0)
             return;
         p = &(*p)->next;
     }
 
     s = g_new0(GDBRegisterState, 1);
     s->base_reg = cpu->gdb_num_regs;
-    s->num_regs = num_regs;
+    s->num_regs = feature->num_regs;
     s->get_reg = get_reg;
     s->set_reg = set_reg;
-    s->xml = xml;
+    s->xml = feature->xml;
 
     /* Add to end of list.  */
-    cpu->gdb_num_regs += num_regs;
+    cpu->gdb_num_regs += feature->num_regs;
     *p = s;
     if (g_pos) {
         if (g_pos != s->base_reg) {
             error_report("Error: Bad gdb register numbering for '%s', "
-                         "expected %d got %d", xml, g_pos, s->base_reg);
+                         "expected %d got %d", feature->xml,
+                         g_pos, s->base_reg);
         } else {
             cpu->gdb_num_g_regs = cpu->gdb_num_regs;
         }
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index cd35bac013..ab4ffe6264 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -522,14 +522,15 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
          */
 #ifdef TARGET_AARCH64
         if (isar_feature_aa64_sve(&cpu->isar)) {
-            int nreg = arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs)->num_regs;
+            GDBFeature *feature =
+                arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs);
             gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
-                                     aarch64_gdb_set_sve_reg, nreg,
-                                     "sve-registers.xml", 0);
+                                     aarch64_gdb_set_sve_reg, feature, 0);
         } else {
             gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg,
                                      aarch64_gdb_set_fpu_reg,
-                                     34, "aarch64-fpu.xml", 0);
+                                     gdb_find_static_feature("aarch64-fpu.xml"),
+                                     0);
         }
         /*
          * Note that we report pauth information via the feature name
@@ -540,19 +541,22 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
         if (isar_feature_aa64_pauth(&cpu->isar)) {
             gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
                                      aarch64_gdb_set_pauth_reg,
-                                     4, "aarch64-pauth.xml", 0);
+                                     gdb_find_static_feature("aarch64-pauth.xml"),
+                                     0);
         }
 #endif
     } else {
         if (arm_feature(env, ARM_FEATURE_NEON)) {
             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
-                                     49, "arm-neon.xml", 0);
+                                     gdb_find_static_feature("arm-neon.xml"),
+                                     0);
         } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
-                                     33, "arm-vfp3.xml", 0);
+                                     gdb_find_static_feature("arm-vfp3.xml"),
+                                     0);
         } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
-                                     17, "arm-vfp.xml", 0);
+                                     gdb_find_static_feature("arm-vfp.xml"), 0);
         }
         if (!arm_feature(env, ARM_FEATURE_M)) {
             /*
@@ -560,29 +564,29 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
              * expose to gdb.
              */
             gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
-                                     2, "arm-vfp-sysregs.xml", 0);
+                                     gdb_find_static_feature("arm-vfp-sysregs.xml"),
+                                     0);
         }
     }
     if (cpu_isar_feature(aa32_mve, cpu) && tcg_enabled()) {
         gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
-                                 1, "arm-m-profile-mve.xml", 0);
+                                 gdb_find_static_feature("arm-m-profile-mve.xml"),
+                                 0);
     }
     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
-                             arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs)->num_regs,
-                             "system-registers.xml", 0);
+                             arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs),
+                             0);
 
 #ifdef CONFIG_TCG
     if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
         gdb_register_coprocessor(cs,
             arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
-            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs)->num_regs,
-            "arm-m-system.xml", 0);
+            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs), 0);
 #ifndef CONFIG_USER_ONLY
         if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
             gdb_register_coprocessor(cs,
                 arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
-                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs)->num_regs,
-                "arm-m-secext.xml", 0);
+                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs), 0);
         }
 #endif
     }
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index b54162cbeb..6732efc5de 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -342,8 +342,7 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
 
     gdb_register_coprocessor(cs, hexagon_hvx_gdb_read_register,
                              hexagon_hvx_gdb_write_register,
-                             NUM_VREGS + NUM_QREGS,
-                             "hexagon-hvx.xml", 0);
+                             gdb_find_static_feature("hexagon-hvx.xml"), 0);
 
     qemu_init_vcpu(cs);
     cpu_reset(cs);
diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c
index 0752fff924..2886b106bb 100644
--- a/target/loongarch/gdbstub.c
+++ b/target/loongarch/gdbstub.c
@@ -101,5 +101,5 @@ static int loongarch_gdb_set_fpu(CPULoongArchState *env,
 void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs)
 {
     gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu,
-                             41, "loongarch-fpu.xml", 0);
+                             gdb_find_static_feature("loongarch-fpu.xml"), 0);
 }
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
index 0a1544cd68..675f2dcd5a 100644
--- a/target/m68k/helper.c
+++ b/target/m68k/helper.c
@@ -152,10 +152,10 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
 
     if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
         gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
-                                 11, "cf-fp.xml", 18);
+                                 gdb_find_static_feature("cf-fp.xml"), 18);
     } else if (m68k_feature(env, M68K_FEATURE_FPU)) {
-        gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg,
-                                 m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", 18);
+        gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg, m68k_fpu_gdb_set_reg,
+                                 gdb_find_static_feature("m68k-fp.xml"), 18);
     }
     /* TODO: Add [E]MAC registers.  */
 }
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 47f37c2519..c804622ab9 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -298,8 +298,9 @@ static void mb_cpu_initfn(Object *obj)
 
     cpu_set_cpustate_pointers(cpu);
     gdb_register_coprocessor(CPU(cpu), mb_cpu_gdb_read_stack_protect,
-                             mb_cpu_gdb_write_stack_protect, 2,
-                             "microblaze-stack-protect.xml", 0);
+                             mb_cpu_gdb_write_stack_protect,
+                             gdb_find_static_feature("microblaze-stack-protect.xml"),
+                             0);
 
     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
 
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index adc647a24e..a0da320e66 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -603,22 +603,23 @@ void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *pcc)
 {
     if (pcc->insns_flags & PPC_FLOAT) {
         gdb_register_coprocessor(cs, gdb_get_float_reg, gdb_set_float_reg,
-                                 33, "power-fpu.xml", 0);
+                                 gdb_find_static_feature("power-fpu.xml"), 0);
     }
     if (pcc->insns_flags & PPC_ALTIVEC) {
         gdb_register_coprocessor(cs, gdb_get_avr_reg, gdb_set_avr_reg,
-                                 34, "power-altivec.xml", 0);
+                                 gdb_find_static_feature("power-altivec.xml"),
+                                 0);
     }
     if (pcc->insns_flags & PPC_SPE) {
         gdb_register_coprocessor(cs, gdb_get_spe_reg, gdb_set_spe_reg,
-                                 34, "power-spe.xml", 0);
+                                 gdb_find_static_feature("power-spe.xml"), 0);
     }
     if (pcc->insns_flags2 & PPC2_VSX) {
         gdb_register_coprocessor(cs, gdb_get_vsx_reg, gdb_set_vsx_reg,
-                                 32, "power-vsx.xml", 0);
+                                 gdb_find_static_feature("power-vsx.xml"), 0);
     }
 #ifndef CONFIG_USER_ONLY
     gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg,
-                             pcc->gdb_spr.num_regs, "power-spr.xml", 0);
+                             &pcc->gdb_spr, 0);
 #endif
 }
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 70c60ad8b1..224c69ea99 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -317,29 +317,33 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
     CPURISCVState *env = &cpu->env;
     if (env->misa_ext & RVD) {
         gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
-                                 32, "riscv-64bit-fpu.xml", 0);
+                                 gdb_find_static_feature("riscv-64bit-fpu.xml"),
+                                 0);
     } else if (env->misa_ext & RVF) {
         gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
-                                 32, "riscv-32bit-fpu.xml", 0);
+                                 gdb_find_static_feature("riscv-32bit-fpu.xml"),
+                                 0);
     }
     if (env->misa_ext & RVV) {
         int base_reg = cs->gdb_num_regs;
         gdb_register_coprocessor(cs, riscv_gdb_get_vector,
                                  riscv_gdb_set_vector,
-                                 ricsv_gen_dynamic_vector_feature(cs, base_reg)->num_regs,
-                                 "riscv-vector.xml", 0);
+                                 ricsv_gen_dynamic_vector_feature(cs, base_reg),
+                                 0);
     }
     switch (env->misa_mxl_max) {
     case MXL_RV32:
         gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
                                  riscv_gdb_set_virtual,
-                                 1, "riscv-32bit-virtual.xml", 0);
+                                 gdb_find_static_feature("riscv-32bit-virtual.xml"),
+                                 0);
         break;
     case MXL_RV64:
     case MXL_RV128:
         gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
                                  riscv_gdb_set_virtual,
-                                 1, "riscv-64bit-virtual.xml", 0);
+                                 gdb_find_static_feature("riscv-64bit-virtual.xml"),
+                                 0);
         break;
     default:
         g_assert_not_reached();
@@ -348,7 +352,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
     if (cpu->cfg.ext_icsr) {
         int base_reg = cs->gdb_num_regs;
         gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
-                                 riscv_gen_dynamic_csr_feature(cs, base_reg)->num_regs,
-                                 "riscv-csr.xml", 0);
+                                 riscv_gen_dynamic_csr_feature(cs, base_reg),
+                                 0);
     }
 }
diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c
index 6fbfd41bc8..02c388dc32 100644
--- a/target/s390x/gdbstub.c
+++ b/target/s390x/gdbstub.c
@@ -69,8 +69,6 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 /* the values represent the positions in s390-acr.xml */
 #define S390_A0_REGNUM 0
 #define S390_A15_REGNUM 15
-/* total number of registers in s390-acr.xml */
-#define S390_NUM_AC_REGS 16
 
 static int cpu_read_ac_reg(CPUS390XState *env, GByteArray *buf, int n)
 {
@@ -98,8 +96,6 @@ static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
 #define S390_FPC_REGNUM 0
 #define S390_F0_REGNUM 1
 #define S390_F15_REGNUM 16
-/* total number of registers in s390-fpr.xml */
-#define S390_NUM_FP_REGS 17
 
 static int cpu_read_fp_reg(CPUS390XState *env, GByteArray *buf, int n)
 {
@@ -132,8 +128,6 @@ static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
 #define S390_V15L_REGNUM 15
 #define S390_V16_REGNUM 16
 #define S390_V31_REGNUM 31
-/* total number of registers in s390-vx.xml */
-#define S390_NUM_VREGS 32
 
 static int cpu_read_vreg(CPUS390XState *env, GByteArray *buf, int n)
 {
@@ -172,8 +166,6 @@ static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n)
 /* the values represent the positions in s390-cr.xml */
 #define S390_C0_REGNUM 0
 #define S390_C15_REGNUM 15
-/* total number of registers in s390-cr.xml */
-#define S390_NUM_C_REGS 16
 
 #ifndef CONFIG_USER_ONLY
 static int cpu_read_c_reg(CPUS390XState *env, GByteArray *buf, int n)
@@ -206,8 +198,6 @@ static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
 #define S390_VIRT_CPUTM_REGNUM  1
 #define S390_VIRT_BEA_REGNUM    2
 #define S390_VIRT_PREFIX_REGNUM 3
-/* total number of registers in s390-virt.xml */
-#define S390_NUM_VIRT_REGS 4
 
 static int cpu_read_virt_reg(CPUS390XState *env, GByteArray *mem_buf, int n)
 {
@@ -254,8 +244,6 @@ static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
 #define S390_VIRT_KVM_PFT_REGNUM    1
 #define S390_VIRT_KVM_PFS_REGNUM    2
 #define S390_VIRT_KVM_PFC_REGNUM    3
-/* total number of registers in s390-virt-kvm.xml */
-#define S390_NUM_VIRT_KVM_REGS 4
 
 static int cpu_read_virt_kvm_reg(CPUS390XState *env, GByteArray *mem_buf, int n)
 {
@@ -303,8 +291,6 @@ static int cpu_write_virt_kvm_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
 #define S390_GS_GSD_REGNUM      1
 #define S390_GS_GSSM_REGNUM     2
 #define S390_GS_GSEPLA_REGNUM   3
-/* total number of registers in s390-gs.xml */
-#define S390_NUM_GS_REGS 4
 
 static int cpu_read_gs_reg(CPUS390XState *env, GByteArray *buf, int n)
 {
@@ -322,33 +308,33 @@ void s390_cpu_gdb_init(CPUState *cs)
 {
     gdb_register_coprocessor(cs, cpu_read_ac_reg,
                              cpu_write_ac_reg,
-                             S390_NUM_AC_REGS, "s390-acr.xml", 0);
+                             gdb_find_static_feature("s390-acr.xml"), 0);
 
     gdb_register_coprocessor(cs, cpu_read_fp_reg,
                              cpu_write_fp_reg,
-                             S390_NUM_FP_REGS, "s390-fpr.xml", 0);
+                             gdb_find_static_feature("s390-fpr.xml"), 0);
 
     gdb_register_coprocessor(cs, cpu_read_vreg,
                              cpu_write_vreg,
-                             S390_NUM_VREGS, "s390-vx.xml", 0);
+                             gdb_find_static_feature("s390-vx.xml"), 0);
 
     gdb_register_coprocessor(cs, cpu_read_gs_reg,
                              cpu_write_gs_reg,
-                             S390_NUM_GS_REGS, "s390-gs.xml", 0);
+                             gdb_find_static_feature("s390-gs.xml"), 0);
 
 #ifndef CONFIG_USER_ONLY
     gdb_register_coprocessor(cs, cpu_read_c_reg,
                              cpu_write_c_reg,
-                             S390_NUM_C_REGS, "s390-cr.xml", 0);
+                             gdb_find_static_feature("s390-cr.xml"), 0);
 
     gdb_register_coprocessor(cs, cpu_read_virt_reg,
                              cpu_write_virt_reg,
-                             S390_NUM_VIRT_REGS, "s390-virt.xml", 0);
+                             gdb_find_static_feature("s390-virt.xml"), 0);
 
     if (kvm_enabled()) {
         gdb_register_coprocessor(cs, cpu_read_virt_kvm_reg,
                                  cpu_write_virt_kvm_reg,
-                                 S390_NUM_VIRT_KVM_REGS, "s390-virt-kvm.xml",
+                                 gdb_find_static_feature("s390-virt-kvm.xml"),
                                  0);
     }
 #endif
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 11/24] gdbstub: Use GDBFeature for GDBRegisterState
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (9 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 10/24] gdbstub: Use GDBFeature for gdb_register_coprocessor Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-07-31  8:43 ` [RFC PATCH 12/24] gdbstub: Simplify XML lookup Akihiko Odaki
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

Simplify GDBRegisterState by replacing num_regs and xml members with
one member that points to GDBFeature.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 gdbstub/gdbstub.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index ab75f6686b..182efe7e0f 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -47,10 +47,9 @@
 
 typedef struct GDBRegisterState {
     int base_reg;
-    int num_regs;
     gdb_get_reg_cb get_reg;
     gdb_set_reg_cb set_reg;
-    const char *xml;
+    const GDBFeature *feature;
     struct GDBRegisterState *next;
 } GDBRegisterState;
 
@@ -390,7 +389,7 @@ static const char *get_feature_xml(const char *p, const char **newp,
             pstrcat(buf, buf_sz, "\"/>");
             for (r = cpu->gdb_regs; r; r = r->next) {
                 pstrcat(buf, buf_sz, "<xi:include href=\"");
-                pstrcat(buf, buf_sz, r->xml);
+                pstrcat(buf, buf_sz, r->feature->xml);
                 pstrcat(buf, buf_sz, "\"/>");
             }
             pstrcat(buf, buf_sz, "</target>");
@@ -438,7 +437,7 @@ static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
     }
 
     for (r = cpu->gdb_regs; r; r = r->next) {
-        if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
+        if (r->base_reg <= reg && reg < r->base_reg + r->feature->num_regs) {
             return r->get_reg(env, buf, reg - r->base_reg);
         }
     }
@@ -456,7 +455,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
     }
 
     for (r = cpu->gdb_regs; r; r = r->next) {
-        if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
+        if (r->base_reg <= reg && reg < r->base_reg + r->feature->num_regs) {
             return r->set_reg(env, mem_buf, reg - r->base_reg);
         }
     }
@@ -479,17 +478,16 @@ void gdb_register_coprocessor(CPUState *cpu,
     p = &cpu->gdb_regs;
     while (*p) {
         /* Check for duplicates.  */
-        if (strcmp((*p)->xml, feature->xmlname) == 0)
+        if ((*p)->feature == feature)
             return;
         p = &(*p)->next;
     }
 
     s = g_new0(GDBRegisterState, 1);
     s->base_reg = cpu->gdb_num_regs;
-    s->num_regs = feature->num_regs;
     s->get_reg = get_reg;
     s->set_reg = set_reg;
-    s->xml = feature->xml;
+    s->feature = feature;
 
     /* Add to end of list.  */
     cpu->gdb_num_regs += feature->num_regs;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 12/24] gdbstub: Simplify XML lookup
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (10 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 11/24] gdbstub: Use GDBFeature for GDBRegisterState Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-08-14 13:27   ` Alex Bennée
  2023-07-31  8:43 ` [RFC PATCH 13/24] hw/core/cpu: Remove gdb_get_dynamic_xml member Akihiko Odaki
                   ` (12 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

Now we know all instances of GDBFeature that is used in CPU so we can
traverse them to find XML. This removes the need for a CPU-specific
lookup function for dynamic XMLs.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 gdbstub/gdbstub.c | 28 +++++++++-------------------
 1 file changed, 9 insertions(+), 19 deletions(-)

diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 182efe7e0f..e5bb2c89ba 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -354,8 +354,7 @@ static const char *get_feature_xml(const char *p, const char **newp,
                                    GDBProcess *process)
 {
     size_t len;
-    int i;
-    const char *name;
+    GDBRegisterState *r;
     CPUState *cpu = gdb_get_first_cpu_in_process(process);
     CPUClass *cc = CPU_GET_CLASS(cpu);
 
@@ -364,15 +363,12 @@ static const char *get_feature_xml(const char *p, const char **newp,
         len++;
     *newp = p + len;
 
-    name = NULL;
     if (strncmp(p, "target.xml", len) == 0) {
         char *buf = process->target_xml;
         const size_t buf_sz = sizeof(process->target_xml);
 
         /* Generate the XML description for this CPU.  */
         if (!buf[0]) {
-            GDBRegisterState *r;
-
             pstrcat(buf, buf_sz,
                     "<?xml version=\"1.0\"?>"
                     "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
@@ -389,28 +385,22 @@ static const char *get_feature_xml(const char *p, const char **newp,
             pstrcat(buf, buf_sz, "\"/>");
             for (r = cpu->gdb_regs; r; r = r->next) {
                 pstrcat(buf, buf_sz, "<xi:include href=\"");
-                pstrcat(buf, buf_sz, r->feature->xml);
+                pstrcat(buf, buf_sz, r->feature->xmlname);
                 pstrcat(buf, buf_sz, "\"/>");
             }
             pstrcat(buf, buf_sz, "</target>");
         }
         return buf;
     }
-    if (cc->gdb_get_dynamic_xml) {
-        char *xmlname = g_strndup(p, len);
-        const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname);
-
-        g_free(xmlname);
-        if (xml) {
-            return xml;
-        }
+    if (strncmp(p, cc->gdb_core_feature->xmlname, len) == 0) {
+        return cc->gdb_core_feature->xml;
     }
-    for (i = 0; ; i++) {
-        name = gdb_features[i].xmlname;
-        if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len))
-            break;
+    for (r = cpu->gdb_regs; r; r = r->next) {
+        if (strncmp(p, r->feature->xmlname, len) == 0) {
+            return r->feature->xml;
+        }
     }
-    return name ? gdb_features[i].xml : NULL;
+    return NULL;
 }
 
 const GDBFeature *gdb_find_static_feature(const char *xmlname)
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 13/24] hw/core/cpu: Remove gdb_get_dynamic_xml member
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (11 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 12/24] gdbstub: Simplify XML lookup Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (11 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

This function is no longer used.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/hw/core/cpu.h |  4 ----
 target/arm/cpu.h      |  6 ------
 target/ppc/cpu.h      |  1 -
 target/arm/cpu.c      |  1 -
 target/arm/gdbstub.c  | 18 ------------------
 target/ppc/cpu_init.c |  3 ---
 target/ppc/gdbstub.c  | 10 ----------
 target/riscv/cpu.c    | 14 --------------
 8 files changed, 57 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 84219c1885..9323d26f84 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -133,9 +133,6 @@ struct SysemuCPUOps;
  *           before the insn which triggers a watchpoint rather than after it.
  * @gdb_arch_name: Optional callback that returns the architecture name known
  * to GDB. The caller must free the returned string with g_free.
- * @gdb_get_dynamic_xml: Callback to return dynamically generated XML for the
- *   gdb stub. Returns a pointer to the XML contents for the specified XML file
- *   or NULL if the CPU doesn't have a dynamically generated content for it.
  * @disas_set_info: Setup architecture specific components of disassembly info
  * @adjust_watchpoint_address: Perform a target-specific adjustment to an
  * address before attempting to match it against watchpoints.
@@ -166,7 +163,6 @@ struct CPUClass {
 
     const GDBFeature *gdb_core_feature;
     gchar * (*gdb_arch_name)(CPUState *cpu);
-    const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
 
     void (*disas_set_info)(CPUState *cpu, disassemble_info *info);
 
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index d6c2378d05..09bf82034d 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1131,12 +1131,6 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
 int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
-/* Returns the dynamically generated XML for the gdb stub.
- * Returns a pointer to the XML contents for the specified XML file or NULL
- * if the XML name doesn't match the predefined one.
- */
-const char *arm_gdb_get_dynamic_xml(CPUState *cpu, const char *xmlname);
-
 int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
                              int cpuid, DumpState *s);
 int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 5f251bdffe..3dc6e545e3 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1382,7 +1382,6 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
 #ifndef CONFIG_USER_ONLY
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu);
-const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
 #endif
 int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
                                int cpuid, DumpState *s);
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index a206ab6b1b..f51612070d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2354,7 +2354,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->sysemu_ops = &arm_sysemu_ops;
 #endif
     cc->gdb_arch_name = arm_gdb_arch_name;
-    cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
     cc->gdb_stop_before_watchpoint = true;
     cc->disas_set_info = arm_disas_set_info;
 
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index ab4ffe6264..100a6eed15 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -492,24 +492,6 @@ static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
 #endif
 #endif /* CONFIG_TCG */
 
-const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
-{
-    ARMCPU *cpu = ARM_CPU(cs);
-
-    if (strcmp(xmlname, "system-registers.xml") == 0) {
-        return cpu->dyn_sysreg_feature.desc.xml;
-    } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
-        return cpu->dyn_svereg_feature.desc.xml;
-    } else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
-        return cpu->dyn_m_systemreg_feature.desc.xml;
-#ifndef CONFIG_USER_ONLY
-    } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
-        return cpu->dyn_m_secextreg_feature.desc.xml;
-#endif
-    }
-    return NULL;
-}
-
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 938cd2b7e1..a3153c4e9f 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7370,9 +7370,6 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
 #endif
 
     cc->gdb_num_core_regs = 71;
-#ifndef CONFIG_USER_ONLY
-    cc->gdb_get_dynamic_xml = ppc_gdb_get_dynamic_xml;
-#endif
 #ifdef USE_APPLE_GDB
     cc->gdb_read_register = ppc_cpu_gdb_read_register_apple;
     cc->gdb_write_register = ppc_cpu_gdb_write_register_apple;
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index a0da320e66..19c4935260 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -375,16 +375,6 @@ void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu)
     pcc->gdb_spr.xmlname = "power-spr.xml";
     pcc->gdb_spr.xml = g_string_free(xml, false);
 }
-
-const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
-{
-    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
-
-    if (strcmp(xml_name, "power-spr.xml") == 0) {
-        return pcc->gdb_spr.xml;
-    }
-    return NULL;
-}
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ceca40cdd9..66c8c0dc57 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1957,19 +1957,6 @@ static gchar *riscv_gdb_arch_name(CPUState *cs)
     }
 }
 
-static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-
-    if (strcmp(xmlname, "riscv-csr.xml") == 0) {
-        return cpu->dyn_csr_feature.xml;
-    } else if (strcmp(xmlname, "riscv-vector.xml") == 0) {
-        return cpu->dyn_vreg_feature.xml;
-    }
-
-    return NULL;
-}
-
 #ifndef CONFIG_USER_ONLY
 static int64_t riscv_get_arch_id(CPUState *cs)
 {
@@ -2147,7 +2134,6 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
     cc->get_arch_id = riscv_get_arch_id;
 #endif
     cc->gdb_arch_name = riscv_gdb_arch_name;
-    cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml;
     cc->tcg_ops = &riscv_tcg_ops;
 
     object_class_property_add(c, "mvendorid", "uint32", cpu_get_mvendorid,
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 14/24] gdbstub: Add members to identify registers to GDBFeature
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (12 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 13/24] hw/core/cpu: Remove gdb_get_dynamic_xml member Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (10 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

These members will be used to help plugins to identify registers.
The added members in instances of GDBFeature dynamically generated by
CPUs will be filled in later changes.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/exec/gdbstub.h  |  2 ++
 scripts/feature_to_c.py | 14 +++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 9b3da5b257..6da4af9612 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -13,6 +13,8 @@
 typedef struct GDBFeature {
     const char *xmlname;
     const char *xml;
+    const char *name;
+    const char * const *regs;
     int num_regs;
 } GDBFeature;
 
diff --git a/scripts/feature_to_c.py b/scripts/feature_to_c.py
index 8eb8c81cf8..11b1bc05c9 100755
--- a/scripts/feature_to_c.py
+++ b/scripts/feature_to_c.py
@@ -46,7 +46,9 @@ def writeliteral(indent, bytes):
         sys.stderr.write(f'unexpected start tag: {element.tag}\n')
         exit(1)
 
+    feature_name = element.attrib['name']
     regnum = 0
+    regnames = []
     regnums = []
     tags = ['feature']
     for event, element in events:
@@ -63,6 +65,7 @@ def writeliteral(indent, bytes):
                 if 'regnum' in element.attrib:
                     regnum = int(element.attrib['regnum'])
 
+                regnames.append(element.attrib['name'])
                 regnums.append(regnum)
                 regnum += 1
 
@@ -81,6 +84,15 @@ def writeliteral(indent, bytes):
     writeliteral(8, bytes(os.path.basename(input), 'utf-8'))
     sys.stdout.write(',\n')
     writeliteral(8, read)
-    sys.stdout.write(f',\n        {num_regs},\n    }},\n')
+    sys.stdout.write(',\n')
+    writeliteral(8, bytes(feature_name, 'utf-8'))
+    sys.stdout.write(',\n        (const char * const []) {\n')
+
+    for index, regname in enumerate(regnames):
+        sys.stdout.write(f'            [{regnums[index] - base_reg}] =\n')
+        writeliteral(16, bytes(regname, 'utf-8'))
+        sys.stdout.write(',\n')
+
+    sys.stdout.write(f'        }},\n        {num_regs},\n    }},\n')
 
 sys.stdout.write('    { NULL }\n};\n')
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 15/24] target/arm: Fill new members of GDBFeature
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (13 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 14/24] gdbstub: Add members to identify registers to GDBFeature Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-08-14 14:56   ` Alex Bennée
  2023-07-31  8:43 ` [RFC PATCH 16/24] target/ppc: " Akihiko Odaki
                   ` (9 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

These members will be used to help plugins to identify registers.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 target/arm/gdbstub.c   | 46 +++++++++++++++++++++++++++---------------
 target/arm/gdbstub64.c | 42 +++++++++++++++++++++++++-------------
 2 files changed, 58 insertions(+), 30 deletions(-)

diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 100a6eed15..56d24028f6 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -270,6 +270,7 @@ static void arm_gen_one_feature_sysreg(GString *s,
     g_string_append_printf(s, " regnum=\"%d\"", regnum);
     g_string_append_printf(s, " group=\"cp_regs\"/>");
     dyn_feature->data.cpregs.keys[dyn_feature->desc.num_regs] = ri_key;
+    ((const char **)dyn_feature->desc.regs)[dyn_feature->desc.num_regs] = ri->name;
     dyn_feature->desc.num_regs++;
 }
 
@@ -316,6 +317,8 @@ static GDBFeature *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
     DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
     gsize num_regs = g_hash_table_size(cpu->cp_regs);
 
+    dyn_feature->desc.name = "org.qemu.gdb.arm.sys.regs";
+    dyn_feature->desc.regs = g_new(const char *, num_regs);
     dyn_feature->desc.num_regs = 0;
     dyn_feature->data.cpregs.keys = g_new(uint32_t, num_regs);
     g_string_printf(s, "<?xml version=\"1.0\"?>");
@@ -418,30 +421,34 @@ static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg)
 }
 
 static GDBFeature *arm_gen_dynamic_m_systemreg_feature(CPUState *cs,
-                                                       int orig_base_reg)
+                                                       int base_reg)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
     GString *s = g_string_new(NULL);
-    int base_reg = orig_base_reg;
-    int i;
+    const char **regs = g_new(const char *, ARRAY_SIZE(m_sysreg_def));
+    int i = 0;
+    int j;
 
     g_string_printf(s, "<?xml version=\"1.0\"?>");
     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.m-system\">\n");
 
-    for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
-        if (arm_feature(env, m_sysreg_def[i].feature)) {
+    for (j = 0; j < ARRAY_SIZE(m_sysreg_def); j++) {
+        if (arm_feature(env, m_sysreg_def[j].feature)) {
+            regs[i] = m_sysreg_def[j].name;
             g_string_append_printf(s,
                 "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
-                m_sysreg_def[i].name, base_reg++);
+                m_sysreg_def[j].name, base_reg + i++);
         }
     }
 
     g_string_append_printf(s, "</feature>");
+    cpu->dyn_m_systemreg_feature.desc.name = "org.gnu.gdb.arm.m-system";
     cpu->dyn_m_systemreg_feature.desc.xmlname = "arm-m-system.xml";
     cpu->dyn_m_systemreg_feature.desc.xml = g_string_free(s, false);
-    cpu->dyn_m_systemreg_feature.desc.num_regs = base_reg - orig_base_reg;
+    cpu->dyn_m_systemreg_feature.desc.regs = regs;
+    cpu->dyn_m_systemreg_feature.desc.num_regs = i;
 
     return &cpu->dyn_m_systemreg_feature.desc;
 }
@@ -462,30 +469,37 @@ static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg)
 }
 
 static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
-                                                       int orig_base_reg)
+                                                       int base_reg)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     GString *s = g_string_new(NULL);
-    int base_reg = orig_base_reg;
-    int i;
+    const char **regs = g_new(const char *, ARRAY_SIZE(m_sysreg_def) * 2);
+    int i = 0;
+    int j;
 
     g_string_printf(s, "<?xml version=\"1.0\"?>");
     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.secext\">\n");
 
-    for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
+    for (j = 0; j < ARRAY_SIZE(m_sysreg_def); j++) {
+        regs[i] = g_strconcat(m_sysreg_def[j].name, "_ns", NULL);
         g_string_append_printf(s,
-            "<reg name=\"%s_ns\" bitsize=\"32\" regnum=\"%d\"/>\n",
-            m_sysreg_def[i].name, base_reg++);
+            "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
+            regs[i], base_reg + i);
+        i++;
+        regs[i] = g_strconcat(m_sysreg_def[j].name, "_s", NULL);
         g_string_append_printf(s,
-            "<reg name=\"%s_s\" bitsize=\"32\" regnum=\"%d\"/>\n",
-            m_sysreg_def[i].name, base_reg++);
+            "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
+            regs[i], base_reg + i);
+        i++;
     }
 
     g_string_append_printf(s, "</feature>");
+    cpu->dyn_m_secextreg_feature.desc.name = "org.gnu.gdb.arm.secext";
     cpu->dyn_m_secextreg_feature.desc.xmlname = "arm-m-secext.xml";
     cpu->dyn_m_secextreg_feature.desc.xml = g_string_free(s, false);
-    cpu->dyn_m_secextreg_feature.desc.num_regs = base_reg - orig_base_reg;
+    cpu->dyn_m_secextreg_feature.desc.regs = regs;
+    cpu->dyn_m_secextreg_feature.desc.num_regs = i;
 
     return &cpu->dyn_m_secextreg_feature.desc;
 }
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 20483ef9bc..c5ed7c0aa3 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -316,15 +316,21 @@ static void output_vector_union_type(GString *s, int reg_width,
     g_string_append(s, "</union>");
 }
 
-GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int orig_base_reg)
+GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int base_reg)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     GString *s = g_string_new(NULL);
     DynamicGDBFeatureInfo *info = &cpu->dyn_svereg_feature;
+    const char **regs;
     int reg_width = cpu->sve_max_vq * 128;
     int pred_width = cpu->sve_max_vq * 16;
-    int base_reg = orig_base_reg;
-    int i;
+    int i = 0;
+    int j;
+
+    info->desc.name = "org.gnu.gdb.aarch64.sve";
+    info->desc.num_regs = 32 + 16 + 4;
+    regs = g_new(const char *, info->desc.num_regs);
+    info->desc.regs = regs;
 
     g_string_printf(s, "<?xml version=\"1.0\"?>");
     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
@@ -339,44 +345,52 @@ GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int orig_base_reg)
                            pred_width / 8);
 
     /* Define the vector registers. */
-    for (i = 0; i < 32; i++) {
+    for (j = 0; j < 32; j++) {
+        regs[i] = g_strdup_printf("z%d", j);
         g_string_append_printf(s,
-                               "<reg name=\"z%d\" bitsize=\"%d\""
+                               "<reg name=\"%s\" bitsize=\"%d\""
                                " regnum=\"%d\" type=\"svev\"/>",
-                               i, reg_width, base_reg++);
+                               regs[i], reg_width, base_reg + i);
+        i++;
     }
 
     /* fpscr & status registers */
+    regs[i] = "fpsr";
     g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
                            " regnum=\"%d\" group=\"float\""
-                           " type=\"int\"/>", base_reg++);
+                           " type=\"int\"/>", base_reg + i++);
+    regs[i] = "fpcr";
     g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
                            " regnum=\"%d\" group=\"float\""
-                           " type=\"int\"/>", base_reg++);
+                           " type=\"int\"/>", base_reg + i++);
 
     /* Define the predicate registers. */
-    for (i = 0; i < 16; i++) {
+    for (j = 0; j < 16; j++) {
+        regs[i] = g_strdup_printf("p%d", j);
         g_string_append_printf(s,
-                               "<reg name=\"p%d\" bitsize=\"%d\""
+                               "<reg name=\"%s\" bitsize=\"%d\""
                                " regnum=\"%d\" type=\"svep\"/>",
-                               i, pred_width, base_reg++);
+                               regs[i], pred_width, base_reg + i);
+        i++;
     }
+    regs[i] = "ffr";
     g_string_append_printf(s,
                            "<reg name=\"ffr\" bitsize=\"%d\""
                            " regnum=\"%d\" group=\"vector\""
                            " type=\"svep\"/>",
-                           pred_width, base_reg++);
+                           pred_width, base_reg + i++);
 
     /* Define the vector length pseudo-register. */
+    regs[i] = "vg";
     g_string_append_printf(s,
                            "<reg name=\"vg\" bitsize=\"64\""
                            " regnum=\"%d\" type=\"int\"/>",
-                           base_reg++);
+                           base_reg + i++);
 
     g_string_append_printf(s, "</feature>");
 
     info->desc.xmlname = "sve-registers.xml";
     info->desc.xml = g_string_free(s, false);
-    info->desc.num_regs = base_reg - orig_base_reg;
+    assert(info->desc.num_regs == i);
     return &info->desc;
 }
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 16/24] target/ppc: Fill new members of GDBFeature
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (14 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 15/24] target/arm: Fill new members of GDBFeature Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-07-31  8:43 ` [RFC PATCH 17/24] target/riscv: " Akihiko Odaki
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

These members will be used to help plugins to identify registers.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 target/ppc/gdbstub.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 19c4935260..ac4ed12371 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -323,7 +323,7 @@ void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu)
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     CPUPPCState *env = &cpu->env;
     GString *xml;
-    char *spr_name;
+    const char **regs;
     unsigned int num_regs = 0;
     int i;
 
@@ -350,6 +350,7 @@ void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu)
         return;
     }
 
+    regs = g_new(const char *, num_regs);
     xml = g_string_new("<?xml version=\"1.0\"?>");
     g_string_append(xml, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
     g_string_append(xml, "<feature name=\"org.qemu.power.spr\">");
@@ -361,9 +362,8 @@ void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu)
             continue;
         }
 
-        spr_name = g_ascii_strdown(spr->name, -1);
-        g_string_append_printf(xml, "<reg name=\"%s\"", spr_name);
-        g_free(spr_name);
+        regs[spr->gdb_id] = g_ascii_strdown(spr->name, -1);
+        g_string_append_printf(xml, "<reg name=\"%s\"", regs[spr->gdb_id]);
 
         g_string_append_printf(xml, " bitsize=\"%d\"", TARGET_LONG_BITS);
         g_string_append(xml, " group=\"spr\"/>");
@@ -371,6 +371,8 @@ void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu)
 
     g_string_append(xml, "</feature>");
 
+    pcc->gdb_spr.name = "org.qemu.power.spr";
+    pcc->gdb_spr.regs = regs;
     pcc->gdb_spr.num_regs = num_regs;
     pcc->gdb_spr.xmlname = "power-spr.xml";
     pcc->gdb_spr.xml = g_string_free(xml, false);
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 17/24] target/riscv: Fill new members of GDBFeature
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (15 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 16/24] target/ppc: " Akihiko Odaki
@ 2023-07-31  8:43 ` 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
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

These members will be used to help plugins to identify registers.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 target/riscv/gdbstub.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 224c69ea99..b3d4d4de3e 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -217,6 +217,7 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
     GString *s = g_string_new(NULL);
+    const char **regs = g_new(const char *, CSR_TABLE_SIZE);
     riscv_csr_predicate_fn predicate;
     int bitsize = 16 << env->misa_mxl_max;
     int i;
@@ -240,11 +241,10 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
         }
         predicate = csr_ops[i].predicate;
         if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
-            if (csr_ops[i].name) {
-                g_string_append_printf(s, "<reg name=\"%s\"", csr_ops[i].name);
-            } else {
-                g_string_append_printf(s, "<reg name=\"csr%03x\"", i);
-            }
+            regs[i] =
+                csr_ops[i].name ?
+                    csr_ops[i].name : g_strdup_printf("csr%03x", i);
+            g_string_append_printf(s, "<reg name=\"%s\"", regs[i]);
             g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
             g_string_append_printf(s, " regnum=\"%d\"/>", base_reg + i);
         }
@@ -252,6 +252,8 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
 
     g_string_append_printf(s, "</feature>");
 
+    cpu->dyn_csr_feature.name = "org.gnu.gdb.riscv.csr";
+    cpu->dyn_csr_feature.regs = regs;
     cpu->dyn_csr_feature.num_regs = CSR_TABLE_SIZE;
     cpu->dyn_csr_feature.xmlname = "riscv-csr.xml";
     cpu->dyn_csr_feature.xml = g_string_free(s, false);
@@ -268,10 +270,12 @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
     RISCVCPU *cpu = RISCV_CPU(cs);
     GString *s = g_string_new(NULL);
     g_autoptr(GString) ts = g_string_new("");
+    const char **regs;
     int reg_width = cpu->cfg.vlen;
     int i;
 
     cpu->dyn_vreg_feature.num_regs = 32;
+    regs = g_new(const char *, cpu->dyn_vreg_feature.num_regs);
 
     g_string_printf(s, "<?xml version=\"1.0\"?>");
     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
@@ -297,15 +301,18 @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
 
     /* Define vector registers */
     for (i = 0; i < cpu->dyn_vreg_feature.num_regs; i++) {
+        regs[i] = g_strdup_printf("v%d", i);
         g_string_append_printf(s,
-                               "<reg name=\"v%d\" bitsize=\"%d\""
+                               "<reg name=\"%s\" bitsize=\"%d\""
                                " regnum=\"%d\" group=\"vector\""
                                " type=\"riscv_vector\"/>",
-                               i, reg_width, base_reg++);
+                               regs[i], reg_width, base_reg++);
     }
 
     g_string_append_printf(s, "</feature>");
 
+    cpu->dyn_vreg_feature.name = "org.gnu.gdb.riscv.vector";
+    cpu->dyn_vreg_feature.regs = regs;
     cpu->dyn_vreg_feature.xmlname = "riscv-vector.xml";
     cpu->dyn_vreg_feature.xml = g_string_free(s, false);
     return &cpu->dyn_vreg_feature;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 18/24] hw/core/cpu: Add a parameter to gdb_read_register/gdb_write_register
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (16 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 17/24] target/riscv: " Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-07-31  8:43 ` [RFC PATCH 19/24] gdbstub: Hide gdb_has_xml Akihiko Odaki
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

gdbstub has a static variable named gdb_has_xml that tells if
workarounds for old GDB versions are required when manipulating
registers for GDB.

Now we are reusing the infrastructure to manipulate registers for
plugins. Plugins will not need these workarounds even when an old GDB
is attached. Converting the static variable to a function parameter
would allow to apply or not to apply workarounds depending on the
context.

This change adds the new parameter and replaces references to
gdb_has_xml with it. New code to pass different values to the functions
will be added later.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/hw/core/cpu.h         |  6 ++++--
 target/alpha/cpu.h            |  6 ++++--
 target/arm/cpu.h              | 13 +++++++++----
 target/avr/cpu.h              |  6 ++++--
 target/cris/cpu.h             |  9 ++++++---
 target/hexagon/internal.h     |  6 ++++--
 target/hppa/cpu.h             |  6 ++++--
 target/i386/cpu.h             |  6 ++++--
 target/loongarch/internals.h  |  6 ++++--
 target/m68k/cpu.h             |  6 ++++--
 target/microblaze/cpu.h       |  6 ++++--
 target/mips/internal.h        |  6 ++++--
 target/openrisc/cpu.h         |  6 ++++--
 target/ppc/cpu.h              | 12 ++++++++----
 target/riscv/cpu.h            |  6 ++++--
 target/rx/cpu.h               |  6 ++++--
 target/s390x/s390x-internal.h |  6 ++++--
 target/sh4/cpu.h              |  6 ++++--
 target/sparc/cpu.h            |  6 ++++--
 target/tricore/cpu.h          |  6 ++++--
 target/xtensa/cpu.h           |  6 ++++--
 gdbstub/gdbstub.c             |  4 ++--
 hw/core/cpu-common.c          |  6 ++++--
 target/alpha/gdbstub.c        |  6 ++++--
 target/arm/gdbstub.c          | 14 ++++++++------
 target/arm/gdbstub64.c        |  6 ++++--
 target/avr/gdbstub.c          |  6 ++++--
 target/cris/gdbstub.c         |  9 ++++++---
 target/hexagon/gdbstub.c      |  6 ++++--
 target/hppa/gdbstub.c         |  6 ++++--
 target/i386/gdbstub.c         | 10 +++++-----
 target/loongarch/gdbstub.c    |  6 ++++--
 target/m68k/gdbstub.c         |  6 ++++--
 target/microblaze/gdbstub.c   |  6 ++++--
 target/mips/gdbstub.c         |  6 ++++--
 target/nios2/cpu.c            |  6 ++++--
 target/openrisc/gdbstub.c     |  6 ++++--
 target/ppc/gdbstub.c          | 22 +++++++++++++---------
 target/riscv/gdbstub.c        |  6 ++++--
 target/rx/gdbstub.c           |  6 ++++--
 target/s390x/gdbstub.c        |  6 ++++--
 target/sh4/gdbstub.c          |  6 ++++--
 target/sparc/gdbstub.c        |  6 ++++--
 target/tricore/gdbstub.c      |  6 ++++--
 target/xtensa/gdbstub.c       |  6 ++++--
 45 files changed, 205 insertions(+), 110 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 9323d26f84..9428e57e7c 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -157,8 +157,10 @@ struct CPUClass {
     int64_t (*get_arch_id)(CPUState *cpu);
     void (*set_pc)(CPUState *cpu, vaddr value);
     vaddr (*get_pc)(CPUState *cpu);
-    int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg);
-    int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
+    int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg,
+                             bool has_xml);
+    int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg,
+                              bool has_xml);
     vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
 
     const GDBFeature *gdb_core_feature;
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 13306665af..46bd9bc37b 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -279,8 +279,10 @@ bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
 hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 #endif /* !CONFIG_USER_ONLY */
 void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags);
-int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                bool has_xml);
+int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                 bool has_xml);
 
 #define cpu_list alpha_cpu_list
 
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 09bf82034d..3dfa29c3aa 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1128,8 +1128,11 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
                                          MemTxAttrs *attrs);
 #endif /* !CONFIG_USER_ONLY */
 
-int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                              bool has_xml);
+
+int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                               bool has_xml);
 
 int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
                              int cpuid, DumpState *s);
@@ -1137,8 +1140,10 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
                              int cpuid, DumpState *s);
 
 #ifdef TARGET_AARCH64
-int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                  bool has_xml);
+int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                   bool has_xml);
 void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
 void aarch64_sve_change_el(CPUARMState *env, int old_el,
                            int new_el, bool el0_a64);
diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index 7225174668..006e79e018 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -157,8 +157,10 @@ extern const struct VMStateDescription vms_avr_cpu;
 void avr_cpu_do_interrupt(CPUState *cpu);
 bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
 hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int avr_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int avr_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                              bool has_xml);
+int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                               bool has_xml);
 int avr_print_insn(bfd_vma addr, disassemble_info *info);
 vaddr avr_cpu_gdb_adjust_breakpoint(CPUState *cpu, vaddr addr);
 
diff --git a/target/cris/cpu.h b/target/cris/cpu.h
index 8e37c6e50d..d3a62c5480 100644
--- a/target/cris/cpu.h
+++ b/target/cris/cpu.h
@@ -198,9 +198,12 @@ hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags);
 
-int crisv10_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int cris_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int crisv10_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                  bool has_xml);
+int cris_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                               bool has_xml);
+int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                bool has_xml);
 
 void cris_initialize_tcg(void);
 void cris_initialize_crisv10_tcg(void);
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index d732b6bb3c..cdd4bb7d26 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -31,8 +31,10 @@
         } \
     } while (0)
 
-int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                              bool has_xml);
+int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                               bool has_xml);
 int hexagon_hvx_gdb_read_register(CPUHexagonState *env, GByteArray *mem_buf, int n);
 int hexagon_hvx_gdb_write_register(CPUHexagonState *env, uint8_t *mem_buf, int n);
 
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 9fe79b1242..a983540dd2 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -321,8 +321,10 @@ static inline void cpu_hppa_change_prot_id(CPUHPPAState *env) { }
 void cpu_hppa_change_prot_id(CPUHPPAState *env);
 #endif
 
-int hppa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int hppa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                               bool has_xml);
+int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                bool has_xml);
 void hppa_cpu_dump_state(CPUState *cs, FILE *f, int);
 #ifndef CONFIG_USER_ONLY
 hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e0771a1043..d177f500b8 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2057,8 +2057,10 @@ void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
 
 void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags);
 
-int x86_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int x86_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                              bool has_xml);
+int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                               bool has_xml);
 
 void x86_cpu_list(void);
 int cpu_x86_support_mca_broadcast(CPUX86State *env);
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 7b0f29c942..a2ff8b3e3d 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -77,8 +77,10 @@ hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 uint64_t read_fcc(CPULoongArchState *env);
 void write_fcc(CPULoongArchState *env, uint64_t val);
 
-int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
-int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
+int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                    bool has_xml);
+int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                     bool has_xml);
 void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs);
 
 #endif
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index cf70282717..b59d076c0c 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -179,8 +179,10 @@ bool m68k_cpu_exec_interrupt(CPUState *cpu, int int_req);
 hwaddr m68k_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 #endif /* !CONFIG_USER_ONLY */
 void m68k_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
-int m68k_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int m68k_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                               bool has_xml);
+int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                bool has_xml);
 
 void m68k_tcg_init(void);
 void m68k_cpu_init_gdb(M68kCPU *cpu);
diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index f6cab6ce19..8840bf17f3 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -368,8 +368,10 @@ G_NORETURN void mb_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
                                            MMUAccessType access_type,
                                            int mmu_idx, uintptr_t retaddr);
 void mb_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
-int mb_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int mb_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                             bool has_xml);
+int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                              bool has_xml);
 int mb_cpu_gdb_read_stack_protect(CPUArchState *cpu, GByteArray *buf, int reg);
 int mb_cpu_gdb_write_stack_protect(CPUArchState *cpu, uint8_t *buf, int reg);
 
diff --git a/target/mips/internal.h b/target/mips/internal.h
index 1d0c026c7d..b5462f53a9 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -92,8 +92,10 @@ extern const char fregnames[32][4];
 extern const struct mips_def_t mips_defs[];
 extern const int mips_defs_number;
 
-int mips_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int mips_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                               bool has_xml);
+int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                bool has_xml);
 
 #define USEG_LIMIT      ((target_ulong)(int32_t)0x7FFFFFFFUL)
 #define KSEG0_BASE      ((target_ulong)(int32_t)0x80000000UL)
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index ce4d605eb7..8c2089db92 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -312,8 +312,10 @@ struct ArchCPU {
 
 void cpu_openrisc_list(void);
 void openrisc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
-int openrisc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int openrisc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                   bool has_xml);
+int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                    bool has_xml);
 void openrisc_translate_init(void);
 int print_insn_or1k(bfd_vma addr, disassemble_info *info);
 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 3dc6e545e3..0849ee6e1f 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1375,10 +1375,14 @@ static inline bool vhyp_cpu_in_nested(PowerPCCPU *cpu)
 #endif /* CONFIG_USER_ONLY */
 
 void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
-int ppc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int ppc_cpu_gdb_read_register_apple(CPUState *cpu, GByteArray *buf, int reg);
-int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
+int ppc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                              bool has_xml);
+int ppc_cpu_gdb_read_register_apple(CPUState *cpu, GByteArray *buf, int reg,
+                                    bool has_xml);
+int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                               bool has_xml);
+int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg,
+                                     bool has_xml);
 #ifndef CONFIG_USER_ONLY
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void ppc_gdb_gen_spr_feature(PowerPCCPU *cpu);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f67751d5b7..46b06b1962 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -421,8 +421,10 @@ int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
                                int cpuid, DumpState *s);
 int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
                                int cpuid, DumpState *s);
-int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                bool has_xml);
+int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                 bool has_xml);
 int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero);
 uint8_t riscv_cpu_default_priority(int irq);
 uint64_t riscv_cpu_all_pending(CPURISCVState *env);
diff --git a/target/rx/cpu.h b/target/rx/cpu.h
index 7f03ffcfed..d1a099cf72 100644
--- a/target/rx/cpu.h
+++ b/target/rx/cpu.h
@@ -126,8 +126,10 @@ bool rx_cpu_exec_interrupt(CPUState *cpu, int int_req);
 hwaddr rx_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 #endif /* !CONFIG_USER_ONLY */
 void rx_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
-int rx_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int rx_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int rx_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                             bool has_xml);
+int rx_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                              bool has_xml);
 
 void rx_translate_init(void);
 void rx_cpu_list(void);
diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h
index 825252d728..4c2bb30358 100644
--- a/target/s390x/s390x-internal.h
+++ b/target/s390x/s390x-internal.h
@@ -316,8 +316,10 @@ uint16_t float128_dcmask(CPUS390XState *env, float128 f1);
 
 
 /* gdbstub.c */
-int s390_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int s390_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                               bool has_xml);
+int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                bool has_xml);
 void s390_cpu_gdb_init(CPUState *cs);
 
 
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index 1399d3840f..74c8f0f574 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -214,8 +214,10 @@ struct ArchCPU {
 
 
 void superh_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
-int superh_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int superh_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int superh_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                 bool has_xml);
+int superh_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                  bool has_xml);
 G_NORETURN void superh_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
                                                MMUAccessType access_type, int mmu_idx,
                                                uintptr_t retaddr);
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 98044572f2..b03174938c 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -573,8 +573,10 @@ hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 #endif
 
 void sparc_cpu_do_interrupt(CPUState *cpu);
-int sparc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int sparc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                bool has_xml);
+int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                 bool has_xml);
 G_NORETURN void sparc_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
                                               MMUAccessType access_type,
                                               int mmu_idx,
diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
index 3708405be8..7da6c88a15 100644
--- a/target/tricore/cpu.h
+++ b/target/tricore/cpu.h
@@ -361,8 +361,10 @@ enum {
 
 uint32_t psw_read(CPUTriCoreState *env);
 void psw_write(CPUTriCoreState *env, uint32_t val);
-int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
-int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
+int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                  bool has_xml);
+int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                   bool has_xml);
 
 void fpu_set_state(CPUTriCoreState *env);
 
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 87fe992ba6..093593eb0c 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -581,8 +581,10 @@ hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void xtensa_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
 void xtensa_count_regs(const XtensaConfig *config,
                        unsigned *n_regs, unsigned *n_core_regs);
-int xtensa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
-int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int xtensa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                 bool has_xml);
+int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                  bool has_xml);
 G_NORETURN void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
                                                MMUAccessType access_type, int mmu_idx,
                                                uintptr_t retaddr);
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index e5bb2c89ba..caef6aabab 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -423,7 +423,7 @@ static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
     GDBRegisterState *r;
 
     if (reg < cc->gdb_num_core_regs) {
-        return cc->gdb_read_register(cpu, buf, reg);
+        return cc->gdb_read_register(cpu, buf, reg, gdb_has_xml);
     }
 
     for (r = cpu->gdb_regs; r; r = r->next) {
@@ -441,7 +441,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
     GDBRegisterState *r;
 
     if (reg < cc->gdb_num_core_regs) {
-        return cc->gdb_write_register(cpu, mem_buf, reg);
+        return cc->gdb_write_register(cpu, mem_buf, reg, gdb_has_xml);
     }
 
     for (r = cpu->gdb_regs; r; r = r->next) {
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index ced66c2b34..549f52f46f 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -89,12 +89,14 @@ void cpu_exit(CPUState *cpu)
     qatomic_set(&cpu->icount_decr_ptr->u16.high, -1);
 }
 
-static int cpu_common_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
+static int cpu_common_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg,
+                                        bool has_xml)
 {
     return 0;
 }
 
-static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg)
+static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg,
+                                         bool has_xml)
 {
     return 0;
 }
diff --git a/target/alpha/gdbstub.c b/target/alpha/gdbstub.c
index 0f8fa150f8..c5b4a190f3 100644
--- a/target/alpha/gdbstub.c
+++ b/target/alpha/gdbstub.c
@@ -21,7 +21,8 @@
 #include "cpu.h"
 #include "gdbstub/helpers.h"
 
-int alpha_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int alpha_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                bool has_xml)
 {
     AlphaCPU *cpu = ALPHA_CPU(cs);
     CPUAlphaState *env = &cpu->env;
@@ -57,7 +58,8 @@ int alpha_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return gdb_get_regl(mem_buf, val);
 }
 
-int alpha_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int alpha_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                 bool has_xml)
 {
     AlphaCPU *cpu = ALPHA_CPU(cs);
     CPUAlphaState *env = &cpu->env;
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 56d24028f6..f941186b58 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -37,7 +37,8 @@ typedef struct RegisterSysregFeatureParam {
    We hack round this by giving the FPA regs zero size when talking to a
    newer gdb.  */
 
-int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                              bool has_xml)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -48,7 +49,7 @@ int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     }
     if (n < 24) {
         /* FPA registers.  */
-        if (gdb_has_xml) {
+        if (has_xml) {
             return 0;
         }
         return gdb_get_zeroes(mem_buf, 12);
@@ -56,7 +57,7 @@ int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     switch (n) {
     case 24:
         /* FPA status register.  */
-        if (gdb_has_xml) {
+        if (has_xml) {
             return 0;
         }
         return gdb_get_reg32(mem_buf, 0);
@@ -72,7 +73,8 @@ int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                               bool has_xml)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -102,7 +104,7 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     }
     if (n < 24) { /* 16-23 */
         /* FPA registers (ignored).  */
-        if (gdb_has_xml) {
+        if (has_xml) {
             return 0;
         }
         return 12;
@@ -110,7 +112,7 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     switch (n) {
     case 24:
         /* FPA status register (ignored).  */
-        if (gdb_has_xml) {
+        if (has_xml) {
             return 0;
         }
         return 4;
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index c5ed7c0aa3..aff3836037 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -22,7 +22,8 @@
 #include "internals.h"
 #include "gdbstub/helpers.h"
 
-int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                  bool has_xml)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -43,7 +44,8 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int aarch64_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int aarch64_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                   bool has_xml)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
diff --git a/target/avr/gdbstub.c b/target/avr/gdbstub.c
index 150344d8b9..c40f4ecd4b 100644
--- a/target/avr/gdbstub.c
+++ b/target/avr/gdbstub.c
@@ -21,7 +21,8 @@
 #include "qemu/osdep.h"
 #include "gdbstub/helpers.h"
 
-int avr_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int avr_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                              bool has_xml)
 {
     AVRCPU *cpu = AVR_CPU(cs);
     CPUAVRState *env = &cpu->env;
@@ -51,7 +52,8 @@ int avr_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int avr_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int avr_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                               bool has_xml)
 {
     AVRCPU *cpu = AVR_CPU(cs);
     CPUAVRState *env = &cpu->env;
diff --git a/target/cris/gdbstub.c b/target/cris/gdbstub.c
index 25c0ca33a5..2b5c0d5f14 100644
--- a/target/cris/gdbstub.c
+++ b/target/cris/gdbstub.c
@@ -21,7 +21,8 @@
 #include "cpu.h"
 #include "gdbstub/helpers.h"
 
-int crisv10_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int crisv10_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                  bool has_xml)
 {
     CRISCPU *cpu = CRIS_CPU(cs);
     CPUCRISState *env = &cpu->env;
@@ -53,7 +54,8 @@ int crisv10_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int cris_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int cris_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                               bool has_xml)
 {
     CRISCPU *cpu = CRIS_CPU(cs);
     CPUCRISState *env = &cpu->env;
@@ -88,7 +90,8 @@ int cris_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int cris_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int cris_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                bool has_xml)
 {
     CRISCPU *cpu = CRIS_CPU(cs);
     CPUCRISState *env = &cpu->env;
diff --git a/target/hexagon/gdbstub.c b/target/hexagon/gdbstub.c
index 54d37e006e..42fa563fc4 100644
--- a/target/hexagon/gdbstub.c
+++ b/target/hexagon/gdbstub.c
@@ -20,7 +20,8 @@
 #include "cpu.h"
 #include "internal.h"
 
-int hexagon_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int hexagon_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                              bool has_xml)
 {
     HexagonCPU *cpu = HEXAGON_CPU(cs);
     CPUHexagonState *env = &cpu->env;
@@ -40,7 +41,8 @@ int hexagon_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     g_assert_not_reached();
 }
 
-int hexagon_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int hexagon_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                               bool has_xml)
 {
     HexagonCPU *cpu = HEXAGON_CPU(cs);
     CPUHexagonState *env = &cpu->env;
diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c
index 48a514384f..44a1869d54 100644
--- a/target/hppa/gdbstub.c
+++ b/target/hppa/gdbstub.c
@@ -21,7 +21,8 @@
 #include "cpu.h"
 #include "gdbstub/helpers.h"
 
-int hppa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int hppa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                               bool has_xml)
 {
     HPPACPU *cpu = HPPA_CPU(cs);
     CPUHPPAState *env = &cpu->env;
@@ -146,7 +147,8 @@ int hppa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     }
 }
 
-int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                bool has_xml)
 {
     HPPACPU *cpu = HPPA_CPU(cs);
     CPUHPPAState *env = &cpu->env;
diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c
index ebb000df6a..56c9aedd6b 100644
--- a/target/i386/gdbstub.c
+++ b/target/i386/gdbstub.c
@@ -32,9 +32,7 @@ static const int gpr_map[16] = {
 static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 
 /*
- * Keep these in sync with assignment to
- * gdb_num_core_regs in target/i386/cpu.c
- * and with the machine description
+ * Keep these in sync with the machine description
  */
 
 /*
@@ -96,7 +94,8 @@ static int gdb_write_reg_cs64(uint32_t hflags, uint8_t *buf, target_ulong *val)
     return 4;
 }
 
-int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                              bool has_xml)
 {
     X86CPU *cpu = X86_CPU(cs);
     CPUX86State *env = &cpu->env;
@@ -248,7 +247,8 @@ static int x86_cpu_gdb_load_seg(X86CPU *cpu, X86Seg sreg, uint8_t *mem_buf)
     return 4;
 }
 
-int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                               bool has_xml)
 {
     X86CPU *cpu = X86_CPU(cs);
     CPUX86State *env = &cpu->env;
diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c
index 2886b106bb..6b14f73084 100644
--- a/target/loongarch/gdbstub.c
+++ b/target/loongarch/gdbstub.c
@@ -30,7 +30,8 @@ void write_fcc(CPULoongArchState *env, uint64_t val)
     }
 }
 
-int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                    bool has_xml)
 {
     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
     CPULoongArchState *env = &cpu->env;
@@ -48,7 +49,8 @@ int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                     bool has_xml)
 {
     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
     CPULoongArchState *env = &cpu->env;
diff --git a/target/m68k/gdbstub.c b/target/m68k/gdbstub.c
index 1e5f033a12..24e636cddc 100644
--- a/target/m68k/gdbstub.c
+++ b/target/m68k/gdbstub.c
@@ -21,7 +21,8 @@
 #include "cpu.h"
 #include "gdbstub/helpers.h"
 
-int m68k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int m68k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                               bool has_xml)
 {
     M68kCPU *cpu = M68K_CPU(cs);
     CPUM68KState *env = &cpu->env;
@@ -48,7 +49,8 @@ int m68k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int m68k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int m68k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                bool has_xml)
 {
     M68kCPU *cpu = M68K_CPU(cs);
     CPUM68KState *env = &cpu->env;
diff --git a/target/microblaze/gdbstub.c b/target/microblaze/gdbstub.c
index 29ac6e9c0f..71962b98de 100644
--- a/target/microblaze/gdbstub.c
+++ b/target/microblaze/gdbstub.c
@@ -46,7 +46,8 @@ enum {
     GDB_SP_SHR,
 };
 
-int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                             bool has_xml)
 {
     MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
     CPUClass *cc = CPU_GET_CLASS(cs);
@@ -111,7 +112,8 @@ int mb_cpu_gdb_read_stack_protect(CPUMBState *env, GByteArray *mem_buf, int n)
     return gdb_get_reg32(mem_buf, val);
 }
 
-int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                              bool has_xml)
 {
     MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
     CPUClass *cc = CPU_GET_CLASS(cs);
diff --git a/target/mips/gdbstub.c b/target/mips/gdbstub.c
index 62d7b72407..9022fc5375 100644
--- a/target/mips/gdbstub.c
+++ b/target/mips/gdbstub.c
@@ -23,7 +23,8 @@
 #include "gdbstub/helpers.h"
 #include "fpu_helper.h"
 
-int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                               bool has_xml)
 {
     MIPSCPU *cpu = MIPS_CPU(cs);
     CPUMIPSState *env = &cpu->env;
@@ -76,7 +77,8 @@ int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                bool has_xml)
 {
     MIPSCPU *cpu = MIPS_CPU(cs);
     CPUMIPSState *env = &cpu->env;
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index bc5cbf81c2..5015866b4d 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -280,7 +280,8 @@ static void nios2_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
     info->print_insn = print_insn_nios2;
 }
 
-static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                       bool has_xml)
 {
     Nios2CPU *cpu = NIOS2_CPU(cs);
     CPUNios2State *env = &cpu->env;
@@ -305,7 +306,8 @@ static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return gdb_get_reg32(mem_buf, val);
 }
 
-static int nios2_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+static int nios2_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                        bool has_xml)
 {
     Nios2CPU *cpu = NIOS2_CPU(cs);
     CPUClass *cc = CPU_GET_CLASS(cs);
diff --git a/target/openrisc/gdbstub.c b/target/openrisc/gdbstub.c
index d1074a0581..5ac841e52a 100644
--- a/target/openrisc/gdbstub.c
+++ b/target/openrisc/gdbstub.c
@@ -21,7 +21,8 @@
 #include "cpu.h"
 #include "gdbstub/helpers.h"
 
-int openrisc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int openrisc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                   bool has_xml)
 {
     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
     CPUOpenRISCState *env = &cpu->env;
@@ -46,7 +47,8 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                    bool has_xml)
 {
     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
     CPUClass *cc = CPU_GET_CLASS(cs);
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index ac4ed12371..fba4b9a2fa 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -48,7 +48,7 @@ static int ppc_gdb_register_len_apple(int n)
     }
 }
 
-static int ppc_gdb_register_len(int n)
+static int ppc_gdb_register_len(int n, bool has_xml)
 {
     switch (n) {
     case 0 ... 31:
@@ -56,7 +56,7 @@ static int ppc_gdb_register_len(int n)
         return sizeof(target_ulong);
     case 32 ... 63:
         /* fprs */
-        if (gdb_has_xml) {
+        if (has_xml) {
             return 0;
         }
         return 8;
@@ -76,7 +76,7 @@ static int ppc_gdb_register_len(int n)
         return sizeof(target_ulong);
     case 70:
         /* fpscr */
-        if (gdb_has_xml) {
+        if (has_xml) {
             return 0;
         }
         return sizeof(target_ulong);
@@ -118,12 +118,13 @@ void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
  * the FP regs zero size when talking to a newer gdb.
  */
 
-int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray *buf, int n)
+int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray *buf, int n,
+                              bool has_xml)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     CPUPPCState *env = &cpu->env;
     uint8_t *mem_buf;
-    int r = ppc_gdb_register_len(n);
+    int r = ppc_gdb_register_len(n, has_xml);
 
     if (!r) {
         return r;
@@ -168,7 +169,8 @@ int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray *buf, int n)
     return r;
 }
 
-int ppc_cpu_gdb_read_register_apple(CPUState *cs, GByteArray *buf, int n)
+int ppc_cpu_gdb_read_register_apple(CPUState *cs, GByteArray *buf, int n,
+                                    bool has_xml)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     CPUPPCState *env = &cpu->env;
@@ -222,11 +224,12 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, GByteArray *buf, int n)
     return r;
 }
 
-int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                               bool has_xml)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     CPUPPCState *env = &cpu->env;
-    int r = ppc_gdb_register_len(n);
+    int r = ppc_gdb_register_len(n, has_xml);
 
     if (!r) {
         return r;
@@ -269,7 +272,8 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     }
     return r;
 }
-int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
+int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n,
+                                     bool has_xml)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     CPUPPCState *env = &cpu->env;
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index b3d4d4de3e..060bfa4317 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -47,7 +47,8 @@ static const struct TypeSize vec_lanes[] = {
     { "uint8", "bytes", 8, 'b' },
 };
 
-int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                bool has_xml)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
@@ -73,7 +74,8 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                 bool has_xml)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
diff --git a/target/rx/gdbstub.c b/target/rx/gdbstub.c
index d7e0e6689b..57d5ed11eb 100644
--- a/target/rx/gdbstub.c
+++ b/target/rx/gdbstub.c
@@ -19,7 +19,8 @@
 #include "cpu.h"
 #include "gdbstub/helpers.h"
 
-int rx_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int rx_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                             bool has_xml)
 {
     RXCPU *cpu = RX_CPU(cs);
     CPURXState *env = &cpu->env;
@@ -51,7 +52,8 @@ int rx_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int rx_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int rx_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                              bool has_xml)
 {
     RXCPU *cpu = RX_CPU(cs);
     CPURXState *env = &cpu->env;
diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c
index 02c388dc32..57871e3b24 100644
--- a/target/s390x/gdbstub.c
+++ b/target/s390x/gdbstub.c
@@ -28,7 +28,8 @@
 #include "sysemu/hw_accel.h"
 #include "sysemu/tcg.h"
 
-int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                               bool has_xml)
 {
     S390CPU *cpu = S390_CPU(cs);
     CPUS390XState *env = &cpu->env;
@@ -44,7 +45,8 @@ int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                bool has_xml)
 {
     S390CPU *cpu = S390_CPU(cs);
     CPUS390XState *env = &cpu->env;
diff --git a/target/sh4/gdbstub.c b/target/sh4/gdbstub.c
index d8e199fc06..9afe6fc116 100644
--- a/target/sh4/gdbstub.c
+++ b/target/sh4/gdbstub.c
@@ -24,7 +24,8 @@
 /* Hint: Use "set architecture sh4" in GDB to see fpu registers */
 /* FIXME: We should use XML for this.  */
 
-int superh_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int superh_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                 bool has_xml)
 {
     SuperHCPU *cpu = SUPERH_CPU(cs);
     CPUSH4State *env = &cpu->env;
@@ -74,7 +75,8 @@ int superh_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int superh_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int superh_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                  bool has_xml)
 {
     SuperHCPU *cpu = SUPERH_CPU(cs);
     CPUSH4State *env = &cpu->env;
diff --git a/target/sparc/gdbstub.c b/target/sparc/gdbstub.c
index a1c8fdc4d5..288cf7d6f7 100644
--- a/target/sparc/gdbstub.c
+++ b/target/sparc/gdbstub.c
@@ -27,7 +27,8 @@
 #define gdb_get_rega(buf, val) gdb_get_regl(buf, val)
 #endif
 
-int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                bool has_xml)
 {
     SPARCCPU *cpu = SPARC_CPU(cs);
     CPUSPARCState *env = &cpu->env;
@@ -104,7 +105,8 @@ int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                 bool has_xml)
 {
     SPARCCPU *cpu = SPARC_CPU(cs);
     CPUSPARCState *env = &cpu->env;
diff --git a/target/tricore/gdbstub.c b/target/tricore/gdbstub.c
index e8f8e5e6ea..a06e590344 100644
--- a/target/tricore/gdbstub.c
+++ b/target/tricore/gdbstub.c
@@ -104,7 +104,8 @@ static void tricore_cpu_gdb_write_csfr(CPUTriCoreState *env, int n,
 }
 
 
-int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                  bool has_xml)
 {
     TriCoreCPU *cpu = TRICORE_CPU(cs);
     CPUTriCoreState *env = &cpu->env;
@@ -119,7 +120,8 @@ int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     return 0;
 }
 
-int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                   bool has_xml)
 {
     TriCoreCPU *cpu = TRICORE_CPU(cs);
     CPUTriCoreState *env = &cpu->env;
diff --git a/target/xtensa/gdbstub.c b/target/xtensa/gdbstub.c
index 4b3bfb7e59..81d97b51b8 100644
--- a/target/xtensa/gdbstub.c
+++ b/target/xtensa/gdbstub.c
@@ -63,7 +63,8 @@ void xtensa_count_regs(const XtensaConfig *config,
     }
 }
 
-int xtensa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+int xtensa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n,
+                                 bool has_xml)
 {
     XtensaCPU *cpu = XTENSA_CPU(cs);
     CPUXtensaState *env = &cpu->env;
@@ -118,7 +119,8 @@ int xtensa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     }
 }
 
-int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n,
+                                  bool has_xml)
 {
     XtensaCPU *cpu = XTENSA_CPU(cs);
     CPUXtensaState *env = &cpu->env;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 19/24] gdbstub: Hide gdb_has_xml
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (17 preceding siblings ...)
  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 ` Akihiko Odaki
  2023-07-31  8:43 ` [RFC PATCH 20/24] gdbstub: Expose functions to read registers Akihiko Odaki
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

gdb_has_xml is no longer referenced by the other components.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 gdbstub/internals.h    | 8 ++++++++
 include/exec/gdbstub.h | 8 --------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/gdbstub/internals.h b/gdbstub/internals.h
index f2b46cce41..92f5ce8cbb 100644
--- a/gdbstub/internals.h
+++ b/gdbstub/internals.h
@@ -234,4 +234,12 @@ void gdb_breakpoint_remove_all(CPUState *cs);
 int gdb_target_memory_rw_debug(CPUState *cs, hwaddr addr,
                                uint8_t *buf, int len, bool is_write);
 
+/**
+ * gdb_has_xml:
+ * This is an ugly hack to cope with both new and old gdb.
+ * If gdb sends qXfer:features:read then assume we're talking to a newish
+ * gdb that understands target descriptions.
+ */
+extern bool gdb_has_xml;
+
 #endif /* GDBSTUB_INTERNALS_H */
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 6da4af9612..cbd1e6ead4 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -40,14 +40,6 @@ const GDBFeature *gdb_find_static_feature(const char *xmlname);
 
 void gdb_set_stop_cpu(CPUState *cpu);
 
-/**
- * gdb_has_xml:
- * This is an ugly hack to cope with both new and old gdb.
- * If gdb sends qXfer:features:read then assume we're talking to a newish
- * gdb that understands target descriptions.
- */
-extern bool gdb_has_xml;
-
 /* in gdbstub-xml.c, generated by scripts/feature_to_c.py */
 extern const GDBFeature gdb_features[];
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 20/24] gdbstub: Expose functions to read registers
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (18 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 19/24] gdbstub: Hide gdb_has_xml Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-07-31  8:43 ` [RFC PATCH 21/24] plugins: Allow " Akihiko Odaki
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

gdb_foreach_feature() enumerates features that are useful to identify
registers. gdb_read_register() actually reads registers.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/exec/gdbstub.h |  6 ++++++
 gdbstub/gdbstub.c      | 38 ++++++++++++++++++++++++++++++--------
 2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index cbd1e6ead4..5e5789f7bb 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -38,6 +38,12 @@ int gdbserver_start(const char *port_or_device);
 
 const GDBFeature *gdb_find_static_feature(const char *xmlname);
 
+void gdb_foreach_feature(CPUState *cpu,
+                         void (* callback)(void *, const GDBFeature *, int),
+                         void *opaque);
+
+int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg, bool has_xml);
+
 void gdb_set_stop_cpu(CPUState *cpu);
 
 /* in gdbstub-xml.c, generated by scripts/feature_to_c.py */
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index caef6aabab..5f76ff7271 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -416,14 +416,32 @@ const GDBFeature *gdb_find_static_feature(const char *xmlname)
     return NULL;
 }
 
-static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
+void gdb_foreach_feature(CPUState *cpu,
+                         void (* callback)(void *, const GDBFeature *, int),
+                         void *opaque)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+    GDBRegisterState *r;
+
+    if (!cc->gdb_core_feature) {
+        return;
+    }
+
+    callback(opaque, cc->gdb_core_feature, 0);
+
+    for (r = cpu->gdb_regs; r; r = r->next) {
+        callback(opaque, r->feature, r->base_reg);
+    }
+}
+
+int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg, bool has_xml)
 {
     CPUClass *cc = CPU_GET_CLASS(cpu);
     CPUArchState *env = cpu->env_ptr;
     GDBRegisterState *r;
 
     if (reg < cc->gdb_num_core_regs) {
-        return cc->gdb_read_register(cpu, buf, reg, gdb_has_xml);
+        return cc->gdb_read_register(cpu, buf, reg, has_xml);
     }
 
     for (r = cpu->gdb_regs; r; r = r->next) {
@@ -434,14 +452,15 @@ static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
     return 0;
 }
 
-static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
+static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg,
+                              bool has_xml)
 {
     CPUClass *cc = CPU_GET_CLASS(cpu);
     CPUArchState *env = cpu->env_ptr;
     GDBRegisterState *r;
 
     if (reg < cc->gdb_num_core_regs) {
-        return cc->gdb_write_register(cpu, mem_buf, reg, gdb_has_xml);
+        return cc->gdb_write_register(cpu, mem_buf, reg, has_xml);
     }
 
     for (r = cpu->gdb_regs; r; r = r->next) {
@@ -1067,7 +1086,7 @@ static void handle_set_reg(GArray *params, void *user_ctx)
     reg_size = strlen(get_param(params, 1)->data) / 2;
     gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 1)->data, reg_size);
     gdb_write_register(gdbserver_state.g_cpu, gdbserver_state.mem_buf->data,
-                       get_param(params, 0)->val_ull);
+                       get_param(params, 0)->val_ull, gdb_has_xml);
     gdb_put_packet("OK");
 }
 
@@ -1087,7 +1106,8 @@ static void handle_get_reg(GArray *params, void *user_ctx)
 
     reg_size = gdb_read_register(gdbserver_state.g_cpu,
                                  gdbserver_state.mem_buf,
-                                 get_param(params, 0)->val_ull);
+                                 get_param(params, 0)->val_ull,
+                                 gdb_has_xml);
     if (!reg_size) {
         gdb_put_packet("E14");
         return;
@@ -1174,7 +1194,8 @@ static void handle_write_all_regs(GArray *params, void *user_ctx)
     for (reg_id = 0;
          reg_id < gdbserver_state.g_cpu->gdb_num_g_regs && len > 0;
          reg_id++) {
-        reg_size = gdb_write_register(gdbserver_state.g_cpu, registers, reg_id);
+        reg_size = gdb_write_register(gdbserver_state.g_cpu, registers, reg_id,
+                                      gdb_has_xml);
         len -= reg_size;
         registers += reg_size;
     }
@@ -1192,7 +1213,8 @@ static void handle_read_all_regs(GArray *params, void *user_ctx)
     for (reg_id = 0; reg_id < gdbserver_state.g_cpu->gdb_num_g_regs; reg_id++) {
         len += gdb_read_register(gdbserver_state.g_cpu,
                                  gdbserver_state.mem_buf,
-                                 reg_id);
+                                 reg_id,
+                                 gdb_has_xml);
     }
     g_assert(len == gdbserver_state.mem_buf->len);
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 21/24] plugins: Allow to read registers
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (19 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 20/24] gdbstub: Expose functions to read registers Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-08-14 15:05   ` Alex Bennée
  2023-07-31  8:43 ` [RFC PATCH 22/24] contrib/plugins: Allow to log registers Akihiko Odaki
                   ` (3 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

It is based on GDB protocol to ensure interface stability.

The timing of the vcpu init hook is also changed so that the hook will
get called after GDB features are initialized.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/qemu/qemu-plugin.h   | 65 ++++++++++++++++++++++++++++++++++--
 cpu.c                        | 11 ------
 hw/core/cpu-common.c         | 10 ++++++
 plugins/api.c                | 40 ++++++++++++++++++++++
 plugins/qemu-plugins.symbols |  2 ++
 5 files changed, 114 insertions(+), 14 deletions(-)

diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
index 50a9957279..214b12bfd6 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -11,6 +11,7 @@
 #ifndef QEMU_QEMU_PLUGIN_H
 #define QEMU_QEMU_PLUGIN_H
 
+#include <glib.h>
 #include <inttypes.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -51,7 +52,7 @@ typedef uint64_t qemu_plugin_id_t;
 
 extern QEMU_PLUGIN_EXPORT int qemu_plugin_version;
 
-#define QEMU_PLUGIN_VERSION 1
+#define QEMU_PLUGIN_VERSION 2
 
 /**
  * struct qemu_info_t - system information for plugins
@@ -218,8 +219,8 @@ struct qemu_plugin_insn;
  * @QEMU_PLUGIN_CB_R_REGS: callback reads the CPU's regs
  * @QEMU_PLUGIN_CB_RW_REGS: callback reads and writes the CPU's regs
  *
- * Note: currently unused, plugins cannot read or change system
- * register state.
+ * Note: currently QEMU_PLUGIN_CB_RW_REGS is unused, plugins cannot change
+ * system register state.
  */
 enum qemu_plugin_cb_flags {
     QEMU_PLUGIN_CB_NO_REGS,
@@ -664,4 +665,62 @@ uint64_t qemu_plugin_end_code(void);
  */
 uint64_t qemu_plugin_entry_code(void);
 
+/**
+ * struct qemu_plugin_register_file_t - register information
+ *
+ * This structure identifies registers. The identifiers included in this
+ * structure are identical with names used in GDB's standard target features
+ * with some extensions. For details, see:
+ * https://sourceware.org/gdb/onlinedocs/gdb/Standard-Target-Features.html
+ *
+ * A register is uniquely identified with the combination of a feature name
+ * and a register name or a register number. It is recommended to derive
+ * register numbers from feature names and register names each time a new vcpu
+ * starts.
+ *
+ * To derive the register number from a feature name and a register name,
+ * first look up qemu_plugin_register_file_t with the feature name, and then
+ * look up the register name in its @regs. The sum of the @base_reg and the
+ * index in the @reg is the register number.
+ *
+ * Note that @regs may have holes; some elements of @regs may be NULL.
+ */
+typedef struct qemu_plugin_register_file_t {
+    /** @name: feature name */
+    const char *name;
+    /** @regs: register names */
+    const char * const *regs;
+    /** @base_reg: the base identified number */
+    int base_reg;
+    /** @num_regs: the number of elements in @regs */
+    int num_regs;
+} qemu_plugin_register_file_t;
+
+/**
+ * qemu_plugin_get_register_files() - returns register information
+ *
+ * @vcpu_index: the index of the vcpu context
+ * @size: the pointer to the variable to hold the number of returned elements
+ *
+ * Returns an array of qemu_plugin_register_file_t. The user should g_free()
+ * the array once no longer needed.
+ */
+qemu_plugin_register_file_t *
+qemu_plugin_get_register_files(unsigned int vcpu_index, int *size);
+
+/**
+ * qemu_plugin_read_register() - read register
+ *
+ * @buf: the byte array to append the read register content to.
+ * @reg: the register identifier determined with
+ *       qemu_plugin_get_register_files().
+ *
+ * This function is only available in a context that register read access is
+ * explicitly requested.
+ *
+ * Returns the size of the read register. The content of @buf is in target byte
+ * order.
+ */
+int qemu_plugin_read_register(GByteArray *buf, int reg);
+
 #endif /* QEMU_QEMU_PLUGIN_H */
diff --git a/cpu.c b/cpu.c
index 1c948d1161..2552c85249 100644
--- a/cpu.c
+++ b/cpu.c
@@ -42,7 +42,6 @@
 #include "hw/core/accel-cpu.h"
 #include "trace/trace-root.h"
 #include "qemu/accel.h"
-#include "qemu/plugin.h"
 
 uintptr_t qemu_host_page_size;
 intptr_t qemu_host_page_mask;
@@ -148,11 +147,6 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
     /* Wait until cpu initialization complete before exposing cpu. */
     cpu_list_add(cpu);
 
-    /* Plugin initialization must wait until cpu_index assigned. */
-    if (tcg_enabled()) {
-        qemu_plugin_vcpu_init_hook(cpu);
-    }
-
 #ifdef CONFIG_USER_ONLY
     assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
            qdev_get_vmsd(DEVICE(cpu))->unmigratable);
@@ -179,11 +173,6 @@ void cpu_exec_unrealizefn(CPUState *cpu)
     }
 #endif
 
-    /* Call the plugin hook before clearing cpu->cpu_index in cpu_list_remove */
-    if (tcg_enabled()) {
-        qemu_plugin_vcpu_exit_hook(cpu);
-    }
-
     cpu_list_remove(cpu);
     /*
      * Now that the vCPU has been removed from the RCU list, we can call
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 549f52f46f..e06a70007a 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -211,6 +211,11 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
         cpu_resume(cpu);
     }
 
+    /* Plugin initialization must wait until the cpu is fully realized. */
+    if (tcg_enabled()) {
+        qemu_plugin_vcpu_init_hook(cpu);
+    }
+
     /* NOTE: latest generic point where the cpu is fully realized */
 }
 
@@ -218,6 +223,11 @@ static void cpu_common_unrealizefn(DeviceState *dev)
 {
     CPUState *cpu = CPU(dev);
 
+    /* Call the plugin hook before clearing the cpu is fully unrealized */
+    if (tcg_enabled()) {
+        qemu_plugin_vcpu_exit_hook(cpu);
+    }
+
     /* NOTE: latest generic point before the cpu is fully unrealized */
     cpu_exec_unrealizefn(cpu);
 }
diff --git a/plugins/api.c b/plugins/api.c
index 2078b16edb..dd7ff5067b 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -35,6 +35,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/main-loop.h"
 #include "qemu/plugin.h"
 #include "qemu/log.h"
 #include "tcg/tcg.h"
@@ -442,3 +443,42 @@ uint64_t qemu_plugin_entry_code(void)
 #endif
     return entry;
 }
+
+static void count_gdb_feature(void *opaque, const GDBFeature *feature,
+                              int base_reg)
+{
+    (*(int *)opaque)++;
+}
+
+static void map_gdb_feature(void *opaque, const GDBFeature *feature,
+                            int base_reg)
+{
+    qemu_plugin_register_file_t **cursor = opaque;
+    (*cursor)->name = feature->name;
+    (*cursor)->regs = feature->regs;
+    (*cursor)->base_reg = base_reg;
+    (*cursor)->num_regs = feature->num_regs;
+    (*cursor)++;
+}
+
+qemu_plugin_register_file_t *
+qemu_plugin_get_register_files(unsigned int vcpu_index, int *size)
+{
+    QEMU_IOTHREAD_LOCK_GUARD();
+
+    *size = 0;
+    gdb_foreach_feature(qemu_get_cpu(vcpu_index), count_gdb_feature, size);
+
+    qemu_plugin_register_file_t *files =
+        g_new(qemu_plugin_register_file_t, *size);
+
+    qemu_plugin_register_file_t *cursor = files;
+    gdb_foreach_feature(qemu_get_cpu(vcpu_index), map_gdb_feature, &cursor);
+
+    return files;
+}
+
+int qemu_plugin_read_register(GByteArray *buf, int reg)
+{
+    return gdb_read_register(current_cpu, buf, reg, true);
+}
diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols
index 71f6c90549..4ed9e70e47 100644
--- a/plugins/qemu-plugins.symbols
+++ b/plugins/qemu-plugins.symbols
@@ -42,4 +42,6 @@
   qemu_plugin_tb_vaddr;
   qemu_plugin_uninstall;
   qemu_plugin_vcpu_for_each;
+  qemu_plugin_get_register_files;
+  qemu_plugin_read_register;
 };
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 22/24] contrib/plugins: Allow to log registers
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (20 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 21/24] plugins: Allow " Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-08-14 15:21   ` Alex Bennée
  2023-07-31  8:43 ` [RFC PATCH 23/24] plugins: Support C++ Akihiko Odaki
                   ` (2 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

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

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]);
+        }
+        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);
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 23/24] plugins: Support C++
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (21 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 22/24] contrib/plugins: Allow to log registers Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-07-31  8:43 ` [RFC PATCH 24/24] contrib/plugins: Add cc plugin Akihiko Odaki
  2023-08-14 15:27 ` [RFC PATCH 00/24] plugins: Allow to read registers Alex Bennée
  24 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

Make qemu-plugin.h consumable for C++ platform.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/qemu/qemu-plugin.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
index 214b12bfd6..8637e3d8cf 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -16,6 +16,8 @@
 #include <stdbool.h>
 #include <stddef.h>
 
+G_BEGIN_DECLS
+
 /*
  * For best performance, build the plugin with -fvisibility=hidden so that
  * QEMU_PLUGIN_LOCAL is implicit. Then, just mark qemu_plugin_install with
@@ -723,4 +725,6 @@ qemu_plugin_get_register_files(unsigned int vcpu_index, int *size);
  */
 int qemu_plugin_read_register(GByteArray *buf, int reg);
 
+G_END_DECLS
+
 #endif /* QEMU_QEMU_PLUGIN_H */
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [RFC PATCH 24/24] contrib/plugins: Add cc plugin
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (22 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 23/24] plugins: Support C++ Akihiko Odaki
@ 2023-07-31  8:43 ` Akihiko Odaki
  2023-08-14 15:23   ` Alex Bennée
  2023-08-14 15:27 ` [RFC PATCH 00/24] plugins: Allow to read registers Alex Bennée
  24 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31  8:43 UTC (permalink / raw)
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x, Akihiko Odaki

This demonstrates how to write a plugin in C++.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 docs/devel/tcg-plugins.rst |  8 ++++++++
 configure                  | 15 ++++++++++++---
 contrib/plugins/Makefile   |  5 +++++
 contrib/plugins/cc.cc      | 15 +++++++++++++++
 tests/tcg/Makefile.target  |  3 +++
 5 files changed, 43 insertions(+), 3 deletions(-)
 create mode 100644 contrib/plugins/cc.cc

diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst
index c9f8b27590..0a11f8036c 100644
--- a/docs/devel/tcg-plugins.rst
+++ b/docs/devel/tcg-plugins.rst
@@ -584,6 +584,14 @@ The plugin has a number of arguments, all of them are optional:
   configuration arguments implies ``l2=on``.
   (default: N = 2097152 (2MB), B = 64, A = 16)
 
+- contrib/plugins/cc.cc
+
+cc plugin demonstrates how to write a plugin in C++. It simply outputs
+"hello, world" to the plugin log::
+
+  $ qemu-system-arm $(QEMU_ARGS) \
+    -plugin ./contrib/plugins/libcc.so -d plugin
+
 API
 ---
 
diff --git a/configure b/configure
index 26ec5e4f54..0065b0dfe0 100755
--- a/configure
+++ b/configure
@@ -293,10 +293,18 @@ else
   cc="${CC-${cross_prefix}gcc}"
 fi
 
-if test -z "${CXX}${cross_prefix}"; then
-  cxx="c++"
+if test -n "${CXX+x}"; then
+  cxx="$CXX"
 else
-  cxx="${CXX-${cross_prefix}g++}"
+  if test -n "${cross_prefix}"; then
+    cxx="${cross_prefix}g++"
+  else
+    cxx="c++"
+  fi
+
+  if ! has "$cxx"; then
+    cxx=
+  fi
 fi
 
 # Preferred ObjC compiler:
@@ -1702,6 +1710,7 @@ echo "MESON=$meson" >> $config_host_mak
 echo "NINJA=$ninja" >> $config_host_mak
 echo "PKG_CONFIG=${pkg_config}" >> $config_host_mak
 echo "CC=$cc" >> $config_host_mak
+echo "CXX=$cxx" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
 
 # use included Linux headers
diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
index b2b9db9f51..93d86b3d07 100644
--- a/contrib/plugins/Makefile
+++ b/contrib/plugins/Makefile
@@ -21,6 +21,9 @@ NAMES += lockstep
 NAMES += hwprofile
 NAMES += cache
 NAMES += drcov
+ifneq ($(CXX),)
+NAMES += cc
+endif
 
 SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
 
@@ -31,6 +34,8 @@ CFLAGS += -fPIC -Wall
 CFLAGS += $(if $(CONFIG_DEBUG_TCG), -ggdb -O0)
 CFLAGS += -I$(SRC_PATH)/include/qemu
 
+CXXFLAGS := $(CFLAGS)
+
 all: $(SONAMES)
 
 %.o: %.c
diff --git a/contrib/plugins/cc.cc b/contrib/plugins/cc.cc
new file mode 100644
index 0000000000..e7270d7adc
--- /dev/null
+++ b/contrib/plugins/cc.cc
@@ -0,0 +1,15 @@
+#include <qemu-plugin.h>
+
+extern "C" {
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
+                                           const qemu_info_t *info, int argc,
+                                           char **argv)
+{
+    qemu_plugin_outs("hello, world\n");
+    return 0;
+}
+
+};
diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target
index 462289f47c..3d7837d3b8 100644
--- a/tests/tcg/Makefile.target
+++ b/tests/tcg/Makefile.target
@@ -149,6 +149,9 @@ PLUGIN_SRC=$(SRC_PATH)/tests/plugin
 PLUGIN_LIB=../../plugin
 VPATH+=$(PLUGIN_LIB)
 PLUGINS=$(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c)))
+ifneq ($(CXX),)
+PLUGINS+=$(patsubst %.cc, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.cc)))
+endif
 
 # We need to ensure expand the run-plugin-TEST-with-PLUGIN
 # pre-requistes manually here as we can't use stems to handle it. We
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  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-14 13:19   ` Alex Bennée
  2 siblings, 1 reply; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-31 13:27 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 31/7/23 10:43, Akihiko Odaki wrote:
> This is a tree-wide change to replace gdb_core_xml_file, the path to
> GDB XML file with gdb_core_feature, the pointer to GDBFeature. This
> also replaces the values assigned to gdb_num_core_regs with the
> num_regs member of GDBFeature where applicable to remove magic numbers.
> 
> A following change will utilize additional information provided by
> GDBFeature to simplify XML file lookup.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   include/hw/core/cpu.h   | 5 +++--
>   target/s390x/cpu.h      | 2 --
>   gdbstub/gdbstub.c       | 6 +++---
>   target/arm/cpu.c        | 4 ++--
>   target/arm/cpu64.c      | 4 ++--
>   target/arm/tcg/cpu32.c  | 3 ++-
>   target/avr/cpu.c        | 4 ++--
>   target/hexagon/cpu.c    | 2 +-
>   target/i386/cpu.c       | 7 +++----
>   target/loongarch/cpu.c  | 4 ++--
>   target/m68k/cpu.c       | 7 ++++---
>   target/microblaze/cpu.c | 4 ++--
>   target/ppc/cpu_init.c   | 4 ++--
>   target/riscv/cpu.c      | 7 ++++---
>   target/rx/cpu.c         | 4 ++--
>   target/s390x/cpu.c      | 4 ++--
>   16 files changed, 36 insertions(+), 35 deletions(-)


> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index d71a162070..a206ab6b1b 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -2353,7 +2353,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>   #ifndef CONFIG_USER_ONLY
>       cc->sysemu_ops = &arm_sysemu_ops;
>   #endif
> -    cc->gdb_num_core_regs = 26;
>       cc->gdb_arch_name = arm_gdb_arch_name;
>       cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
>       cc->gdb_stop_before_watchpoint = true;
> @@ -2378,7 +2377,8 @@ static void cpu_register_class_init(ObjectClass *oc, void *data)
>       CPUClass *cc = CPU_CLASS(acc);
>   
>       acc->info = data;
> -    cc->gdb_core_xml_file = "arm-core.xml";
> +    cc->gdb_core_feature = gdb_find_static_feature("arm-core.xml");

Can we have:

   cc->gdb_core_feature = gdb_find_static_feature(cc->gdb_core_xml_file);

once in hw/core/cpu-common.c::cpu_class_init()?

(haven't verified, just wondering)

> +    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
>   }




^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 02/24] gdbstub: Introduce GDBFeature structure
  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
  2 siblings, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-31 13:34 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 31/7/23 10:43, Akihiko Odaki wrote:
> Before this change, the information from a XML file was stored in an
> array that is not descriptive. Introduce a dedicated structure type to
> make it easier to understand and to extend with more fields.

Great idea!

> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   MAINTAINERS             |  2 +-
>   meson.build             |  2 +-
>   include/exec/gdbstub.h  |  9 ++++--
>   gdbstub/gdbstub.c       |  4 +--
>   stubs/gdbstub.c         |  6 ++--
>   scripts/feature_to_c.py | 44 ++++++++++++++++++++++++++
>   scripts/feature_to_c.sh | 69 -----------------------------------------
>   7 files changed, 58 insertions(+), 78 deletions(-)
>   create mode 100755 scripts/feature_to_c.py
>   delete mode 100644 scripts/feature_to_c.sh


> diff --git a/scripts/feature_to_c.py b/scripts/feature_to_c.py
> new file mode 100755
> index 0000000000..5a5b49367b
> --- /dev/null
> +++ b/scripts/feature_to_c.py
> @@ -0,0 +1,44 @@

SPDX-License-Identifier: GPL-2.0-or-later ?

> +#!/usr/bin/env python3
> +
> +import os, sys
> +
> +def writeliteral(indent, bytes):
> +    sys.stdout.write(' ' * indent)
> +    sys.stdout.write('"')
> +    quoted = True
> +
> +    for c in bytes:
> +        if not quoted:
> +            sys.stdout.write('\n')
> +            sys.stdout.write(' ' * indent)
> +            sys.stdout.write('"')
> +            quoted = True
> +
> +        if c == b'"'[0]:
> +            sys.stdout.write('\\"')
> +        elif c == b'\\'[0]:
> +            sys.stdout.write('\\\\')
> +        elif c == b'\n'[0]:
> +            sys.stdout.write('\\n"')
> +            quoted = False
> +        elif c >= 32 and c < 127:
> +            sys.stdout.write(c.to_bytes(1, 'big').decode())
> +        else:
> +            sys.stdout.write(f'\{c:03o}')
> +
> +    if quoted:
> +        sys.stdout.write('"')
> +
> +sys.stdout.write('#include "qemu/osdep.h"\n#include "exec/gdbstub.h"\n\nconst GDBFeature gdb_features[] = {\n')

Preferably split in 3 calls for readability, otherwise:

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 03/24] gdbstub: Add num_regs member to GDBFeature
  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
  1 sibling, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-31 13:35 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 31/7/23 10:43, Akihiko Odaki wrote:
> Currently the number of registers exposed to GDB is written as magic
> numbers in code. Derive the number of registers GDB actually see from
> XML files to replace the magic numbers in code later.

Nice :)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   include/exec/gdbstub.h  |  1 +
>   scripts/feature_to_c.py | 46 +++++++++++++++++++++++++++++++++++++++--
>   2 files changed, 45 insertions(+), 2 deletions(-)



^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  2023-07-31 13:27   ` Philippe Mathieu-Daudé
@ 2023-07-31 13:37     ` Akihiko Odaki
  0 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31 13:37 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/07/31 22:27, Philippe Mathieu-Daudé wrote:
> On 31/7/23 10:43, Akihiko Odaki wrote:
>> This is a tree-wide change to replace gdb_core_xml_file, the path to
>> GDB XML file with gdb_core_feature, the pointer to GDBFeature. This
>> also replaces the values assigned to gdb_num_core_regs with the
>> num_regs member of GDBFeature where applicable to remove magic numbers.
>>
>> A following change will utilize additional information provided by
>> GDBFeature to simplify XML file lookup.
>>
>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>> ---
>>   include/hw/core/cpu.h   | 5 +++--
>>   target/s390x/cpu.h      | 2 --
>>   gdbstub/gdbstub.c       | 6 +++---
>>   target/arm/cpu.c        | 4 ++--
>>   target/arm/cpu64.c      | 4 ++--
>>   target/arm/tcg/cpu32.c  | 3 ++-
>>   target/avr/cpu.c        | 4 ++--
>>   target/hexagon/cpu.c    | 2 +-
>>   target/i386/cpu.c       | 7 +++----
>>   target/loongarch/cpu.c  | 4 ++--
>>   target/m68k/cpu.c       | 7 ++++---
>>   target/microblaze/cpu.c | 4 ++--
>>   target/ppc/cpu_init.c   | 4 ++--
>>   target/riscv/cpu.c      | 7 ++++---
>>   target/rx/cpu.c         | 4 ++--
>>   target/s390x/cpu.c      | 4 ++--
>>   16 files changed, 36 insertions(+), 35 deletions(-)
> 
> 
>> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
>> index d71a162070..a206ab6b1b 100644
>> --- a/target/arm/cpu.c
>> +++ b/target/arm/cpu.c
>> @@ -2353,7 +2353,6 @@ static void arm_cpu_class_init(ObjectClass *oc, 
>> void *data)
>>   #ifndef CONFIG_USER_ONLY
>>       cc->sysemu_ops = &arm_sysemu_ops;
>>   #endif
>> -    cc->gdb_num_core_regs = 26;
>>       cc->gdb_arch_name = arm_gdb_arch_name;
>>       cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
>>       cc->gdb_stop_before_watchpoint = true;
>> @@ -2378,7 +2377,8 @@ static void cpu_register_class_init(ObjectClass 
>> *oc, void *data)
>>       CPUClass *cc = CPU_CLASS(acc);
>>       acc->info = data;
>> -    cc->gdb_core_xml_file = "arm-core.xml";
>> +    cc->gdb_core_feature = gdb_find_static_feature("arm-core.xml");
> 
> Can we have:
> 
>    cc->gdb_core_feature = gdb_find_static_feature(cc->gdb_core_xml_file);
> 
> once in hw/core/cpu-common.c::cpu_class_init()?
> 
> (haven't verified, just wondering)

Unfortunately no, cpu_class_init() earlier than this line. Also the 
feature needs to be resolved here because the next line refers to it.

> 
>> +    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
>>   }
> 
> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 07/24] target/arm: Use GDBFeature for dynamic XML
  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
  1 sibling, 1 reply; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-31 13:44 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 31/7/23 10:43, Akihiko Odaki wrote:
> In preparation for a change to use GDBFeature as a parameter of
> gdb_register_coprocessor(), convert the internal representation of
> dynamic feature from plain XML to GDBFeature.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   target/arm/cpu.h       | 20 +++++------
>   target/arm/internals.h |  2 +-
>   target/arm/gdbstub.c   | 80 +++++++++++++++++++++++-------------------
>   target/arm/gdbstub64.c | 11 +++---
>   4 files changed, 60 insertions(+), 53 deletions(-)
> 
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 88e5accda6..d6c2378d05 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -136,23 +136,21 @@ enum {
>    */
>   
>   /**
> - * DynamicGDBXMLInfo:
> - * @desc: Contains the XML descriptions.
> - * @num: Number of the registers in this XML seen by GDB.
> + * DynamicGDBFeatureInfo:
> + * @desc: Contains the feature descriptions.
>    * @data: A union with data specific to the set of registers
>    *    @cpregs_keys: Array that contains the corresponding Key of
>    *                  a given cpreg with the same order of the cpreg
>    *                  in the XML description.
>    */
> -typedef struct DynamicGDBXMLInfo {
> -    char *desc;
> -    int num;
> +typedef struct DynamicGDBFeatureInfo {
> +    GDBFeature desc;
>       union {
>           struct {
>               uint32_t *keys;
>           } cpregs;
>       } data;
> -} DynamicGDBXMLInfo;
> +} DynamicGDBFeatureInfo;
>   
>   /* CPU state for each instance of a generic timer (in cp15 c14) */
>   typedef struct ARMGenericTimer {
> @@ -881,10 +879,10 @@ struct ArchCPU {
>       uint64_t *cpreg_vmstate_values;
>       int32_t cpreg_vmstate_array_len;
>   
> -    DynamicGDBXMLInfo dyn_sysreg_xml;
> -    DynamicGDBXMLInfo dyn_svereg_xml;
> -    DynamicGDBXMLInfo dyn_m_systemreg_xml;
> -    DynamicGDBXMLInfo dyn_m_secextreg_xml;
> +    DynamicGDBFeatureInfo dyn_sysreg_feature;
> +    DynamicGDBFeatureInfo dyn_svereg_feature;
> +    DynamicGDBFeatureInfo dyn_m_systemreg_feature;
> +    DynamicGDBFeatureInfo dyn_m_secextreg_feature;

Since now DynamicGDBFeatureInfo.desc contains xmlname, we can replace
all these by a generic 'DynamicGDBFeatureInfo *dyn_features' and have
arm_gdb_get_dynamic_xml() looking up the xmlname.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> @@ -489,14 +497,14 @@ const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
>       ARMCPU *cpu = ARM_CPU(cs);
>   
>       if (strcmp(xmlname, "system-registers.xml") == 0) {
> -        return cpu->dyn_sysreg_xml.desc;
> +        return cpu->dyn_sysreg_feature.desc.xml;
>       } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
> -        return cpu->dyn_svereg_xml.desc;
> +        return cpu->dyn_svereg_feature.desc.xml;
>       } else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
> -        return cpu->dyn_m_systemreg_xml.desc;
> +        return cpu->dyn_m_systemreg_feature.desc.xml;
>   #ifndef CONFIG_USER_ONLY
>       } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
> -        return cpu->dyn_m_secextreg_xml.desc;
> +        return cpu->dyn_m_secextreg_feature.desc.xml;
>   #endif
>       }
>       return NULL;



^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 08/24] target/ppc: Use GDBFeature for dynamic XML
  2023-07-31  8:43 ` [RFC PATCH 08/24] target/ppc: " Akihiko Odaki
@ 2023-07-31 13:45   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-31 13:45 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 31/7/23 10:43, Akihiko Odaki wrote:
> In preparation for a change to use GDBFeature as a parameter of
> gdb_register_coprocessor(), convert the internal representation of
> dynamic feature from plain XML to GDBFeature.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   target/ppc/cpu-qom.h  |  3 +--
>   target/ppc/cpu.h      |  2 +-
>   target/ppc/cpu_init.c |  2 +-
>   target/ppc/gdbstub.c  | 13 +++++++------
>   4 files changed, 10 insertions(+), 10 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 09/24] target/riscv: Use GDBFeature for dynamic XML
  2023-07-31  8:43 ` [RFC PATCH 09/24] target/riscv: " Akihiko Odaki
@ 2023-07-31 13:46   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-31 13:46 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 31/7/23 10:43, Akihiko Odaki wrote:
> In preparation for a change to use GDBFeature as a parameter of
> gdb_register_coprocessor(), convert the internal representation of
> dynamic feature from plain XML to GDBFeature.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   target/riscv/cpu.h     |  4 ++--
>   target/riscv/cpu.c     |  4 ++--
>   target/riscv/gdbstub.c | 25 ++++++++++++++-----------
>   3 files changed, 18 insertions(+), 15 deletions(-)
> 
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 6ea22e0eea..f67751d5b7 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -391,8 +391,8 @@ struct ArchCPU {
>       CPUNegativeOffsetState neg;
>       CPURISCVState env;
>   
> -    char *dyn_csr_xml;
> -    char *dyn_vreg_xml;
> +    GDBFeature dyn_csr_feature;
> +    GDBFeature dyn_vreg_feature;

Similar comment that ARM (dyn_features array).

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 02/24] gdbstub: Introduce GDBFeature structure
  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
  2 siblings, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-31 13:51 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 31/7/23 10:43, Akihiko Odaki wrote:
> Before this change, the information from a XML file was stored in an
> array that is not descriptive. Introduce a dedicated structure type to
> make it easier to understand and to extend with more fields.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   MAINTAINERS             |  2 +-
>   meson.build             |  2 +-
>   include/exec/gdbstub.h  |  9 ++++--
>   gdbstub/gdbstub.c       |  4 +--
>   stubs/gdbstub.c         |  6 ++--
>   scripts/feature_to_c.py | 44 ++++++++++++++++++++++++++
>   scripts/feature_to_c.sh | 69 -----------------------------------------
>   7 files changed, 58 insertions(+), 78 deletions(-)
>   create mode 100755 scripts/feature_to_c.py
>   delete mode 100644 scripts/feature_to_c.sh


> diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
> index 7d743fe1e9..bd5bc91dda 100644
> --- a/include/exec/gdbstub.h
> +++ b/include/exec/gdbstub.h
> @@ -10,6 +10,11 @@
>   #define GDB_WATCHPOINT_READ      3
>   #define GDB_WATCHPOINT_ACCESS    4
>   
> +typedef struct GDBFeature {
> +    const char *xmlname;
> +    const char *xml;
> +} GDBFeature;
> +
>   
>   /* Get or set a register.  Returns the size of the register.  */
>   typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
> @@ -38,7 +43,7 @@ void gdb_set_stop_cpu(CPUState *cpu);
>    */
>   extern bool gdb_has_xml;
>   
> -/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
> -extern const char *const xml_builtin[][2];
> +/* in gdbstub-xml.c, generated by scripts/feature_to_c.py */
> +extern const GDBFeature gdb_features[];
Maybe clearer named gdb_static_features[].


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 04/24] gdbstub: Introduce gdb_find_static_feature()
  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
  1 sibling, 0 replies; 61+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-31 13:52 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 31/7/23 10:43, Akihiko Odaki wrote:
> This function is useful to determine the number of registers exposed to
> GDB from the XML name.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>   include/exec/gdbstub.h |  2 ++
>   gdbstub/gdbstub.c      | 13 +++++++++++++
>   2 files changed, 15 insertions(+)
> 
> diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
> index 22e5add5b1..3115dc21c0 100644
> --- a/include/exec/gdbstub.h
> +++ b/include/exec/gdbstub.h
> @@ -34,6 +34,8 @@ void gdb_register_coprocessor(CPUState *cpu,
>    */
>   int gdbserver_start(const char *port_or_device);
>   
> +const GDBFeature *gdb_find_static_feature(const char *xmlname);
> +
>   void gdb_set_stop_cpu(CPUState *cpu);
>   
>   /**
> diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
> index fad70200d8..6d9cef5b95 100644
> --- a/gdbstub/gdbstub.c
> +++ b/gdbstub/gdbstub.c
> @@ -414,6 +414,19 @@ static const char *get_feature_xml(const char *p, const char **newp,
>       return name ? gdb_features[i].xml : NULL;
>   }
>   
> +const GDBFeature *gdb_find_static_feature(const char *xmlname)
> +{
> +    const GDBFeature *feature;

Alternatively (in case you consider the suggestion to use array
of dyn_features):

const GDBFeature *gdb_find_feature(const GDBFeature *gdb_features,
                                    const char *xmlname)
{
     const GDBFeature *feature;
     const GDBFeature *features = gdb_features ?: gdb_static_features;

> +    for (feature = gdb_features; feature->xmlname; feature++) {
> +        if (!strcmp(feature->xmlname, xmlname)) {
> +            return feature;
> +        }
> +    }
> +
> +    return NULL;
> +}

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 07/24] target/arm: Use GDBFeature for dynamic XML
  2023-07-31 13:44   ` Philippe Mathieu-Daudé
@ 2023-07-31 14:00     ` Akihiko Odaki
  0 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-07-31 14:00 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Paolo Bonzini, Alex Bennée, Thomas Huth, Alexandre Iooss,
	Mahmoud Mandour, Eduardo Habkost, Marcel Apfelbaum, Yanan Wang,
	Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/07/31 22:44, Philippe Mathieu-Daudé wrote:
> On 31/7/23 10:43, Akihiko Odaki wrote:
>> In preparation for a change to use GDBFeature as a parameter of
>> gdb_register_coprocessor(), convert the internal representation of
>> dynamic feature from plain XML to GDBFeature.
>>
>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>> ---
>>   target/arm/cpu.h       | 20 +++++------
>>   target/arm/internals.h |  2 +-
>>   target/arm/gdbstub.c   | 80 +++++++++++++++++++++++-------------------
>>   target/arm/gdbstub64.c | 11 +++---
>>   4 files changed, 60 insertions(+), 53 deletions(-)
>>
>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
>> index 88e5accda6..d6c2378d05 100644
>> --- a/target/arm/cpu.h
>> +++ b/target/arm/cpu.h
>> @@ -136,23 +136,21 @@ enum {
>>    */
>>   /**
>> - * DynamicGDBXMLInfo:
>> - * @desc: Contains the XML descriptions.
>> - * @num: Number of the registers in this XML seen by GDB.
>> + * DynamicGDBFeatureInfo:
>> + * @desc: Contains the feature descriptions.
>>    * @data: A union with data specific to the set of registers
>>    *    @cpregs_keys: Array that contains the corresponding Key of
>>    *                  a given cpreg with the same order of the cpreg
>>    *                  in the XML description.
>>    */
>> -typedef struct DynamicGDBXMLInfo {
>> -    char *desc;
>> -    int num;
>> +typedef struct DynamicGDBFeatureInfo {
>> +    GDBFeature desc;
>>       union {
>>           struct {
>>               uint32_t *keys;
>>           } cpregs;
>>       } data;
>> -} DynamicGDBXMLInfo;
>> +} DynamicGDBFeatureInfo;
>>   /* CPU state for each instance of a generic timer (in cp15 c14) */
>>   typedef struct ARMGenericTimer {
>> @@ -881,10 +879,10 @@ struct ArchCPU {
>>       uint64_t *cpreg_vmstate_values;
>>       int32_t cpreg_vmstate_array_len;
>> -    DynamicGDBXMLInfo dyn_sysreg_xml;
>> -    DynamicGDBXMLInfo dyn_svereg_xml;
>> -    DynamicGDBXMLInfo dyn_m_systemreg_xml;
>> -    DynamicGDBXMLInfo dyn_m_secextreg_xml;
>> +    DynamicGDBFeatureInfo dyn_sysreg_feature;
>> +    DynamicGDBFeatureInfo dyn_svereg_feature;
>> +    DynamicGDBFeatureInfo dyn_m_systemreg_feature;
>> +    DynamicGDBFeatureInfo dyn_m_secextreg_feature;
> 
> Since now DynamicGDBFeatureInfo.desc contains xmlname, we can replace
> all these by a generic 'DynamicGDBFeatureInfo *dyn_features' and have
> arm_gdb_get_dynamic_xml() looking up the xmlname.

In patch 12, cpu-specific gdb_get_dynamic_xml() function is removed, and 
gdbstub instead looks up an internal list it holds.

> 
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> 
>> @@ -489,14 +497,14 @@ const char *arm_gdb_get_dynamic_xml(CPUState 
>> *cs, const char *xmlname)
>>       ARMCPU *cpu = ARM_CPU(cs);
>>       if (strcmp(xmlname, "system-registers.xml") == 0) {
>> -        return cpu->dyn_sysreg_xml.desc;
>> +        return cpu->dyn_sysreg_feature.desc.xml;
>>       } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
>> -        return cpu->dyn_svereg_xml.desc;
>> +        return cpu->dyn_svereg_feature.desc.xml;
>>       } else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
>> -        return cpu->dyn_m_systemreg_xml.desc;
>> +        return cpu->dyn_m_systemreg_feature.desc.xml;
>>   #ifndef CONFIG_USER_ONLY
>>       } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
>> -        return cpu->dyn_m_secextreg_xml.desc;
>> +        return cpu->dyn_m_secextreg_feature.desc.xml;
>>   #endif
>>       }
>>       return NULL;
> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 01/24] contrib/plugins: Use GRWLock in execlog
  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
  0 siblings, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 10:48 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> execlog had the following comment:
>> As we could have multiple threads trying to do this we need to
>> serialise the expansion under a lock. Threads accessing already
>> created entries can continue without issue even if the ptr array
>> gets reallocated during resize.
>
> However, when the ptr array gets reallocated, the other threads may have
> a stale reference to the old buffer. This results in use-after-free.
>
> Use GRWLock to properly fix this issue.
>
> Fixes: 3d7caf145e ("contrib/plugins: add execlog to log instruction execution and memory access")
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 02/24] gdbstub: Introduce GDBFeature structure
  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
  2 siblings, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 11:33 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> Before this change, the information from a XML file was stored in an
> array that is not descriptive. Introduce a dedicated structure type to
> make it easier to understand and to extend with more fields.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>

with Phillipe's suggested updates:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 03/24] gdbstub: Add num_regs member to GDBFeature
  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
  1 sibling, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 11:44 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> Currently the number of registers exposed to GDB is written as magic
> numbers in code. Derive the number of registers GDB actually see from
> XML files to replace the magic numbers in code later.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 04/24] gdbstub: Introduce gdb_find_static_feature()
  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
  1 sibling, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 11:56 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> This function is useful to determine the number of registers exposed to
> GDB from the XML name.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  include/exec/gdbstub.h |  2 ++
>  gdbstub/gdbstub.c      | 13 +++++++++++++
>  2 files changed, 15 insertions(+)
>
> diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
> index 22e5add5b1..3115dc21c0 100644
> --- a/include/exec/gdbstub.h
> +++ b/include/exec/gdbstub.h
> @@ -34,6 +34,8 @@ void gdb_register_coprocessor(CPUState *cpu,
>   */
>  int gdbserver_start(const char *port_or_device);
>  
> +const GDBFeature *gdb_find_static_feature(const char *xmlname);
> +
>  void gdb_set_stop_cpu(CPUState *cpu);
>  
>  /**
> diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
> index fad70200d8..6d9cef5b95 100644
> --- a/gdbstub/gdbstub.c
> +++ b/gdbstub/gdbstub.c
> @@ -414,6 +414,19 @@ static const char *get_feature_xml(const char *p, const char **newp,
>      return name ? gdb_features[i].xml : NULL;
>  }
>  
> +const GDBFeature *gdb_find_static_feature(const char *xmlname)
> +{
> +    const GDBFeature *feature;
> +
> +    for (feature = gdb_features; feature->xmlname; feature++) {
> +        if (!strcmp(feature->xmlname, xmlname)) {

I'd prefer g_strcmp0(feature->xmlname, xmlname) == 0 but either way:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  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-08-14 11:59   ` Alex Bennée
  2023-08-16 13:47     ` Akihiko Odaki
  2023-08-14 13:19   ` Alex Bennée
  2 siblings, 1 reply; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 11:59 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> This is a tree-wide change to replace gdb_core_xml_file, the path to
> GDB XML file with gdb_core_feature, the pointer to GDBFeature. This
> also replaces the values assigned to gdb_num_core_regs with the
> num_regs member of GDBFeature where applicable to remove magic numbers.
>
> A following change will utilize additional information provided by
> GDBFeature to simplify XML file lookup.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  include/hw/core/cpu.h   | 5 +++--
>  target/s390x/cpu.h      | 2 --
>  gdbstub/gdbstub.c       | 6 +++---
>  target/arm/cpu.c        | 4 ++--
>  target/arm/cpu64.c      | 4 ++--
>  target/arm/tcg/cpu32.c  | 3 ++-
>  target/avr/cpu.c        | 4 ++--
>  target/hexagon/cpu.c    | 2 +-
>  target/i386/cpu.c       | 7 +++----
>  target/loongarch/cpu.c  | 4 ++--
>  target/m68k/cpu.c       | 7 ++++---
>  target/microblaze/cpu.c | 4 ++--
>  target/ppc/cpu_init.c   | 4 ++--
>  target/riscv/cpu.c      | 7 ++++---
>  target/rx/cpu.c         | 4 ++--
>  target/s390x/cpu.c      | 4 ++--
>  16 files changed, 36 insertions(+), 35 deletions(-)
>
> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> index fdcbe87352..84219c1885 100644
> --- a/include/hw/core/cpu.h
> +++ b/include/hw/core/cpu.h
> @@ -23,6 +23,7 @@
>  #include "hw/qdev-core.h"
>  #include "disas/dis-asm.h"
>  #include "exec/cpu-common.h"
> +#include "exec/gdbstub.h"
>  #include "exec/hwaddr.h"
>  #include "exec/memattrs.h"
>  #include "qapi/qapi-types-run-state.h"
> @@ -127,7 +128,7 @@ struct SysemuCPUOps;
>   *       breakpoint.  Used by AVR to handle a gdb mis-feature with
>   *       its Harvard architecture split code and data.
>   * @gdb_num_core_regs: Number of core registers accessible to GDB.

It seems redundant to have this when gdb_core_features already
encapsulates this, especially since...

> - * @gdb_core_xml_file: File name for core registers GDB XML description.
> + * @gdb_core_feature: GDB core feature description.
>   * @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
>   *           before the insn which triggers a watchpoint rather than after it.
>   * @gdb_arch_name: Optional callback that returns the architecture name known
> @@ -163,7 +164,7 @@ struct CPUClass {
>      int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
>      vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
>  
> -    const char *gdb_core_xml_file;
> +    const GDBFeature *gdb_core_feature;
>      gchar * (*gdb_arch_name)(CPUState *cpu);
>      const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
>  
<snip>
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index d71a162070..a206ab6b1b 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -2353,7 +2353,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>  #ifndef CONFIG_USER_ONLY
>      cc->sysemu_ops = &arm_sysemu_ops;
>  #endif
> -    cc->gdb_num_core_regs = 26;
>      cc->gdb_arch_name = arm_gdb_arch_name;
>      cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
>      cc->gdb_stop_before_watchpoint = true;
> @@ -2378,7 +2377,8 @@ static void cpu_register_class_init(ObjectClass *oc, void *data)
>      CPUClass *cc = CPU_CLASS(acc);
>  
>      acc->info = data;
> -    cc->gdb_core_xml_file = "arm-core.xml";
> +    cc->gdb_core_feature = gdb_find_static_feature("arm-core.xml");
> +    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;

You are doing assignments like this. I think something like this in
gdbstub:

modified   gdbstub/gdbstub.c
@@ -440,7 +440,7 @@ int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg, bool has_xml)
     CPUArchState *env = cpu->env_ptr;
     GDBRegisterState *r;
 
-    if (reg < cc->gdb_num_core_regs) {
+    if (reg < cc->gdb_core_feature->num_regs) {
         return cc->gdb_read_register(cpu, buf, reg, has_xml);
     }
 
@@ -459,7 +459,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg,
     CPUArchState *env = cpu->env_ptr;
     GDBRegisterState *r;
 
-    if (reg < cc->gdb_num_core_regs) {
+    if (reg < cc->gdb_core_feature->num_regs) {
         return cc->gdb_write_register(cpu, mem_buf, reg, has_xml);
     }

makes most of the uses go away. Some of the other arches might need
target specific tweaks.

<snip>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 07/24] target/arm: Use GDBFeature for dynamic XML
  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-08-14 13:01   ` Alex Bennée
  1 sibling, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 13:01 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> In preparation for a change to use GDBFeature as a parameter of
> gdb_register_coprocessor(), convert the internal representation of
> dynamic feature from plain XML to GDBFeature.

FWIW one of the aims I had with my stalled rewrite of the register API
was to move all this XML generation into common code:

  https://github.com/qemu/qemu/compare/master...stsquad:qemu:introspection/registers#diff-f6409265629976beb19cc9b8d96889b67c006a265586615f491e7d59dd83dc44R68

to avoid each of the targets having to mess with constructing their own
XML and just concentrate of the semantics of each register type.

>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  target/arm/cpu.h       | 20 +++++------
>  target/arm/internals.h |  2 +-
>  target/arm/gdbstub.c   | 80 +++++++++++++++++++++++-------------------
>  target/arm/gdbstub64.c | 11 +++---
>  4 files changed, 60 insertions(+), 53 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 88e5accda6..d6c2378d05 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -136,23 +136,21 @@ enum {
>   */
>  
>  /**
> - * DynamicGDBXMLInfo:
> - * @desc: Contains the XML descriptions.
> - * @num: Number of the registers in this XML seen by GDB.
> + * DynamicGDBFeatureInfo:
> + * @desc: Contains the feature descriptions.
>   * @data: A union with data specific to the set of registers
>   *    @cpregs_keys: Array that contains the corresponding Key of
>   *                  a given cpreg with the same order of the cpreg
>   *                  in the XML description.
>   */
> -typedef struct DynamicGDBXMLInfo {
> -    char *desc;
> -    int num;
> +typedef struct DynamicGDBFeatureInfo {
> +    GDBFeature desc;
>      union {
>          struct {
>              uint32_t *keys;
>          } cpregs;
>      } data;
> -} DynamicGDBXMLInfo;
> +} DynamicGDBFeatureInfo;
>  
>  /* CPU state for each instance of a generic timer (in cp15 c14) */
>  typedef struct ARMGenericTimer {
> @@ -881,10 +879,10 @@ struct ArchCPU {
>      uint64_t *cpreg_vmstate_values;
>      int32_t cpreg_vmstate_array_len;
>  
> -    DynamicGDBXMLInfo dyn_sysreg_xml;
> -    DynamicGDBXMLInfo dyn_svereg_xml;
> -    DynamicGDBXMLInfo dyn_m_systemreg_xml;
> -    DynamicGDBXMLInfo dyn_m_secextreg_xml;
> +    DynamicGDBFeatureInfo dyn_sysreg_feature;
> +    DynamicGDBFeatureInfo dyn_svereg_feature;
> +    DynamicGDBFeatureInfo dyn_m_systemreg_feature;
> +    DynamicGDBFeatureInfo dyn_m_secextreg_feature;
>  
>      /* Timers used by the generic (architected) timer */
>      QEMUTimer *gt_timer[NUM_GTIMERS];
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 0f01bc32a8..8421a755af 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -1388,7 +1388,7 @@ static inline uint64_t pmu_counter_mask(CPUARMState *env)
>  }
>  
>  #ifdef TARGET_AARCH64
> -int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
> +GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cpu, int base_reg);
>  int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray *buf, int reg);
>  int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg);
>  int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg);
> diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
> index f421c5d041..cd35bac013 100644
> --- a/target/arm/gdbstub.c
> +++ b/target/arm/gdbstub.c
> @@ -25,11 +25,11 @@
>  #include "internals.h"
>  #include "cpregs.h"
>  
> -typedef struct RegisterSysregXmlParam {
> +typedef struct RegisterSysregFeatureParam {
>      CPUState *cs;
>      GString *s;
>      int n;
> -} RegisterSysregXmlParam;
> +} RegisterSysregFeatureParam;
>  
>  /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
>     whatever the target description contains.  Due to a historical mishap
> @@ -243,7 +243,7 @@ static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
>      const ARMCPRegInfo *ri;
>      uint32_t key;
>  
> -    key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
> +    key = cpu->dyn_sysreg_feature.data.cpregs.keys[reg];
>      ri = get_arm_cp_reginfo(cpu->cp_regs, key);
>      if (ri) {
>          if (cpreg_field_is_64bit(ri)) {
> @@ -260,7 +260,8 @@ static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
>      return 0;
>  }
>  
> -static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
> +static void arm_gen_one_feature_sysreg(GString *s,
> +                                       DynamicGDBFeatureInfo *dyn_feature,
>                                         ARMCPRegInfo *ri, uint32_t ri_key,
>                                         int bitsize, int regnum)
>  {
> @@ -268,25 +269,25 @@ static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
>      g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
>      g_string_append_printf(s, " regnum=\"%d\"", regnum);
>      g_string_append_printf(s, " group=\"cp_regs\"/>");
> -    dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
> -    dyn_xml->num++;
> +    dyn_feature->data.cpregs.keys[dyn_feature->desc.num_regs] = ri_key;
> +    dyn_feature->desc.num_regs++;
>  }
>  
> -static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
> -                                        gpointer p)
> +static void arm_register_sysreg_for_feature(gpointer key, gpointer value,
> +                                            gpointer p)
>  {
>      uint32_t ri_key = (uintptr_t)key;
>      ARMCPRegInfo *ri = value;
> -    RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
> +    RegisterSysregFeatureParam *param = (RegisterSysregFeatureParam *)p;
>      GString *s = param->s;
>      ARMCPU *cpu = ARM_CPU(param->cs);
>      CPUARMState *env = &cpu->env;
> -    DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
> +    DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
>  
>      if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
>          if (arm_feature(env, ARM_FEATURE_AARCH64)) {
>              if (ri->state == ARM_CP_STATE_AA64) {
> -                arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
> +                arm_gen_one_feature_sysreg(s , dyn_feature, ri, ri_key, 64,
>                                             param->n++);
>              }
>          } else {
> @@ -296,10 +297,10 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
>                      return;
>                  }
>                  if (ri->type & ARM_CP_64BIT) {
> -                    arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
> +                    arm_gen_one_feature_sysreg(s , dyn_feature, ri, ri_key, 64,
>                                                 param->n++);
>                  } else {
> -                    arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
> +                    arm_gen_one_feature_sysreg(s , dyn_feature, ri, ri_key, 32,
>                                                 param->n++);
>                  }
>              }
> @@ -307,21 +308,24 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
>      }
>  }
>  
> -static int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
> +static GDBFeature *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      GString *s = g_string_new(NULL);
> -    RegisterSysregXmlParam param = {cs, s, base_reg};
> +    RegisterSysregFeatureParam param = {cs, s, base_reg};
> +    DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
> +    gsize num_regs = g_hash_table_size(cpu->cp_regs);
>  
> -    cpu->dyn_sysreg_xml.num = 0;
> -    cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
> +    dyn_feature->desc.num_regs = 0;
> +    dyn_feature->data.cpregs.keys = g_new(uint32_t, num_regs);
>      g_string_printf(s, "<?xml version=\"1.0\"?>");
>      g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
>      g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
> -    g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
> +    g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_feature, &param);
>      g_string_append_printf(s, "</feature>");
> -    cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
> -    return cpu->dyn_sysreg_xml.num;
> +    dyn_feature->desc.xmlname = "system-registers.xml";
> +    dyn_feature->desc.xml = g_string_free(s, false);
> +    return &dyn_feature->desc;
>  }
>  
>  #ifdef CONFIG_TCG
> @@ -413,7 +417,8 @@ static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg)
>      return 0; /* TODO */
>  }
>  
> -static int arm_gen_dynamic_m_systemreg_xml(CPUState *cs, int orig_base_reg)
> +static GDBFeature *arm_gen_dynamic_m_systemreg_feature(CPUState *cs,
> +                                                       int orig_base_reg)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
> @@ -434,10 +439,11 @@ static int arm_gen_dynamic_m_systemreg_xml(CPUState *cs, int orig_base_reg)
>      }
>  
>      g_string_append_printf(s, "</feature>");
> -    cpu->dyn_m_systemreg_xml.desc = g_string_free(s, false);
> -    cpu->dyn_m_systemreg_xml.num = base_reg - orig_base_reg;
> +    cpu->dyn_m_systemreg_feature.desc.xmlname = "arm-m-system.xml";
> +    cpu->dyn_m_systemreg_feature.desc.xml = g_string_free(s, false);
> +    cpu->dyn_m_systemreg_feature.desc.num_regs = base_reg - orig_base_reg;
>  
> -    return cpu->dyn_m_systemreg_xml.num;
> +    return &cpu->dyn_m_systemreg_feature.desc;
>  }
>  
>  #ifndef CONFIG_USER_ONLY
> @@ -455,7 +461,8 @@ static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg)
>      return 0; /* TODO */
>  }
>  
> -static int arm_gen_dynamic_m_secextreg_xml(CPUState *cs, int orig_base_reg)
> +static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
> +                                                       int orig_base_reg)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      GString *s = g_string_new(NULL);
> @@ -476,10 +483,11 @@ static int arm_gen_dynamic_m_secextreg_xml(CPUState *cs, int orig_base_reg)
>      }
>  
>      g_string_append_printf(s, "</feature>");
> -    cpu->dyn_m_secextreg_xml.desc = g_string_free(s, false);
> -    cpu->dyn_m_secextreg_xml.num = base_reg - orig_base_reg;
> +    cpu->dyn_m_secextreg_feature.desc.xmlname = "arm-m-secext.xml";
> +    cpu->dyn_m_secextreg_feature.desc.xml = g_string_free(s, false);
> +    cpu->dyn_m_secextreg_feature.desc.num_regs = base_reg - orig_base_reg;
>  
> -    return cpu->dyn_m_secextreg_xml.num;
> +    return &cpu->dyn_m_secextreg_feature.desc;
>  }
>  #endif
>  #endif /* CONFIG_TCG */
> @@ -489,14 +497,14 @@ const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
>      ARMCPU *cpu = ARM_CPU(cs);
>  
>      if (strcmp(xmlname, "system-registers.xml") == 0) {
> -        return cpu->dyn_sysreg_xml.desc;
> +        return cpu->dyn_sysreg_feature.desc.xml;
>      } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
> -        return cpu->dyn_svereg_xml.desc;
> +        return cpu->dyn_svereg_feature.desc.xml;
>      } else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
> -        return cpu->dyn_m_systemreg_xml.desc;
> +        return cpu->dyn_m_systemreg_feature.desc.xml;
>  #ifndef CONFIG_USER_ONLY
>      } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
> -        return cpu->dyn_m_secextreg_xml.desc;
> +        return cpu->dyn_m_secextreg_feature.desc.xml;
>  #endif
>      }
>      return NULL;
> @@ -514,7 +522,7 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>           */
>  #ifdef TARGET_AARCH64
>          if (isar_feature_aa64_sve(&cpu->isar)) {
> -            int nreg = arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs);
> +            int nreg = arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs)->num_regs;
>              gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
>                                       aarch64_gdb_set_sve_reg, nreg,
>                                       "sve-registers.xml", 0);
> @@ -560,20 +568,20 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>                                   1, "arm-m-profile-mve.xml", 0);
>      }
>      gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
> -                             arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
> +                             arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs)->num_regs,
>                               "system-registers.xml", 0);
>  
>  #ifdef CONFIG_TCG
>      if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
>          gdb_register_coprocessor(cs,
>              arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
> -            arm_gen_dynamic_m_systemreg_xml(cs, cs->gdb_num_regs),
> +            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs)->num_regs,
>              "arm-m-system.xml", 0);
>  #ifndef CONFIG_USER_ONLY
>          if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
>              gdb_register_coprocessor(cs,
>                  arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
> -                arm_gen_dynamic_m_secextreg_xml(cs, cs->gdb_num_regs),
> +                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs)->num_regs,
>                  "arm-m-secext.xml", 0);
>          }
>  #endif
> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
> index d7b79a6589..20483ef9bc 100644
> --- a/target/arm/gdbstub64.c
> +++ b/target/arm/gdbstub64.c
> @@ -316,11 +316,11 @@ static void output_vector_union_type(GString *s, int reg_width,
>      g_string_append(s, "</union>");
>  }
>  
> -int arm_gen_dynamic_svereg_xml(CPUState *cs, int orig_base_reg)
> +GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int orig_base_reg)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      GString *s = g_string_new(NULL);
> -    DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
> +    DynamicGDBFeatureInfo *info = &cpu->dyn_svereg_feature;
>      int reg_width = cpu->sve_max_vq * 128;
>      int pred_width = cpu->sve_max_vq * 16;
>      int base_reg = orig_base_reg;
> @@ -375,7 +375,8 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int orig_base_reg)
>  
>      g_string_append_printf(s, "</feature>");
>  
> -    info->desc = g_string_free(s, false);
> -    info->num = base_reg - orig_base_reg;
> -    return info->num;
> +    info->desc.xmlname = "sve-registers.xml";
> +    info->desc.xml = g_string_free(s, false);
> +    info->desc.num_regs = base_reg - orig_base_reg;
> +    return &info->desc;
>  }

Otherwise:

Acked-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 10/24] gdbstub: Use GDBFeature for gdb_register_coprocessor
  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
  0 siblings, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 13:13 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> This is a tree-wide change to introduce GDBFeature parameter to
> gdb_register_coprocessor(). The new parameter just replaces num_regs
> and xml parameters for now. GDBFeature will be utilized to simplify XML
> lookup in a following change.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  include/exec/gdbstub.h     |  2 +-
>  gdbstub/gdbstub.c          | 13 +++++++------
>  target/arm/gdbstub.c       | 36 ++++++++++++++++++++----------------
>  target/hexagon/cpu.c       |  3 +--
>  target/loongarch/gdbstub.c |  2 +-
>  target/m68k/helper.c       |  6 +++---
>  target/microblaze/cpu.c    |  5 +++--
>  target/ppc/gdbstub.c       | 11 ++++++-----
>  target/riscv/gdbstub.c     | 20 ++++++++++++--------
>  target/s390x/gdbstub.c     | 28 +++++++---------------------
>  10 files changed, 61 insertions(+), 65 deletions(-)
>
> diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
> index 3115dc21c0..9b3da5b257 100644
> --- a/include/exec/gdbstub.h
> +++ b/include/exec/gdbstub.h
> @@ -22,7 +22,7 @@ typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
>  typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
>  void gdb_register_coprocessor(CPUState *cpu,
>                                gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
> -                              int num_regs, const char *xml, int g_pos);
> +                              const GDBFeature *feature, int g_pos);
>  
>  /**
>   * gdbserver_start: start the gdb server
> diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
> index 6f2e0cb06f..ab75f6686b 100644
> --- a/gdbstub/gdbstub.c
> +++ b/gdbstub/gdbstub.c
> @@ -471,7 +471,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
>  
>  void gdb_register_coprocessor(CPUState *cpu,
>                                gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
> -                              int num_regs, const char *xml, int g_pos)
> +                              const GDBFeature *feature, int g_pos)
>  {
>      GDBRegisterState *s;
>      GDBRegisterState **p;

As we are expecting gdb_find_static_feature to always succeed should we
maybe:

 g_assert(feature);

to avoid errors creeping in later (although I guess we'll seg almost
immediately after)?

> @@ -479,25 +479,26 @@ void gdb_register_coprocessor(CPUState *cpu,
>      p = &cpu->gdb_regs;
>      while (*p) {
>          /* Check for duplicates.  */
> -        if (strcmp((*p)->xml, xml) == 0)
> +        if (strcmp((*p)->xml, feature->xmlname) == 0)
>              return;
>          p = &(*p)->next;
>      }
>  
>      s = g_new0(GDBRegisterState, 1);
>      s->base_reg = cpu->gdb_num_regs;
> -    s->num_regs = num_regs;
> +    s->num_regs = feature->num_regs;
>      s->get_reg = get_reg;
>      s->set_reg = set_reg;
> -    s->xml = xml;
> +    s->xml = feature->xml;
>  
>      /* Add to end of list.  */
> -    cpu->gdb_num_regs += num_regs;
> +    cpu->gdb_num_regs += feature->num_regs;
>      *p = s;
>      if (g_pos) {
>          if (g_pos != s->base_reg) {
>              error_report("Error: Bad gdb register numbering for '%s', "
> -                         "expected %d got %d", xml, g_pos, s->base_reg);
> +                         "expected %d got %d", feature->xml,
> +                         g_pos, s->base_reg);
>          } else {
>              cpu->gdb_num_g_regs = cpu->gdb_num_regs;
>          }
> diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
> index cd35bac013..ab4ffe6264 100644
> --- a/target/arm/gdbstub.c
> +++ b/target/arm/gdbstub.c
> @@ -522,14 +522,15 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>           */
>  #ifdef TARGET_AARCH64
>          if (isar_feature_aa64_sve(&cpu->isar)) {
> -            int nreg = arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs)->num_regs;
> +            GDBFeature *feature =
> +                arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs);
>              gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
> -                                     aarch64_gdb_set_sve_reg, nreg,
> -                                     "sve-registers.xml", 0);
> +                                     aarch64_gdb_set_sve_reg, feature, 0);
>          } else {
>              gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg,
>                                       aarch64_gdb_set_fpu_reg,
> -                                     34, "aarch64-fpu.xml", 0);
> +                                     gdb_find_static_feature("aarch64-fpu.xml"),
> +                                     0);
>          }
>          /*
>           * Note that we report pauth information via the feature name
> @@ -540,19 +541,22 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>          if (isar_feature_aa64_pauth(&cpu->isar)) {
>              gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
>                                       aarch64_gdb_set_pauth_reg,
> -                                     4, "aarch64-pauth.xml", 0);
> +                                     gdb_find_static_feature("aarch64-pauth.xml"),
> +                                     0);
>          }
>  #endif
>      } else {
>          if (arm_feature(env, ARM_FEATURE_NEON)) {
>              gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
> -                                     49, "arm-neon.xml", 0);
> +                                     gdb_find_static_feature("arm-neon.xml"),
> +                                     0);
>          } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
>              gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
> -                                     33, "arm-vfp3.xml", 0);
> +                                     gdb_find_static_feature("arm-vfp3.xml"),
> +                                     0);
>          } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
>              gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
> -                                     17, "arm-vfp.xml", 0);
> +                                     gdb_find_static_feature("arm-vfp.xml"), 0);
>          }
>          if (!arm_feature(env, ARM_FEATURE_M)) {
>              /*
> @@ -560,29 +564,29 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>               * expose to gdb.
>               */
>              gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
> -                                     2, "arm-vfp-sysregs.xml", 0);
> +                                     gdb_find_static_feature("arm-vfp-sysregs.xml"),
> +                                     0);
>          }
>      }
>      if (cpu_isar_feature(aa32_mve, cpu) && tcg_enabled()) {
>          gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
> -                                 1, "arm-m-profile-mve.xml", 0);
> +                                 gdb_find_static_feature("arm-m-profile-mve.xml"),
> +                                 0);
>      }
>      gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
> -                             arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs)->num_regs,
> -                             "system-registers.xml", 0);
> +                             arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs),
> +                             0);
>  
>  #ifdef CONFIG_TCG
>      if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
>          gdb_register_coprocessor(cs,
>              arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
> -            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs)->num_regs,
> -            "arm-m-system.xml", 0);
> +            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs), 0);
>  #ifndef CONFIG_USER_ONLY
>          if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
>              gdb_register_coprocessor(cs,
>                  arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
> -                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs)->num_regs,
> -                "arm-m-secext.xml", 0);
> +                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs), 0);
>          }
>  #endif
>      }
> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
> index b54162cbeb..6732efc5de 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -342,8 +342,7 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
>  
>      gdb_register_coprocessor(cs, hexagon_hvx_gdb_read_register,
>                               hexagon_hvx_gdb_write_register,
> -                             NUM_VREGS + NUM_QREGS,
> -                             "hexagon-hvx.xml", 0);
> +                             gdb_find_static_feature("hexagon-hvx.xml"), 0);
>  
>      qemu_init_vcpu(cs);
>      cpu_reset(cs);
> diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c
> index 0752fff924..2886b106bb 100644
> --- a/target/loongarch/gdbstub.c
> +++ b/target/loongarch/gdbstub.c
> @@ -101,5 +101,5 @@ static int loongarch_gdb_set_fpu(CPULoongArchState *env,
>  void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs)
>  {
>      gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu,
> -                             41, "loongarch-fpu.xml", 0);
> +                             gdb_find_static_feature("loongarch-fpu.xml"), 0);
>  }
> diff --git a/target/m68k/helper.c b/target/m68k/helper.c
> index 0a1544cd68..675f2dcd5a 100644
> --- a/target/m68k/helper.c
> +++ b/target/m68k/helper.c
> @@ -152,10 +152,10 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
>  
>      if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
>          gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
> -                                 11, "cf-fp.xml", 18);
> +                                 gdb_find_static_feature("cf-fp.xml"), 18);
>      } else if (m68k_feature(env, M68K_FEATURE_FPU)) {
> -        gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg,
> -                                 m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", 18);
> +        gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg, m68k_fpu_gdb_set_reg,
> +                                 gdb_find_static_feature("m68k-fp.xml"), 18);
>      }
>      /* TODO: Add [E]MAC registers.  */
>  }
> diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
> index 47f37c2519..c804622ab9 100644
> --- a/target/microblaze/cpu.c
> +++ b/target/microblaze/cpu.c
> @@ -298,8 +298,9 @@ static void mb_cpu_initfn(Object *obj)
>  
>      cpu_set_cpustate_pointers(cpu);
>      gdb_register_coprocessor(CPU(cpu), mb_cpu_gdb_read_stack_protect,
> -                             mb_cpu_gdb_write_stack_protect, 2,
> -                             "microblaze-stack-protect.xml", 0);
> +                             mb_cpu_gdb_write_stack_protect,
> +                             gdb_find_static_feature("microblaze-stack-protect.xml"),
> +                             0);
>  
>      set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
>  
> diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
> index adc647a24e..a0da320e66 100644
> --- a/target/ppc/gdbstub.c
> +++ b/target/ppc/gdbstub.c
> @@ -603,22 +603,23 @@ void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *pcc)
>  {
>      if (pcc->insns_flags & PPC_FLOAT) {
>          gdb_register_coprocessor(cs, gdb_get_float_reg, gdb_set_float_reg,
> -                                 33, "power-fpu.xml", 0);
> +                                 gdb_find_static_feature("power-fpu.xml"), 0);
>      }
>      if (pcc->insns_flags & PPC_ALTIVEC) {
>          gdb_register_coprocessor(cs, gdb_get_avr_reg, gdb_set_avr_reg,
> -                                 34, "power-altivec.xml", 0);
> +                                 gdb_find_static_feature("power-altivec.xml"),
> +                                 0);
>      }
>      if (pcc->insns_flags & PPC_SPE) {
>          gdb_register_coprocessor(cs, gdb_get_spe_reg, gdb_set_spe_reg,
> -                                 34, "power-spe.xml", 0);
> +                                 gdb_find_static_feature("power-spe.xml"), 0);
>      }
>      if (pcc->insns_flags2 & PPC2_VSX) {
>          gdb_register_coprocessor(cs, gdb_get_vsx_reg, gdb_set_vsx_reg,
> -                                 32, "power-vsx.xml", 0);
> +                                 gdb_find_static_feature("power-vsx.xml"), 0);
>      }
>  #ifndef CONFIG_USER_ONLY
>      gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg,
> -                             pcc->gdb_spr.num_regs, "power-spr.xml", 0);
> +                             &pcc->gdb_spr, 0);
>  #endif
>  }
> diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
> index 70c60ad8b1..224c69ea99 100644
> --- a/target/riscv/gdbstub.c
> +++ b/target/riscv/gdbstub.c
> @@ -317,29 +317,33 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
>      CPURISCVState *env = &cpu->env;
>      if (env->misa_ext & RVD) {
>          gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
> -                                 32, "riscv-64bit-fpu.xml", 0);
> +                                 gdb_find_static_feature("riscv-64bit-fpu.xml"),
> +                                 0);
>      } else if (env->misa_ext & RVF) {
>          gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
> -                                 32, "riscv-32bit-fpu.xml", 0);
> +                                 gdb_find_static_feature("riscv-32bit-fpu.xml"),
> +                                 0);
>      }
>      if (env->misa_ext & RVV) {
>          int base_reg = cs->gdb_num_regs;
>          gdb_register_coprocessor(cs, riscv_gdb_get_vector,
>                                   riscv_gdb_set_vector,
> -                                 ricsv_gen_dynamic_vector_feature(cs, base_reg)->num_regs,
> -                                 "riscv-vector.xml", 0);
> +                                 ricsv_gen_dynamic_vector_feature(cs, base_reg),
> +                                 0);
>      }
>      switch (env->misa_mxl_max) {
>      case MXL_RV32:
>          gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
>                                   riscv_gdb_set_virtual,
> -                                 1, "riscv-32bit-virtual.xml", 0);
> +                                 gdb_find_static_feature("riscv-32bit-virtual.xml"),
> +                                 0);
>          break;
>      case MXL_RV64:
>      case MXL_RV128:
>          gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
>                                   riscv_gdb_set_virtual,
> -                                 1, "riscv-64bit-virtual.xml", 0);
> +                                 gdb_find_static_feature("riscv-64bit-virtual.xml"),
> +                                 0);
>          break;
>      default:
>          g_assert_not_reached();
> @@ -348,7 +352,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
>      if (cpu->cfg.ext_icsr) {
>          int base_reg = cs->gdb_num_regs;
>          gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
> -                                 riscv_gen_dynamic_csr_feature(cs, base_reg)->num_regs,
> -                                 "riscv-csr.xml", 0);
> +                                 riscv_gen_dynamic_csr_feature(cs, base_reg),
> +                                 0);
>      }
>  }
> diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c
> index 6fbfd41bc8..02c388dc32 100644
> --- a/target/s390x/gdbstub.c
> +++ b/target/s390x/gdbstub.c
> @@ -69,8 +69,6 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
>  /* the values represent the positions in s390-acr.xml */
>  #define S390_A0_REGNUM 0
>  #define S390_A15_REGNUM 15
> -/* total number of registers in s390-acr.xml */
> -#define S390_NUM_AC_REGS 16
>  
>  static int cpu_read_ac_reg(CPUS390XState *env, GByteArray *buf, int n)
>  {
> @@ -98,8 +96,6 @@ static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
>  #define S390_FPC_REGNUM 0
>  #define S390_F0_REGNUM 1
>  #define S390_F15_REGNUM 16
> -/* total number of registers in s390-fpr.xml */
> -#define S390_NUM_FP_REGS 17
>  
>  static int cpu_read_fp_reg(CPUS390XState *env, GByteArray *buf, int n)
>  {
> @@ -132,8 +128,6 @@ static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
>  #define S390_V15L_REGNUM 15
>  #define S390_V16_REGNUM 16
>  #define S390_V31_REGNUM 31
> -/* total number of registers in s390-vx.xml */
> -#define S390_NUM_VREGS 32
>  
>  static int cpu_read_vreg(CPUS390XState *env, GByteArray *buf, int n)
>  {
> @@ -172,8 +166,6 @@ static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n)
>  /* the values represent the positions in s390-cr.xml */
>  #define S390_C0_REGNUM 0
>  #define S390_C15_REGNUM 15
> -/* total number of registers in s390-cr.xml */
> -#define S390_NUM_C_REGS 16
>  
>  #ifndef CONFIG_USER_ONLY
>  static int cpu_read_c_reg(CPUS390XState *env, GByteArray *buf, int n)
> @@ -206,8 +198,6 @@ static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
>  #define S390_VIRT_CPUTM_REGNUM  1
>  #define S390_VIRT_BEA_REGNUM    2
>  #define S390_VIRT_PREFIX_REGNUM 3
> -/* total number of registers in s390-virt.xml */
> -#define S390_NUM_VIRT_REGS 4
>  
>  static int cpu_read_virt_reg(CPUS390XState *env, GByteArray *mem_buf, int n)
>  {
> @@ -254,8 +244,6 @@ static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
>  #define S390_VIRT_KVM_PFT_REGNUM    1
>  #define S390_VIRT_KVM_PFS_REGNUM    2
>  #define S390_VIRT_KVM_PFC_REGNUM    3
> -/* total number of registers in s390-virt-kvm.xml */
> -#define S390_NUM_VIRT_KVM_REGS 4
>  
>  static int cpu_read_virt_kvm_reg(CPUS390XState *env, GByteArray *mem_buf, int n)
>  {
> @@ -303,8 +291,6 @@ static int cpu_write_virt_kvm_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
>  #define S390_GS_GSD_REGNUM      1
>  #define S390_GS_GSSM_REGNUM     2
>  #define S390_GS_GSEPLA_REGNUM   3
> -/* total number of registers in s390-gs.xml */
> -#define S390_NUM_GS_REGS 4
>  
>  static int cpu_read_gs_reg(CPUS390XState *env, GByteArray *buf, int n)
>  {
> @@ -322,33 +308,33 @@ void s390_cpu_gdb_init(CPUState *cs)
>  {
>      gdb_register_coprocessor(cs, cpu_read_ac_reg,
>                               cpu_write_ac_reg,
> -                             S390_NUM_AC_REGS, "s390-acr.xml", 0);
> +                             gdb_find_static_feature("s390-acr.xml"), 0);
>  
>      gdb_register_coprocessor(cs, cpu_read_fp_reg,
>                               cpu_write_fp_reg,
> -                             S390_NUM_FP_REGS, "s390-fpr.xml", 0);
> +                             gdb_find_static_feature("s390-fpr.xml"), 0);
>  
>      gdb_register_coprocessor(cs, cpu_read_vreg,
>                               cpu_write_vreg,
> -                             S390_NUM_VREGS, "s390-vx.xml", 0);
> +                             gdb_find_static_feature("s390-vx.xml"), 0);
>  
>      gdb_register_coprocessor(cs, cpu_read_gs_reg,
>                               cpu_write_gs_reg,
> -                             S390_NUM_GS_REGS, "s390-gs.xml", 0);
> +                             gdb_find_static_feature("s390-gs.xml"), 0);
>  
>  #ifndef CONFIG_USER_ONLY
>      gdb_register_coprocessor(cs, cpu_read_c_reg,
>                               cpu_write_c_reg,
> -                             S390_NUM_C_REGS, "s390-cr.xml", 0);
> +                             gdb_find_static_feature("s390-cr.xml"), 0);
>  
>      gdb_register_coprocessor(cs, cpu_read_virt_reg,
>                               cpu_write_virt_reg,
> -                             S390_NUM_VIRT_REGS, "s390-virt.xml", 0);
> +                             gdb_find_static_feature("s390-virt.xml"), 0);
>  
>      if (kvm_enabled()) {
>          gdb_register_coprocessor(cs, cpu_read_virt_kvm_reg,
>                                   cpu_write_virt_kvm_reg,
> -                                 S390_NUM_VIRT_KVM_REGS, "s390-virt-kvm.xml",
> +                                 gdb_find_static_feature("s390-virt-kvm.xml"),
>                                   0);
>      }
>  #endif

Otherwise:

Acked-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  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-08-14 11:59   ` Alex Bennée
@ 2023-08-14 13:19   ` Alex Bennée
  2 siblings, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 13:19 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> This is a tree-wide change to replace gdb_core_xml_file, the path to
> GDB XML file with gdb_core_feature, the pointer to GDBFeature. This
> also replaces the values assigned to gdb_num_core_regs with the
> num_regs member of GDBFeature where applicable to remove magic numbers.
>
> A following change will utilize additional information provided by
> GDBFeature to simplify XML file lookup.

re: other comment about assert(). Maybe gdb_find_static_feature() needs to assert
success because:

Thread 1 "qemu-loongarch6" received signal SIGSEGV, Segmentation fault.
loongarch_cpu_class_init (c=<optimized out>, data=<optimized out>) at ../../target/loongarch/cpu.c:726
726         cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
(gdb) p/x cc->gdb_core_feature 
$1 = 0x0
(gdb) l
721         cc->disas_set_info = loongarch_cpu_disas_set_info;
722         cc->gdb_read_register = loongarch_cpu_gdb_read_register;
723         cc->gdb_write_register = loongarch_cpu_gdb_write_register;
724         cc->disas_set_info = loongarch_cpu_disas_set_info;
725         cc->gdb_core_feature = gdb_find_static_feature("loongarch-base64.xml");
726         cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
727         cc->gdb_stop_before_watchpoint = true;
728         cc->gdb_arch_name = loongarch_gdb_arch_name;
729
730     #ifdef CONFIG_TCG

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 12/24] gdbstub: Simplify XML lookup
  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
  0 siblings, 1 reply; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 13:27 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> Now we know all instances of GDBFeature that is used in CPU so we can
> traverse them to find XML. This removes the need for a CPU-specific
> lookup function for dynamic XMLs.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  gdbstub/gdbstub.c | 28 +++++++++-------------------
>  1 file changed, 9 insertions(+), 19 deletions(-)
>
> diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
> index 182efe7e0f..e5bb2c89ba 100644
> --- a/gdbstub/gdbstub.c
> +++ b/gdbstub/gdbstub.c
> @@ -354,8 +354,7 @@ static const char *get_feature_xml(const char *p, const char **newp,
>                                     GDBProcess *process)
>  {
>      size_t len;
> -    int i;
> -    const char *name;
> +    GDBRegisterState *r;
>      CPUState *cpu = gdb_get_first_cpu_in_process(process);
>      CPUClass *cc = CPU_GET_CLASS(cpu);
>  
> @@ -364,15 +363,12 @@ static const char *get_feature_xml(const char *p, const char **newp,
>          len++;
>      *newp = p + len;
>  
> -    name = NULL;
>      if (strncmp(p, "target.xml", len) == 0) {
>          char *buf = process->target_xml;
>          const size_t buf_sz = sizeof(process->target_xml);
>  
>          /* Generate the XML description for this CPU.  */
>          if (!buf[0]) {
> -            GDBRegisterState *r;
> -
>              pstrcat(buf, buf_sz,
>                      "<?xml version=\"1.0\"?>"
>                      "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
> @@ -389,28 +385,22 @@ static const char *get_feature_xml(const char *p, const char **newp,
>              pstrcat(buf, buf_sz, "\"/>");
>              for (r = cpu->gdb_regs; r; r = r->next) {
>                  pstrcat(buf, buf_sz, "<xi:include href=\"");
> -                pstrcat(buf, buf_sz, r->feature->xml);
> +                pstrcat(buf, buf_sz, r->feature->xmlname);
>                  pstrcat(buf, buf_sz, "\"/>");
>              }
>              pstrcat(buf, buf_sz, "</target>");
>          }
>          return buf;
>      }

It would be nice to modernise this code before adding to it. The static
target_xml buffer and use of pstrcat could be replaced by GString code
that is less sketchy.


> -    if (cc->gdb_get_dynamic_xml) {
> -        char *xmlname = g_strndup(p, len);
> -        const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname);
> -
> -        g_free(xmlname);
> -        if (xml) {
> -            return xml;
> -        }
> +    if (strncmp(p, cc->gdb_core_feature->xmlname, len) == 0) {
> +        return cc->gdb_core_feature->xml;
>      }
> -    for (i = 0; ; i++) {
> -        name = gdb_features[i].xmlname;
> -        if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len))
> -            break;
> +    for (r = cpu->gdb_regs; r; r = r->next) {
> +        if (strncmp(p, r->feature->xmlname, len) == 0) {
> +            return r->feature->xml;
> +        }
>      }
> -    return name ? gdb_features[i].xml : NULL;
> +    return NULL;
>  }
>  
>  const GDBFeature *gdb_find_static_feature(const char *xmlname)


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 13/24] hw/core/cpu: Remove gdb_get_dynamic_xml member
  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
  0 siblings, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 13:29 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> This function is no longer used.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 14/24] gdbstub: Add members to identify registers to GDBFeature
  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
  0 siblings, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 13:30 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> These members will be used to help plugins to identify registers.

I'm wary of exposing gdb'isms directly to plugins. However making stuff
easier for the gdbstub internals is ok. I shall reserve judgement until
I've read the rest of the series.


> The added members in instances of GDBFeature dynamically generated by
> CPUs will be filled in later changes.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  include/exec/gdbstub.h  |  2 ++
>  scripts/feature_to_c.py | 14 +++++++++++++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
> index 9b3da5b257..6da4af9612 100644
> --- a/include/exec/gdbstub.h
> +++ b/include/exec/gdbstub.h
> @@ -13,6 +13,8 @@
>  typedef struct GDBFeature {
>      const char *xmlname;
>      const char *xml;
> +    const char *name;
> +    const char * const *regs;
>      int num_regs;
>  } GDBFeature;
>  
> diff --git a/scripts/feature_to_c.py b/scripts/feature_to_c.py
> index 8eb8c81cf8..11b1bc05c9 100755
> --- a/scripts/feature_to_c.py
> +++ b/scripts/feature_to_c.py
> @@ -46,7 +46,9 @@ def writeliteral(indent, bytes):
>          sys.stderr.write(f'unexpected start tag: {element.tag}\n')
>          exit(1)
>  
> +    feature_name = element.attrib['name']
>      regnum = 0
> +    regnames = []
>      regnums = []
>      tags = ['feature']
>      for event, element in events:
> @@ -63,6 +65,7 @@ def writeliteral(indent, bytes):
>                  if 'regnum' in element.attrib:
>                      regnum = int(element.attrib['regnum'])
>  
> +                regnames.append(element.attrib['name'])
>                  regnums.append(regnum)
>                  regnum += 1
>  
> @@ -81,6 +84,15 @@ def writeliteral(indent, bytes):
>      writeliteral(8, bytes(os.path.basename(input), 'utf-8'))
>      sys.stdout.write(',\n')
>      writeliteral(8, read)
> -    sys.stdout.write(f',\n        {num_regs},\n    }},\n')
> +    sys.stdout.write(',\n')
> +    writeliteral(8, bytes(feature_name, 'utf-8'))
> +    sys.stdout.write(',\n        (const char * const []) {\n')
> +
> +    for index, regname in enumerate(regnames):
> +        sys.stdout.write(f'            [{regnums[index] - base_reg}] =\n')
> +        writeliteral(16, bytes(regname, 'utf-8'))
> +        sys.stdout.write(',\n')
> +
> +    sys.stdout.write(f'        }},\n        {num_regs},\n    }},\n')
>  
>  sys.stdout.write('    { NULL }\n};\n')


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 15/24] target/arm: Fill new members of GDBFeature
  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
  0 siblings, 1 reply; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 14:56 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> These members will be used to help plugins to identify registers.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  target/arm/gdbstub.c   | 46 +++++++++++++++++++++++++++---------------
>  target/arm/gdbstub64.c | 42 +++++++++++++++++++++++++-------------
>  2 files changed, 58 insertions(+), 30 deletions(-)
>
> diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
> index 100a6eed15..56d24028f6 100644
> --- a/target/arm/gdbstub.c
> +++ b/target/arm/gdbstub.c
> @@ -270,6 +270,7 @@ static void arm_gen_one_feature_sysreg(GString *s,
>      g_string_append_printf(s, " regnum=\"%d\"", regnum);
>      g_string_append_printf(s, " group=\"cp_regs\"/>");
>      dyn_feature->data.cpregs.keys[dyn_feature->desc.num_regs] = ri_key;
> +    ((const char **)dyn_feature->desc.regs)[dyn_feature->desc.num_regs] = ri->name;
>      dyn_feature->desc.num_regs++;
>  }
>  
> @@ -316,6 +317,8 @@ static GDBFeature *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
>      DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
>      gsize num_regs = g_hash_table_size(cpu->cp_regs);
>  
> +    dyn_feature->desc.name = "org.qemu.gdb.arm.sys.regs";
> +    dyn_feature->desc.regs = g_new(const char *, num_regs);

AIUI this means we now have an array of register names which mirrors the
names embedded in the XML. This smells like a few steps away from just
abstracting the whole XML away from the targets and generating them
inside gdbstub when we need them. As per my stalled attempt I referenced
earlier.


>      dyn_feature->desc.num_regs = 0;
>      dyn_feature->data.cpregs.keys = g_new(uint32_t, num_regs);
>      g_string_printf(s, "<?xml version=\"1.0\"?>");
> @@ -418,30 +421,34 @@ static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg)
>  }
>  
>  static GDBFeature *arm_gen_dynamic_m_systemreg_feature(CPUState *cs,
> -                                                       int orig_base_reg)
> +                                                       int base_reg)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
>      GString *s = g_string_new(NULL);
> -    int base_reg = orig_base_reg;
> -    int i;
> +    const char **regs = g_new(const char *, ARRAY_SIZE(m_sysreg_def));
> +    int i = 0;
> +    int j;
>  
>      g_string_printf(s, "<?xml version=\"1.0\"?>");
>      g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
>      g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.m-system\">\n");
>  
> -    for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
> -        if (arm_feature(env, m_sysreg_def[i].feature)) {
> +    for (j = 0; j < ARRAY_SIZE(m_sysreg_def); j++) {
> +        if (arm_feature(env, m_sysreg_def[j].feature)) {
> +            regs[i] = m_sysreg_def[j].name;
>              g_string_append_printf(s,
>                  "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
> -                m_sysreg_def[i].name, base_reg++);
> +                m_sysreg_def[j].name, base_reg + i++);
>          }
>      }
>  
>      g_string_append_printf(s, "</feature>");
> +    cpu->dyn_m_systemreg_feature.desc.name = "org.gnu.gdb.arm.m-system";
>      cpu->dyn_m_systemreg_feature.desc.xmlname = "arm-m-system.xml";
>      cpu->dyn_m_systemreg_feature.desc.xml = g_string_free(s, false);
> -    cpu->dyn_m_systemreg_feature.desc.num_regs = base_reg - orig_base_reg;
> +    cpu->dyn_m_systemreg_feature.desc.regs = regs;
> +    cpu->dyn_m_systemreg_feature.desc.num_regs = i;
>  
>      return &cpu->dyn_m_systemreg_feature.desc;
>  }
> @@ -462,30 +469,37 @@ static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg)
>  }
>  
>  static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
> -                                                       int orig_base_reg)
> +                                                       int base_reg)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      GString *s = g_string_new(NULL);
> -    int base_reg = orig_base_reg;
> -    int i;
> +    const char **regs = g_new(const char *, ARRAY_SIZE(m_sysreg_def) * 2);
> +    int i = 0;
> +    int j;
>  
>      g_string_printf(s, "<?xml version=\"1.0\"?>");
>      g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
>      g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.secext\">\n");
>  
> -    for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
> +    for (j = 0; j < ARRAY_SIZE(m_sysreg_def); j++) {
> +        regs[i] = g_strconcat(m_sysreg_def[j].name, "_ns", NULL);
>          g_string_append_printf(s,
> -            "<reg name=\"%s_ns\" bitsize=\"32\" regnum=\"%d\"/>\n",
> -            m_sysreg_def[i].name, base_reg++);
> +            "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
> +            regs[i], base_reg + i);
> +        i++;
> +        regs[i] = g_strconcat(m_sysreg_def[j].name, "_s", NULL);
>          g_string_append_printf(s,
> -            "<reg name=\"%s_s\" bitsize=\"32\" regnum=\"%d\"/>\n",
> -            m_sysreg_def[i].name, base_reg++);
> +            "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
> +            regs[i], base_reg + i);
> +        i++;
>      }
>  
>      g_string_append_printf(s, "</feature>");
> +    cpu->dyn_m_secextreg_feature.desc.name = "org.gnu.gdb.arm.secext";
>      cpu->dyn_m_secextreg_feature.desc.xmlname = "arm-m-secext.xml";
>      cpu->dyn_m_secextreg_feature.desc.xml = g_string_free(s, false);
> -    cpu->dyn_m_secextreg_feature.desc.num_regs = base_reg - orig_base_reg;
> +    cpu->dyn_m_secextreg_feature.desc.regs = regs;
> +    cpu->dyn_m_secextreg_feature.desc.num_regs = i;
>  
>      return &cpu->dyn_m_secextreg_feature.desc;
>  }
> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
> index 20483ef9bc..c5ed7c0aa3 100644
> --- a/target/arm/gdbstub64.c
> +++ b/target/arm/gdbstub64.c
> @@ -316,15 +316,21 @@ static void output_vector_union_type(GString *s, int reg_width,
>      g_string_append(s, "</union>");
>  }
>  
> -GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int orig_base_reg)
> +GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int base_reg)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      GString *s = g_string_new(NULL);
>      DynamicGDBFeatureInfo *info = &cpu->dyn_svereg_feature;
> +    const char **regs;
>      int reg_width = cpu->sve_max_vq * 128;
>      int pred_width = cpu->sve_max_vq * 16;
> -    int base_reg = orig_base_reg;
> -    int i;
> +    int i = 0;
> +    int j;
> +
> +    info->desc.name = "org.gnu.gdb.aarch64.sve";
> +    info->desc.num_regs = 32 + 16 + 4;
> +    regs = g_new(const char *, info->desc.num_regs);
> +    info->desc.regs = regs;
>  
>      g_string_printf(s, "<?xml version=\"1.0\"?>");
>      g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
> @@ -339,44 +345,52 @@ GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int orig_base_reg)
>                             pred_width / 8);
>  
>      /* Define the vector registers. */
> -    for (i = 0; i < 32; i++) {
> +    for (j = 0; j < 32; j++) {
> +        regs[i] = g_strdup_printf("z%d", j);
>          g_string_append_printf(s,
> -                               "<reg name=\"z%d\" bitsize=\"%d\""
> +                               "<reg name=\"%s\" bitsize=\"%d\""
>                                 " regnum=\"%d\" type=\"svev\"/>",
> -                               i, reg_width, base_reg++);
> +                               regs[i], reg_width, base_reg + i);
> +        i++;
>      }
>  
>      /* fpscr & status registers */
> +    regs[i] = "fpsr";
>      g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
>                             " regnum=\"%d\" group=\"float\""
> -                           " type=\"int\"/>", base_reg++);
> +                           " type=\"int\"/>", base_reg + i++);
> +    regs[i] = "fpcr";
>      g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
>                             " regnum=\"%d\" group=\"float\""
> -                           " type=\"int\"/>", base_reg++);
> +                           " type=\"int\"/>", base_reg + i++);
>  
>      /* Define the predicate registers. */
> -    for (i = 0; i < 16; i++) {
> +    for (j = 0; j < 16; j++) {
> +        regs[i] = g_strdup_printf("p%d", j);
>          g_string_append_printf(s,
> -                               "<reg name=\"p%d\" bitsize=\"%d\""
> +                               "<reg name=\"%s\" bitsize=\"%d\""
>                                 " regnum=\"%d\" type=\"svep\"/>",
> -                               i, pred_width, base_reg++);
> +                               regs[i], pred_width, base_reg + i);
> +        i++;
>      }
> +    regs[i] = "ffr";
>      g_string_append_printf(s,
>                             "<reg name=\"ffr\" bitsize=\"%d\""
>                             " regnum=\"%d\" group=\"vector\""
>                             " type=\"svep\"/>",
> -                           pred_width, base_reg++);
> +                           pred_width, base_reg + i++);
>  
>      /* Define the vector length pseudo-register. */
> +    regs[i] = "vg";
>      g_string_append_printf(s,
>                             "<reg name=\"vg\" bitsize=\"64\""
>                             " regnum=\"%d\" type=\"int\"/>",
> -                           base_reg++);
> +                           base_reg + i++);
>  
>      g_string_append_printf(s, "</feature>");
>  
>      info->desc.xmlname = "sve-registers.xml";
>      info->desc.xml = g_string_free(s, false);
> -    info->desc.num_regs = base_reg - orig_base_reg;
> +    assert(info->desc.num_regs == i);
>      return &info->desc;
>  }


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 21/24] plugins: Allow to read registers
  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
  0 siblings, 1 reply; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 15:05 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> It is based on GDB protocol to ensure interface stability.

See comments bellow.

> The timing of the vcpu init hook is also changed so that the hook will
> get called after GDB features are initialized.

This might be worth splitting to a separate patch for cleaner bisecting.

>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  include/qemu/qemu-plugin.h   | 65 ++++++++++++++++++++++++++++++++++--
>  cpu.c                        | 11 ------
>  hw/core/cpu-common.c         | 10 ++++++
>  plugins/api.c                | 40 ++++++++++++++++++++++
>  plugins/qemu-plugins.symbols |  2 ++
>  5 files changed, 114 insertions(+), 14 deletions(-)
>
> diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
> index 50a9957279..214b12bfd6 100644
> --- a/include/qemu/qemu-plugin.h
> +++ b/include/qemu/qemu-plugin.h
> @@ -11,6 +11,7 @@
>  #ifndef QEMU_QEMU_PLUGIN_H
>  #define QEMU_QEMU_PLUGIN_H
>  
> +#include <glib.h>
>  #include <inttypes.h>
>  #include <stdbool.h>
>  #include <stddef.h>
> @@ -51,7 +52,7 @@ typedef uint64_t qemu_plugin_id_t;
>  
>  extern QEMU_PLUGIN_EXPORT int qemu_plugin_version;
>  
> -#define QEMU_PLUGIN_VERSION 1
> +#define QEMU_PLUGIN_VERSION 2
>  
>  /**
>   * struct qemu_info_t - system information for plugins
> @@ -218,8 +219,8 @@ struct qemu_plugin_insn;
>   * @QEMU_PLUGIN_CB_R_REGS: callback reads the CPU's regs
>   * @QEMU_PLUGIN_CB_RW_REGS: callback reads and writes the CPU's regs
>   *
> - * Note: currently unused, plugins cannot read or change system
> - * register state.
> + * Note: currently QEMU_PLUGIN_CB_RW_REGS is unused, plugins cannot change
> + * system register state.
>   */
>  enum qemu_plugin_cb_flags {
>      QEMU_PLUGIN_CB_NO_REGS,
> @@ -664,4 +665,62 @@ uint64_t qemu_plugin_end_code(void);
>   */
>  uint64_t qemu_plugin_entry_code(void);
>  
> +/**
> + * struct qemu_plugin_register_file_t - register information
> + *
> + * This structure identifies registers. The identifiers included in this
> + * structure are identical with names used in GDB's standard target features
> + * with some extensions. For details, see:
> + *
> https://sourceware.org/gdb/onlinedocs/gdb/Standard-Target-Features.html

I'm not super keen on baking GDB-isms into the plugin register
interface.

> + *
> + * A register is uniquely identified with the combination of a feature name
> + * and a register name or a register number. It is recommended to derive
> + * register numbers from feature names and register names each time a new vcpu
> + * starts.

Do you have examples of clashing register names from different feature
sets? 

> + *
> + * To derive the register number from a feature name and a register name,
> + * first look up qemu_plugin_register_file_t with the feature name, and then
> + * look up the register name in its @regs. The sum of the @base_reg and the
> + * index in the @reg is the register number.
> + *
> + * Note that @regs may have holes; some elements of @regs may be NULL.
> + */
> +typedef struct qemu_plugin_register_file_t {
> +    /** @name: feature name */
> +    const char *name;
> +    /** @regs: register names */
> +    const char * const *regs;
> +    /** @base_reg: the base identified number */
> +    int base_reg;
> +    /** @num_regs: the number of elements in @regs */
> +    int num_regs;
> +} qemu_plugin_register_file_t;
> +
> +/**
> + * qemu_plugin_get_register_files() - returns register information
> + *
> + * @vcpu_index: the index of the vcpu context
> + * @size: the pointer to the variable to hold the number of returned elements
> + *
> + * Returns an array of qemu_plugin_register_file_t. The user should g_free()
> + * the array once no longer needed.
> + */
> +qemu_plugin_register_file_t *
> +qemu_plugin_get_register_files(unsigned int vcpu_index, int *size);

I think I'd rather have a simpler interface that returns an anonymous
handle to the plugin. For example:

  struct qemu_plugin_register;
  struct qemu_plugin_register qemu_plugin_find_register(const char *name);

> +
> +/**
> + * qemu_plugin_read_register() - read register
> + *
> + * @buf: the byte array to append the read register content to.
> + * @reg: the register identifier determined with
> + *       qemu_plugin_get_register_files().
> + *
> + * This function is only available in a context that register read access is
> + * explicitly requested.
> + *
> + * Returns the size of the read register. The content of @buf is in target byte
> + * order.
> + */
> +int qemu_plugin_read_register(GByteArray *buf, int reg);

and this then becomes:

  int qemu_plugin_read_register(GByteArray *buf, struct qemu_plugin_register);

in practice these can become anonymous pointers which hide the
implementation details from the plugin itself. Then the details of
mapping the register to a gdb regnum can be kept in the plugin code
keeping us free to further re-factor the code as we go.

The plugin code works quite hard to try and avoid leaking implementation
details to plugins so as not to tie QEMU's hands in re-factoring. While
the interface provided is technically GDB's, not QEMUs I don't think its
a particularly nice one to expose.

<snip>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 22/24] contrib/plugins: Allow to log registers
  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
  2023-08-16 14:59     ` Akihiko Odaki
  0 siblings, 1 reply; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 15:21 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 24/24] contrib/plugins: Add cc plugin
  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
  0 siblings, 1 reply; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 15:23 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> This demonstrates how to write a plugin in C++.
>
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  docs/devel/tcg-plugins.rst |  8 ++++++++
>  configure                  | 15 ++++++++++++---
>  contrib/plugins/Makefile   |  5 +++++
>  contrib/plugins/cc.cc      | 15 +++++++++++++++
>  tests/tcg/Makefile.target  |  3 +++
>  5 files changed, 43 insertions(+), 3 deletions(-)
>  create mode 100644 contrib/plugins/cc.cc
>
> diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst
> index c9f8b27590..0a11f8036c 100644
> --- a/docs/devel/tcg-plugins.rst
> +++ b/docs/devel/tcg-plugins.rst
> @@ -584,6 +584,14 @@ The plugin has a number of arguments, all of them are optional:
>    configuration arguments implies ``l2=on``.
>    (default: N = 2097152 (2MB), B = 64, A = 16)
>  
> +- contrib/plugins/cc.cc
> +
> +cc plugin demonstrates how to write a plugin in C++. It simply outputs
> +"hello, world" to the plugin log::
> +
> +  $ qemu-system-arm $(QEMU_ARGS) \
> +    -plugin ./contrib/plugins/libcc.so -d plugin
> +

I'm going to assume this is useful because you have some out of tree C++
plugins? I'd drop the last two patches for now until there is a slightly
more compelling use case.

The C++ compiler detection moved into meson in b485458e00 (configure,
meson: move C++ compiler detection to meson.build) so I don't think
there is currently a compelling reason to bring this back into
configure.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 00/24] plugins: Allow to read registers
  2023-07-31  8:43 [RFC PATCH 00/24] plugins: Allow to read registers Akihiko Odaki
                   ` (23 preceding siblings ...)
  2023-07-31  8:43 ` [RFC PATCH 24/24] contrib/plugins: Add cc plugin Akihiko Odaki
@ 2023-08-14 15:27 ` Alex Bennée
  24 siblings, 0 replies; 61+ messages in thread
From: Alex Bennée @ 2023-08-14 15:27 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> I and other people in the University of Tokyo, where I research processor
> design, found TCG plugins are very useful for processor design
> exploration.

Thanks for the submission - I've finished my initial review pass.

I think introducing register introspection into the plugins subsystem is
a very worthwhile addition. I'm also happy (for now) to use the
underlying gdb support for it in lieu of a greater refactoring of QEMU's
multiple register introspection features.

> The feature we find missing is the capability to read registers from
> plugins. In this series, I propose to add such a capability by reusing
> gdbstub code.
>
> The reuse of gdbstub code ensures the long-term stability of the TCG plugin
> interface for register access without incurring a burden to maintain yet
> another interface for register access.

However I don't want to expose the gdb detail to plugins to leave us a
free hand in further internal clean-ups later on.

> This process to add TCG plugin involves four major changes. The first one
> is to add GDBFeature structure that represents a GDB feature, which usually
> includes registers. GDBFeature can be generated from static XML files or
> dynamically generated by architecture-specific code. In fact, this is a
> refactoring independent of the feature this series adds, and potentially
> it's benefitial even without the plugin feature. The plugin feature will
> utilize this new structure to describe registers exposed to plugins.

I think we can get cleanups to this handling in ahead of the wider
plugin feature. Ideally it would be nice to push the XML generation into
gdbstub itself but that might be more of a refactor than you are willing
to pursue for the time being.

> The second one is to make gdb_read_register/gdb_write_register usable
> outside of gdbstub context.
>
> The third one is to actually make registers readable for plugins.

Modulo isolating the plugin API from gdb specifics I'm happy with this
approach.

> The last one is to allow to implement a QEMU plugin in C++. A plugin that
> I'll describe later is written in C++.

I would want a more compelling reason that a hello world plugin for
this. Only because QEMU has removed a bunch of C++ dependency over the
last few years so I don't think we are in a rush to re-introduce it. 

Are you OK to do a re-spin addressing the comments so far?

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  2023-08-14 11:59   ` Alex Bennée
@ 2023-08-16 13:47     ` Akihiko Odaki
  2023-08-16 15:00       ` Alex Bennée
  0 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-08-16 13:47 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/08/14 20:59, Alex Bennée wrote:
> 
> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
> 
>> This is a tree-wide change to replace gdb_core_xml_file, the path to
>> GDB XML file with gdb_core_feature, the pointer to GDBFeature. This
>> also replaces the values assigned to gdb_num_core_regs with the
>> num_regs member of GDBFeature where applicable to remove magic numbers.
>>
>> A following change will utilize additional information provided by
>> GDBFeature to simplify XML file lookup.
>>
>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>> ---
>>   include/hw/core/cpu.h   | 5 +++--
>>   target/s390x/cpu.h      | 2 --
>>   gdbstub/gdbstub.c       | 6 +++---
>>   target/arm/cpu.c        | 4 ++--
>>   target/arm/cpu64.c      | 4 ++--
>>   target/arm/tcg/cpu32.c  | 3 ++-
>>   target/avr/cpu.c        | 4 ++--
>>   target/hexagon/cpu.c    | 2 +-
>>   target/i386/cpu.c       | 7 +++----
>>   target/loongarch/cpu.c  | 4 ++--
>>   target/m68k/cpu.c       | 7 ++++---
>>   target/microblaze/cpu.c | 4 ++--
>>   target/ppc/cpu_init.c   | 4 ++--
>>   target/riscv/cpu.c      | 7 ++++---
>>   target/rx/cpu.c         | 4 ++--
>>   target/s390x/cpu.c      | 4 ++--
>>   16 files changed, 36 insertions(+), 35 deletions(-)
>>
>> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
>> index fdcbe87352..84219c1885 100644
>> --- a/include/hw/core/cpu.h
>> +++ b/include/hw/core/cpu.h
>> @@ -23,6 +23,7 @@
>>   #include "hw/qdev-core.h"
>>   #include "disas/dis-asm.h"
>>   #include "exec/cpu-common.h"
>> +#include "exec/gdbstub.h"
>>   #include "exec/hwaddr.h"
>>   #include "exec/memattrs.h"
>>   #include "qapi/qapi-types-run-state.h"
>> @@ -127,7 +128,7 @@ struct SysemuCPUOps;
>>    *       breakpoint.  Used by AVR to handle a gdb mis-feature with
>>    *       its Harvard architecture split code and data.
>>    * @gdb_num_core_regs: Number of core registers accessible to GDB.
> 
> It seems redundant to have this when gdb_core_features already
> encapsulates this, especially since...
> 
>> - * @gdb_core_xml_file: File name for core registers GDB XML description.
>> + * @gdb_core_feature: GDB core feature description.
>>    * @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
>>    *           before the insn which triggers a watchpoint rather than after it.
>>    * @gdb_arch_name: Optional callback that returns the architecture name known
>> @@ -163,7 +164,7 @@ struct CPUClass {
>>       int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
>>       vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
>>   
>> -    const char *gdb_core_xml_file;
>> +    const GDBFeature *gdb_core_feature;
>>       gchar * (*gdb_arch_name)(CPUState *cpu);
>>       const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
>>   
> <snip>
>> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
>> index d71a162070..a206ab6b1b 100644
>> --- a/target/arm/cpu.c
>> +++ b/target/arm/cpu.c
>> @@ -2353,7 +2353,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>>   #ifndef CONFIG_USER_ONLY
>>       cc->sysemu_ops = &arm_sysemu_ops;
>>   #endif
>> -    cc->gdb_num_core_regs = 26;
>>       cc->gdb_arch_name = arm_gdb_arch_name;
>>       cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
>>       cc->gdb_stop_before_watchpoint = true;
>> @@ -2378,7 +2377,8 @@ static void cpu_register_class_init(ObjectClass *oc, void *data)
>>       CPUClass *cc = CPU_CLASS(acc);
>>   
>>       acc->info = data;
>> -    cc->gdb_core_xml_file = "arm-core.xml";
>> +    cc->gdb_core_feature = gdb_find_static_feature("arm-core.xml");
>> +    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
> 
> You are doing assignments like this. I think something like this in
> gdbstub:
> 
> modified   gdbstub/gdbstub.c
> @@ -440,7 +440,7 @@ int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg, bool has_xml)
>       CPUArchState *env = cpu->env_ptr;
>       GDBRegisterState *r;
>   
> -    if (reg < cc->gdb_num_core_regs) {
> +    if (reg < cc->gdb_core_feature->num_regs) {
>           return cc->gdb_read_register(cpu, buf, reg, has_xml);
>       }
>   
> @@ -459,7 +459,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg,
>       CPUArchState *env = cpu->env_ptr;
>       GDBRegisterState *r;
>   
> -    if (reg < cc->gdb_num_core_regs) {
> +    if (reg < cc->gdb_core_feature->num_regs) {
>           return cc->gdb_write_register(cpu, mem_buf, reg, has_xml);
>       }
> 
> makes most of the uses go away. Some of the other arches might need
> target specific tweaks.

The problem is how to deal with the target specific tweaks. ppc requires 
gdb_num_core_regs to have some value greater than 
cc->gdb_core_feature->num_regs for compatibility with legacy GDB. Other 
architectures simply do not have XMLs. Simply replacing 
cc->gdb_num_core_regs with cc->gdb_core_feature->num_regs will break 
those architectures.

> 
> <snip>
> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 12/24] gdbstub: Simplify XML lookup
  2023-08-14 13:27   ` Alex Bennée
@ 2023-08-16 13:51     ` Akihiko Odaki
  0 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-08-16 13:51 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/08/14 22:27, Alex Bennée wrote:
> 
> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
> 
>> Now we know all instances of GDBFeature that is used in CPU so we can
>> traverse them to find XML. This removes the need for a CPU-specific
>> lookup function for dynamic XMLs.
>>
>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>> ---
>>   gdbstub/gdbstub.c | 28 +++++++++-------------------
>>   1 file changed, 9 insertions(+), 19 deletions(-)
>>
>> diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
>> index 182efe7e0f..e5bb2c89ba 100644
>> --- a/gdbstub/gdbstub.c
>> +++ b/gdbstub/gdbstub.c
>> @@ -354,8 +354,7 @@ static const char *get_feature_xml(const char *p, const char **newp,
>>                                      GDBProcess *process)
>>   {
>>       size_t len;
>> -    int i;
>> -    const char *name;
>> +    GDBRegisterState *r;
>>       CPUState *cpu = gdb_get_first_cpu_in_process(process);
>>       CPUClass *cc = CPU_GET_CLASS(cpu);
>>   
>> @@ -364,15 +363,12 @@ static const char *get_feature_xml(const char *p, const char **newp,
>>           len++;
>>       *newp = p + len;
>>   
>> -    name = NULL;
>>       if (strncmp(p, "target.xml", len) == 0) {
>>           char *buf = process->target_xml;
>>           const size_t buf_sz = sizeof(process->target_xml);
>>   
>>           /* Generate the XML description for this CPU.  */
>>           if (!buf[0]) {
>> -            GDBRegisterState *r;
>> -
>>               pstrcat(buf, buf_sz,
>>                       "<?xml version=\"1.0\"?>"
>>                       "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
>> @@ -389,28 +385,22 @@ static const char *get_feature_xml(const char *p, const char **newp,
>>               pstrcat(buf, buf_sz, "\"/>");
>>               for (r = cpu->gdb_regs; r; r = r->next) {
>>                   pstrcat(buf, buf_sz, "<xi:include href=\"");
>> -                pstrcat(buf, buf_sz, r->feature->xml);
>> +                pstrcat(buf, buf_sz, r->feature->xmlname);
>>                   pstrcat(buf, buf_sz, "\"/>");
>>               }
>>               pstrcat(buf, buf_sz, "</target>");
>>           }
>>           return buf;
>>       }
> 
> It would be nice to modernise this code before adding to it. The static
> target_xml buffer and use of pstrcat could be replaced by GString code
> that is less sketchy.

I saw you did that yourself. Nevertheless I included my own 
implementation for the suggestion in v3. It uses 
g_markup_printf_escaped() for extra caution and better readability (i.e. 
the xi:include tags are written in a format: <xi:include href=\"%s\"/>).

> 
> 
>> -    if (cc->gdb_get_dynamic_xml) {
>> -        char *xmlname = g_strndup(p, len);
>> -        const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname);
>> -
>> -        g_free(xmlname);
>> -        if (xml) {
>> -            return xml;
>> -        }
>> +    if (strncmp(p, cc->gdb_core_feature->xmlname, len) == 0) {
>> +        return cc->gdb_core_feature->xml;
>>       }
>> -    for (i = 0; ; i++) {
>> -        name = gdb_features[i].xmlname;
>> -        if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len))
>> -            break;
>> +    for (r = cpu->gdb_regs; r; r = r->next) {
>> +        if (strncmp(p, r->feature->xmlname, len) == 0) {
>> +            return r->feature->xml;
>> +        }
>>       }
>> -    return name ? gdb_features[i].xml : NULL;
>> +    return NULL;
>>   }
>>   
>>   const GDBFeature *gdb_find_static_feature(const char *xmlname)
> 
> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 15/24] target/arm: Fill new members of GDBFeature
  2023-08-14 14:56   ` Alex Bennée
@ 2023-08-16 14:23     ` Akihiko Odaki
  2023-08-16 15:03       ` Alex Bennée
  0 siblings, 1 reply; 61+ messages in thread
From: Akihiko Odaki @ 2023-08-16 14:23 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/08/14 23:56, Alex Bennée wrote:
> 
> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
> 
>> These members will be used to help plugins to identify registers.
>>
>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>> ---
>>   target/arm/gdbstub.c   | 46 +++++++++++++++++++++++++++---------------
>>   target/arm/gdbstub64.c | 42 +++++++++++++++++++++++++-------------
>>   2 files changed, 58 insertions(+), 30 deletions(-)
>>
>> diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
>> index 100a6eed15..56d24028f6 100644
>> --- a/target/arm/gdbstub.c
>> +++ b/target/arm/gdbstub.c
>> @@ -270,6 +270,7 @@ static void arm_gen_one_feature_sysreg(GString *s,
>>       g_string_append_printf(s, " regnum=\"%d\"", regnum);
>>       g_string_append_printf(s, " group=\"cp_regs\"/>");
>>       dyn_feature->data.cpregs.keys[dyn_feature->desc.num_regs] = ri_key;
>> +    ((const char **)dyn_feature->desc.regs)[dyn_feature->desc.num_regs] = ri->name;
>>       dyn_feature->desc.num_regs++;
>>   }
>>   
>> @@ -316,6 +317,8 @@ static GDBFeature *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
>>       DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
>>       gsize num_regs = g_hash_table_size(cpu->cp_regs);
>>   
>> +    dyn_feature->desc.name = "org.qemu.gdb.arm.sys.regs";
>> +    dyn_feature->desc.regs = g_new(const char *, num_regs);
> 
> AIUI this means we now have an array of register names which mirrors the
> names embedded in the XML. This smells like a few steps away from just
> abstracting the whole XML away from the targets and generating them
> inside gdbstub when we need them. As per my stalled attempt I referenced
> earlier.

The abstraction is strictly limited for identifiers. Most plugin should 
already have some knowledge of how registers are used. For example, a 
plugin that tracks stack frame for RISC-V should know sp is the stack 
pointer register. Similarly, a cycle simulator plugin should know how 
registers are used in a program. Only identifiers matter in such cases.

I'm definitely *not* in favor of abstracting the whole XML for plugins. 
It will be too hard to maintain ABI compatibility when a new attribute 
emerges, for example.

> 
> 
>>       dyn_feature->desc.num_regs = 0;
>>       dyn_feature->data.cpregs.keys = g_new(uint32_t, num_regs);
>>       g_string_printf(s, "<?xml version=\"1.0\"?>");
>> @@ -418,30 +421,34 @@ static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg)
>>   }
>>   
>>   static GDBFeature *arm_gen_dynamic_m_systemreg_feature(CPUState *cs,
>> -                                                       int orig_base_reg)
>> +                                                       int base_reg)
>>   {
>>       ARMCPU *cpu = ARM_CPU(cs);
>>       CPUARMState *env = &cpu->env;
>>       GString *s = g_string_new(NULL);
>> -    int base_reg = orig_base_reg;
>> -    int i;
>> +    const char **regs = g_new(const char *, ARRAY_SIZE(m_sysreg_def));
>> +    int i = 0;
>> +    int j;
>>   
>>       g_string_printf(s, "<?xml version=\"1.0\"?>");
>>       g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
>>       g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.m-system\">\n");
>>   
>> -    for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
>> -        if (arm_feature(env, m_sysreg_def[i].feature)) {
>> +    for (j = 0; j < ARRAY_SIZE(m_sysreg_def); j++) {
>> +        if (arm_feature(env, m_sysreg_def[j].feature)) {
>> +            regs[i] = m_sysreg_def[j].name;
>>               g_string_append_printf(s,
>>                   "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
>> -                m_sysreg_def[i].name, base_reg++);
>> +                m_sysreg_def[j].name, base_reg + i++);
>>           }
>>       }
>>   
>>       g_string_append_printf(s, "</feature>");
>> +    cpu->dyn_m_systemreg_feature.desc.name = "org.gnu.gdb.arm.m-system";
>>       cpu->dyn_m_systemreg_feature.desc.xmlname = "arm-m-system.xml";
>>       cpu->dyn_m_systemreg_feature.desc.xml = g_string_free(s, false);
>> -    cpu->dyn_m_systemreg_feature.desc.num_regs = base_reg - orig_base_reg;
>> +    cpu->dyn_m_systemreg_feature.desc.regs = regs;
>> +    cpu->dyn_m_systemreg_feature.desc.num_regs = i;
>>   
>>       return &cpu->dyn_m_systemreg_feature.desc;
>>   }
>> @@ -462,30 +469,37 @@ static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg)
>>   }
>>   
>>   static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
>> -                                                       int orig_base_reg)
>> +                                                       int base_reg)
>>   {
>>       ARMCPU *cpu = ARM_CPU(cs);
>>       GString *s = g_string_new(NULL);
>> -    int base_reg = orig_base_reg;
>> -    int i;
>> +    const char **regs = g_new(const char *, ARRAY_SIZE(m_sysreg_def) * 2);
>> +    int i = 0;
>> +    int j;
>>   
>>       g_string_printf(s, "<?xml version=\"1.0\"?>");
>>       g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
>>       g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.secext\">\n");
>>   
>> -    for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
>> +    for (j = 0; j < ARRAY_SIZE(m_sysreg_def); j++) {
>> +        regs[i] = g_strconcat(m_sysreg_def[j].name, "_ns", NULL);
>>           g_string_append_printf(s,
>> -            "<reg name=\"%s_ns\" bitsize=\"32\" regnum=\"%d\"/>\n",
>> -            m_sysreg_def[i].name, base_reg++);
>> +            "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
>> +            regs[i], base_reg + i);
>> +        i++;
>> +        regs[i] = g_strconcat(m_sysreg_def[j].name, "_s", NULL);
>>           g_string_append_printf(s,
>> -            "<reg name=\"%s_s\" bitsize=\"32\" regnum=\"%d\"/>\n",
>> -            m_sysreg_def[i].name, base_reg++);
>> +            "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
>> +            regs[i], base_reg + i);
>> +        i++;
>>       }
>>   
>>       g_string_append_printf(s, "</feature>");
>> +    cpu->dyn_m_secextreg_feature.desc.name = "org.gnu.gdb.arm.secext";
>>       cpu->dyn_m_secextreg_feature.desc.xmlname = "arm-m-secext.xml";
>>       cpu->dyn_m_secextreg_feature.desc.xml = g_string_free(s, false);
>> -    cpu->dyn_m_secextreg_feature.desc.num_regs = base_reg - orig_base_reg;
>> +    cpu->dyn_m_secextreg_feature.desc.regs = regs;
>> +    cpu->dyn_m_secextreg_feature.desc.num_regs = i;
>>   
>>       return &cpu->dyn_m_secextreg_feature.desc;
>>   }
>> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
>> index 20483ef9bc..c5ed7c0aa3 100644
>> --- a/target/arm/gdbstub64.c
>> +++ b/target/arm/gdbstub64.c
>> @@ -316,15 +316,21 @@ static void output_vector_union_type(GString *s, int reg_width,
>>       g_string_append(s, "</union>");
>>   }
>>   
>> -GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int orig_base_reg)
>> +GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int base_reg)
>>   {
>>       ARMCPU *cpu = ARM_CPU(cs);
>>       GString *s = g_string_new(NULL);
>>       DynamicGDBFeatureInfo *info = &cpu->dyn_svereg_feature;
>> +    const char **regs;
>>       int reg_width = cpu->sve_max_vq * 128;
>>       int pred_width = cpu->sve_max_vq * 16;
>> -    int base_reg = orig_base_reg;
>> -    int i;
>> +    int i = 0;
>> +    int j;
>> +
>> +    info->desc.name = "org.gnu.gdb.aarch64.sve";
>> +    info->desc.num_regs = 32 + 16 + 4;
>> +    regs = g_new(const char *, info->desc.num_regs);
>> +    info->desc.regs = regs;
>>   
>>       g_string_printf(s, "<?xml version=\"1.0\"?>");
>>       g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
>> @@ -339,44 +345,52 @@ GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int orig_base_reg)
>>                              pred_width / 8);
>>   
>>       /* Define the vector registers. */
>> -    for (i = 0; i < 32; i++) {
>> +    for (j = 0; j < 32; j++) {
>> +        regs[i] = g_strdup_printf("z%d", j);
>>           g_string_append_printf(s,
>> -                               "<reg name=\"z%d\" bitsize=\"%d\""
>> +                               "<reg name=\"%s\" bitsize=\"%d\""
>>                                  " regnum=\"%d\" type=\"svev\"/>",
>> -                               i, reg_width, base_reg++);
>> +                               regs[i], reg_width, base_reg + i);
>> +        i++;
>>       }
>>   
>>       /* fpscr & status registers */
>> +    regs[i] = "fpsr";
>>       g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
>>                              " regnum=\"%d\" group=\"float\""
>> -                           " type=\"int\"/>", base_reg++);
>> +                           " type=\"int\"/>", base_reg + i++);
>> +    regs[i] = "fpcr";
>>       g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
>>                              " regnum=\"%d\" group=\"float\""
>> -                           " type=\"int\"/>", base_reg++);
>> +                           " type=\"int\"/>", base_reg + i++);
>>   
>>       /* Define the predicate registers. */
>> -    for (i = 0; i < 16; i++) {
>> +    for (j = 0; j < 16; j++) {
>> +        regs[i] = g_strdup_printf("p%d", j);
>>           g_string_append_printf(s,
>> -                               "<reg name=\"p%d\" bitsize=\"%d\""
>> +                               "<reg name=\"%s\" bitsize=\"%d\""
>>                                  " regnum=\"%d\" type=\"svep\"/>",
>> -                               i, pred_width, base_reg++);
>> +                               regs[i], pred_width, base_reg + i);
>> +        i++;
>>       }
>> +    regs[i] = "ffr";
>>       g_string_append_printf(s,
>>                              "<reg name=\"ffr\" bitsize=\"%d\""
>>                              " regnum=\"%d\" group=\"vector\""
>>                              " type=\"svep\"/>",
>> -                           pred_width, base_reg++);
>> +                           pred_width, base_reg + i++);
>>   
>>       /* Define the vector length pseudo-register. */
>> +    regs[i] = "vg";
>>       g_string_append_printf(s,
>>                              "<reg name=\"vg\" bitsize=\"64\""
>>                              " regnum=\"%d\" type=\"int\"/>",
>> -                           base_reg++);
>> +                           base_reg + i++);
>>   
>>       g_string_append_printf(s, "</feature>");
>>   
>>       info->desc.xmlname = "sve-registers.xml";
>>       info->desc.xml = g_string_free(s, false);
>> -    info->desc.num_regs = base_reg - orig_base_reg;
>> +    assert(info->desc.num_regs == i);
>>       return &info->desc;
>>   }
> 
> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 21/24] plugins: Allow to read registers
  2023-08-14 15:05   ` Alex Bennée
@ 2023-08-16 14:38     ` Akihiko Odaki
  0 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-08-16 14:38 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/08/15 0:05, Alex Bennée wrote:
> 
> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
> 
>> It is based on GDB protocol to ensure interface stability.
> 
> See comments bellow.
> 
>> The timing of the vcpu init hook is also changed so that the hook will
>> get called after GDB features are initialized.
> 
> This might be worth splitting to a separate patch for cleaner bisecting.
> 
>>
>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>> ---
>>   include/qemu/qemu-plugin.h   | 65 ++++++++++++++++++++++++++++++++++--
>>   cpu.c                        | 11 ------
>>   hw/core/cpu-common.c         | 10 ++++++
>>   plugins/api.c                | 40 ++++++++++++++++++++++
>>   plugins/qemu-plugins.symbols |  2 ++
>>   5 files changed, 114 insertions(+), 14 deletions(-)
>>
>> diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
>> index 50a9957279..214b12bfd6 100644
>> --- a/include/qemu/qemu-plugin.h
>> +++ b/include/qemu/qemu-plugin.h
>> @@ -11,6 +11,7 @@
>>   #ifndef QEMU_QEMU_PLUGIN_H
>>   #define QEMU_QEMU_PLUGIN_H
>>   
>> +#include <glib.h>
>>   #include <inttypes.h>
>>   #include <stdbool.h>
>>   #include <stddef.h>
>> @@ -51,7 +52,7 @@ typedef uint64_t qemu_plugin_id_t;
>>   
>>   extern QEMU_PLUGIN_EXPORT int qemu_plugin_version;
>>   
>> -#define QEMU_PLUGIN_VERSION 1
>> +#define QEMU_PLUGIN_VERSION 2
>>   
>>   /**
>>    * struct qemu_info_t - system information for plugins
>> @@ -218,8 +219,8 @@ struct qemu_plugin_insn;
>>    * @QEMU_PLUGIN_CB_R_REGS: callback reads the CPU's regs
>>    * @QEMU_PLUGIN_CB_RW_REGS: callback reads and writes the CPU's regs
>>    *
>> - * Note: currently unused, plugins cannot read or change system
>> - * register state.
>> + * Note: currently QEMU_PLUGIN_CB_RW_REGS is unused, plugins cannot change
>> + * system register state.
>>    */
>>   enum qemu_plugin_cb_flags {
>>       QEMU_PLUGIN_CB_NO_REGS,
>> @@ -664,4 +665,62 @@ uint64_t qemu_plugin_end_code(void);
>>    */
>>   uint64_t qemu_plugin_entry_code(void);
>>   
>> +/**
>> + * struct qemu_plugin_register_file_t - register information
>> + *
>> + * This structure identifies registers. The identifiers included in this
>> + * structure are identical with names used in GDB's standard target features
>> + * with some extensions. For details, see:
>> + *
>> https://sourceware.org/gdb/onlinedocs/gdb/Standard-Target-Features.html
> 
> I'm not super keen on baking GDB-isms into the plugin register
> interface.

I used GDB names here because I just didn't want to invent feature 
register names again. We can use any other register name dictionary if 
desired.

> 
>> + *
>> + * A register is uniquely identified with the combination of a feature name
>> + * and a register name or a register number. It is recommended to derive
>> + * register numbers from feature names and register names each time a new vcpu
>> + * starts.
> 
> Do you have examples of clashing register names from different feature
> sets?

No. A possible situation that the feature name matters is that a vendor 
extension becomes a standard extension with some modifications. In such 
a case, plugins written for the ratified standard extension may reject 
to work with the processor with the original vendor extension. While 
such a situation has not happened for QEMU and it's unlikely to happen, 
I'm advising to use feature name for register identification just for 
caution.

> 
>> + *
>> + * To derive the register number from a feature name and a register name,
>> + * first look up qemu_plugin_register_file_t with the feature name, and then
>> + * look up the register name in its @regs. The sum of the @base_reg and the
>> + * index in the @reg is the register number.
>> + *
>> + * Note that @regs may have holes; some elements of @regs may be NULL.
>> + */
>> +typedef struct qemu_plugin_register_file_t {
>> +    /** @name: feature name */
>> +    const char *name;
>> +    /** @regs: register names */
>> +    const char * const *regs;
>> +    /** @base_reg: the base identified number */
>> +    int base_reg;
>> +    /** @num_regs: the number of elements in @regs */
>> +    int num_regs;
>> +} qemu_plugin_register_file_t;
>> +
>> +/**
>> + * qemu_plugin_get_register_files() - returns register information
>> + *
>> + * @vcpu_index: the index of the vcpu context
>> + * @size: the pointer to the variable to hold the number of returned elements
>> + *
>> + * Returns an array of qemu_plugin_register_file_t. The user should g_free()
>> + * the array once no longer needed.
>> + */
>> +qemu_plugin_register_file_t *
>> +qemu_plugin_get_register_files(unsigned int vcpu_index, int *size);
> 
> I think I'd rather have a simpler interface that returns an anonymous
> handle to the plugin. For example:
> 
>    struct qemu_plugin_register;
>    struct qemu_plugin_register qemu_plugin_find_register(const char *name);
> 
>> +
>> +/**
>> + * qemu_plugin_read_register() - read register
>> + *
>> + * @buf: the byte array to append the read register content to.
>> + * @reg: the register identifier determined with
>> + *       qemu_plugin_get_register_files().
>> + *
>> + * This function is only available in a context that register read access is
>> + * explicitly requested.
>> + *
>> + * Returns the size of the read register. The content of @buf is in target byte
>> + * order.
>> + */
>> +int qemu_plugin_read_register(GByteArray *buf, int reg);
> 
> and this then becomes:
> 
>    int qemu_plugin_read_register(GByteArray *buf, struct qemu_plugin_register);
> 
> in practice these can become anonymous pointers which hide the
> implementation details from the plugin itself. Then the details of
> mapping the register to a gdb regnum can be kept in the plugin code
> keeping us free to further re-factor the code as we go.
> 
> The plugin code works quite hard to try and avoid leaking implementation
> details to plugins so as not to tie QEMU's hands in re-factoring. While
> the interface provided is technically GDB's, not QEMUs I don't think its
> a particularly nice one to expose.

Unfortunately "struct qemu_plugin_register" will not work. C requires 
the size of the struct to be known before a declaration of a function 
that uses the struct as a return value or parameter.

The best thing we can do is to add typedef just in a manner similar to 
qemu_plugin_id_t.

I added a function that returns all register information instead of a 
function that looks up a register so that a plugin can enumerate 
registers. Such capability is useful for a plugin that dumps all 
registers or a plugin that simulates processor (such a plugin may want 
to warn if there are unknown registers).

I'm just using GDB regnum here because I just needed some numbers. The 
numbers are actually arbitrary and I intentionally did not assure that 
the numbers are identical with what GDB use in the documentation 
comments. We may use any other arbitrary numbers as we want in the future.

> 
> <snip>
> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 22/24] contrib/plugins: Allow to log registers
  2023-08-14 15:21   ` Alex Bennée
@ 2023-08-16 14:59     ` Akihiko Odaki
  0 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-08-16 14:59 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/08/15 0:21, Alex Bennée wrote:
> 
> 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

I changed this plugin so that it only emits register values when changed 
in v4 (I noticed I sent a wrong patch in v3), but it's not readable as 
much as your suggestion. It now emits like:

0, 0x4001b4, 0xd10043ff, "sub sp, sp, #0x10", reg, 70 ff 7f 00 00 40 00 00

This is because it's following the current CSV-like format of execlog 
output.

It will not also emit the value like 0x70ff7f0000400000 since the plugin 
does not know how the bytes should be interpreted. In fact, in this case 
I think it is in little endian and should be written as 0x4000007fff70. 
However the plugin does not have such knowledge.

> 
> 
>> +        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);
> 
> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  2023-08-16 13:47     ` Akihiko Odaki
@ 2023-08-16 15:00       ` Alex Bennée
  2023-08-16 15:10         ` Akihiko Odaki
  0 siblings, 1 reply; 61+ messages in thread
From: Alex Bennée @ 2023-08-16 15:00 UTC (permalink / raw)
  To: Alex Bennée, Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> On 2023/08/14 20:59, Alex Bennée wrote:
>> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
>> 
>>> This is a tree-wide change to replace gdb_core_xml_file, the path to
>>> GDB XML file with gdb_core_feature, the pointer to GDBFeature. This
>>> also replaces the values assigned to gdb_num_core_regs with the
>>> num_regs member of GDBFeature where applicable to remove magic numbers.
>>>
>>> A following change will utilize additional information provided by
>>> GDBFeature to simplify XML file lookup.
>>>
>>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>>> ---
>>>   include/hw/core/cpu.h   | 5 +++--
>>>   target/s390x/cpu.h      | 2 --
>>>   gdbstub/gdbstub.c       | 6 +++---
>>>   target/arm/cpu.c        | 4 ++--
>>>   target/arm/cpu64.c      | 4 ++--
>>>   target/arm/tcg/cpu32.c  | 3 ++-
>>>   target/avr/cpu.c        | 4 ++--
>>>   target/hexagon/cpu.c    | 2 +-
>>>   target/i386/cpu.c       | 7 +++----
>>>   target/loongarch/cpu.c  | 4 ++--
>>>   target/m68k/cpu.c       | 7 ++++---
>>>   target/microblaze/cpu.c | 4 ++--
>>>   target/ppc/cpu_init.c   | 4 ++--
>>>   target/riscv/cpu.c      | 7 ++++---
>>>   target/rx/cpu.c         | 4 ++--
>>>   target/s390x/cpu.c      | 4 ++--
>>>   16 files changed, 36 insertions(+), 35 deletions(-)
>>>
>>> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
>>> index fdcbe87352..84219c1885 100644
>>> --- a/include/hw/core/cpu.h
>>> +++ b/include/hw/core/cpu.h
>>> @@ -23,6 +23,7 @@
>>>   #include "hw/qdev-core.h"
>>>   #include "disas/dis-asm.h"
>>>   #include "exec/cpu-common.h"
>>> +#include "exec/gdbstub.h"
>>>   #include "exec/hwaddr.h"
>>>   #include "exec/memattrs.h"
>>>   #include "qapi/qapi-types-run-state.h"
>>> @@ -127,7 +128,7 @@ struct SysemuCPUOps;
>>>    *       breakpoint.  Used by AVR to handle a gdb mis-feature with
>>>    *       its Harvard architecture split code and data.
>>>    * @gdb_num_core_regs: Number of core registers accessible to GDB.
>> It seems redundant to have this when gdb_core_features already
>> encapsulates this, especially since...
>> 
>>> - * @gdb_core_xml_file: File name for core registers GDB XML description.
>>> + * @gdb_core_feature: GDB core feature description.
>>>    * @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
>>>    *           before the insn which triggers a watchpoint rather than after it.
>>>    * @gdb_arch_name: Optional callback that returns the architecture name known
>>> @@ -163,7 +164,7 @@ struct CPUClass {
>>>       int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
>>>       vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
>>>   -    const char *gdb_core_xml_file;
>>> +    const GDBFeature *gdb_core_feature;
>>>       gchar * (*gdb_arch_name)(CPUState *cpu);
>>>       const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
>>>   
>> <snip>
>>> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
>>> index d71a162070..a206ab6b1b 100644
>>> --- a/target/arm/cpu.c
>>> +++ b/target/arm/cpu.c
>>> @@ -2353,7 +2353,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>>>   #ifndef CONFIG_USER_ONLY
>>>       cc->sysemu_ops = &arm_sysemu_ops;
>>>   #endif
>>> -    cc->gdb_num_core_regs = 26;
>>>       cc->gdb_arch_name = arm_gdb_arch_name;
>>>       cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
>>>       cc->gdb_stop_before_watchpoint = true;
>>> @@ -2378,7 +2377,8 @@ static void cpu_register_class_init(ObjectClass *oc, void *data)
>>>       CPUClass *cc = CPU_CLASS(acc);
>>>         acc->info = data;
>>> -    cc->gdb_core_xml_file = "arm-core.xml";
>>> +    cc->gdb_core_feature = gdb_find_static_feature("arm-core.xml");
>>> +    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
>> You are doing assignments like this. I think something like this in
>> gdbstub:
>> modified   gdbstub/gdbstub.c
>> @@ -440,7 +440,7 @@ int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg, bool has_xml)
>>       CPUArchState *env = cpu->env_ptr;
>>       GDBRegisterState *r;
>>   -    if (reg < cc->gdb_num_core_regs) {
>> +    if (reg < cc->gdb_core_feature->num_regs) {
>>           return cc->gdb_read_register(cpu, buf, reg, has_xml);
>>       }
>>   @@ -459,7 +459,7 @@ static int gdb_write_register(CPUState *cpu,
>> uint8_t *mem_buf, int reg,
>>       CPUArchState *env = cpu->env_ptr;
>>       GDBRegisterState *r;
>>   -    if (reg < cc->gdb_num_core_regs) {
>> +    if (reg < cc->gdb_core_feature->num_regs) {
>>           return cc->gdb_write_register(cpu, mem_buf, reg, has_xml);
>>       }
>> makes most of the uses go away. Some of the other arches might need
>> target specific tweaks.
>
> The problem is how to deal with the target specific tweaks. ppc
> requires gdb_num_core_regs to have some value greater than
> cc->gdb_core_feature->num_regs for compatibility with legacy GDB.
> Other architectures simply do not have XMLs. Simply replacing
> cc->gdb_num_core_regs with cc->gdb_core_feature->num_regs will break
> those architectures.

How about:

  int core_regs = cc->gdb_core_feature ? cc->gdb_core_feature->num_regs
  : cc->gdb_num_core_regs

And document the field as for legacy gdb use only?

>
>> <snip>
>> 


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 15/24] target/arm: Fill new members of GDBFeature
  2023-08-16 14:23     ` Akihiko Odaki
@ 2023-08-16 15:03       ` Alex Bennée
  2023-08-16 15:11         ` Akihiko Odaki
  0 siblings, 1 reply; 61+ messages in thread
From: Alex Bennée @ 2023-08-16 15:03 UTC (permalink / raw)
  To: Alex Bennée, Akihiko Odaki
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x


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

> On 2023/08/14 23:56, Alex Bennée wrote:
>> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
>> 
>>> These members will be used to help plugins to identify registers.
>>>
>>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>>> ---
>>>   target/arm/gdbstub.c   | 46 +++++++++++++++++++++++++++---------------
>>>   target/arm/gdbstub64.c | 42 +++++++++++++++++++++++++-------------
>>>   2 files changed, 58 insertions(+), 30 deletions(-)
>>>
>>> diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
>>> index 100a6eed15..56d24028f6 100644
>>> --- a/target/arm/gdbstub.c
>>> +++ b/target/arm/gdbstub.c
>>> @@ -270,6 +270,7 @@ static void arm_gen_one_feature_sysreg(GString *s,
>>>       g_string_append_printf(s, " regnum=\"%d\"", regnum);
>>>       g_string_append_printf(s, " group=\"cp_regs\"/>");
>>>       dyn_feature->data.cpregs.keys[dyn_feature->desc.num_regs] = ri_key;
>>> +    ((const char **)dyn_feature->desc.regs)[dyn_feature->desc.num_regs] = ri->name;
>>>       dyn_feature->desc.num_regs++;
>>>   }
>>>   @@ -316,6 +317,8 @@ static GDBFeature
>>> *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
>>>       DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
>>>       gsize num_regs = g_hash_table_size(cpu->cp_regs);
>>>   +    dyn_feature->desc.name = "org.qemu.gdb.arm.sys.regs";
>>> +    dyn_feature->desc.regs = g_new(const char *, num_regs);
>> AIUI this means we now have an array of register names which mirrors
>> the
>> names embedded in the XML. This smells like a few steps away from just
>> abstracting the whole XML away from the targets and generating them
>> inside gdbstub when we need them. As per my stalled attempt I referenced
>> earlier.
>
> The abstraction is strictly limited for identifiers. Most plugin
> should already have some knowledge of how registers are used. For
> example, a plugin that tracks stack frame for RISC-V should know sp is
> the stack pointer register. Similarly, a cycle simulator plugin should
> know how registers are used in a program. Only identifiers matter in
> such cases.
>
> I'm definitely *not* in favor of abstracting the whole XML for
> plugins. It will be too hard to maintain ABI compatibility when a new
> attribute emerges, for example.

No I agree the XML shouldn't go near the plugins. I was just looking to
avoid having an XML builder for every target.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 24/24] contrib/plugins: Add cc plugin
  2023-08-14 15:23   ` Alex Bennée
@ 2023-08-16 15:04     ` Akihiko Odaki
  0 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-08-16 15:04 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/08/15 0:23, Alex Bennée wrote:
> 
> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
> 
>> This demonstrates how to write a plugin in C++.
>>
>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>> ---
>>   docs/devel/tcg-plugins.rst |  8 ++++++++
>>   configure                  | 15 ++++++++++++---
>>   contrib/plugins/Makefile   |  5 +++++
>>   contrib/plugins/cc.cc      | 15 +++++++++++++++
>>   tests/tcg/Makefile.target  |  3 +++
>>   5 files changed, 43 insertions(+), 3 deletions(-)
>>   create mode 100644 contrib/plugins/cc.cc
>>
>> diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst
>> index c9f8b27590..0a11f8036c 100644
>> --- a/docs/devel/tcg-plugins.rst
>> +++ b/docs/devel/tcg-plugins.rst
>> @@ -584,6 +584,14 @@ The plugin has a number of arguments, all of them are optional:
>>     configuration arguments implies ``l2=on``.
>>     (default: N = 2097152 (2MB), B = 64, A = 16)
>>   
>> +- contrib/plugins/cc.cc
>> +
>> +cc plugin demonstrates how to write a plugin in C++. It simply outputs
>> +"hello, world" to the plugin log::
>> +
>> +  $ qemu-system-arm $(QEMU_ARGS) \
>> +    -plugin ./contrib/plugins/libcc.so -d plugin
>> +
> 
> I'm going to assume this is useful because you have some out of tree C++
> plugins? I'd drop the last two patches for now until there is a slightly
> more compelling use case.

The out-of-tree plugin is mentioned in the cover letter and available at:
https://github.com/shioya-lab/sniper/tree/akihikodaki/bb/frontend/qemu-frontend

This plugin emits a trace of execution for use in Sniper simulator. I 
believe it's useful for other people doing microarchitecture research 
since processor simulation infrastructure is often written in C++.

> 
> The C++ compiler detection moved into meson in b485458e00 (configure,
> meson: move C++ compiler detection to meson.build) so I don't think
> there is currently a compelling reason to bring this back into
> configure.
> 

It is necessary because TCG tests use Makefile and config-host.mak is 
emitted by configure. We can remove C++ detection from configure when 
TCG tests or the config-host.mak generation migrate to Meson.


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 06/24] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  2023-08-16 15:00       ` Alex Bennée
@ 2023-08-16 15:10         ` Akihiko Odaki
  0 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-08-16 15:10 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/08/17 0:00, Alex Bennée wrote:
> 
> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
> 
>> On 2023/08/14 20:59, Alex Bennée wrote:
>>> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
>>>
>>>> This is a tree-wide change to replace gdb_core_xml_file, the path to
>>>> GDB XML file with gdb_core_feature, the pointer to GDBFeature. This
>>>> also replaces the values assigned to gdb_num_core_regs with the
>>>> num_regs member of GDBFeature where applicable to remove magic numbers.
>>>>
>>>> A following change will utilize additional information provided by
>>>> GDBFeature to simplify XML file lookup.
>>>>
>>>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>>>> ---
>>>>    include/hw/core/cpu.h   | 5 +++--
>>>>    target/s390x/cpu.h      | 2 --
>>>>    gdbstub/gdbstub.c       | 6 +++---
>>>>    target/arm/cpu.c        | 4 ++--
>>>>    target/arm/cpu64.c      | 4 ++--
>>>>    target/arm/tcg/cpu32.c  | 3 ++-
>>>>    target/avr/cpu.c        | 4 ++--
>>>>    target/hexagon/cpu.c    | 2 +-
>>>>    target/i386/cpu.c       | 7 +++----
>>>>    target/loongarch/cpu.c  | 4 ++--
>>>>    target/m68k/cpu.c       | 7 ++++---
>>>>    target/microblaze/cpu.c | 4 ++--
>>>>    target/ppc/cpu_init.c   | 4 ++--
>>>>    target/riscv/cpu.c      | 7 ++++---
>>>>    target/rx/cpu.c         | 4 ++--
>>>>    target/s390x/cpu.c      | 4 ++--
>>>>    16 files changed, 36 insertions(+), 35 deletions(-)
>>>>
>>>> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
>>>> index fdcbe87352..84219c1885 100644
>>>> --- a/include/hw/core/cpu.h
>>>> +++ b/include/hw/core/cpu.h
>>>> @@ -23,6 +23,7 @@
>>>>    #include "hw/qdev-core.h"
>>>>    #include "disas/dis-asm.h"
>>>>    #include "exec/cpu-common.h"
>>>> +#include "exec/gdbstub.h"
>>>>    #include "exec/hwaddr.h"
>>>>    #include "exec/memattrs.h"
>>>>    #include "qapi/qapi-types-run-state.h"
>>>> @@ -127,7 +128,7 @@ struct SysemuCPUOps;
>>>>     *       breakpoint.  Used by AVR to handle a gdb mis-feature with
>>>>     *       its Harvard architecture split code and data.
>>>>     * @gdb_num_core_regs: Number of core registers accessible to GDB.
>>> It seems redundant to have this when gdb_core_features already
>>> encapsulates this, especially since...
>>>
>>>> - * @gdb_core_xml_file: File name for core registers GDB XML description.
>>>> + * @gdb_core_feature: GDB core feature description.
>>>>     * @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
>>>>     *           before the insn which triggers a watchpoint rather than after it.
>>>>     * @gdb_arch_name: Optional callback that returns the architecture name known
>>>> @@ -163,7 +164,7 @@ struct CPUClass {
>>>>        int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
>>>>        vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
>>>>    -    const char *gdb_core_xml_file;
>>>> +    const GDBFeature *gdb_core_feature;
>>>>        gchar * (*gdb_arch_name)(CPUState *cpu);
>>>>        const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
>>>>    
>>> <snip>
>>>> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
>>>> index d71a162070..a206ab6b1b 100644
>>>> --- a/target/arm/cpu.c
>>>> +++ b/target/arm/cpu.c
>>>> @@ -2353,7 +2353,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>>>>    #ifndef CONFIG_USER_ONLY
>>>>        cc->sysemu_ops = &arm_sysemu_ops;
>>>>    #endif
>>>> -    cc->gdb_num_core_regs = 26;
>>>>        cc->gdb_arch_name = arm_gdb_arch_name;
>>>>        cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
>>>>        cc->gdb_stop_before_watchpoint = true;
>>>> @@ -2378,7 +2377,8 @@ static void cpu_register_class_init(ObjectClass *oc, void *data)
>>>>        CPUClass *cc = CPU_CLASS(acc);
>>>>          acc->info = data;
>>>> -    cc->gdb_core_xml_file = "arm-core.xml";
>>>> +    cc->gdb_core_feature = gdb_find_static_feature("arm-core.xml");
>>>> +    cc->gdb_num_core_regs = cc->gdb_core_feature->num_regs;
>>> You are doing assignments like this. I think something like this in
>>> gdbstub:
>>> modified   gdbstub/gdbstub.c
>>> @@ -440,7 +440,7 @@ int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg, bool has_xml)
>>>        CPUArchState *env = cpu->env_ptr;
>>>        GDBRegisterState *r;
>>>    -    if (reg < cc->gdb_num_core_regs) {
>>> +    if (reg < cc->gdb_core_feature->num_regs) {
>>>            return cc->gdb_read_register(cpu, buf, reg, has_xml);
>>>        }
>>>    @@ -459,7 +459,7 @@ static int gdb_write_register(CPUState *cpu,
>>> uint8_t *mem_buf, int reg,
>>>        CPUArchState *env = cpu->env_ptr;
>>>        GDBRegisterState *r;
>>>    -    if (reg < cc->gdb_num_core_regs) {
>>> +    if (reg < cc->gdb_core_feature->num_regs) {
>>>            return cc->gdb_write_register(cpu, mem_buf, reg, has_xml);
>>>        }
>>> makes most of the uses go away. Some of the other arches might need
>>> target specific tweaks.
>>
>> The problem is how to deal with the target specific tweaks. ppc
>> requires gdb_num_core_regs to have some value greater than
>> cc->gdb_core_feature->num_regs for compatibility with legacy GDB.
>> Other architectures simply do not have XMLs. Simply replacing
>> cc->gdb_num_core_regs with cc->gdb_core_feature->num_regs will break
>> those architectures.
> 
> How about:
> 
>    int core_regs = cc->gdb_core_feature ? cc->gdb_core_feature->num_regs
>    : cc->gdb_num_core_regs
> 
> And document the field as for legacy gdb use only?

I'm not sure. It looks a more error-prone way to derive the core 
register number.

> 
>>
>>> <snip>
>>>
> 
> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [RFC PATCH 15/24] target/arm: Fill new members of GDBFeature
  2023-08-16 15:03       ` Alex Bennée
@ 2023-08-16 15:11         ` Akihiko Odaki
  0 siblings, 0 replies; 61+ messages in thread
From: Akihiko Odaki @ 2023-08-16 15:11 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Thomas Huth, Alexandre Iooss, Mahmoud Mandour,
	Eduardo Habkost, Marcel Apfelbaum, Philippe Mathieu-Daudé,
	Yanan Wang, Richard Henderson, Marc-André Lureau,
	Daniel P. Berrangé,
	John Snow, Cleber Rosa, Peter Maydell, Michael Rolnik,
	Edgar E. Iglesias, Brian Cain, Song Gao, Xiaojuan Yang,
	Laurent Vivier, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo,
	Chris Wulff, Marek Vasut, Stafford Horne,
	Daniel Henrique Barboza, Cédric Le Goater, David Gibson,
	Greg Kurz, Nicholas Piggin, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Liu Zhiwei, Yoshinori Sato,
	David Hildenbrand, Ilya Leoshkevich, Mark Cave-Ayland,
	Artyom Tarasenko, Bastian Koppelmann, Max Filippov, qemu-devel,
	qemu-arm, qemu-ppc, qemu-riscv, qemu-s390x

On 2023/08/17 0:03, Alex Bennée wrote:
> 
> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
> 
>> On 2023/08/14 23:56, Alex Bennée wrote:
>>> Akihiko Odaki <akihiko.odaki@daynix.com> writes:
>>>
>>>> These members will be used to help plugins to identify registers.
>>>>
>>>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>>>> ---
>>>>    target/arm/gdbstub.c   | 46 +++++++++++++++++++++++++++---------------
>>>>    target/arm/gdbstub64.c | 42 +++++++++++++++++++++++++-------------
>>>>    2 files changed, 58 insertions(+), 30 deletions(-)
>>>>
>>>> diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
>>>> index 100a6eed15..56d24028f6 100644
>>>> --- a/target/arm/gdbstub.c
>>>> +++ b/target/arm/gdbstub.c
>>>> @@ -270,6 +270,7 @@ static void arm_gen_one_feature_sysreg(GString *s,
>>>>        g_string_append_printf(s, " regnum=\"%d\"", regnum);
>>>>        g_string_append_printf(s, " group=\"cp_regs\"/>");
>>>>        dyn_feature->data.cpregs.keys[dyn_feature->desc.num_regs] = ri_key;
>>>> +    ((const char **)dyn_feature->desc.regs)[dyn_feature->desc.num_regs] = ri->name;
>>>>        dyn_feature->desc.num_regs++;
>>>>    }
>>>>    @@ -316,6 +317,8 @@ static GDBFeature
>>>> *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
>>>>        DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
>>>>        gsize num_regs = g_hash_table_size(cpu->cp_regs);
>>>>    +    dyn_feature->desc.name = "org.qemu.gdb.arm.sys.regs";
>>>> +    dyn_feature->desc.regs = g_new(const char *, num_regs);
>>> AIUI this means we now have an array of register names which mirrors
>>> the
>>> names embedded in the XML. This smells like a few steps away from just
>>> abstracting the whole XML away from the targets and generating them
>>> inside gdbstub when we need them. As per my stalled attempt I referenced
>>> earlier.
>>
>> The abstraction is strictly limited for identifiers. Most plugin
>> should already have some knowledge of how registers are used. For
>> example, a plugin that tracks stack frame for RISC-V should know sp is
>> the stack pointer register. Similarly, a cycle simulator plugin should
>> know how registers are used in a program. Only identifiers matter in
>> such cases.
>>
>> I'm definitely *not* in favor of abstracting the whole XML for
>> plugins. It will be too hard to maintain ABI compatibility when a new
>> attribute emerges, for example.
> 
> No I agree the XML shouldn't go near the plugins. I was just looking to
> avoid having an XML builder for every target.

Oh, I see. It's done in v4 with patch "gdbstub: Introduce 
GDBFeatureBuilder".

> 


^ permalink raw reply	[flat|nested] 61+ messages in thread

end of thread, other threads:[~2023-08-16 15:12 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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).