Re: [PATCH v2] util: Delete checks for old host definitions

2023-09-02 Thread Akihiko Odaki

Hi,

Can anyone have look at this?

I also have another patch similar but for thunk. It was reviewed but no 
one has made a pull request yet:

https://patchew.org/QEMU/20230808152314.102036-1-akihiko.od...@daynix.com/

Regards,
Akihiko Odaki

On 2023/08/11 7:59, Akihiko Odaki wrote:

IA-64 and PA-RISC host support is already removed with commit
b1cef6d02f("Drop remaining bits of ia64 host support").

Signed-off-by: Akihiko Odaki 
---
  util/async-teardown.c |  3 ---
  util/oslib-posix.c| 14 ++
  2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/util/async-teardown.c b/util/async-teardown.c
index 62cdeb0f20..396963c091 100644
--- a/util/async-teardown.c
+++ b/util/async-teardown.c
@@ -121,10 +121,7 @@ static void *new_stack_for_clone(void)
  
  /* Allocate a new stack and get a pointer to its top. */

  stack_ptr = qemu_alloc_stack(_size);
-#if !defined(HOST_HPPA)
-/* The top is at the end of the area, except on HPPA. */
  stack_ptr += stack_size;
-#endif
  
  return stack_ptr;

  }
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 760390b31e..6da3cc5014 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -585,7 +585,7 @@ char *qemu_get_pid_name(pid_t pid)
  
  void *qemu_alloc_stack(size_t *sz)

  {
-void *ptr, *guardpage;
+void *ptr;
  int flags;
  #ifdef CONFIG_DEBUG_STACK_USAGE
  void *ptr2;
@@ -618,17 +618,7 @@ void *qemu_alloc_stack(size_t *sz)
  abort();
  }
  
-#if defined(HOST_IA64)

-/* separate register stack */
-guardpage = ptr + (((*sz - pagesz) / 2) & ~pagesz);
-#elif defined(HOST_HPPA)
-/* stack grows up */
-guardpage = ptr + *sz - pagesz;
-#else
-/* stack grows down */
-guardpage = ptr;
-#endif
-if (mprotect(guardpage, pagesz, PROT_NONE) != 0) {
+if (mprotect(ptr, pagesz, PROT_NONE) != 0) {
  perror("failed to set up stack guard page");
  abort();
  }




[PATCH v2] linux-user: Undo incomplete mmap

2023-09-02 Thread Akihiko Odaki
When the host page size is greater than the target page size and
MAP_FIXED or MAP_FIXED_NOREPLACE is requested, mmap will be done for
three parts: start, middle, and end. If a later part of mmap fail,
mmap done in the earlier parts must be reverted.

Fixes: 54936004fd ("mmap emulation")
Signed-off-by: Akihiko Odaki 
---
V1 -> V2: Rebased.

 linux-user/mmap.c | 65 +--
 1 file changed, 40 insertions(+), 25 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 9aab48d4a3..72521f8d27 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -224,13 +224,15 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
target_prot)
 
 /* map an incomplete host page */
 static bool mmap_frag(abi_ulong real_start, abi_ulong start, abi_ulong last,
-  int prot, int flags, int fd, off_t offset)
+  int prot, int flags, int fd, off_t offset, bool *mapped)
 {
 abi_ulong real_last;
 void *host_start;
 int prot_old, prot_new;
 int host_prot_old, host_prot_new;
 
+*mapped = false;
+
 if (!(flags & MAP_ANONYMOUS)
 && (flags & MAP_TYPE) == MAP_SHARED
 && (prot & PROT_WRITE)) {
@@ -271,6 +273,7 @@ static bool mmap_frag(abi_ulong real_start, abi_ulong 
start, abi_ulong last,
 return false;
 }
 prot_old = prot;
+*mapped = true;
 }
 prot_new = prot | prot_old;
 
@@ -448,7 +451,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, 
abi_ulong align)
 abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
  int flags, int fd, off_t offset)
 {
-abi_ulong ret, last, real_start, real_last, retaddr, host_len;
+abi_ulong ret, last, real_start, retaddr, host_len;
 abi_ulong passthrough_start = -1, passthrough_last = 0;
 int page_flags;
 off_t host_offset;
@@ -577,12 +580,16 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 passthrough_start = start;
 passthrough_last = last;
 } else {
+abi_ulong middle_start = HOST_PAGE_ALIGN(start);
+abi_ulong middle_last = ((start + len) & qemu_host_page_mask) - 1;
+abi_ulong mapped_len = 0;
+bool mapped;
+
 if (start & ~TARGET_PAGE_MASK) {
 errno = EINVAL;
 goto fail;
 }
 last = start + len - 1;
-real_last = HOST_PAGE_ALIGN(last) - 1;
 
 /*
  * Test if requested memory area fits target address space
@@ -649,35 +656,26 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 }
 
 /* handle the start of the mapping */
-if (start > real_start) {
-if (real_last == real_start + qemu_host_page_size - 1) {
+if (start < middle_start) {
+if (last < middle_start) {
 /* one single host page */
 if (!mmap_frag(real_start, start, last,
-   target_prot, flags, fd, offset)) {
+   target_prot, flags, fd, offset, )) {
 goto fail;
 }
 goto the_end1;
 }
-if (!mmap_frag(real_start, start,
-   real_start + qemu_host_page_size - 1,
-   target_prot, flags, fd, offset)) {
+if (!mmap_frag(real_start, start, middle_start - 1,
+   target_prot, flags, fd, offset, )) {
 goto fail;
 }
-real_start += qemu_host_page_size;
-}
-/* handle the end of the mapping */
-if (last < real_last) {
-abi_ulong real_page = real_last - qemu_host_page_size + 1;
-if (!mmap_frag(real_page, real_page, last,
-   target_prot, flags, fd,
-   offset + real_page - start)) {
-goto fail;
+if (mapped) {
+mapped_len = qemu_host_page_size;
 }
-real_last -= qemu_host_page_size;
 }
 
 /* map the middle (easier) */
-if (real_start < real_last) {
+if (middle_start < middle_last) {
 void *p, *want_p;
 off_t offset1;
 size_t len1;
@@ -685,10 +683,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 if (flags & MAP_ANONYMOUS) {
 offset1 = 0;
 } else {
-offset1 = offset + real_start - start;
+offset1 = offset + middle_start - start;
 }
-len1 = real_last - real_start + 1;
-want_p = g2h_untagged(real_start);
+len1 = middle_last - middle_start + 1;
+want_p = g2h_untagged(middle_start);
 
 p = mmap(want_p, len1, target_to_host_prot(target_prot),
  flags, fd, offset1);
@@ -697,10 +695,27 @@ abi_long 

[PATCH v6 15/18] plugins: Allow to read registers

2023-09-02 Thread 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.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1706
Signed-off-by: Akihiko Odaki 
---
 include/qemu/qemu-plugin.h   | 65 ++--
 plugins/api.c| 40 ++
 plugins/qemu-plugins.symbols |  2 ++
 3 files changed, 104 insertions(+), 3 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 
 #include 
 #include 
 #include 
@@ -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/plugins/api.c b/plugins/api.c
index 2078b16edb..e1b22c98f5 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);
+
+

[PATCH v6 16/18] contrib/plugins: Allow to log registers

2023-09-02 Thread Akihiko Odaki
This demonstrates how a register can be read from a plugin.

Signed-off-by: Akihiko Odaki 
---
 docs/devel/tcg-plugins.rst |  10 ++-
 contrib/plugins/execlog.c  | 140 -
 2 files changed, 117 insertions(+), 33 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 
`__.
+
+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 82dc2f584e..aa05840fd0 100644
--- a/contrib/plugins/execlog.c
+++ b/contrib/plugins/execlog.c
@@ -15,27 +15,43 @@
 
 #include 
 
+typedef struct CPU {
+/* Store last executed instruction on each vCPU as a GString */
+GString *last_exec;
+GByteArray *reg_history[2];
+
+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_lock(_array_lock);
-while (cpu_index >= last_exec->len) {
-GString *s = g_string_new(NULL);
-g_ptr_array_add(last_exec, s);
+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_history[0] = g_byte_array_new();
+cpus[num_cpus].reg_history[1] = g_byte_array_new();
+num_cpus++;
+}
 }
 g_rw_lock_writer_unlock(_array_lock);
 }
@@ -50,8 +66,8 @@ static void vcpu_mem(unsigned int cpu_index, 
qemu_plugin_meminfo_t info,
 
 /* Find vCPU in array */
 g_rw_lock_reader_lock(_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(_array_lock);
 
 /* Indicate type of memory access */
@@ -77,28 +93,42 @@ 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;
+int n;
+int i;
 
-/* Find or create vCPU in array */
 g_rw_lock_reader_lock(_array_lock);
-if (cpu_index >= last_exec->len) {
-g_rw_lock_reader_unlock(_array_lock);
-expand_last_exec(cpu_index);
-g_rw_lock_reader_lock(_array_lock);
-}
-s = g_ptr_array_index(last_exec, cpu_index);
-g_rw_lock_reader_unlock(_array_lock);
 
 /* Print previous instruction in cache */
-if (s->len) {
-qemu_plugin_outs(s->str);
+if (cpus[cpu_index].last_exec->len) {
+if (cpus[cpu_index].reg >= 0) {
+GByteArray *current = cpus[cpu_index].reg_history[0];
+GByteArray *last = cpus[cpu_index].reg_history[1];
+
+g_byte_array_set_size(current, 0);
+n = qemu_plugin_read_register(current, cpus[cpu_index].reg);
+
+if (n != last->len || memcmp(current->data, last->data, n)) {
+g_string_append(cpus[cpu_index].last_exec, ", reg,");
+for (i = 0; i < n; i++) {
+g_string_append_printf(cpus[cpu_index].last_exec, " %02x",
+   current->data[i]);
+}
+}
+
+cpus[cpu_index].reg_history[0] = last;
+cpus[cpu_index].reg_history[1] = current;
+}
+
+qemu_plugin_outs(cpus[cpu_index].last_exec->str);
 qemu_plugin_outs("\n");
 }
 
 /* Store new instruction in cache */
 /* vcpu_mem will 

[PATCH v6 03/18] hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature

2023-09-02 Thread 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 
---
 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 4f5c7eb04e..09f1aca624 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;
 const 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 a03d9baa12..34ef45c94a 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -384,7 +384,7 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 g_ptr_array_add(
 a,
 g_markup_printf_escaped("",
-cc->gdb_core_xml_file));
+cc->gdb_core_feature->xmlname));
 for (r = cpu->gdb_regs; r; r = r->next) {
 g_ptr_array_add(
 a,
@@ -1496,7 +1496,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+");
 }
 
@@ -1538,7 +1538,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 4147c19597..5f07133419 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 = _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 6b91aab6b7..65f84bfb18 100644

[PATCH v6 14/18] cpu: Call plugin hooks only when ready

2023-09-02 Thread Akihiko Odaki
The initialization and exit hooks will not affect the state of vCPU,
but they may depend on the state of vCPU. Therefore, it's better to
call plugin hooks after the vCPU state is fully initialized and before
it gets uninitialized.

Signed-off-by: Akihiko Odaki 
---
 cpu.c| 11 ---
 hw/core/cpu-common.c | 10 ++
 2 files changed, 10 insertions(+), 11 deletions(-)

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 ced66c2b34..be1544687e 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -209,6 +209,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 */
 }
 
@@ -216,6 +221,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);
 }
-- 
2.42.0




[PATCH v6 05/18] target/arm: Use GDBFeature for dynamic XML

2023-09-02 Thread 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 
Acked-by: Richard Henderson 
---
 target/arm/cpu.h   |  20 +++---
 target/arm/internals.h |   2 +-
 target/arm/gdbstub.c   | 134 ++---
 target/arm/gdbstub64.c |  90 ---
 4 files changed, 108 insertions(+), 138 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..ca20e4fd1e 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 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 b7ace24bfc..fc0aa6f235 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -25,11 +25,10 @@
 #include "internals.h"
 #include "cpregs.h"
 
-typedef struct RegisterSysregXmlParam {
+typedef struct RegisterSysregFeatureParam {
 CPUState *cs;
-GString *s;
-int n;
-} RegisterSysregXmlParam;
+GDBFeatureBuilder builder;
+} RegisterSysregFeatureParam;
 
 /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
whatever the target description contains.  Due to a historical mishap
@@ -215,7 +214,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)) {
@@ -232,34 +231,32 @@ 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(GDBFeatureBuilder *builder,
+   DynamicGDBFeatureInfo *dyn_feature,
ARMCPRegInfo *ri, uint32_t ri_key,
-   int bitsize, int regnum)
+   int bitsize)
 {
-g_string_append_printf(s, "name);
-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++;
+int num = gdb_feature_builder_append_reg(builder, ri->name, bitsize,
+ "int", "cp_regs");
+
+dyn_feature->data.cpregs.keys[num] = ri_key;
 }
 
-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 

[PATCH v6 06/18] target/ppc: Use GDBFeature for dynamic XML

2023-09-02 Thread 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 
Reviewed-by: Richard Henderson 
---
 target/ppc/cpu-qom.h  |  3 +--
 target/ppc/cpu.h  |  2 +-
 target/ppc/cpu_init.c |  2 +-
 target/ppc/gdbstub.c  | 45 ++-
 4 files changed, 17 insertions(+), 35 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 ec5731e5d6..43de40ac36 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -300,15 +300,21 @@ 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 = >env;
-GString *xml;
-char *spr_name;
+GDBFeatureBuilder builder;
 unsigned int num_regs = 0;
 int i;
 
+if (pcc->gdb_spr.xml) {
+return;
+}
+
+gdb_feature_builder_init(, >gdb_spr,
+ "org.qemu.power.spr", "power-spr.xml");
+
 for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
 ppc_spr_t *spr = >spr_cb[i];
 
@@ -326,35 +332,12 @@ void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
  */
 spr->gdb_id = num_regs;
 num_regs++;
-}
-
-if (pcc->gdb_spr_xml) {
-return;
-}
-
-xml = g_string_new("");
-g_string_append(xml, "");
-g_string_append(xml, "");
 
-for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
-ppc_spr_t *spr = >spr_cb[i];
-
-if (!spr->name) {
-continue;
-}
-
-spr_name = g_ascii_strdown(spr->name, -1);
-g_string_append_printf(xml, "");
+gdb_feature_builder_append_reg(, g_ascii_strdown(spr->name, 
-1),
+   TARGET_LONG_BITS, "int", "spr");
 }
 
-g_string_append(xml, "");
-
-pcc->gdb_num_sprs = num_regs;
-pcc->gdb_spr_xml = g_string_free(xml, false);
+gdb_feature_builder_end();
 }
 
 const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
@@ -362,7 +345,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;
 }
@@ -600,6 +583,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.42.0




[PATCH v6 04/18] gdbstub: Introduce GDBFeatureBuilder

2023-09-02 Thread Akihiko Odaki
GDBFeatureBuilder unifies the logic to generate dynamic GDBFeature.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Richard Henderson 
---
 include/exec/gdbstub.h | 20 ++
 gdbstub/gdbstub.c  | 59 ++
 2 files changed, 79 insertions(+)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 3091e7a706..1ea2631c24 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -16,6 +16,11 @@ typedef struct GDBFeature {
 int num_regs;
 } GDBFeature;
 
+typedef struct GDBFeatureBuilder {
+GDBFeature *feature;
+GPtrArray *xml;
+} GDBFeatureBuilder;
+
 
 /* Get or set a register.  Returns the size of the register.  */
 typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
@@ -34,6 +39,21 @@ void gdb_register_coprocessor(CPUState *cpu,
  */
 int gdbserver_start(const char *port_or_device);
 
+void gdb_feature_builder_init(GDBFeatureBuilder *builder, GDBFeature *feature,
+  const char *name, const char *xmlname);
+
+void gdb_feature_builder_append_tag(const GDBFeatureBuilder *builder,
+const char *format, ...)
+G_GNUC_PRINTF(2, 3);
+
+int gdb_feature_builder_append_reg(const GDBFeatureBuilder *builder,
+   const char *name,
+   int bitsize,
+   const char *type,
+   const char *group);
+
+void gdb_feature_builder_end(const GDBFeatureBuilder *builder);
+
 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 34ef45c94a..6b530f1e1e 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -414,6 +414,65 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 return name ? gdb_static_features[i].xml : NULL;
 }
 
+void gdb_feature_builder_init(GDBFeatureBuilder *builder, GDBFeature *feature,
+  const char *name, const char *xmlname)
+{
+char *header = g_markup_printf_escaped(
+""
+""
+"",
+name);
+
+builder->feature = feature;
+builder->xml = g_ptr_array_new();
+g_ptr_array_add(builder->xml, header);
+feature->xmlname = xmlname;
+feature->num_regs = 0;
+}
+
+void gdb_feature_builder_append_tag(const GDBFeatureBuilder *builder,
+const char *format, ...)
+{
+va_list ap;
+va_start(ap, format);
+g_ptr_array_add(builder->xml, g_markup_vprintf_escaped(format, ap));
+va_end(ap);
+}
+
+int gdb_feature_builder_append_reg(const GDBFeatureBuilder *builder,
+   const char *name,
+   int bitsize,
+   const char *type,
+   const char *group)
+{
+if (group) {
+gdb_feature_builder_append_tag(
+builder,
+"",
+name, bitsize, type, group);
+} else {
+gdb_feature_builder_append_tag(
+builder, "",
+name, bitsize, type);
+}
+
+return builder->feature->num_regs++;
+}
+
+void gdb_feature_builder_end(const GDBFeatureBuilder *builder)
+{
+g_ptr_array_add(builder->xml, (void *)"");
+g_ptr_array_add(builder->xml, NULL);
+
+builder->feature->xml = g_strjoinv(NULL, (void *)builder->xml->pdata);
+
+for (guint i = 0; i < builder->xml->len - 2; i++) {
+g_free(g_ptr_array_index(builder->xml, i));
+}
+
+g_ptr_array_free(builder->xml, TRUE);
+}
+
 const GDBFeature *gdb_find_static_feature(const char *xmlname)
 {
 const GDBFeature *feature;
-- 
2.42.0




[PATCH v6 07/18] target/riscv: Use GDBFeature for dynamic XML

2023-09-02 Thread 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 
---
 target/riscv/cpu.h |  4 +--
 target/riscv/cpu.c |  4 +--
 target/riscv/gdbstub.c | 77 ++
 3 files changed, 37 insertions(+), 48 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 48f1426299..86a477bfc0 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..cdae406751 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -212,12 +212,13 @@ 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)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
-GString *s = g_string_new(NULL);
+GDBFeatureBuilder builder;
 riscv_csr_predicate_fn predicate;
+const char *name;
 int bitsize = 16 << env->misa_mxl_max;
 int i;
 
@@ -230,9 +231,8 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)
 bitsize = 64;
 }
 
-g_string_printf(s, "");
-g_string_append_printf(s, "");
-g_string_append_printf(s, "");
+gdb_feature_builder_init(, >dyn_csr_feature,
+ "org.gnu.gdb.riscv.csr", "riscv-csr.xml");
 
 for (i = 0; i < CSR_TABLE_SIZE; i++) {
 if (env->priv_ver < csr_ops[i].min_priv_ver) {
@@ -240,72 +240,63 @@ static int riscv_gen_dynamic_csr_xml(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, "", base_reg + i);
+
+gdb_feature_builder_append_reg(, name, bitsize,
+   "int", NULL);
 }
 }
 
-g_string_append_printf(s, "");
-
-cpu->dyn_csr_xml = g_string_free(s, false);
+gdb_feature_builder_end();
 
 #if !defined(CONFIG_USER_ONLY)
 env->debugger = false;
 #endif
 
-return CSR_TABLE_SIZE;
+return >dyn_csr_feature;
 }
 
-static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
+static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
-GString *s = g_string_new(NULL);
-g_autoptr(GString) ts = g_string_new("");
+GDBFeatureBuilder builder;
 int reg_width = cpu->cfg.vlen;
-int num_regs = 0;
 int i;
 
-g_string_printf(s, "");
-g_string_append_printf(s, "");
-g_string_append_printf(s, "");
+gdb_feature_builder_init(, >dyn_vreg_feature,
+ "org.gnu.gdb.riscv.vector", "riscv-vector.xml");
 
 /* First define types and totals in a whole VL */
 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
 int count = reg_width / vec_lanes[i].size;
-g_string_printf(ts, "%s", vec_lanes[i].id);
-g_string_append_printf(s,
-   "",
-   ts->str, vec_lanes[i].gdb_type, count);
+gdb_feature_builder_append_tag(
+, "",
+vec_lanes[i].id, vec_lanes[i].gdb_type, count);
 }
 
 /* Define unions */
-g_string_append_printf(s, "");
+gdb_feature_builder_append_tag(, "");
 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
-g_string_append_printf(s, "",
-   vec_lanes[i].suffix,
-   vec_lanes[i].id);
+gdb_feature_builder_append_tag(,
+   "",
+   vec_lanes[i].suffix, vec_lanes[i].id);
 }
-g_string_append(s, "");
+gdb_feature_builder_append_tag(, "");
 
 /* Define vector registers */
 for (i = 0; i < 32; i++) {
-g_string_append_printf(s,
-   "",
-   i, 

[PATCH v6 11/18] hw/core/cpu: Remove gdb_get_dynamic_xml member

2023-09-02 Thread Akihiko Odaki
This function is no longer used.

Signed-off-by: Akihiko Odaki 
---
 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 09f1aca624..8fc9a1a140 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;
 const 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 5f07133419..f26c0ded18 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 = _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 99040e0c4c..40c3f50c89 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -442,24 +442,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 9f2aad7aa9..5af9a0cbe3 

[PATCH v6 13/18] gdbstub: Expose functions to read registers

2023-09-02 Thread Akihiko Odaki
gdb_foreach_feature() enumerates features that are useful to identify
registers. gdb_read_register() actually reads registers.

Signed-off-by: Akihiko Odaki 
---
 include/exec/gdbstub.h |  6 ++
 gdbstub/gdbstub.c  | 20 +++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 5bfaaa0306..cb6b3b17bd 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -59,6 +59,12 @@ void gdb_feature_builder_end(const GDBFeatureBuilder 
*builder);
 
 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);
+
 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 9217fc7900..215d5d4fa5 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -483,7 +483,25 @@ const GDBFeature *gdb_find_static_feature(const char 
*xmlname)
 g_assert_not_reached();
 }
 
-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)
 {
 CPUClass *cc = CPU_GET_CLASS(cpu);
 CPUArchState *env = cpu->env_ptr;
-- 
2.42.0




[PATCH v6 01/18] gdbstub: Add num_regs member to GDBFeature

2023-09-02 Thread 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 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alex Bennée 
---
 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 ecbc60a934..7dc097fcf6 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 bcbcb83beb..e04d6b2df7 100755
--- a/scripts/feature_to_c.py
+++ b/scripts/feature_to_c.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 # SPDX-License-Identifier: GPL-2.0-or-later
 
-import os, sys
+import os, sys, xml.etree.ElementTree
 
 def writeliteral(indent, bytes):
 sys.stdout.write(' ' * indent)
@@ -39,10 +39,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.42.0




[PATCH v6 12/18] gdbstub: Add members to identify registers to GDBFeature

2023-09-02 Thread 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 
---
 include/exec/gdbstub.h  |  3 +++
 gdbstub/gdbstub.c   | 10 --
 target/riscv/gdbstub.c  |  4 +---
 scripts/feature_to_c.py | 14 +-
 4 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 1f5fb4da25..5bfaaa0306 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -13,12 +13,15 @@
 typedef struct GDBFeature {
 const char *xmlname;
 const char *xml;
+const char *name;
+const char * const *regs;
 int num_regs;
 } GDBFeature;
 
 typedef struct GDBFeatureBuilder {
 GDBFeature *feature;
 GPtrArray *xml;
+GPtrArray *regs;
 } GDBFeatureBuilder;
 
 
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 6c8816e3ad..9217fc7900 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -416,9 +416,10 @@ void gdb_feature_builder_init(GDBFeatureBuilder *builder, 
GDBFeature *feature,
 
 builder->feature = feature;
 builder->xml = g_ptr_array_new();
+builder->regs = g_ptr_array_new();
 g_ptr_array_add(builder->xml, header);
 feature->xmlname = xmlname;
-feature->num_regs = 0;
+feature->name = name;
 }
 
 void gdb_feature_builder_append_tag(const GDBFeatureBuilder *builder,
@@ -447,7 +448,9 @@ int gdb_feature_builder_append_reg(const GDBFeatureBuilder 
*builder,
 name, bitsize, type);
 }
 
-return builder->feature->num_regs++;
+g_ptr_array_add(builder->regs, (void *)name);
+
+return builder->regs->len;
 }
 
 void gdb_feature_builder_end(const GDBFeatureBuilder *builder)
@@ -462,6 +465,9 @@ void gdb_feature_builder_end(const GDBFeatureBuilder 
*builder)
 }
 
 g_ptr_array_free(builder->xml, TRUE);
+
+builder->feature->num_regs = builder->regs->len;
+builder->feature->regs = (void *)g_ptr_array_free(builder->regs, FALSE);
 }
 
 const GDBFeature *gdb_find_static_feature(const char *xmlname)
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index d4f9eb1516..a2ec9a3701 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -240,11 +240,9 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState 
*cs)
 }
 predicate = csr_ops[i].predicate;
 if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
-g_autofree char *dynamic_name = NULL;
 name = csr_ops[i].name;
 if (!name) {
-dynamic_name = g_strdup_printf("csr%03x", i);
-name = dynamic_name;
+name = g_strdup_printf("csr%03x", i);
 }
 
 gdb_feature_builder_append_reg(, name, bitsize,
diff --git a/scripts/feature_to_c.py b/scripts/feature_to_c.py
index e04d6b2df7..807af0e685 100755
--- a/scripts/feature_to_c.py
+++ b/scripts/feature_to_c.py
@@ -50,7 +50,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:
@@ -67,6 +69,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
 
@@ -85,6 +88,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.42.0




[PATCH v6 17/18] plugins: Support C++

2023-09-02 Thread Akihiko Odaki
Make qemu-plugin.h consumable for C++ platform.

Signed-off-by: Akihiko Odaki 
---
 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 
 #include 
 
+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.42.0




[PATCH v6 08/18] gdbstub: Use GDBFeature for gdb_register_coprocessor

2023-09-02 Thread 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 
Acked-by: Alex Bennée 
---
 include/exec/gdbstub.h |  2 +-
 gdbstub/gdbstub.c  | 13 +++--
 target/arm/gdbstub.c   | 34 ++
 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 | 18 ++
 target/s390x/gdbstub.c | 28 +++-
 10 files changed, 57 insertions(+), 65 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 1ea2631c24..1f5fb4da25 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -27,7 +27,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 6b530f1e1e..b641e87fd1 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -530,7 +530,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;
@@ -538,25 +538,26 @@ void gdb_register_coprocessor(CPUState *cpu,
 p = >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 fc0aa6f235..99040e0c4c 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -472,14 +472,14 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
  */
 #ifdef TARGET_AARCH64
 if (isar_feature_aa64_sve(>isar)) {
-int nreg = arm_gen_dynamic_svereg_feature(cs)->num_regs;
+GDBFeature *feature = arm_gen_dynamic_svereg_feature(cs);
 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
@@ -490,19 +490,22 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
 if (isar_feature_aa64_pauth(>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"),
+   

[PATCH v6 10/18] gdbstub: Simplify XML lookup

2023-09-02 Thread 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 
---
 gdbstub/gdbstub.c | 24 
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 1c5cbc0472..6c8816e3ad 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -352,8 +352,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);
 
@@ -362,7 +361,6 @@ 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) {
 /* Generate the XML description for this CPU.  */
 if (!process->target_xml) {
@@ -396,21 +394,15 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 }
 return process->target_xml;
 }
-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_static_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_static_features[i].xml : NULL;
+return NULL;
 }
 
 void gdb_feature_builder_init(GDBFeatureBuilder *builder, GDBFeature *feature,
-- 
2.42.0




[PATCH v6 09/18] gdbstub: Use GDBFeature for GDBRegisterState

2023-09-02 Thread Akihiko Odaki
Simplify GDBRegisterState by replacing num_regs and xml members with
one member that points to GDBFeature.

Signed-off-by: Akihiko Odaki 
---
 gdbstub/gdbstub.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index b641e87fd1..1c5cbc0472 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;
 
@@ -389,7 +388,7 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 g_ptr_array_add(
 a,
 g_markup_printf_escaped("",
-r->xml));
+r->feature->xmlname));
 }
 g_ptr_array_add(a, g_strdup(""));
 g_ptr_array_add(a, NULL);
@@ -497,7 +496,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);
 }
 }
@@ -515,7 +514,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);
 }
 }
@@ -538,17 +537,16 @@ void gdb_register_coprocessor(CPUState *cpu,
 p = >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.42.0




[PATCH v6 02/18] gdbstub: Introduce gdb_find_static_feature()

2023-09-02 Thread Akihiko Odaki
This function is useful to determine the number of registers exposed to
GDB from the XML name.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alex Bennée 
Reviewed-by: Richard Henderson 
---
 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 7dc097fcf6..3091e7a706 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);
 
 /* in gdbstub-xml.c, generated by scripts/feature_to_c.py */
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 61c811f42b..a03d9baa12 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_static_features[i].xml : NULL;
 }
 
+const GDBFeature *gdb_find_static_feature(const char *xmlname)
+{
+const GDBFeature *feature;
+
+for (feature = gdb_static_features; feature->xmlname; feature++) {
+if (!strcmp(feature->xmlname, xmlname)) {
+return feature;
+}
+}
+
+g_assert_not_reached();
+}
+
 static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
 {
 CPUClass *cc = CPU_GET_CLASS(cpu);
-- 
2.42.0




[PATCH v6 00/18] plugins: Allow to read registers

2023-09-02 Thread Akihiko Odaki
Based-on: <20230903043030.20708-1-akihiko.od...@daynix.com>
("[PATCH 0/8] gdbstub and TCG plugin improvements")

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, 03] introduces num_regs member to GDBFeature.
Patch [04, 11] converts dynamic features to use GDBFeature.
Patch 12 adds members useful to identify registers to GDBFeature.
Patch 13 makes registers readable outside of gdbstub context.
Patch [14, 16] add the feature to read registers from plugins.
Patch [17, 18] make 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

V5 -> V6:
  Rebased to "[PATCH 0/8] gdbstub and TCG plugin improvements"

V4 -> V5:
  Corrected g_rw_lock_writer_lock() call. (Richard Henderson)
  Replaced abort() with g_assert_not_reached(). (Richard Henderson)
  Fixed CSR name leak in target/riscv. (Richard Henderson)
  Removed gdb_has_xml variable.

V3 -> V4:
  Added execlog changes I forgot to include in the last version.

V2 -> V3:
  Added patch "hw/core/cpu: Return static value with gdb_arch_name()".
  Added patch "gdbstub: Dynamically allocate target.xml buffer".
  (Alex Bennée)
  Added patch "gdbstub: Introduce GDBFeatureBuilder". (Alex Bennée)
  Dropped Reviewed-by tags for "target/*: Use GDBFeature for dynamic XML".
  Changed gdb_find_static_feature() to abort on failure. (Alex Bennée)
  Changed the execlog plugin to log the register value only when changed.
  (Alex Bennée)
  Dropped 0x prefixes for register value logs for conciseness.

V1 -> V2:
  Added SPDX-License-Identifier: GPL-2.0-or-later. (Philippe Mathieu-Daudé)
  Split long lines. (Philippe Mathieu-Daudé)
  Renamed gdb_features to gdb_static_features (Philippe Mathieu-Daudé)
  Dropped RFC.

Akihiko Odaki (18):
  gdbstub: Add num_regs member to GDBFeature
  gdbstub: Introduce gdb_find_static_feature()
  hw/core/cpu: Replace gdb_core_xml_file with gdb_core_feature
  gdbstub: Introduce GDBFeatureBuilder
  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
  gdbstub: Expose functions to read registers
  cpu: Call plugin hooks only when ready
  plugins: Allow to read registers
  contrib/plugins: Allow to log registers
  plugins: Support C++
  contrib/plugins: Add cc plugin

 docs/devel/tcg-plugins.rst   |  18 +++-
 configure|  15 +++-
 include/exec/gdbstub.h   |  34 ++-
 include/hw/core/cpu.h|   9 +-
 include/qemu/qemu-plugin.h   |  69 +-
 target/arm/cpu.h |  26 ++
 target/arm/internals.h   |   2 +-
 target/ppc/cpu-qom.h |   3 +-
 target/ppc/cpu.h |   3 +-
 target/riscv/cpu.h   |   4 +-
 target/s390x/cpu.h   |   2 -
 contrib/plugins/execlog.c| 140 ++---
 cpu.c|  11 ---
 gdbstub/gdbstub.c| 145 --
 hw/core/cpu-common.c |  10 +++
 plugins/api.c|  40 +
 target/arm/cpu.c |   5 +-
 target/arm/cpu64.c   |   4 +-
 target/arm/gdbstub.c | 170 +++
 target/arm/gdbstub64.c   |  90 ---
 target/arm/tcg/cpu32.c   |   3 +-
 target/avr/cpu.c |   4 

[PATCH v6 18/18] contrib/plugins: Add cc plugin

2023-09-02 Thread Akihiko Odaki
This demonstrates how to write a plugin in C++.

Signed-off-by: Akihiko Odaki 
---
 docs/devel/tcg-plugins.rst |  8 
 configure  | 15 ---
 contrib/plugins/Makefile   |  5 +
 contrib/plugins/cc.cc  | 17 +
 tests/tcg/Makefile.target  |  3 +++
 5 files changed, 45 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 00..83a5528db0
--- /dev/null
+++ b/contrib/plugins/cc.cc
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include 
+
+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.42.0




[PATCH 7/8] target/ppc: Remove references to gdb_has_xml

2023-09-02 Thread Akihiko Odaki
GDB has XML support since 6.7 which was released in 2007.
It's time to remove support for old GDB versions without XML support.

Signed-off-by: Akihiko Odaki 
---
 target/ppc/gdbstub.c | 18 --
 1 file changed, 18 deletions(-)

diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 72df36ca06..ec5731e5d6 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -54,12 +54,6 @@ static int ppc_gdb_register_len(int n)
 case 0 ... 31:
 /* gprs */
 return sizeof(target_ulong);
-case 32 ... 63:
-/* fprs */
-if (gdb_has_xml) {
-return 0;
-}
-return 8;
 case 66:
 /* cr */
 case 69:
@@ -74,12 +68,6 @@ static int ppc_gdb_register_len(int n)
 case 68:
 /* ctr */
 return sizeof(target_ulong);
-case 70:
-/* fpscr */
-if (gdb_has_xml) {
-return 0;
-}
-return sizeof(target_ulong);
 default:
 return 0;
 }
@@ -132,9 +120,6 @@ int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray 
*buf, int n)
 if (n < 32) {
 /* gprs */
 gdb_get_regl(buf, env->gpr[n]);
-} else if (n < 64) {
-/* fprs */
-gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32));
 } else {
 switch (n) {
 case 64:
@@ -158,9 +143,6 @@ int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray 
*buf, int n)
 case 69:
 gdb_get_reg32(buf, cpu_read_xer(env));
 break;
-case 70:
-gdb_get_reg32(buf, env->fpscr);
-break;
 }
 }
 mem_buf = buf->data + buf->len - r;
-- 
2.42.0




[PATCH 4/8] hw/core/cpu: Return static value with gdb_arch_name()

2023-09-02 Thread Akihiko Odaki
All implementations of gdb_arch_name() returns dynamic duplicates of
static strings. It's also unlikely that there will be an implementation
of gdb_arch_name() that returns a truly dynamic value due to the nature
of the function returning a well-known identifiers. Qualify the value
gdb_arch_name() with const and make all of its implementations return
static strings.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Alex Bennée 
---
 include/hw/core/cpu.h  | 2 +-
 target/ppc/internal.h  | 2 +-
 gdbstub/gdbstub.c  | 4 +---
 target/arm/cpu.c   | 6 +++---
 target/arm/cpu64.c | 4 ++--
 target/i386/cpu.c  | 6 +++---
 target/loongarch/cpu.c | 4 ++--
 target/ppc/gdbstub.c   | 6 +++---
 target/riscv/cpu.c | 6 +++---
 target/s390x/cpu.c | 4 ++--
 target/tricore/cpu.c   | 4 ++--
 11 files changed, 23 insertions(+), 25 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index fdcbe87352..4f5c7eb04e 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -164,7 +164,7 @@ struct CPUClass {
 vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
 
 const char *gdb_core_xml_file;
-gchar * (*gdb_arch_name)(CPUState *cpu);
+const 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/ppc/internal.h b/target/ppc/internal.h
index 57acb3212c..974b37aa60 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -221,7 +221,7 @@ void destroy_ppc_opcodes(PowerPCCPU *cpu);
 
 /* gdbstub.c */
 void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
-gchar *ppc_gdb_arch_name(CPUState *cs);
+const gchar *ppc_gdb_arch_name(CPUState *cs);
 
 /**
  * prot_for_access_type:
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 2772f07bbe..78711801db 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -379,11 +379,9 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 ""
 "");
 if (cc->gdb_arch_name) {
-gchar *arch = cc->gdb_arch_name(cpu);
 pstrcat(buf, buf_sz, "");
-pstrcat(buf, buf_sz, arch);
+pstrcat(buf, buf_sz, cc->gdb_arch_name(cpu));
 pstrcat(buf, buf_sz, "");
-g_free(arch);
 }
 pstrcat(buf, buf_sz, "gdb_core_xml_file);
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d71a162070..4147c19597 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2281,15 +2281,15 @@ static Property arm_cpu_properties[] = {
 DEFINE_PROP_END_OF_LIST()
 };
 
-static gchar *arm_gdb_arch_name(CPUState *cs)
+static const gchar *arm_gdb_arch_name(CPUState *cs)
 {
 ARMCPU *cpu = ARM_CPU(cs);
 CPUARMState *env = >env;
 
 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-return g_strdup("iwmmxt");
+return "iwmmxt";
 }
-return g_strdup("arm");
+return "arm";
 }
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 96158093cc..6b91aab6b7 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -743,9 +743,9 @@ static void aarch64_cpu_finalizefn(Object *obj)
 {
 }
 
-static gchar *aarch64_gdb_arch_name(CPUState *cs)
+static const gchar *aarch64_gdb_arch_name(CPUState *cs)
 {
-return g_strdup("aarch64");
+return "aarch64";
 }
 
 static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 97ad229d8b..68bea8d3f0 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5910,12 +5910,12 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel 
*model)
 memset(>user_features, 0, sizeof(env->user_features));
 }
 
-static gchar *x86_gdb_arch_name(CPUState *cs)
+static const gchar *x86_gdb_arch_name(CPUState *cs)
 {
 #ifdef TARGET_X86_64
-return g_strdup("i386:x86-64");
+return "i386:x86-64";
 #else
-return g_strdup("i386");
+return "i386";
 #endif
 }
 
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ad93ecac92..49565da3fa 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -692,9 +692,9 @@ static const struct SysemuCPUOps loongarch_sysemu_ops = {
 };
 #endif
 
-static gchar *loongarch_gdb_arch_name(CPUState *cs)
+static const gchar *loongarch_gdb_arch_name(CPUState *cs)
 {
-return g_strdup("loongarch64");
+return "loongarch64";
 }
 
 static void loongarch_cpu_class_init(ObjectClass *c, void *data)
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index ca39efdc35..72df36ca06 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -589,12 +589,12 @@ static int gdb_set_vsx_reg(CPUPPCState *env, uint8_t 
*mem_buf, int n)
 return 0;
 }
 
-gchar *ppc_gdb_arch_name(CPUState *cs)
+const gchar *ppc_gdb_arch_name(CPUState *cs)
 {
 #if defined(TARGET_PPC64)
-return g_strdup("powerpc:common64");
+return 

[PATCH 3/8] target/arm: Move the reference to arm-core.xml

2023-09-02 Thread 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 
Reviewed-by: Richard Henderson 
---
 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 = _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.42.0




[PATCH 5/8] gdbstub: Dynamically allocate target.xml buffer

2023-09-02 Thread Akihiko Odaki
There is no guarantee that target.xml fits in 1024 bytes, and the fixed
buffer length requires tedious buffer overflow check. Dynamically
allocate the target.xml buffer to resolve these problems.

Suggested-by: Alex Bennée 
Signed-off-by: Akihiko Odaki 
---
 gdbstub/internals.h |  2 +-
 gdbstub/gdbstub.c   | 44 
 gdbstub/softmmu.c   |  2 +-
 3 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/gdbstub/internals.h b/gdbstub/internals.h
index f2b46cce41..4876ebd74f 100644
--- a/gdbstub/internals.h
+++ b/gdbstub/internals.h
@@ -33,7 +33,7 @@ typedef struct GDBProcess {
 uint32_t pid;
 bool attached;
 
-char target_xml[1024];
+char *target_xml;
 } GDBProcess;
 
 enum RSState {
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 78711801db..3f97dc66e5 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -367,33 +367,37 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
 
 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]) {
+if (!process->target_xml) {
+g_autoptr(GPtrArray) a = g_ptr_array_new_with_free_func(g_free);
 GDBRegisterState *r;
 
-pstrcat(buf, buf_sz,
-""
-""
-"");
+g_ptr_array_add(
+a,
+g_strdup(""
+ ""
+ ""));
 if (cc->gdb_arch_name) {
-pstrcat(buf, buf_sz, "");
-pstrcat(buf, buf_sz, cc->gdb_arch_name(cpu));
-pstrcat(buf, buf_sz, "");
+g_ptr_array_add(
+a,
+g_markup_printf_escaped("%s",
+cc->gdb_arch_name(cpu)));
 }
-pstrcat(buf, buf_sz, "gdb_core_xml_file);
-pstrcat(buf, buf_sz, "\"/>");
+g_ptr_array_add(
+a,
+g_markup_printf_escaped("",
+cc->gdb_core_xml_file));
 for (r = cpu->gdb_regs; r; r = r->next) {
-pstrcat(buf, buf_sz, "xml);
-pstrcat(buf, buf_sz, "\"/>");
+g_ptr_array_add(
+a,
+g_markup_printf_escaped("",
+r->xml));
 }
-pstrcat(buf, buf_sz, "");
+g_ptr_array_add(a, g_strdup(""));
+g_ptr_array_add(a, NULL);
+process->target_xml = g_strjoinv(NULL, (void *)a->pdata);
 }
-return buf;
+return process->target_xml;
 }
 if (cc->gdb_get_dynamic_xml) {
 char *xmlname = g_strndup(p, len);
@@ -2199,6 +2203,6 @@ void gdb_create_default_process(GDBState *s)
 process = >processes[s->process_num - 1];
 process->pid = pid;
 process->attached = false;
-process->target_xml[0] = '\0';
+process->target_xml = NULL;
 }
 
diff --git a/gdbstub/softmmu.c b/gdbstub/softmmu.c
index f509b7285d..5282324764 100644
--- a/gdbstub/softmmu.c
+++ b/gdbstub/softmmu.c
@@ -293,7 +293,7 @@ static int find_cpu_clusters(Object *child, void *opaque)
 assert(cluster->cluster_id != UINT32_MAX);
 process->pid = cluster->cluster_id + 1;
 process->attached = false;
-process->target_xml[0] = '\0';
+process->target_xml = NULL;
 
 return 0;
 }
-- 
2.42.0




[PATCH 0/8] gdbstub and TCG plugin improvements

2023-09-02 Thread Akihiko Odaki
This series extracts fixes and refactorings that can be applied
independently from "[PATCH RESEND v5 00/26] plugins: Allow to read
registers" as suggested by Nicholas Piggin.

Patch "target/ppc: Remove references to gdb_has_xml" is also updated to
remove some dead code I missed earlier and thus the Reviewed-by tag is
dropped.

Akihiko Odaki (8):
  contrib/plugins: Use GRWLock in execlog
  gdbstub: Introduce GDBFeature structure
  target/arm: Move the reference to arm-core.xml
  hw/core/cpu: Return static value with gdb_arch_name()
  gdbstub: Dynamically allocate target.xml buffer
  target/arm: Remove references to gdb_has_xml
  target/ppc: Remove references to gdb_has_xml
  gdbstub: Remove gdb_has_xml variable

 MAINTAINERS   |  2 +-
 meson.build   |  2 +-
 gdbstub/internals.h   |  2 +-
 include/exec/gdbstub.h| 17 --
 include/hw/core/cpu.h |  2 +-
 target/ppc/internal.h |  2 +-
 contrib/plugins/execlog.c | 16 +
 gdbstub/gdbstub.c | 63 +++
 gdbstub/softmmu.c |  3 +-
 gdbstub/user.c|  1 -
 stubs/gdbstub.c   |  6 ++--
 target/arm/cpu.c  |  9 ++---
 target/arm/cpu64.c|  4 +--
 target/arm/gdbstub.c  | 32 ++
 target/i386/cpu.c |  6 ++--
 target/loongarch/cpu.c|  4 +--
 target/ppc/gdbstub.c  | 24 ++
 target/riscv/cpu.c|  6 ++--
 target/s390x/cpu.c|  4 +--
 target/tricore/cpu.c  |  4 +--
 scripts/feature_to_c.py   | 48 +++
 scripts/feature_to_c.sh   | 69 ---
 22 files changed, 124 insertions(+), 202 deletions(-)
 create mode 100755 scripts/feature_to_c.py
 delete mode 100644 scripts/feature_to_c.sh

-- 
2.42.0




[PATCH 2/8] gdbstub: Introduce GDBFeature structure

2023-09-02 Thread 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 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alex Bennée 
Reviewed-by: Richard Henderson 
---
 MAINTAINERS |  2 +-
 meson.build |  2 +-
 include/exec/gdbstub.h  |  9 --
 gdbstub/gdbstub.c   |  4 +--
 stubs/gdbstub.c |  6 ++--
 scripts/feature_to_c.py | 48 
 scripts/feature_to_c.sh | 69 -
 7 files changed, 62 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..3f08093321 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -10,6 +10,11 @@
 #define GDB_WATCHPOINT_READ  3
 #define GDB_WATCHPOINT_ACCESS4
 
+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_static_features[];
 
 #endif
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 6911b73c07..2772f07bbe 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_static_features[i].xmlname;
 if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len))
 break;
 }
-return name ? xml_builtin[i][1] : NULL;
+return name ? gdb_static_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..580e20702b 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_static_features */
 
-const char *const xml_builtin[][2] = {
-  { NULL, NULL }
+const GDBFeature gdb_static_features[] = {
+  { NULL }
 };
diff --git a/scripts/feature_to_c.py b/scripts/feature_to_c.py
new file mode 100755
index 00..bcbcb83beb
--- /dev/null
+++ b/scripts/feature_to_c.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+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' \
+ '\n'
+ 'const GDBFeature gdb_static_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

[PATCH 6/8] target/arm: Remove references to gdb_has_xml

2023-09-02 Thread Akihiko Odaki
GDB has XML support since 6.7 which was released in 2007.
It's time to remove support for old GDB versions without XML support.

Signed-off-by: Akihiko Odaki 
Acked-by: Alex Bennée 
---
 target/arm/gdbstub.c | 32 ++--
 1 file changed, 2 insertions(+), 30 deletions(-)

diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index f421c5d041..b7ace24bfc 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -46,21 +46,7 @@ int arm_cpu_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)
 /* Core integer register.  */
 return gdb_get_reg32(mem_buf, env->regs[n]);
 }
-if (n < 24) {
-/* FPA registers.  */
-if (gdb_has_xml) {
-return 0;
-}
-return gdb_get_zeroes(mem_buf, 12);
-}
-switch (n) {
-case 24:
-/* FPA status register.  */
-if (gdb_has_xml) {
-return 0;
-}
-return gdb_get_reg32(mem_buf, 0);
-case 25:
+if (n == 25) {
 /* CPSR, or XPSR for M-profile */
 if (arm_feature(env, ARM_FEATURE_M)) {
 return gdb_get_reg32(mem_buf, xpsr_read(env));
@@ -100,21 +86,7 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 env->regs[n] = tmp;
 return 4;
 }
-if (n < 24) { /* 16-23 */
-/* FPA registers (ignored).  */
-if (gdb_has_xml) {
-return 0;
-}
-return 12;
-}
-switch (n) {
-case 24:
-/* FPA status register (ignored).  */
-if (gdb_has_xml) {
-return 0;
-}
-return 4;
-case 25:
+if (n == 25) {
 /* CPSR, or XPSR for M-profile */
 if (arm_feature(env, ARM_FEATURE_M)) {
 /*
-- 
2.42.0




[PATCH 1/8] contrib/plugins: Use GRWLock in execlog

2023-09-02 Thread 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 
Reviewed-by: Alex Bennée 
---
 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..82dc2f584e 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(_array_lock);
+g_rw_lock_writer_lock(_array_lock);
 while (cpu_index >= last_exec->len) {
 GString *s = g_string_new(NULL);
 g_ptr_array_add(last_exec, s);
 }
-g_mutex_unlock(_array_lock);
+g_rw_lock_writer_unlock(_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(_array_lock);
 g_assert(cpu_index < last_exec->len);
 s = g_ptr_array_index(last_exec, cpu_index);
+g_rw_lock_reader_unlock(_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(_array_lock);
 if (cpu_index >= last_exec->len) {
+g_rw_lock_reader_unlock(_array_lock);
 expand_last_exec(cpu_index);
+g_rw_lock_reader_lock(_array_lock);
 }
 s = g_ptr_array_index(last_exec, cpu_index);
+g_rw_lock_reader_unlock(_array_lock);
 
 /* Print previous instruction in cache */
 if (s->len) {
-- 
2.42.0




[PATCH 8/8] gdbstub: Remove gdb_has_xml variable

2023-09-02 Thread Akihiko Odaki
GDB has XML support since 6.7 which was released in 2007.
It's time to remove support for old GDB versions without XML support.

Signed-off-by: Akihiko Odaki 
---
 include/exec/gdbstub.h |  8 
 gdbstub/gdbstub.c  | 13 -
 gdbstub/softmmu.c  |  1 -
 gdbstub/user.c |  1 -
 4 files changed, 23 deletions(-)

diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 3f08093321..ecbc60a934 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -35,14 +35,6 @@ int gdbserver_start(const char *port_or_device);
 
 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_static_features[];
 
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 3f97dc66e5..61c811f42b 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -75,8 +75,6 @@ void gdb_init_gdbserver_state(void)
 gdbserver_state.sstep_flags &= gdbserver_state.supported_sstep_flags;
 }
 
-bool gdb_has_xml;
-
 /* writes 2*len+1 bytes in buf */
 void gdb_memtohex(GString *buf, const uint8_t *mem, int len)
 {
@@ -1054,11 +1052,6 @@ static void handle_set_reg(GArray *params, void 
*user_ctx)
 {
 int reg_size;
 
-if (!gdb_has_xml) {
-gdb_put_packet("");
-return;
-}
-
 if (params->len != 2) {
 gdb_put_packet("E22");
 return;
@@ -1075,11 +1068,6 @@ static void handle_get_reg(GArray *params, void 
*user_ctx)
 {
 int reg_size;
 
-if (!gdb_has_xml) {
-gdb_put_packet("");
-return;
-}
-
 if (!params->len) {
 gdb_put_packet("E14");
 return;
@@ -1542,7 +1530,6 @@ static void handle_query_xfer_features(GArray *params, 
void *user_ctx)
 return;
 }
 
-gdb_has_xml = true;
 p = get_param(params, 0)->data;
 xml = get_feature_xml(p, , process);
 if (!xml) {
diff --git a/gdbstub/softmmu.c b/gdbstub/softmmu.c
index 5282324764..42645d2220 100644
--- a/gdbstub/softmmu.c
+++ b/gdbstub/softmmu.c
@@ -97,7 +97,6 @@ static void gdb_chr_event(void *opaque, QEMUChrEvent event)
 
 vm_stop(RUN_STATE_PAUSED);
 replay_gdb_attached();
-gdb_has_xml = false;
 break;
 default:
 break;
diff --git a/gdbstub/user.c b/gdbstub/user.c
index 5b375be1d9..7ab6e5d975 100644
--- a/gdbstub/user.c
+++ b/gdbstub/user.c
@@ -198,7 +198,6 @@ static void gdb_accept_init(int fd)
 gdbserver_state.c_cpu = gdb_first_attached_cpu();
 gdbserver_state.g_cpu = gdbserver_state.c_cpu;
 gdbserver_user_state.fd = fd;
-gdb_has_xml = false;
 }
 
 static bool gdb_accept_socket(int gdb_fd)
-- 
2.42.0




Re: [PATCH v3 16/16] tcg/loongarch64: Implement 128-bit load & store

2023-09-02 Thread Jiajie Chen



On 2023/9/3 09:06, Richard Henderson wrote:

On 9/1/23 22:02, Jiajie Chen wrote:

If LSX is available, use LSX instructions to implement 128-bit load &
store.


Is this really guaranteed to be an atomic 128-bit operation?



Song Gao, please check this.


Or, as for many vector processors, is this really two separate 64-bit 
memory operations under the hood?



+static void tcg_out_qemu_ldst_i128(TCGContext *s, TCGReg data_lo, 
TCGReg data_hi,
+   TCGReg addr_reg, MemOpIdx oi, 
bool is_ld)

+{
+    TCGLabelQemuLdst *ldst;
+    HostAddress h;
+
+    ldst = prepare_host_addr(s, , addr_reg, oi, true);
+    if (is_ld) {
+    tcg_out_opc_vldx(s, TCG_VEC_TMP0, h.base, h.index);
+    tcg_out_opc_vpickve2gr_d(s, data_lo, TCG_VEC_TMP0, 0);
+    tcg_out_opc_vpickve2gr_d(s, data_hi, TCG_VEC_TMP0, 1);
+    } else {
+    tcg_out_opc_vinsgr2vr_d(s, TCG_VEC_TMP0, data_lo, 0);
+    tcg_out_opc_vinsgr2vr_d(s, TCG_VEC_TMP0, data_hi, 1);
+    tcg_out_opc_vstx(s, TCG_VEC_TMP0, h.base, h.index);
+    }


You should use h.aa.atom < MO_128 to determine if 128-bit atomicity, 
and therefore the vector operation, is required.  I assume the gr<->vr 
moves have a cost and two integer operations are preferred when 
allowable.


Compare the other implementations of this function.


r~




Re: [PATCH v3 16/16] tcg/loongarch64: Implement 128-bit load & store

2023-09-02 Thread Richard Henderson

On 9/1/23 22:02, Jiajie Chen wrote:

If LSX is available, use LSX instructions to implement 128-bit load &
store.


Is this really guaranteed to be an atomic 128-bit operation?

Or, as for many vector processors, is this really two separate 64-bit memory operations 
under the hood?




+static void tcg_out_qemu_ldst_i128(TCGContext *s, TCGReg data_lo, TCGReg 
data_hi,
+   TCGReg addr_reg, MemOpIdx oi, bool is_ld)
+{
+TCGLabelQemuLdst *ldst;
+HostAddress h;
+
+ldst = prepare_host_addr(s, , addr_reg, oi, true);
+if (is_ld) {
+tcg_out_opc_vldx(s, TCG_VEC_TMP0, h.base, h.index);
+tcg_out_opc_vpickve2gr_d(s, data_lo, TCG_VEC_TMP0, 0);
+tcg_out_opc_vpickve2gr_d(s, data_hi, TCG_VEC_TMP0, 1);
+} else {
+tcg_out_opc_vinsgr2vr_d(s, TCG_VEC_TMP0, data_lo, 0);
+tcg_out_opc_vinsgr2vr_d(s, TCG_VEC_TMP0, data_hi, 1);
+tcg_out_opc_vstx(s, TCG_VEC_TMP0, h.base, h.index);
+}


You should use h.aa.atom < MO_128 to determine if 128-bit atomicity, and therefore the 
vector operation, is required.  I assume the gr<->vr moves have a cost and two integer 
operations are preferred when allowable.


Compare the other implementations of this function.


r~



Re: [PATCH v3 05/16] tcg/loongarch64: Lower add/sub_vec to vadd/vsub

2023-09-02 Thread Richard Henderson

On 9/1/23 22:02, Jiajie Chen wrote:

Lower the following ops:

- add_vec
- sub_vec

Signed-off-by: Jiajie Chen 
---
  tcg/loongarch64/tcg-target-con-set.h |  1 +
  tcg/loongarch64/tcg-target-con-str.h |  1 +
  tcg/loongarch64/tcg-target.c.inc | 60 
  3 files changed, 62 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 8c8ea5d919..2d5dce75c3 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -32,4 +32,5 @@ C_O1_I2(r, rZ, ri)
  C_O1_I2(r, rZ, rJ)
  C_O1_I2(r, rZ, rZ)
  C_O1_I2(w, w, wM)
+C_O1_I2(w, w, wA)
  C_O1_I4(r, rZ, rJ, rZ, rZ)
diff --git a/tcg/loongarch64/tcg-target-con-str.h 
b/tcg/loongarch64/tcg-target-con-str.h
index a8a1c44014..2ba9c135ac 100644
--- a/tcg/loongarch64/tcg-target-con-str.h
+++ b/tcg/loongarch64/tcg-target-con-str.h
@@ -27,3 +27,4 @@ CONST('Z', TCG_CT_CONST_ZERO)
  CONST('C', TCG_CT_CONST_C12)
  CONST('W', TCG_CT_CONST_WSZ)
  CONST('M', TCG_CT_CONST_VCMP)
+CONST('A', TCG_CT_CONST_VADD)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 129dd92910..0edcf5be35 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -177,6 +177,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind 
kind, int slot)
  #define TCG_CT_CONST_C12   0x1000
  #define TCG_CT_CONST_WSZ   0x2000
  #define TCG_CT_CONST_VCMP  0x4000
+#define TCG_CT_CONST_VADD  0x8000
  
  #define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)

  #define ALL_VECTOR_REGSMAKE_64BIT_MASK(32, 32)
@@ -214,6 +215,9 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct, int vece)
  if ((ct & TCG_CT_CONST_VCMP) && -0x10 <= vec_val && vec_val <= 0x1f) {
  return true;
  }
+if ((ct & TCG_CT_CONST_VADD) && -0x1f <= vec_val && vec_val <= 0x1f) {
+return true;
+}
  return false;
  }
  
@@ -1646,6 +1650,18 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,

  [TCG_COND_LTU] = {OPC_VSLTI_BU, OPC_VSLTI_HU, OPC_VSLTI_WU, 
OPC_VSLTI_DU},
  };
  LoongArchInsn insn;
+static const LoongArchInsn add_vec_insn[4] = {
+OPC_VADD_B, OPC_VADD_H, OPC_VADD_W, OPC_VADD_D
+};
+static const LoongArchInsn add_vec_imm_insn[4] = {
+OPC_VADDI_BU, OPC_VADDI_HU, OPC_VADDI_WU, OPC_VADDI_DU
+};
+static const LoongArchInsn sub_vec_insn[4] = {
+OPC_VSUB_B, OPC_VSUB_H, OPC_VSUB_W, OPC_VSUB_D
+};
+static const LoongArchInsn sub_vec_imm_insn[4] = {
+OPC_VSUBI_BU, OPC_VSUBI_HU, OPC_VSUBI_WU, OPC_VSUBI_DU
+};
  
  a0 = args[0];

  a1 = args[1];
@@ -1712,6 +1728,44 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
  }
  tcg_out32(s, encode_vdvjvk_insn(insn, a0, a1, a2));
  break;
+case INDEX_op_add_vec:
+if (const_args[2]) {
+int64_t value = sextract64(a2, 0, 8 << vece);
+/* Try vaddi/vsubi */
+if (0 <= value && value <= 0x1f) {
+tcg_out32(s, encode_vdvjuk5_insn(add_vec_imm_insn[vece], a0, \
+ a1, value));
+break;
+} else if (-0x1f <= value && value < 0) {
+tcg_out32(s, encode_vdvjuk5_insn(sub_vec_imm_insn[vece], a0, \
+ a1, -value));
+break;
+}
+
+/* constraint TCG_CT_CONST_VADD ensures unreachable */
+g_assert_not_reached();
+}
+tcg_out32(s, encode_vdvjvk_insn(add_vec_insn[vece], a0, a1, a2));
+break;
+case INDEX_op_sub_vec:
+if (const_args[2]) {
+int64_t value = sextract64(a2, 0, 8 << vece);
+/* Try vaddi/vsubi */
+if (0 <= value && value <= 0x1f) {
+tcg_out32(s, encode_vdvjuk5_insn(sub_vec_imm_insn[vece], a0, \
+ a1, value));
+break;
+} else if (-0x1f <= value && value < 0) {
+tcg_out32(s, encode_vdvjuk5_insn(add_vec_imm_insn[vece], a0, \
+ a1, -value));
+break;
+}
+
+/* constraint TCG_CT_CONST_VADD ensures unreachable */
+g_assert_not_reached();
+}
+tcg_out32(s, encode_vdvjvk_insn(sub_vec_insn[vece], a0, a1, a2));


It would be nice to share code here.  Perhaps

case INDEX_op_sub_vec:
   if (!const_args[2]) {
   tcg_out32(s, encode_vdvjvk_insn(sub_vec_insn[vece], a0, a1, a2));
   break;
   }
   a2 = -a2;
   goto do_addi_vec;
   case INDEX_op_add_vec:
   if (!const_args[2]) {
   tcg_out32(s, encode_vdvjvk_insn(add_vec_insn[vece], a0, a1, a2));
   break;
   }
   do_addi_vec:
   ...

or a helper function.

Otherwise,
Reviewed-by: Richard Henderson 


r~



Re: [PATCH v3 04/16] tcg/loongarch64: Lower cmp_vec to vseq/vsle/vslt

2023-09-02 Thread Richard Henderson

On 9/1/23 22:02, Jiajie Chen wrote:

Signed-off-by: Jiajie Chen
---
  tcg/loongarch64/tcg-target-con-set.h |  1 +
  tcg/loongarch64/tcg-target-con-str.h |  1 +
  tcg/loongarch64/tcg-target.c.inc | 65 
  3 files changed, 67 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v3 03/16] tcg: pass vece to tcg_target_const_match()

2023-09-02 Thread Richard Henderson

On 9/1/23 22:02, Jiajie Chen wrote:

Pass vece to tcg_target_const_match() to allow correct interpretation of
const args of vector ops.

Signed-off-by: Jiajie Chen
---
  tcg/aarch64/tcg-target.c.inc | 2 +-
  tcg/arm/tcg-target.c.inc | 2 +-
  tcg/i386/tcg-target.c.inc| 2 +-
  tcg/loongarch64/tcg-target.c.inc | 2 +-
  tcg/mips/tcg-target.c.inc| 2 +-
  tcg/ppc/tcg-target.c.inc | 2 +-
  tcg/riscv/tcg-target.c.inc   | 2 +-
  tcg/s390x/tcg-target.c.inc   | 2 +-
  tcg/sparc64/tcg-target.c.inc | 2 +-
  tcg/tcg.c| 4 ++--
  tcg/tci/tcg-target.c.inc | 2 +-
  11 files changed, 12 insertions(+), 12 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 06/15] configure: remove boolean variables for targets

2023-09-02 Thread Richard Henderson

On 9/2/23 05:59, Paolo Bonzini wrote:

Just use $targetos always.

Signed-off-by: Paolo Bonzini
---
  configure | 55 +--
  1 file changed, 13 insertions(+), 42 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: Error: .seh_endproc used in segment '.text' instead of expected '.text$qemu_close_socket_osfhandle'

2023-09-02 Thread Liviu Ionescu



> On 2 Sep 2023, at 21:43, Liviu Ionescu  wrote:
> 
> ... With the same build scripts, compiling QEMU 7.1.0 was ok, the problem was 
> introduced in the last year.

I also tried 7.2.5, and it passed the build, with the same scripts and the same 
toolchain, so the problem seems to be specific to 8.x.

For now I'll stick to 7.2.5, until the issues with the 8.1.0 build will be 
clarified.

Regards,

Liviu




Re: /util/cpuinfo-aarch64.c:58:22: error: 'HWCAP_USCAT' undeclared

2023-09-02 Thread Michael Tokarev

02.09.2023 23:01, Marcin Juszkiewicz wrote:
...

The offending code in `/util/cpuinfo-aarch64.c` is:


 > ```c
 > #ifdef CONFIG_LINUX
 >  unsigned long hwcap = qemu_getauxval(AT_HWCAP);
 >  info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
 >  info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
 >  info |= (hwcap & HWCAP_AES ? CPUINFO_AES: 0);
 > #endif
 > ```


The reason is that on this distribution the  header
file does not define HWCAP_USCAT:


I would recommend either upgrading your distro or staying at QEMU 8.1
release.

HWCAP_USCAT was added to glibc in June 2018. As your distribution is not 
supported anymore you can also patch glibc in your system.


I don't know if other distributions are also affected, my build
platform for all xPack standalone binaries is Ubuntu 18.04 LTS.


I do not know any supported distribution release without it.


In this very case it's trivial to work-around this by using

#ifndef HWCAP_USCAT
# define HWCAP_USCAT 0
#endif

or just commenting-out this line.

But 18.04 being unsupported is true still.

/mjt




Re: /util/cpuinfo-aarch64.c:58:22: error: 'HWCAP_USCAT' undeclared

2023-09-02 Thread Marcin Juszkiewicz

W dniu 2.09.2023 o 20:11, Liviu Ionescu pisze:

When trying to build 8.1.0 on an Ubuntu 18.04 aarch64, I get the
above error.


Ubuntu 18.04 is not supported anymore by Canonical. End-Of-Life was in
May 2023.


The offending code in `/util/cpuinfo-aarch64.c` is:


> ```c
> #ifdef CONFIG_LINUX
>  unsigned long hwcap = qemu_getauxval(AT_HWCAP);
>  info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
>  info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
>  info |= (hwcap & HWCAP_AES ? CPUINFO_AES: 0);
> #endif
> ```


The reason is that on this distribution the  header
file does not define HWCAP_USCAT:


I would recommend either upgrading your distro or staying at QEMU 8.1
release.

HWCAP_USCAT was added to glibc in June 2018. As your distribution is not 
supported anymore you can also patch glibc in your system.



I don't know if other distributions are also affected, my build
platform for all xPack standalone binaries is Ubuntu 18.04 LTS.


I do not know any supported distribution release without it.


I know that 18.04 is an old version, but I use the xPack QEMU mainly
to run unit tests, and in some enterprise environments the machines
used for testing are sometimes pretty outdated, thus 18.04 will
remain the base build platform for a while.

It would be very nice if QEMU would still compile on Ubuntu 18.04, as
it did before 8.1.0.




Error: .seh_endproc used in segment '.text' instead of expected '.text$qemu_close_socket_osfhandle'

2023-09-02 Thread Liviu Ionescu
When compiling 8.1.0 for Windows (with mingw-w64-gcc on Linux), I got the 
following error:

```
[634/1917] Compiling C object libqemuutil.a.p/util_oslib-win32.c.obj
FAILED: libqemuutil.a.p/util_oslib-win32.c.obj 
/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/xpacks/.bin/x86_64-w64-mingw32-gcc
 -m64 -mcx16 -Ilibqemuutil.a.p -I. -I../../../sources/qemu-8.1.0.git -Iqapi 
-Itrace -Iui -Iui/shader 
-I/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/x86_64-w64-mingw32/install/include
 -Iinclude 
-I/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/x86_64-w64-mingw32/install/include/glib-2.0
 
-I/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/x86_64-w64-mingw32/install/lib/glib-2.0/include
 
-I/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/x86_64-w64-mingw32/install/include/pixman-1
 -fdiagnostics-color=auto -Wall -Winvalid-pch -std=gnu11 -O2 -g 
-fstack-protector-strong -Wundef -Wwrite-strings -Wmissing-prototypes 
-Wstrict-prototypes -Wredundant-decls -Wold-style-declaration 
-Wold-style-definition -Wtype-limits -Wformat-security -Wformat-y2k -Winit-self 
-Wignored-qualifiers -Wempty-body -Wnested-externs -Wendif-labels 
-Wexpansion-to-defined -Wimplicit-fallthrough=2 -Wmissing-format-attribute 
-Wno-missing-include-dirs -Wno-shift-negative-value -Wno-psabi -iquote . 
-iquote 
/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/sources/qemu-8.1.0.git
 -iquote 
/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/sources/qemu-8.1.0.git/include
 -iquote 
/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/sources/qemu-8.1.0.git/host/include/x86_64
 -iquote 
/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/sources/qemu-8.1.0.git/host/include/generic
 -iquote 
/home/ilg/Work/xpack-dev-tools/qemu-riscv-xpack.git/build/win32-x64/sources/qemu-8.1.0.git/tcg/i386
 -mms-bitfields -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE 
-fno-strict-aliasing -fno-common -fwrapv -fno-pie -no-pie -ffunction-sections 
-fdata-sections -pipe -O2 -D__USE_MINGW_ACCESS -w -mms-bitfields -pthread 
-mms-bitfields -MD -MQ libqemuutil.a.p/util_oslib-win32.c.obj -MF 
libqemuutil.a.p/util_oslib-win32.c.obj.d -o 
libqemuutil.a.p/util_oslib-win32.c.obj -c 
../../../sources/qemu-8.1.0.git/util/oslib-win32.c
{standard input}: Assembler messages:
{standard input}:2859: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2860: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2862: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2863: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2867: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2868: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2872: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2873: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2875: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2876: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2882: Error: CFI instruction used without previous 
.cfi_startproc
{standard input}:2909: Error: .cfi_endproc without corresponding .cfi_startproc
{standard input}:2911: Error: .seh_endproc used in segment '.text' instead of 
expected '.text$qemu_close_socket_osfhandle'
{standard input}: Error: open CFI at the end of file; missing .cfi_endproc 
directive
{standard input}:19020: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:19024: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:19025: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:19032: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:19033: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:19054: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:19058: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:19059: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:24038: Error: invalid operands (.text and 
.text$qemu_close_socket_osfhandle sections) for `-'
{standard input}:10743: Error: can't resolve .text - .LFB7879
{standard input}:23588: Error: can't resolve .text - .LFB7879
[635/1917] Compiling C object libqemuutil.a.p/util_event_notifier-win32.c.obj
[636/1917] Compiling C object libqemuutil.a.p/util_cutils.c.obj
[637/1917] Compiling C object libqemuutil.a.p/util_qemu-thread-win32.c.obj
[638/1917] 

/util/cpuinfo-aarch64.c:58:22: error: 'HWCAP_USCAT' undeclared

2023-09-02 Thread Liviu Ionescu
When trying to build 8.1.0 on an Ubuntu 18.04 aarch64, I get the above error.

The offending code in `/util/cpuinfo-aarch64.c` is:

```c
#ifdef CONFIG_LINUX
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
info |= (hwcap & HWCAP_AES ? CPUINFO_AES: 0);
#endif
```

The reason is that on this distribution the  header file does not 
define HWCAP_USCAT:

```
root@9c7ad90af4f8:/# cat /usr/include/aarch64-linux-gnu/bits/hwcap.h
/* Defines for bits in AT_HWCAP.  AArch64 Linux version.
   Copyright (C) 2016-2018 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   .  */

#if !defined (_SYS_AUXV_H)
# error "Never include  directly; use  instead."
#endif

/* The following must match the kernel's .  */
#define HWCAP_FP(1 << 0)
#define HWCAP_ASIMD (1 << 1)
#define HWCAP_EVTSTRM   (1 << 2)
#define HWCAP_AES   (1 << 3)
#define HWCAP_PMULL (1 << 4)
#define HWCAP_SHA1  (1 << 5)
#define HWCAP_SHA2  (1 << 6)
#define HWCAP_CRC32 (1 << 7)
#define HWCAP_ATOMICS   (1 << 8)
#define HWCAP_FPHP  (1 << 9)
#define HWCAP_ASIMDHP   (1 << 10)
#define HWCAP_CPUID (1 << 11)
#define HWCAP_ASIMDRDM  (1 << 12)
#define HWCAP_JSCVT (1 << 13)
#define HWCAP_FCMA  (1 << 14)
#define HWCAP_LRCPC (1 << 15)
#define HWCAP_DCPOP (1 << 16)
#define HWCAP_SHA3  (1 << 17)
#define HWCAP_SM3   (1 << 18)
#define HWCAP_SM4   (1 << 19)
#define HWCAP_ASIMDDP   (1 << 20)
#define HWCAP_SHA512(1 << 21)
#define HWCAP_SVE   (1 << 22)
root@9c7ad90af4f8:/# 
```

The full list of definitions should include:

```
#define HWCAP_ASIMDFHM  (1 << 23)
#define HWCAP_DIT   (1 << 24)
#define HWCAP_USCAT (1 << 25)
#define HWCAP_ILRCPC(1 << 26)
#define HWCAP_FLAGM (1 << 27)
#define HWCAP_SSBS  (1 << 28)
```

I don't know the meaning behind these bits, and how important is for QEMU to 
correctly identify them all.

Since I know my build environment, my quick and dirty workaround was to pass 
the definition via the preprocessor options:

```
CPPFLAGS+=" -DHWCAP_USCAT=(1<<25)"
```

However, for QEMU this is not a solution.

A possible solution would be to compile the code conditionally:

```
#ifdef CONFIG_LINUX
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
#ifdef HWCAP_USCAT
info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
#endif
info |= (hwcap & HWCAP_AES ? CPUINFO_AES: 0);
#endif
```

I don't know if other distributions are also affected, my build platform for 
all xPack standalone binaries is Ubuntu 18.04 LTS.

I know that 18.04 is an old version, but I use the xPack QEMU mainly to run 
unit tests, and in some enterprise environments the machines used for testing 
are sometimes pretty outdated, thus 18.04 will remain the base build platform 
for a while.

It would be very nice if QEMU would still compile on Ubuntu 18.04, as it did 
before 8.1.0.



Regards,

Liviu




[PATCH 15/15] configure: remove dead code

2023-09-02 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 configure | 8 
 1 file changed, 8 deletions(-)

diff --git a/configure b/configure
index 6404b659718..a8d79602098 100755
--- a/configure
+++ b/configure
@@ -1126,14 +1126,6 @@ else
 done
 fi
 
-# see if system emulation was really requested
-case " $target_list " in
-  *"-softmmu "*) softmmu=yes
-  ;;
-  *) softmmu=no
-  ;;
-esac
-
 if test "$tcg" = "auto"; then
   if test -z "$target_list"; then
 tcg="disabled"
-- 
2.41.0




[PATCH 13/15] configure, meson: remove target OS symbols from config-host.mak

2023-09-02 Thread Paolo Bonzini
Stop applying config-host.mak to the sourcesets, since it does not
have any more CONFIG_* symbols coming from the command line.

Signed-off-by: Paolo Bonzini 
---
 Makefile   |  2 +-
 chardev/meson.build|  2 +-
 configure  | 18 -
 docs/devel/kconfig.rst |  2 +-
 gdbstub/meson.build|  4 ++--
 meson.build| 40 +-
 qga/meson.build|  4 ++--
 storage-daemon/meson.build |  2 +-
 tcg/meson.build|  2 +-
 tests/meson.build  |  2 +-
 tests/qtest/meson.build| 12 ++--
 tests/unit/meson.build |  6 +++---
 12 files changed, 46 insertions(+), 50 deletions(-)

diff --git a/Makefile b/Makefile
index 118c28e80d9..bfc4b2c8e92 100644
--- a/Makefile
+++ b/Makefile
@@ -313,7 +313,7 @@ endif
@echo  'Documentation targets:'
$(call print-help,html man,Build documentation in specified format)
@echo  ''
-ifdef CONFIG_WIN32
+ifneq ($(filter msi, $(ninja-targets)),)
@echo  'Windows targets:'
$(call print-help,installer,Build NSIS-based installer for QEMU)
$(call print-help,msi,Build MSI-based installer for qemu-ga)
diff --git a/chardev/meson.build b/chardev/meson.build
index fb630b429eb..6d56ad32fdb 100644
--- a/chardev/meson.build
+++ b/chardev/meson.build
@@ -26,7 +26,7 @@ chardev_ss.add(when: 'CONFIG_WIN32', if_true: files(
   'char-win.c',
 ))
 
-chardev_ss = chardev_ss.apply(config_host, strict: false)
+chardev_ss = chardev_ss.apply(config_targetos, strict: false)
 
 system_ss.add(files(
 'char-hmp-cmds.c',
diff --git a/configure b/configure
index f3ffaca1878..6404b659718 100755
--- a/configure
+++ b/configure
@@ -1683,32 +1683,14 @@ echo >> $config_host_mak
 echo all: >> $config_host_mak
 
 if test "$targetos" = "windows"; then
-  echo "CONFIG_WIN32=y" >> $config_host_mak
   echo "QEMU_GA_MANUFACTURER=${QEMU_GA_MANUFACTURER-QEMU}" >> $config_host_mak
   echo "QEMU_GA_DISTRO=${QEMU_GA_DISTRO-Linux}" >> $config_host_mak
   echo "QEMU_GA_VERSION=${QEMU_GA_VERSION-$(cat "$source_path"/VERSION)}" >> 
$config_host_mak
-else
-  echo "CONFIG_POSIX=y" >> $config_host_mak
-fi
-
-if test "$targetos" = "linux" ; then
-  echo "CONFIG_LINUX=y" >> $config_host_mak
-fi
-
-if test "$targetos" = "darwin" ; then
-  echo "CONFIG_DARWIN=y" >> $config_host_mak
 fi
 
 echo "SRC_PATH=$source_path" >> $config_host_mak
 echo "TARGET_DIRS=$target_list" >> $config_host_mak
 
-# XXX: suppress that
-case $targetos in
-  gnu/kfreebsd | freebsd | dragonfly | netbsd | openbsd | darwin)
-echo "CONFIG_BSD=y" >> $config_host_mak
-;;
-esac
-
 if test -n "$gdb_bin"; then
 gdb_version=$($gdb_bin --version | head -n 1)
 if version_ge ${gdb_version##* } 9.1; then
diff --git a/docs/devel/kconfig.rst b/docs/devel/kconfig.rst
index e3a544e463f..73f52de1067 100644
--- a/docs/devel/kconfig.rst
+++ b/docs/devel/kconfig.rst
@@ -316,6 +316,6 @@ variable::
 
 host_kconfig = \
   (have_tpm ? ['CONFIG_TPM=y'] : []) + \
-  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
+  (targetos == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
   ...
diff --git a/gdbstub/meson.build b/gdbstub/meson.build
index 77762e0b3e1..9500b9dc4e6 100644
--- a/gdbstub/meson.build
+++ b/gdbstub/meson.build
@@ -14,8 +14,8 @@ gdb_system_ss = ss.source_set()
 gdb_user_ss.add(files('gdbstub.c', 'user.c'))
 gdb_system_ss.add(files('gdbstub.c', 'softmmu.c'))
 
-gdb_user_ss = gdb_user_ss.apply(config_host, strict: false)
-gdb_system_ss = gdb_system_ss.apply(config_host, strict: false)
+gdb_user_ss = gdb_user_ss.apply(config_targetos, strict: false)
+gdb_system_ss = gdb_system_ss.apply(config_targetos, strict: false)
 
 libgdb_user = static_library('gdb_user',
  gdb_user_ss.sources() + genh,
diff --git a/meson.build b/meson.build
index f6d079f4cda..d3feac656cb 100644
--- a/meson.build
+++ b/meson.build
@@ -2069,10 +2069,15 @@ config_host_data.set('CONFIG_MODULE_UPGRADES', 
get_option('module_upgrades'))
 config_host_data.set('CONFIG_ATTR', libattr.found())
 config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', 
get_option('block_drv_whitelist_in_tools'))
 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
+config_host_data.set('CONFIG_BSD', targetos in bsd_oses)
 config_host_data.set('CONFIG_COCOA', cocoa.found())
+config_host_data.set('CONFIG_DARWIN', targetos == 'darwin')
 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
+config_host_data.set('CONFIG_LINUX', targetos == 'linux')
+config_host_data.set('CONFIG_POSIX', targetos != 'windows')
+config_host_data.set('CONFIG_WIN32', targetos == 'windows')
 config_host_data.set('CONFIG_LZO', lzo.found())
 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
 config_host_data.set('CONFIG_BLKIO', 

[PATCH 14/15] meson: list leftover CONFIG_* symbols

2023-09-02 Thread Paolo Bonzini
There are no config-host.mak symbols anymore that are needed in
config-host.h; the only symbols that are included in config_host_data via
the foreach loop are:

- CONFIG_DEFAULT_TARGETS, which is not used by C code.

- CONFIG_TCG and CONFIG_TCG_INTERPRETER, which are not part of config-host.mak

So, list these two symbols explicitly.

Signed-off-by: Paolo Bonzini 
---
 docs/devel/build-system.rst |  8 ++--
 meson.build | 10 ++
 2 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst
index 64efa26b905..0f990bb3e90 100644
--- a/docs/devel/build-system.rst
+++ b/docs/devel/build-system.rst
@@ -460,17 +460,13 @@ Built by configure:
 
 ``config-host.mak``
   When configure has determined the characteristics of the build host it
-  will write them to this file for use in ``Makefile`` and to a smaller
-  extent ``meson.build``. These include the paths to various tools and a
-  variety of ``CONFIG_*`` variables related to optionally enabled features.
+  will write the paths to various tools to this file, for use in ``Makefile``
+  and to a smaller extent ``meson.build``.
 
   ``config-host.mak`` is also used as a dependency checking mechanism. If make
   sees that the modification timestamp on configure is newer than that on
   ``config-host.mak``, then configure will be re-run.
 
-  The variables defined here apply to all QEMU
-  build outputs.
-
 ``config-meson.cross``
 
   A Meson "cross file" (or native file) used to communicate the paths to
diff --git a/meson.build b/meson.build
index d3feac656cb..cde2b58b91e 100644
--- a/meson.build
+++ b/meson.build
@@ -691,7 +691,6 @@ if get_option('tcg').allowed()
   endif
   if get_option('tcg_interpreter')
 tcg_arch = 'tci'
-config_host += { 'CONFIG_TCG_INTERPRETER': 'y' }
   elif host_arch == 'x86_64'
 tcg_arch = 'i386'
   elif host_arch == 'ppc64'
@@ -701,7 +700,6 @@ if get_option('tcg').allowed()
 language: all_languages)
 
   accelerators += 'CONFIG_TCG'
-  config_host += { 'CONFIG_TCG': 'y' }
 endif
 
 if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
@@ -2132,6 +2130,10 @@ if seccomp.found()
 endif
 config_host_data.set('CONFIG_SNAPPY', snappy.found())
 config_host_data.set('CONFIG_SOLARIS', targetos == 'sunos')
+if get_option('tcg').allowed()
+  config_host_data.set('CONFIG_TCG', 1)
+  config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
+endif
 config_host_data.set('CONFIG_TPM', have_tpm)
 config_host_data.set('CONFIG_TSAN', get_option('tsan'))
 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
@@ -2760,12 +2762,6 @@ if targetos == 'windows' and 'cpp' in all_languages
 endif
 config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
 
-foreach k, v: config_host
-  if k.startswith('CONFIG_')
-config_host_data.set(k, v == 'y' ? 1 : v)
-  endif
-endforeach
-
 # Older versions of MinGW do not import _lock_file and _unlock_file properly.
 # This was fixed for v6.0.0 with commit b48e3ac8969d.
 if targetos == 'windows'
-- 
2.41.0




[PATCH 03/15] configure: remove HOST_CC

2023-09-02 Thread Paolo Bonzini
$(HOST_CC) is only used to invoke the preprocessor, and $(CC) can be
used instead now that there is a Tricore C compiler.  Remove the variable
from config-host.mak.

Reviewed-by: Richard Henderson 
Reviewed-by: Daniel P. Berrangé 
Signed-off-by: Paolo Bonzini 
---
 configure | 1 -
 tests/tcg/tricore/Makefile.softmmu-target | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/configure b/configure
index b9af8282293..7743c18f2fe 100755
--- a/configure
+++ b/configure
@@ -1800,7 +1800,6 @@ fi
 mkdir -p tests/tcg
 echo "# Automatically generated by configure - do not modify" > 
$config_host_mak
 echo "SRC_PATH=$source_path" >> $config_host_mak
-echo "HOST_CC=$host_cc" >> $config_host_mak
 
 # versioned checked in the main config_host.mak above
 if test -n "$gdb_bin"; then
diff --git a/tests/tcg/tricore/Makefile.softmmu-target 
b/tests/tcg/tricore/Makefile.softmmu-target
index aff7c1b5802..2ec0bd36225 100644
--- a/tests/tcg/tricore/Makefile.softmmu-target
+++ b/tests/tcg/tricore/Makefile.softmmu-target
@@ -28,7 +28,7 @@ TESTS += test_context_save_areas.c.tst
 QEMU_OPTS += -M tricore_testboard -cpu tc27x -nographic -kernel
 
 %.pS: $(ASM_TESTS_PATH)/%.S
-   $(HOST_CC) -E -o $@ $<
+   $(CC) -E -o $@ $<
 
 %.o: %.pS
$(AS) $(ASFLAGS) -o $@ $<
-- 
2.41.0




[PATCH 12/15] configure, meson: remove CONFIG_SOLARIS from config-host.mak

2023-09-02 Thread Paolo Bonzini
CONFIG_SOLARIS is only used to pick tap implementations.  But the
target OS is invariant and does not depend on the configuration, so move
away from config_host and just use unconditional rules in softmmu_ss.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 configure   |  3 ---
 meson.build |  1 +
 net/meson.build | 18 ++
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/configure b/configure
index 017977f72b3..f3ffaca1878 100755
--- a/configure
+++ b/configure
@@ -1699,9 +1699,6 @@ if test "$targetos" = "darwin" ; then
   echo "CONFIG_DARWIN=y" >> $config_host_mak
 fi
 
-if test "$targetos" = "sunos" ; then
-  echo "CONFIG_SOLARIS=y" >> $config_host_mak
-fi
 echo "SRC_PATH=$source_path" >> $config_host_mak
 echo "TARGET_DIRS=$target_list" >> $config_host_mak
 
diff --git a/meson.build b/meson.build
index 9100e2a9794..f6d079f4cda 100644
--- a/meson.build
+++ b/meson.build
@@ -2126,6 +2126,7 @@ if seccomp.found()
   config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
 endif
 config_host_data.set('CONFIG_SNAPPY', snappy.found())
+config_host_data.set('CONFIG_SOLARIS', targetos == 'sunos')
 config_host_data.set('CONFIG_TPM', have_tpm)
 config_host_data.set('CONFIG_TSAN', get_option('tsan'))
 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
diff --git a/net/meson.build b/net/meson.build
index bdf564a57b2..d2d70634e5e 100644
--- a/net/meson.build
+++ b/net/meson.build
@@ -41,15 +41,17 @@ if have_vhost_net_user
   system_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-user-stub.c'))
 endif
 
-system_ss.add(when: 'CONFIG_LINUX', if_true: files('tap-linux.c'))
-system_ss.add(when: 'CONFIG_BSD', if_true: files('tap-bsd.c'))
-system_ss.add(when: 'CONFIG_SOLARIS', if_true: files('tap-solaris.c'))
-tap_posix = ['tap.c']
-if not config_host.has_key('CONFIG_LINUX') and not 
config_host.has_key('CONFIG_BSD') and not config_host.has_key('CONFIG_SOLARIS')
-  tap_posix += 'tap-stub.c'
+if targetos == 'windows'
+  system_ss.add(files('tap-win32.c'))
+elif targetos == 'linux'
+  system_ss.add(files('tap.c', 'tap-linux.c'))
+elif targetos in bsd_oses
+  system_ss.add(files('tap.c', 'tap-bsd.c'))
+elif targetos == 'solaris'
+  system_ss.add(files('tap.c', 'tap-solaris.c'))
+else
+  system_ss.add(files('tap.c', 'tap-stub.c'))
 endif
-system_ss.add(when: 'CONFIG_POSIX', if_true: files(tap_posix))
-system_ss.add(when: 'CONFIG_WIN32', if_true: files('tap-win32.c'))
 if have_vhost_net_vdpa
   system_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('vhost-vdpa.c'), 
if_false: files('vhost-vdpa-stub.c'))
   system_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-vdpa-stub.c'))
-- 
2.41.0




[PATCH 07/15] configure: move --enable-debug-tcg to meson

2023-09-02 Thread Paolo Bonzini
Reviewed-by: Richard Henderson 
Reviewed-by: Peter Maydell 
Signed-off-by: Paolo Bonzini 
---
 configure | 11 +--
 meson.build   |  3 ++-
 meson_options.txt |  2 ++
 scripts/meson-buildoptions.sh |  3 +++
 4 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/configure b/configure
index f96f7359a83..afd6121b616 100755
--- a/configure
+++ b/configure
@@ -248,7 +248,6 @@ done
 
 git_submodules_action="update"
 git="git"
-debug_tcg="no"
 docs="auto"
 EXESUF=""
 prefix="/usr/local"
@@ -727,13 +726,9 @@ for opt do
 # configure to be used by RPM and similar macros that set
 # lots of directory switches by default.
   ;;
-  --enable-debug-tcg) debug_tcg="yes"
-  ;;
-  --disable-debug-tcg) debug_tcg="no"
-  ;;
   --enable-debug)
   # Enable debugging options that aren't excessively noisy
-  debug_tcg="yes"
+  meson_option_parse --enable-debug-tcg ""
   meson_option_parse --enable-debug-graph-lock ""
   meson_option_parse --enable-debug-mutex ""
   meson_option_add -Doptimization=0
@@ -933,7 +928,6 @@ cat << EOF
   linux-user  all linux usermode emulation targets
   bsd-userall BSD usermode emulation targets
   pie Position Independent Executables
-  debug-tcg   TCG debugging (default is disabled)
 
 NOTE: The object files are built at the place where configure is launched
 EOF
@@ -1684,9 +1678,6 @@ echo >> $config_host_mak
 
 echo all: >> $config_host_mak
 
-if test "$debug_tcg" = "yes" ; then
-  echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
-fi
 if test "$targetos" = "windows"; then
   echo "CONFIG_WIN32=y" >> $config_host_mak
   echo "QEMU_GA_MANUFACTURER=${QEMU_GA_MANUFACTURER-QEMU}" >> $config_host_mak
diff --git a/meson.build b/meson.build
index 9bcf117f8a4..baf47613650 100644
--- a/meson.build
+++ b/meson.build
@@ -2199,6 +2199,7 @@ config_host_data.set10('CONFIG_COROUTINE_POOL', 
have_coroutine_pool)
 config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
 config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
 config_host_data.set('CONFIG_DEBUG_STACK_USAGE', 
get_option('debug_stack_usage'))
+config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
 config_host_data.set('CONFIG_GPROF', get_option('gprof'))
 config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', 
get_option('live_block_migration').allowed())
 config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
@@ -4156,7 +4157,7 @@ if config_all.has_key('CONFIG_TCG')
 summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
   endif
   summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
-  summary_info += {'TCG debug enabled': 
config_host.has_key('CONFIG_DEBUG_TCG')}
+  summary_info += {'TCG debug enabled': get_option('debug_tcg')}
 endif
 summary_info += {'target list':   ' '.join(target_dirs)}
 if have_system
diff --git a/meson_options.txt b/meson_options.txt
index aaea5ddd779..5d6b889554c 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -83,6 +83,8 @@ option('xen_pci_passthrough', type: 'feature', value: 'auto',
description: 'Xen PCI passthrough support')
 option('tcg', type: 'feature', value: 'enabled',
description: 'TCG support')
+option('debug_tcg', type: 'boolean', value: false,
+   description: 'TCG debugging')
 option('tcg_interpreter', type: 'boolean', value: false,
description: 'TCG with bytecode interpreter (slow)')
 option('safe_stack', type: 'boolean', value: false,
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index 9da3fe299b7..5567fd29985 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -29,6 +29,7 @@ meson_options_help() {
   printf "%s\n" '  --enable-debug-mutex mutex debugging support'
   printf "%s\n" '  --enable-debug-stack-usage'
   printf "%s\n" '   measure coroutine stack usage'
+  printf "%s\n" '  --enable-debug-tcg   TCG debugging'
   printf "%s\n" '  --enable-fdt[=CHOICE]Whether and how to find the libfdt 
library'
   printf "%s\n" '   (choices: 
auto/disabled/enabled/internal/system)'
   printf "%s\n" '  --enable-fuzzing build fuzzing targets'
@@ -276,6 +277,8 @@ _meson_option_parse() {
 --disable-debug-mutex) printf "%s" -Ddebug_mutex=false ;;
 --enable-debug-stack-usage) printf "%s" -Ddebug_stack_usage=true ;;
 --disable-debug-stack-usage) printf "%s" -Ddebug_stack_usage=false ;;
+--enable-debug-tcg) printf "%s" -Ddebug_tcg=true ;;
+--disable-debug-tcg) printf "%s" -Ddebug_tcg=false ;;
 --enable-dmg) printf "%s" -Ddmg=enabled ;;
 --disable-dmg) printf "%s" -Ddmg=disabled ;;
 --docdir=*) quote_sh "-Ddocdir=$2" ;;
-- 
2.41.0




[PATCH 05/15] meson: compile bundled device trees

2023-09-02 Thread Paolo Bonzini
If dtc is available, compile the .dts files in the pc-bios directory
instead of using the precompiled binaries.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 pc-bios/Makefile| 19 ---
 pc-bios/meson.build | 25 +
 2 files changed, 21 insertions(+), 23 deletions(-)
 delete mode 100644 pc-bios/Makefile

diff --git a/pc-bios/Makefile b/pc-bios/Makefile
deleted file mode 100644
index 315288df84e..000
--- a/pc-bios/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# NOTE: only compilable with x86 cross compile tools
-#
-include ../config-host.mak
-
-DEFINES=
-
-TARGETS=
-
-all: $(TARGETS)
-
-%.o: %.S
-   $(CC) $(DEFINES) -c -o $@ $<
-
-%.dtb: %.dts
-   dtc -I dts -O dtb -o $@ $<
-
-clean:
-   rm -f $(TARGETS) *.o *~
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index a7224ef4699..e67fa433a1b 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -57,10 +57,6 @@ blobs = [
   'efi-e1000e.rom',
   'efi-vmxnet3.rom',
   'qemu-nsis.bmp',
-  'bamboo.dtb',
-  'canyonlands.dtb',
-  'petalogix-s3adsp1800.dtb',
-  'petalogix-ml605.dtb',
   'multiboot.bin',
   'multiboot_dma.bin',
   'linuxboot.bin',
@@ -84,6 +80,27 @@ blobs = [
   'vof-nvram.bin',
 ]
 
+dtc = find_program('dtc', required: false)
+foreach f : [
+  'bamboo.dts',
+  'canyonlands.dts',
+  'petalogix-s3adsp1800.dts',
+  'petalogix-ml605.dts',
+]
+  out = fs.replace_suffix(f, '.dtb')
+  if dtc.found()
+custom_target(f,
+build_by_default: have_system,
+input: files(f),
+output: out,
+install: get_option('install_blobs'),
+install_dir: qemu_datadir,
+command: [ dtc, '-I', 'dts', '-O', 'dtb', '-o', '@OUTPUT@', '@INPUT0@' 
])
+  else
+blobs += out
+  endif
+endforeach
+
 if get_option('install_blobs')
   install_data(blobs, install_dir: qemu_datadir)
 endif
-- 
2.41.0




[PATCH 11/15] configure, meson: move --enable-plugins to meson

2023-09-02 Thread Paolo Bonzini
While the option still needs to be parsed in the configure script
(it's needed by tests/tcg, and also to decide about recursing
into contrib/plugins), passing it to Meson can be done with -D
instead of using config-host.mak.

Signed-off-by: Paolo Bonzini 
---
 accel/tcg/meson.build |  4 +++-
 configure |  5 +
 meson.build   |  7 ---
 meson_options.txt |  2 ++
 plugins/meson.build   | 12 +++-
 scripts/meson-buildoptions.sh |  3 +++
 tests/Makefile.include|  2 +-
 tests/meson.build |  6 ++
 8 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build
index 166bef173b8..8ace7837079 100644
--- a/accel/tcg/meson.build
+++ b/accel/tcg/meson.build
@@ -11,7 +11,9 @@ tcg_ss.add(files(
 ))
 tcg_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-exec.c'))
 tcg_ss.add(when: 'CONFIG_SYSTEM_ONLY', if_false: files('user-exec-stub.c'))
-tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c')])
+if get_option('plugins')
+  tcg_ss.add(files('plugin-gen.c'))
+endif
 tcg_ss.add(when: libdw, if_true: files('debuginfo.c'))
 tcg_ss.add(when: 'CONFIG_LINUX', if_true: files('perf.c'))
 specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
diff --git a/configure b/configure
index 9980eaeef57..017977f72b3 100755
--- a/configure
+++ b/configure
@@ -1712,10 +1712,6 @@ case $targetos in
 ;;
 esac
 
-if test "$plugins" = "yes" ; then
-echo "CONFIG_PLUGIN=y" >> $config_host_mak
-fi
-
 if test -n "$gdb_bin"; then
 gdb_version=$($gdb_bin --version | head -n 1)
 if version_ge ${gdb_version##* } 9.1; then
@@ -1906,6 +1902,7 @@ if test "$skip_meson" = no; then
   test "$cfi" != false && meson_option_add "-Dcfi=$cfi"
   test "$docs" != auto && meson_option_add "-Ddocs=$docs"
   test -n "${LIB_FUZZING_ENGINE+xxx}" && meson_option_add 
"-Dfuzzing_engine=$LIB_FUZZING_ENGINE"
+  test "$plugins" = yes && meson_option_add "-Dplugins=true"
   test "$qemu_suffix" != qemu && meson_option_add "-Dqemu_suffix=$qemu_suffix"
   test "$smbd" != '' && meson_option_add "-Dsmbd=$smbd"
   test "$tcg" != enabled && meson_option_add "-Dtcg=$tcg"
diff --git a/meson.build b/meson.build
index baf47613650..9100e2a9794 100644
--- a/meson.build
+++ b/meson.build
@@ -730,7 +730,7 @@ glib_cflags = []
 if enable_modules
   gmodule = dependency('gmodule-export-2.0', version: glib_req_ver, required: 
true,
method: 'pkg-config')
-elif config_host.has_key('CONFIG_PLUGIN')
+elif get_option('plugins')
   gmodule = dependency('gmodule-no-export-2.0', version: glib_req_ver, 
required: true,
method: 'pkg-config')
 else
@@ -2115,6 +2115,7 @@ if numa.found()
dependencies: numa))
 endif
 config_host_data.set('CONFIG_OPENGL', opengl.found())
+config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
 config_host_data.set('CONFIG_RBD', rbd.found())
 config_host_data.set('CONFIG_RDMA', rdma.found())
 config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
@@ -3883,7 +3884,7 @@ endforeach
 
 # Other build targets
 
-if 'CONFIG_PLUGIN' in config_host
+if get_option('plugins')
   install_headers('include/qemu/qemu-plugin.h')
 endif
 
@@ -4156,7 +4157,7 @@ if config_all.has_key('CONFIG_TCG')
   else
 summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
   endif
-  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
+  summary_info += {'TCG plugins':   get_option('plugins')}
   summary_info += {'TCG debug enabled': get_option('debug_tcg')}
 endif
 summary_info += {'target list':   ' '.join(target_dirs)}
diff --git a/meson_options.txt b/meson_options.txt
index 5d6b889554c..e48086e2562 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -83,6 +83,8 @@ option('xen_pci_passthrough', type: 'feature', value: 'auto',
description: 'Xen PCI passthrough support')
 option('tcg', type: 'feature', value: 'enabled',
description: 'TCG support')
+option('plugins', type: 'boolean', value: false,
+   description: 'TCG plugins via shared library loading')
 option('debug_tcg', type: 'boolean', value: false,
description: 'TCG debugging')
 option('tcg_interpreter', type: 'boolean', value: false,
diff --git a/plugins/meson.build b/plugins/meson.build
index 752377c66d3..71ed996ed31 100644
--- a/plugins/meson.build
+++ b/plugins/meson.build
@@ -13,8 +13,10 @@ if not enable_modules
   endif
 endif
 
-specific_ss.add(when: 'CONFIG_PLUGIN', if_true: [files(
-  'loader.c',
-  'core.c',
-  'api.c',
-), declare_dependency(link_args: plugin_ldflags)])
+if get_option('plugins')
+  specific_ss.add(files(
+'loader.c',
+'core.c',
+'api.c',
+  ), declare_dependency(link_args: plugin_ldflags))
+endif
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index 5567fd29985..6b16ad94f4b 100644
--- a/scripts/meson-buildoptions.sh
+++ 

[PATCH 02/15] meson: update unsupported host/CPU messages

2023-09-02 Thread Paolo Bonzini
Unsupported CPU and OSes are not really going away, but the
project simply does not guarantee that they work.  Rephrase
the messages accordingly.  While at it, move the warning for
TCI performance at the end where it is more visible.

Signed-off-by: Paolo Bonzini 
---
 meson.build | 45 ++---
 1 file changed, 26 insertions(+), 19 deletions(-)

diff --git a/meson.build b/meson.build
index 98e68ef0b1e..9bcf117f8a4 100644
--- a/meson.build
+++ b/meson.build
@@ -678,9 +678,7 @@ endif
 tcg_arch = host_arch
 if get_option('tcg').allowed()
   if host_arch == 'unknown'
-if get_option('tcg_interpreter')
-  warning('Unsupported CPU @0@, will use TCG with TCI (slow)'.format(cpu))
-else
+if not get_option('tcg_interpreter')
   error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
 endif
   elif get_option('tcg_interpreter')
@@ -4317,28 +4315,37 @@ summary_info += {'selinux':   selinux}
 summary_info += {'libdw': libdw}
 summary(summary_info, bool_yn: true, section: 'Dependencies')
 
-if not supported_cpus.contains(cpu)
+if host_arch == 'unknown'
   message()
-  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
+  warning('UNSUPPORTED HOST CPU')
   message()
-  message('CPU host architecture ' + cpu + ' support is not currently 
maintained.')
-  message('The QEMU project intends to remove support for this host CPU in')
-  message('a future release if nobody volunteers to maintain it and to')
-  message('provide a build host for our continuous integration setup.')
-  message('configure has succeeded and you can continue to build, but')
-  message('if you care about QEMU on this platform you should contact')
-  message('us upstream at qemu-devel@nongnu.org.')
+  message('Support for CPU host architecture ' + cpu + ' is not currently')
+  message('maintained. The QEMU project does not guarantee that QEMU will')
+  message('compile or work on this host CPU. You can help by volunteering')
+  message('to maintain it and providing a build host for our continuous.')
+  message('integration setup.')
+  if get_option('tcg').allowed() and target_dirs.length() > 0
+message()
+message('configure has succeeded and you can continue to build, but')
+message('QEMU will use a slow interpreter to emulate the target CPU.')
+  endif
 endif
 
 if not supported_oses.contains(targetos)
   message()
-  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
+  warning('UNSUPPORTED HOST OS')
   message()
-  message('Host OS ' + targetos + 'support is not currently maintained.')
-  message('The QEMU project intends to remove support for this host OS in')
-  message('a future release if nobody volunteers to maintain it and to')
-  message('provide a build host for our continuous integration setup.')
+  message('Support for host OS ' + targetos + 'is not currently maintained.')
   message('configure has succeeded and you can continue to build, but')
-  message('if you care about QEMU on this platform you should contact')
-  message('us upstream at qemu-devel@nongnu.org.')
+  message('the QEMU project does not guarantee that QEMU will compile or')
+  message('work on this operating system. You can help by volunteering')
+  message('to maintain it and providing a build host for our continuous.')
+  message('integration setup. This will ensure that future versions of QEMU')
+  message('will keep working on ' + targetos + '.')
+endif
+
+if host_arch == 'unknown' or not supported_oses.contains(targetos)
+  message()
+  message('If you care about QEMU on this platform, please contact the')
+  message('developers at qemu-devel@nongnu.org.')
 endif
-- 
2.41.0




[PATCH 06/15] configure: remove boolean variables for targets

2023-09-02 Thread Paolo Bonzini
Just use $targetos always.

Signed-off-by: Paolo Bonzini 
---
 configure | 55 +--
 1 file changed, 13 insertions(+), 42 deletions(-)

diff --git a/configure b/configure
index 378a0de9fb6..f96f7359a83 100755
--- a/configure
+++ b/configure
@@ -374,45 +374,14 @@ fi
 
 # OS specific
 
-mingw32="no"
-bsd="no"
-linux="no"
-solaris="no"
 case $targetos in
 windows)
-  mingw32="yes"
   plugins="no"
   pie="no"
 ;;
-gnu/kfreebsd)
-  bsd="yes"
-;;
-freebsd)
-  bsd="yes"
-  # needed for kinfo_getvmmap(3) in libutil.h
-;;
-dragonfly)
-  bsd="yes"
-;;
-netbsd)
-  bsd="yes"
-;;
-openbsd)
-  bsd="yes"
-;;
-darwin)
-  bsd="yes"
-  darwin="yes"
-;;
-sunos)
-  solaris="yes"
-;;
 haiku)
   pie="no"
 ;;
-linux)
-  linux="yes"
-;;
 esac
 
 if test ! -z "$cpu" ; then
@@ -627,7 +596,7 @@ do
 fi
 done
 
-if test "$mingw32" = "yes" ; then
+if test "$targetos" = "windows" ; then
   EXESUF=".exe"
   prefix="/qemu"
   bindir=""
@@ -809,7 +778,7 @@ for opt do
   ;;
   --enable-download) download="enabled"; git_submodules_action=update;
   ;;
-  --enable-plugins) if test "$mingw32" = "yes"; then
+  --enable-plugins) if test "$targetos" = "windows"; then
 error_exit "TCG plugins not currently supported on 
Windows platforms"
 else
 plugins="yes"
@@ -1080,7 +1049,7 @@ fi
 # by default.  Only enable by default for git builds
 if test -z "$werror" ; then
 if test -e "$source_path/.git" && \
-{ test "$linux" = "yes" || test "$mingw32" = "yes"; }; then
+{ test "$targetos" = linux || test "$targetos" = "windows"; }; then
 werror="yes"
 else
 werror="no"
@@ -1718,7 +1687,7 @@ echo all: >> $config_host_mak
 if test "$debug_tcg" = "yes" ; then
   echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
 fi
-if test "$mingw32" = "yes" ; then
+if test "$targetos" = "windows"; then
   echo "CONFIG_WIN32=y" >> $config_host_mak
   echo "QEMU_GA_MANUFACTURER=${QEMU_GA_MANUFACTURER-QEMU}" >> $config_host_mak
   echo "QEMU_GA_DISTRO=${QEMU_GA_DISTRO-Linux}" >> $config_host_mak
@@ -1727,24 +1696,26 @@ else
   echo "CONFIG_POSIX=y" >> $config_host_mak
 fi
 
-if test "$linux" = "yes" ; then
+if test "$targetos" = "linux" ; then
   echo "CONFIG_LINUX=y" >> $config_host_mak
 fi
 
-if test "$darwin" = "yes" ; then
+if test "$targetos" = "darwin" ; then
   echo "CONFIG_DARWIN=y" >> $config_host_mak
 fi
 
-if test "$solaris" = "yes" ; then
+if test "$targetos" = "sunos" ; then
   echo "CONFIG_SOLARIS=y" >> $config_host_mak
 fi
 echo "SRC_PATH=$source_path" >> $config_host_mak
 echo "TARGET_DIRS=$target_list" >> $config_host_mak
 
 # XXX: suppress that
-if [ "$bsd" = "yes" ] ; then
-  echo "CONFIG_BSD=y" >> $config_host_mak
-fi
+case $targetos in
+  gnu/kfreebsd | freebsd | dragonfly | netbsd | openbsd | darwin)
+echo "CONFIG_BSD=y" >> $config_host_mak
+;;
+esac
 
 if test "$plugins" = "yes" ; then
 echo "CONFIG_PLUGIN=y" >> $config_host_mak
@@ -1774,7 +1745,7 @@ echo "CC=$cc" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
 
 # use included Linux headers for KVM architectures
-if test "$linux" = "yes" && test -n "$linux_arch"; then
+if test "$targetos" = "linux" && test -n "$linux_arch"; then
   symlink "$source_path/linux-headers/asm-$linux_arch" linux-headers/asm
 fi
 
-- 
2.41.0




[PATCH 09/15] contrib/plugins: use an independent makefile

2023-09-02 Thread Paolo Bonzini
The initial reason to write this patch was to remove the last use of
CONFIG_DEBUG_TCG from the makefiles; the flags to use to build TCG
plugins are unrelated to --enable-debug-tcg, and instead they should
be the same as those used to build emulators (the plugins are not build
via meson for demonstration reasons only).

However, since contrib/plugins/Makefile is also the last case of doing
a compilation job using config-host.mak, go a step further and make it
use a completely separate configuration file, removing all references
to compilers from the toplevel config-host.mak.  Clean up references to
empty variables, and use .SECONDARY so that intermediate object files
are not deleted.

Reviewed-by: Daniel P. Berrangé 
Signed-off-by: Paolo Bonzini 
---
 configure| 12 +---
 contrib/plugins/Makefile | 18 +-
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/configure b/configure
index afd6121b616..1be8b430a54 100755
--- a/configure
+++ b/configure
@@ -245,7 +245,7 @@ for opt do
   esac
 done
 
-
+default_cflags='-O2 -g'
 git_submodules_action="update"
 git="git"
 docs="auto"
@@ -732,6 +732,7 @@ for opt do
   meson_option_parse --enable-debug-graph-lock ""
   meson_option_parse --enable-debug-mutex ""
   meson_option_add -Doptimization=0
+  default_cflags='-O0 -g'
   ;;
   --disable-tcg) tcg="disabled"
  plugins="no"
@@ -1731,8 +1732,6 @@ echo "PYTHON=$python" >> $config_host_mak
 echo "GENISOIMAGE=$genisoimage" >> $config_host_mak
 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 "EXESUF=$EXESUF" >> $config_host_mak
 
 # use included Linux headers for KVM architectures
@@ -1757,6 +1756,13 @@ if test "$ccache_cpp2" = "yes"; then
   echo "export CCACHE_CPP2=y" >> $config_host_mak
 fi
 
+# contrib/plugins configuration
+echo "# Automatically generated by configure - do not modify" > 
contrib/plugins/$config_host_mak
+echo "SRC_PATH=$source_path/contrib/plugins" >> 
contrib/plugins/$config_host_mak
+echo "PKG_CONFIG=${pkg_config}" >> contrib/plugins/$config_host_mak
+echo "CC=$cc $CPU_CFLAGS" >> contrib/plugins/$config_host_mak
+echo "CFLAGS=${CFLAGS-$default_cflags} $EXTRA_CFLAGS" >> 
contrib/plugins/$config_host_mak
+
 # tests/tcg configuration
 (config_host_mak=tests/tcg/config-host.mak
 mkdir -p tests/tcg
diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
index b2b9db9f51a..0751201bcb3 100644
--- a/contrib/plugins/Makefile
+++ b/contrib/plugins/Makefile
@@ -6,11 +6,11 @@
 # programs that the main configure has already done for us.
 #
 
-BUILD_DIR := $(CURDIR)/../..
+include config-host.mak
 
-include $(BUILD_DIR)/config-host.mak
+TOP_SRC_PATH = $(SRC_PATH)/../..
 
-VPATH += $(SRC_PATH)/contrib/plugins
+VPATH += $(SRC_PATH)
 
 NAMES :=
 NAMES += execlog
@@ -26,21 +26,21 @@ SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
 
 # The main QEMU uses Glib extensively so it's perfectly fine to use it
 # in plugins (which many example do).
-CFLAGS := $(shell $(PKG_CONFIG) --cflags glib-2.0)
-CFLAGS += -fPIC -Wall
-CFLAGS += $(if $(CONFIG_DEBUG_TCG), -ggdb -O0)
-CFLAGS += -I$(SRC_PATH)/include/qemu
+PLUGIN_CFLAGS := $(shell $(PKG_CONFIG) --cflags glib-2.0)
+PLUGIN_CFLAGS += -fPIC -Wall
+PLUGIN_CFLAGS += -I$(TOP_SRC_PATH)/include/qemu
 
 all: $(SONAMES)
 
 %.o: %.c
-   $(CC) $(CFLAGS) -c -o $@ $<
+   $(CC) $(CFLAGS) $(PLUGIN_CFLAGS) -c -o $@ $<
 
 lib%.so: %.o
-   $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDLIBS)
+   $(CC) -shared -Wl,-soname,$@ -o $@ $^
 
 clean:
rm -f *.o *.so *.d
rm -Rf .libs
 
 .PHONY: all clean
+.SECONDARY:
-- 
2.41.0




[PATCH v2 00/15] configure cleanups for QEMU 8.2

2023-09-02 Thread Paolo Bonzini
This includes a few more patches cleaning up the configure/meson
separation.  The highlights are fixing --host-cc, removing the last
traces of compiler detection from config-host.mak, and dropping the
useless pc-bios/Makefile.

Compared to v1, I have also removed the loop that takes random CONFIG_*
lines of config-host.mak and shoves them into config-host.h.  These were
the last remains of the old scripts/create_config logic, but they are not
needed anymore because all config-host.h tests are done in meson.build or
come from meson-level options.  We're definitely getting into diminishing
returns land (which is a good thing), but I believe it's worth having a
few extra patches to further reduce the coupling between config-host.mak
and meson.build.

To be honest, the plugin code would probably be a lot simpler if
contrib/plugins/Makefile was turned into a meson.build file.  As things
stand, the "are plugins enabled?" logic has to stay in configure, in order
to decide whether to build contrib/plugins.  However, contrib/plugins
was left as a separate build process for demonstration purposes, so I
am not going to change that.  If desired, this can be changed in the
future (together with moving all the $plugins logic from configure
to meson.build).  Perhaps the "external project" module from Meson
could be used too, but right now it is limited to projects with
a "configure" phase.

Paolo

Paolo Bonzini (15):
  meson: do not unnecessarily use cmake for dependencies
  meson: update unsupported host/CPU messages
  configure: remove HOST_CC
  configure: create native file with contents of $host_cc
  meson: compile bundled device trees
  configure: remove boolean variables for targets
  configure: move --enable-debug-tcg to meson
  meson: test for CONFIG_TCG in config_all
  contrib/plugins: use an independent makefile
  configure: unify recursion into sub-Makefiles
  configure, meson: move --enable-plugins to meson
  configure, meson: remove CONFIG_SOLARIS from config-host.mak
  configure, meson: remove target OS symbols from config-host.mak
  meson: list leftover CONFIG_* symbols
  configure: remove dead code

 Makefile  |  29 +++--
 accel/tcg/meson.build |   4 +-
 chardev/meson.build   |   2 +-
 configure | 125 ++
 contrib/plugins/Makefile  |  18 ++--
 docs/devel/build-system.rst   |   8 +-
 docs/devel/kconfig.rst|   2 +-
 gdbstub/meson.build   |   4 +-
 meson.build   | 106 ++
 meson_options.txt |   4 +
 net/meson.build   |  18 ++--
 pc-bios/Makefile  |  19 
 pc-bios/meson.build   |  25 -
 plugins/meson.build   |  12 ++-
 qga/meson.build   |   4 +-
 scripts/meson-buildoptions.sh |   6 ++
 storage-daemon/meson.build|   2 +-
 tcg/meson.build   |   2 +-
 tests/Makefile.include|   2 +-
 tests/meson.build |   8 +-
 tests/migration/meson.build   |   2 +-
 tests/qtest/meson.build   |  18 ++--
 tests/tcg/tricore/Makefile.softmmu-target |   2 +-
 tests/unit/meson.build|   6 +-
 24 files changed, 198 insertions(+), 230 deletions(-)
 delete mode 100644 pc-bios/Makefile

-- 
2.41.0




[PATCH 10/15] configure: unify recursion into sub-Makefiles

2023-09-02 Thread Paolo Bonzini
Treat contrib/plugins the same as the firmware.

Signed-off-by: Paolo Bonzini 
---
 Makefile  | 27 ---
 configure | 13 -
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/Makefile b/Makefile
index 5d48dfac18a..118c28e80d9 100644
--- a/Makefile
+++ b/Makefile
@@ -164,14 +164,6 @@ ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
 endif
 endif
 
-ifeq ($(CONFIG_PLUGIN),y)
-.PHONY: plugins
-plugins:
-   $(call quiet-command,\
-   $(MAKE) $(SUBDIR_MAKEFLAGS) -C contrib/plugins V="$(V)", \
-   "BUILD", "example plugins")
-endif # $(CONFIG_PLUGIN)
-
 else # config-host.mak does not exist
 ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if 
$(MAKECMDGOALS),,fail))
 $(error Please call configure before running make)
@@ -184,15 +176,20 @@ include $(SRC_PATH)/tests/Makefile.include
 
 all: recurse-all
 
-ROMS_RULES=$(foreach t, all clean distclean, $(addsuffix /$(t), $(ROMS)))
-.PHONY: $(ROMS_RULES)
-$(ROMS_RULES):
+SUBDIR_RULES=$(foreach t, all clean distclean, $(addsuffix /$(t), $(SUBDIRS)))
+.PHONY: $(SUBDIR_RULES)
+$(SUBDIR_RULES):
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" 
TARGET_DIR="$(dir $@)" $(notdir $@),)
 
+ifneq ($(filter contrib/plugins, $(SUBDIRS)),)
+.PHONY: plugins
+plugins: contrib/plugins/all
+endif
+
 .PHONY: recurse-all recurse-clean
-recurse-all: $(addsuffix /all, $(ROMS))
-recurse-clean: $(addsuffix /clean, $(ROMS))
-recurse-distclean: $(addsuffix /distclean, $(ROMS))
+recurse-all: $(addsuffix /all, $(SUBDIRS))
+recurse-clean: $(addsuffix /clean, $(SUBDIRS))
+recurse-distclean: $(addsuffix /distclean, $(SUBDIRS))
 
 ##
 
@@ -296,7 +293,7 @@ help:
$(call print-help,cscope,Generate cscope index)
$(call print-help,sparse,Run sparse on the QEMU source)
@echo  ''
-ifeq ($(CONFIG_PLUGIN),y)
+ifneq ($(filter contrib/plugins, $(SUBDIRS)),)
@echo  'Plugin targets:'
$(call print-help,plugins,Build the example TCG plugins)
@echo  ''
diff --git a/configure b/configure
index 1be8b430a54..9980eaeef57 100755
--- a/configure
+++ b/configure
@@ -256,6 +256,7 @@ softmmu="yes"
 linux_user=""
 bsd_user=""
 plugins="$default_feature"
+subdirs=""
 ninja=""
 python=
 download="enabled"
@@ -1067,6 +1068,9 @@ if test "$static" = "yes" ; then
   fi
 fi
 test "$plugins" = "" && plugins=yes
+if test "$plugins" = "yes"; then
+  subdirs="$subdirs contrib/plugins"
+fi
 
 cat > $TMPC << EOF
 
@@ -1627,12 +1631,11 @@ done
 echo "# Automatically generated by configure - do not modify" > 
Makefile.prereqs
 
 # Mac OS X ships with a broken assembler
-roms=
 if have_target i386-softmmu x86_64-softmmu && \
 test "$targetos" != "darwin" && test "$targetos" != "sunos" && \
 test "$targetos" != "haiku" && \
 probe_target_compiler i386-softmmu; then
-roms="pc-bios/optionrom"
+subdirs="$subdirs pc-bios/optionrom"
 config_mak=pc-bios/optionrom/config.mak
 echo "# Automatically generated by configure - do not modify" > $config_mak
 echo "TOPSRC_DIR=$source_path" >> $config_mak
@@ -1641,7 +1644,7 @@ fi
 
 if have_target ppc-softmmu ppc64-softmmu && \
 probe_target_compiler ppc-softmmu; then
-roms="$roms pc-bios/vof"
+subdirs="$subdirs pc-bios/vof"
 config_mak=pc-bios/vof/config.mak
 echo "# Automatically generated by configure - do not modify" > $config_mak
 echo "SRC_DIR=$source_path/pc-bios/vof" >> $config_mak
@@ -1660,7 +1663,7 @@ if have_target s390x-softmmu && probe_target_compiler 
s390x-softmmu && \
   echo "WARNING: Your compiler does not support the z900!"
   echo " The s390-ccw bios will only work with guest CPUs >= z10."
 fi
-roms="$roms pc-bios/s390-ccw"
+subdirs="$subdirs pc-bios/s390-ccw"
 config_mak=pc-bios/s390-ccw/config-host.mak
 echo "# Automatically generated by configure - do not modify" > $config_mak
 echo "SRC_PATH=$source_path/pc-bios/s390-ccw" >> $config_mak
@@ -1727,7 +1730,7 @@ if test "$container" != no; then
 echo "ENGINE=$container" >> $config_host_mak
 echo "RUNC=$runc" >> $config_host_mak
 fi
-echo "ROMS=$roms" >> $config_host_mak
+echo "SUBDIRS=$subdirs" >> $config_host_mak
 echo "PYTHON=$python" >> $config_host_mak
 echo "GENISOIMAGE=$genisoimage" >> $config_host_mak
 echo "MESON=$meson" >> $config_host_mak
-- 
2.41.0




[PATCH 04/15] configure: create native file with contents of $host_cc

2023-09-02 Thread Paolo Bonzini
The argument of --host-cc is not obeyed when cross compiling.  To avoid
this issue, place it in a configuration file and pass it to meson
with --native-file.

While at it, clarify that --host-cc is not obeyed anyway when _not_
cross compiling, because cc="$host_cc" is placed before --host-cc is
processed.

Reviewed-by: Richard Henderson 
Reviewed-by: Daniel P. Berrangé 
Signed-off-by: Paolo Bonzini 
---
 configure | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/configure b/configure
index 7743c18f2fe..378a0de9fb6 100755
--- a/configure
+++ b/configure
@@ -288,7 +288,7 @@ static="no"
 #  ${cross_prefix}gcc (if cross-prefix specified)
 #  system compiler
 if test -z "${CC}${cross_prefix}"; then
-  cc="$host_cc"
+  cc="cc"
 else
   cc="${CC-${cross_prefix}gcc}"
 fi
@@ -927,8 +927,8 @@ Advanced options (experts only):
   -Dmesonoptname=val   passthrough option to meson unmodified
   --cross-prefix=PREFIXuse PREFIX for compile tools, PREFIX can be blank 
[$cross_prefix]
   --cc=CC  use C compiler CC [$cc]
-  --host-cc=CC use C compiler CC [$host_cc] for code run at
-   build time
+  --host-cc=CC when cross compiling, use C compiler CC for code run
+   at build time [$host_cc]
   --cxx=CXXuse C++ compiler CXX [$cxx]
   --objcc=OBJCCuse Objective-C compiler OBJCC [$objcc]
   --extra-cflags=CFLAGSappend extra C compiler flags CFLAGS
@@ -1892,7 +1892,6 @@ if test "$skip_meson" = no; then
   echo "windres = [$(meson_quote $windres)]" >> $cross
   echo "windmc = [$(meson_quote $windmc)]" >> $cross
   if test "$cross_compile" = "yes"; then
-cross_arg="--cross-file config-meson.cross"
 echo "[host_machine]" >> $cross
 echo "system = '$targetos'" >> $cross
 case "$cpu" in
@@ -1909,6 +1908,14 @@ if test "$skip_meson" = no; then
 else
 echo "endian = 'little'" >> $cross
 fi
+cross_arg="--cross-file config-meson.cross"
+
+native="config-meson.native.new"
+echo "# Automatically generated by configure - do not modify" > $native
+echo "[binaries]" >> $native
+echo "c = [$(meson_quote $host_cc)]" >> $native
+mv $native config-meson.native
+cross_arg="$cross_arg --native-file config-meson.native"
   else
 cross_arg="--native-file config-meson.cross"
   fi
-- 
2.41.0




[PATCH 01/15] meson: do not unnecessarily use cmake for dependencies

2023-09-02 Thread Paolo Bonzini
Both gvnc and sysprof-capture come with pkg-config files, so specify
the method to find them.

Reviewed-by: Daniel P. Berrangé 
Signed-off-by: Paolo Bonzini 
---
 tests/migration/meson.build | 2 +-
 tests/qtest/meson.build | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/migration/meson.build b/tests/migration/meson.build
index ac71f132901..a91aa61c659 100644
--- a/tests/migration/meson.build
+++ b/tests/migration/meson.build
@@ -1,4 +1,4 @@
-sysprof = dependency('sysprof-capture-4', required: false)
+sysprof = dependency('sysprof-capture-4', method: 'pkg-config', required: 
false)
 glib_static = dependency('glib-2.0', version: glib_req_ver, required: false,
  method: 'pkg-config', static: true)
 
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index b071d400b37..df63909ee51 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -321,7 +321,7 @@ qtests = {
 }
 
 if vnc.found()
-  gvnc = dependency('gvnc-1.0', required: false)
+  gvnc = dependency('gvnc-1.0', method: 'pkg-config', required: false)
   if gvnc.found()
 qtests += {'vnc-display-test': [gvnc]}
 qtests_generic += [ 'vnc-display-test' ]
-- 
2.41.0




[PATCH 08/15] meson: test for CONFIG_TCG in config_all

2023-09-02 Thread Paolo Bonzini
CONFIG_TCG is not included in *-config-devices.h, so the test is
always failing.

Fixes: 74884cb1a6d ("qtest/meson.build: check CONFIG_TCG for boot-serial-test 
in qtests_ppc", 2022-03-14)
Fixes: 44d827ea69e ("qtest/meson.build: check CONFIG_TCG for prom-env-test in 
qtests_ppc", 2022-03-14)
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 tests/qtest/meson.build | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index df63909ee51..c0751ef7c35 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -155,8 +155,8 @@ qtests_ppc = \
   qtests_filter + \
   (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : 
[]) +\
   (config_all_devices.has_key('CONFIG_M48T59') ? ['m48t59-test'] : []) +   
  \
-  (config_all_devices.has_key('CONFIG_TCG') ? ['prom-env-test'] : []) +
  \
-  (config_all_devices.has_key('CONFIG_TCG') ? ['boot-serial-test'] : []) + 
  \
+  (config_all.has_key('CONFIG_TCG') ? ['prom-env-test'] : []) +
  \
+  (config_all.has_key('CONFIG_TCG') ? ['boot-serial-test'] : []) + 
  \
   ['boot-order-test']
 
 qtests_ppc64 = \
-- 
2.41.0