[PATCH 11/12] target-info: dispatch CPU QMP, dump, and Angel semihosting

Yonggang Luo <[email protected]>
Newsgroups org.nongnu.qemu-devel,org.nongnu.qemu-arm,org.nongnu.qemu-riscv
Message-ID <[email protected]>
- Combined binaries cannot keep one global C symbol per arch for
  query-cpu-definitions, dump notes, or Angel semihosting. Put those
  handlers on a process-wide TargetCpuOps table and fill one member
  at a time.
- TARGET_INFO_CPU_OP is type_init (MODULE_INIT_QOM). That runs after
  target_info_qom_set_target(), so ELF constructors only queue the
  callback. target_info_register_cpu_op() stores the impl only when
  cpu_type matches the selected TargetInfo; a duplicate slot is
  reported and ignored. A NULL member means this target has no
  handler, not "too early".
- Keep the table in target-info.c (common_ss) and filter with
  target_info()->cpu_type so user-mode can resolve TARGET_INFO_CPU_OP.
  Take the address of the impl so the same macro stores both function
  pointers and ops tables.
- QMP query-cpu-definitions and query-cpu-model-expansion dispatch
  from hw/core/machine-qmp-cmds.c. Dump cpu_get_dump_info and
  cpu_get_note_size dispatch from hw/core/cpu-system.c. Arch handlers
  are static with an arch prefix (s390_query_*, arm_get_dump_info,
  ...). ppc and mips drop expansion stubs; the dispatcher errors
  instead.
- Angel semihosting uses CPUSemihostingOps on TargetCpuOps.semihosting.
  ARM and RISC-V keep a static ops table in common-semi-target.c and
  register it with TARGET_INFO_CPU_OP. Wrappers in common-semi.h call
  target_info_cpu_ops()->semihosting. Always compile those files so
  both tables exist in a combined link.
- Drop stubs/qmp-cpu.c and stubs/dump.c: every system binary has the
  wrappers, and tools do not implement these commands. Keep
  stubs/qmp-cpu-s390x.c for comparison/baseline.

Signed-off-by: Yonggang Luo <[email protected]>
---
 MAINTAINERS                           |  1 -
 hw/core/cpu-system.c                  | 23 +++++++++++
 hw/core/machine-qmp-cmds.c            | 26 +++++++++++++
 include/qemu/target-info-qom.h        | 41 ++++++++++++++++++++
 include/semihosting/common-semi.h     | 56 ++++++++++++++++++++++++---
 stubs/dump.c                          | 27 -------------
 stubs/meson.build                     |  2 -
 stubs/qmp-cpu.c                       | 21 ----------
 target-info.c                         | 32 +++++++++++++++
 target/arm/arch_dump.c                |  8 +++-
 target/arm/arm-qmp-cmds.c             | 15 +++++--
 target/arm/common-semi-target.c       | 23 ++++++++---
 target/arm/meson.build                |  7 +---
 target/i386/arch_dump.c               |  8 +++-
 target/i386/cpu-system.c              | 12 ++++--
 target/i386/cpu.c                     |  6 ++-
 target/loongarch/arch_dump.c          |  8 +++-
 target/loongarch/loongarch-qmp-cmds.c | 15 +++++--
 target/mips/system/mips-qmp-cmds.c    | 15 +++----
 target/ppc/arch_dump.c                |  8 +++-
 target/ppc/ppc-qmp-cmds.c             | 15 +++----
 target/riscv/arch_dump.c              |  8 +++-
 target/riscv/common-semi-target.c     | 25 ++++++++----
 target/riscv/meson.build              |  4 +-
 target/riscv/riscv-qmp-cmds.c         | 15 +++++--
 target/s390x/arch_dump.c              |  8 +++-
 target/s390x/cpu_models_system.c      | 15 +++++--
 27 files changed, 313 insertions(+), 131 deletions(-)
 delete mode 100644 stubs/dump.c
 delete mode 100644 stubs/qmp-cpu.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 902db77218e..08e84e4ac6d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3348,7 +3348,6 @@ F: include/system/dump-arch.h
 F: include/system/dump.h
 F: qapi/dump.json
 F: scripts/dump-guest-memory.py
-F: stubs/dump.c
 F: docs/specs/vmcoreinfo.rst
 F: tests/qtest/vmcoreinfo-test.c
 F: tests/qtest/dump-test.c
diff --git a/hw/core/cpu-system.c b/hw/core/cpu-system.c
index 14eb4ed87f8..6dfbbac7f24 100644
--- a/hw/core/cpu-system.c
+++ b/hw/core/cpu-system.c
@@ -24,7 +24,9 @@
 #include "exec/cputlb.h"
 #include "exec/target_page.h"
 #include "system/memory.h"
+#include "system/dump-arch.h"
 #include "qemu/target-info.h"
+#include "qemu/target-info-qom.h"
 #include "hw/core/qdev.h"
 #include "hw/core/qdev-properties.h"
 #include "hw/core/sysemu-cpu-ops.h"
@@ -127,6 +129,27 @@ int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
     return (*cpu->cc->sysemu_ops->write_elf64_note)(f, cpu, cpuid, opaque);
 }
 
+int cpu_get_dump_info(ArchDumpInfo *info,
+                      const struct GuestPhysBlockList *guest_phys_blocks)
+{
+    const TargetCpuOps *ops = target_info_cpu_ops();
+
+    if (!ops->get_dump_info) {
+        return -1;
+    }
+    return ops->get_dump_info(info, guest_phys_blocks);
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+    const TargetCpuOps *ops = target_info_cpu_ops();
+
+    if (!ops->get_note_size) {
+        return -1;
+    }
+    return ops->get_note_size(class, machine, nr_cpus);
+}
+
 bool cpu_internal_is_big_endian(CPUState *cpu)
 {
     if (cpu->cc->sysemu_ops->internal_is_big_endian) {
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index e6e6ecc31e3..f8297203848 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -449,3 +449,29 @@ void qmp_dump_skeys(const char *filename, Error **errp)
     }
     DUMP_SKEYS_INTERFACE_CLASS(oc)->qmp_dump_skeys(filename, errp);
 }
+
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+{
+    const TargetCpuOps *ops = target_info_cpu_ops();
+
+    if (!ops->query_cpu_definitions) {
+        error_setg(errp,
+                   "CPU model definitions are not supported on this target");
+        return NULL;
+    }
+    return ops->query_cpu_definitions(errp);
+}
+
+CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
+                                                     CpuModelInfo *model,
+                                                     Error **errp)
+{
+    const TargetCpuOps *ops = target_info_cpu_ops();
+
+    if (!ops->query_cpu_model_expansion) {
+        error_setg(errp,
+                   "CPU model expansion is not supported on this target");
+        return NULL;
+    }
+    return ops->query_cpu_model_expansion(type, model, errp);
+}
diff --git a/include/qemu/target-info-qom.h b/include/qemu/target-info-qom.h
index 3b59cf82d65..0f0f49faaa8 100644
--- a/include/qemu/target-info-qom.h
+++ b/include/qemu/target-info-qom.h
@@ -10,8 +10,12 @@
 #define QEMU_TARGET_INFO_QOM_H
 
 #include "qemu/target-info-impl.h"
+#include "qapi/error.h"
+#include "qemu/compiler.h"
 #include "qom/object.h"
 
+#include <stddef.h>
+
 #define TYPE_TARGET_INFO "target-info"
 
 #define TYPE_TARGET_SPECIFIC "target-specific"
@@ -40,6 +44,43 @@ typedef struct TargetInfoQomClass {
 
 OBJECT_DECLARE_TYPE(TargetInfoQom, TargetInfoQomClass, TARGET_INFO)
 
+typedef struct ArchDumpInfo ArchDumpInfo;
+struct GuestPhysBlockList;
+typedef struct CPUSemihostingOps CPUSemihostingOps;
+
+typedef struct TargetCpuOps {
+    CpuDefinitionInfoList *(*query_cpu_definitions)(Error **errp);
+    CpuModelExpansionInfo *(*query_cpu_model_expansion)(
+        CpuModelExpansionType type, CpuModelInfo *model, Error **errp);
+    int (*get_dump_info)(ArchDumpInfo *info,
+                         const struct GuestPhysBlockList *guest_phys_blocks);
+    ssize_t (*get_note_size)(int class, int machine, int nr_cpus);
+    const CPUSemihostingOps *semihosting;
+} TargetCpuOps;
+
+/**
+ * target_info_register_cpu_op:
+ * @cpu_type: CPU_RESOLVING_TYPE of the registering architecture
+ * @offset: offsetof(TargetCpuOps, member) for the slot being filled
+ * @impl: handler or ops table stored at that offset
+ *
+ * Combined binaries merge one member at a time so QMP, dump, and
+ * semihosting (or split QMP files) can register independently.
+ * MODULE_INIT_QOM runs after target_info_qom_set_target(), so only
+ * the selected cpu_type is stored.
+ */
+void target_info_register_cpu_op(const char *cpu_type, size_t offset,
+                                 void *impl);
+const TargetCpuOps *target_info_cpu_ops(void);
+
+#define TARGET_INFO_CPU_OP(cpu_type, member, impl)                            \
+static void glue(target_info_cpu_op_, impl)(void)                             \
+{                                                                             \
+    target_info_register_cpu_op((cpu_type), offsetof(TargetCpuOps, member),   \
+                                (void *)&(impl));                             \
+}                                                                             \
+type_init(glue(target_info_cpu_op_, impl))
+
 /**
  * target_info_qom_set_target:
  * @name: -target token, or NULL/%empty to infer from the program
diff --git a/include/semihosting/common-semi.h b/include/semihosting/common-semi.h
index aa511a46f42..f86a855a3dd 100644
--- a/include/semihosting/common-semi.h
+++ b/include/semihosting/common-semi.h
@@ -34,12 +34,56 @@
 #ifndef COMMON_SEMI_H
 #define COMMON_SEMI_H
 
+#include "exec/cpu-common.h"
+#include "qemu/target-info-qom.h"
+
+typedef struct CPUSemihostingOps {
+    uint64_t (*arg)(CPUState *cs, int argno);
+    void (*set_ret)(CPUState *cs, uint64_t ret);
+    bool (*is_64bit)(CPUArchState *env);
+    bool (*sys_exit_is_extended)(CPUState *cs);
+    uint64_t (*stack_bottom)(CPUState *cs);
+    bool (*has_synccache)(CPUArchState *env);
+} CPUSemihostingOps;
+
 void do_common_semihosting(CPUState *cs);
-uint64_t common_semi_arg(CPUState *cs, int argno);
-void common_semi_set_ret(CPUState *cs, uint64_t ret);
-bool is_64bit_semihosting(CPUArchState *env);
-bool common_semi_sys_exit_is_extended(CPUState *cs);
-uint64_t common_semi_stack_bottom(CPUState *cs);
-bool common_semi_has_synccache(CPUArchState *env);
+
+static inline const CPUSemihostingOps *cpu_semihosting_ops(void)
+{
+    const CPUSemihostingOps *ops = target_info_cpu_ops()->semihosting;
+
+    g_assert(ops);
+    return ops;
+}
+
+static inline uint64_t common_semi_arg(CPUState *cs, int argno)
+{
+    return cpu_semihosting_ops()->arg(cs, argno);
+}
+
+static inline void common_semi_set_ret(CPUState *cs, uint64_t ret)
+{
+    cpu_semihosting_ops()->set_ret(cs, ret);
+}
+
+static inline bool is_64bit_semihosting(CPUArchState *env)
+{
+    return cpu_semihosting_ops()->is_64bit(env);
+}
+
+static inline bool common_semi_sys_exit_is_extended(CPUState *cs)
+{
+    return cpu_semihosting_ops()->sys_exit_is_extended(cs);
+}
+
+static inline uint64_t common_semi_stack_bottom(CPUState *cs)
+{
+    return cpu_semihosting_ops()->stack_bottom(cs);
+}
+
+static inline bool common_semi_has_synccache(CPUArchState *env)
+{
+    return cpu_semihosting_ops()->has_synccache(env);
+}
 
 #endif /* COMMON_SEMI_H */
diff --git a/stubs/dump.c b/stubs/dump.c
deleted file mode 100644
index df7897b72b1..00000000000
--- a/stubs/dump.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * QEMU dump
- *
- * Copyright Fujitsu, Corp. 2011, 2012
- *
- * Authors:
- *     Wen Congyang <[email protected]>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "system/dump-arch.h"
-
-int cpu_get_dump_info(ArchDumpInfo *info,
-                      const struct GuestPhysBlockList *guest_phys_blocks)
-{
-    return -1;
-}
-
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
-{
-    return -1;
-}
-
diff --git a/stubs/meson.build b/stubs/meson.build
index 3b2f2680b19..94024aef868 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -68,7 +68,6 @@ if have_system
   # adding more of these.  If the symbol is used in specific_ss,
   # in particular, consider defining a preprocessor macro via
   # Kconfig or configs/targets/.
-  stub_ss.add(files('dump.c'))
   stub_ss.add(files('cmos.c'))
   stub_ss.add(files('fw_cfg.c'))
   if igvm.found()
@@ -82,7 +81,6 @@ if have_system
   stub_ss.add(files('qmp-i386-sev.c'))
   stub_ss.add(files('qmp-i386-sgx.c'))
   stub_ss.add(files('qmp-i386-xen.c'))
-  stub_ss.add(files('qmp-cpu.c'))
   stub_ss.add(files('qmp-cpu-s390x.c'))
   stub_ss.add(files('qmp-cpu-s390x-kvm.c'))
   stub_ss.add(files('hmp-cmd-info_mem.c'))
diff --git a/stubs/qmp-cpu.c b/stubs/qmp-cpu.c
deleted file mode 100644
index a8c7ee89b9d..00000000000
--- a/stubs/qmp-cpu.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qapi/qapi-commands-machine.h"
-
-CpuModelExpansionInfo *
-qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                              CpuModelInfo *model,
-                              Error **errp)
-{
-    error_setg(errp, "CPU model expansion is not supported on this target");
-    return NULL;
-}
-
-CpuDefinitionInfoList *
-qmp_query_cpu_definitions(Error **errp)
-{
-    error_setg(errp, "CPU model definitions are not supported on this target");
-    return NULL;
-}
diff --git a/target-info.c b/target-info.c
index ce7f9797dce..aa4be08bb94 100644
--- a/target-info.c
+++ b/target-info.c
@@ -7,9 +7,11 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "qemu/target-info.h"
 #include "qemu/target-info-qapi.h"
 #include "qemu/target-info-impl.h"
+#include "qemu/target-info-qom.h"
 #include "qapi/error.h"
 
 const char *target_name(void)
@@ -124,3 +126,33 @@ bool target_config_xen(void)
 {
     return target_info()->config_xen;
 }
+
+static TargetCpuOps target_cpu_ops;
+
+void target_info_register_cpu_op(const char *cpu_type, size_t offset,
+                                 void *impl)
+{
+    const TargetInfo *ti = target_info();
+    void **slot;
+
+    g_assert(ti);
+    g_assert(offset + sizeof(void *) <= sizeof(TargetCpuOps));
+    g_assert((offset % sizeof(void *)) == 0);
+
+    if (strcmp(cpu_type, ti->cpu_type)) {
+        return;
+    }
+
+    slot = (void **)((char *)&target_cpu_ops + offset);
+    if (*slot) {
+        error_report("TargetCpuOps already registered for type '%s' (offset %zu)",
+                     cpu_type, offset);
+        return;
+    }
+    *slot = impl;
+}
+
+const TargetCpuOps *target_info_cpu_ops(void)
+{
+    return &target_cpu_ops;
+}
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
index 1dd79849c13..e072516bdac 100644
--- a/target/arm/arch_dump.c
+++ b/target/arm/arch_dump.c
@@ -24,6 +24,7 @@
 #include "system/dump.h"
 #include "cpu-features.h"
 #include "internals.h"
+#include "qemu/target-info-qom.h"
 
 /* struct user_pt_regs from arch/arm64/include/uapi/asm/ptrace.h */
 struct aarch64_user_regs {
@@ -385,7 +386,7 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
     return 0;
 }
 
-int cpu_get_dump_info(ArchDumpInfo *info,
+static int arm_get_dump_info(ArchDumpInfo *info,
                       const GuestPhysBlockList *guest_phys_blocks)
 {
     ARMCPU *cpu;
@@ -439,7 +440,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
     return 0;
 }
 
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+static ssize_t arm_get_note_size(int class, int machine, int nr_cpus)
 {
     ARMCPU *cpu = ARM_CPU(first_cpu);
     size_t note_size;
@@ -459,3 +460,6 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 
     return note_size * nr_cpus;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_dump_info, arm_get_dump_info);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_note_size, arm_get_note_size);
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
index 83ec95c290f..c85bde5d79d 100644
--- a/target/arm/arm-qmp-cmds.c
+++ b/target/arm/arm-qmp-cmds.c
@@ -32,6 +32,7 @@
 #include "qobject/qdict.h"
 #include "qom/qom-qobject.h"
 #include "cpu.h"
+#include "qemu/target-info-qom.h"
 
 static GICCapability *gic_cap_new(int version)
 {
@@ -79,9 +80,10 @@ static const char *cpu_model_advertised_features[] = {
     NULL
 };
 
-CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                                                     CpuModelInfo *model,
-                                                     Error **errp)
+static CpuModelExpansionInfo *
+arm_query_cpu_model_expansion(CpuModelExpansionType type,
+                              CpuModelInfo *model,
+                              Error **errp)
 {
     CpuModelExpansionInfo *expansion_info;
     const QDict *qdict_in;
@@ -216,7 +218,7 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
     QAPI_LIST_PREPEND(*cpu_list, info);
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+static CpuDefinitionInfoList *arm_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
@@ -227,3 +229,8 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 
     return cpu_list;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_definitions,
+                   arm_query_cpu_definitions);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_model_expansion,
+                   arm_query_cpu_model_expansion);
diff --git a/target/arm/common-semi-target.c b/target/arm/common-semi-target.c
index 2b77ce9c17b..eccd3735df8 100644
--- a/target/arm/common-semi-target.c
+++ b/target/arm/common-semi-target.c
@@ -12,7 +12,7 @@
 #include "semihosting/common-semi.h"
 #include "target/arm/cpu-qom.h"
 
-uint64_t common_semi_arg(CPUState *cs, int argno)
+static uint64_t arm_common_semi_arg(CPUState *cs, int argno)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -23,7 +23,7 @@ uint64_t common_semi_arg(CPUState *cs, int argno)
     }
 }
 
-void common_semi_set_ret(CPUState *cs, uint64_t ret)
+static void arm_common_semi_set_ret(CPUState *cs, uint64_t ret)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -34,25 +34,36 @@ void common_semi_set_ret(CPUState *cs, uint64_t ret)
     }
 }
 
-bool common_semi_sys_exit_is_extended(CPUState *cs)
+static bool arm_common_semi_sys_exit_is_extended(CPUState *cs)
 {
     return is_a64(cpu_env(cs));
 }
 
-bool is_64bit_semihosting(CPUArchState *env)
+static bool arm_is_64bit_semihosting(CPUArchState *env)
 {
     return is_a64(env);
 }
 
-uint64_t common_semi_stack_bottom(CPUState *cs)
+static uint64_t arm_common_semi_stack_bottom(CPUState *cs)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
     return is_a64(env) ? env->xregs[31] : env->regs[13];
 }
 
-bool common_semi_has_synccache(CPUArchState *env)
+static bool arm_common_semi_has_synccache(CPUArchState *env)
 {
     /* Ok for A64, invalid for A32/T32 */
     return is_a64(env);
 }
+
+static const CPUSemihostingOps arm_semihosting_ops = {
+    .arg = arm_common_semi_arg,
+    .set_ret = arm_common_semi_set_ret,
+    .is_64bit = arm_is_64bit_semihosting,
+    .sys_exit_is_extended = arm_common_semi_sys_exit_is_extended,
+    .stack_bottom = arm_common_semi_stack_bottom,
+    .has_synccache = arm_common_semi_has_synccache,
+};
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, semihosting, arm_semihosting_ops);
diff --git a/target/arm/meson.build b/target/arm/meson.build
index 0369f96b4cc..dfcec55bd97 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -44,13 +44,10 @@ arm_stubs_ss.add(files(
 arm_user_ss.add(files(
   'el2-stubs.c',
   'cpregs-omap-stub.c',
+  'common-semi-target.c',
 ))
-arm_user_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING',
-		        if_true: files('common-semi-target.c'))
 
-arm_common_system_ss.add(files('cpu.c'))
-arm_common_system_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING',
-		                 if_true: files('common-semi-target.c'))
+arm_common_system_ss.add(files('cpu.c', 'common-semi-target.c'))
 arm_common_system_ss.add(files(
   'arch_dump.c',
   'arm-powerctl.c',
diff --git a/target/i386/arch_dump.c b/target/i386/arch_dump.c
index 16e47c4747d..c060b2b4ccb 100644
--- a/target/i386/arch_dump.c
+++ b/target/i386/arch_dump.c
@@ -16,6 +16,7 @@
 #include "system/dump.h"
 #include "elf.h"
 #include "system/memory_mapping.h"
+#include "qemu/target-info-qom.h"
 
 #define ELF_NOTE_SIZE(hdr_size, name_size, desc_size)   \
     ((DIV_ROUND_UP((hdr_size), 4)                       \
@@ -394,7 +395,7 @@ int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
     return cpu_write_qemu_note(f, &cpu->env, s, 0);
 }
 
-int cpu_get_dump_info(ArchDumpInfo *info,
+static int x86_get_dump_info(ArchDumpInfo *info,
                       const GuestPhysBlockList *guest_phys_blocks)
 {
     bool lma = false;
@@ -429,7 +430,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
     return 0;
 }
 
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+static ssize_t x86_get_note_size(int class, int machine, int nr_cpus)
 {
     int name_size = 5; /* "CORE" or "QEMU" */
     size_t elf_note_size = 0;
@@ -459,3 +460,6 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 
     return (elf_note_size + qemu_note_size) * nr_cpus;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_dump_info, x86_get_dump_info);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_note_size, x86_get_note_size);
diff --git a/target/i386/cpu-system.c b/target/i386/cpu-system.c
index c8bbf0cbafd..d2babd1ba09 100644
--- a/target/i386/cpu-system.c
+++ b/target/i386/cpu-system.c
@@ -29,6 +29,7 @@
 #include "qapi/qapi-commands-machine.h"
 
 #include "cpu-internal.h"
+#include "qemu/target-info-qom.h"
 
 /* Return a QDict containing keys for all properties that can be included
  * in static expansion of CPU models. All properties set by x86_cpu_load_model()
@@ -188,10 +189,10 @@ out:
     return xc;
 }
 
-CpuModelExpansionInfo *
-qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                                                      CpuModelInfo *model,
-                                                      Error **errp)
+static CpuModelExpansionInfo *
+x86_query_cpu_model_expansion(CpuModelExpansionType type,
+                              CpuModelInfo *model,
+                              Error **errp)
 {
     X86CPU *xc = NULL;
     Error *err = NULL;
@@ -241,6 +242,9 @@ out:
     return ret;
 }
 
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_model_expansion,
+                   x86_query_cpu_model_expansion);
+
 void cpu_clear_apic_feature(CPUX86State *env)
 {
     env->features[FEAT_1_EDX] &= ~CPUID_APIC;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 5805d33ab92..4e31b8a2a60 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -48,6 +48,7 @@
 #include "system/address-spaces.h"
 #include "hw/core/boards.h"
 #include "hw/i386/sgx-epc.h"
+#include "qemu/target-info-qom.h"
 #endif
 #include "system/qtest.h"
 #include "tcg/tcg-cpu.h"
@@ -8191,7 +8192,7 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
     QAPI_LIST_PREPEND(*cpu_list, info);
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+static CpuDefinitionInfoList *x86_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list = get_sorted_cpu_model_list();
@@ -8200,6 +8201,9 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
     return cpu_list;
 }
 
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_definitions,
+                   x86_query_cpu_definitions);
+
 #endif /* !CONFIG_USER_ONLY */
 
 static uint8_t x86_cpu_get_host_avx10_version(void)
diff --git a/target/loongarch/arch_dump.c b/target/loongarch/arch_dump.c
index 9d84faef969..af4ab5df5b5 100644
--- a/target/loongarch/arch_dump.c
+++ b/target/loongarch/arch_dump.c
@@ -22,6 +22,7 @@
 #include "elf.h"
 #include "system/dump.h"
 #include "internals.h"
+#include "qemu/target-info-qom.h"
 
 /* struct user_pt_regs from arch/loongarch/include/uapi/asm/ptrace.h */
 struct loongarch_user_regs {
@@ -142,7 +143,7 @@ int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
     return ret;
 }
 
-int cpu_get_dump_info(ArchDumpInfo *info,
+static int loongarch_get_dump_info(ArchDumpInfo *info,
                       const GuestPhysBlockList *guest_phys_blocks)
 {
     info->d_machine = EM_LOONGARCH;
@@ -152,7 +153,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
     return 0;
 }
 
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+static ssize_t loongarch_get_note_size(int class, int machine, int nr_cpus)
 {
     size_t note_size = 0;
 
@@ -162,3 +163,6 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 
     return note_size * nr_cpus;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_dump_info, loongarch_get_dump_info);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_note_size, loongarch_get_note_size);
diff --git a/target/loongarch/loongarch-qmp-cmds.c b/target/loongarch/loongarch-qmp-cmds.c
index f053f22bb8c..848ad640aee 100644
--- a/target/loongarch/loongarch-qmp-cmds.c
+++ b/target/loongarch/loongarch-qmp-cmds.c
@@ -14,6 +14,7 @@
 #include "qobject/qdict.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qom/qom-qobject.h"
+#include "qemu/target-info-qom.h"
 
 static void loongarch_cpu_add_definition(gpointer data, gpointer user_data)
 {
@@ -28,7 +29,7 @@ static void loongarch_cpu_add_definition(gpointer data, gpointer user_data)
     QAPI_LIST_PREPEND(*cpu_list, info);
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+static CpuDefinitionInfoList *loongarch_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
@@ -45,9 +46,10 @@ static const char *cpu_model_advertised_features[] = {
     "ptw", NULL
 };
 
-CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                                                     CpuModelInfo *model,
-                                                     Error **errp)
+static CpuModelExpansionInfo *
+loongarch_query_cpu_model_expansion(CpuModelExpansionType type,
+                                    CpuModelInfo *model,
+                                    Error **errp)
 {
     Visitor *visitor;
     CpuModelExpansionInfo *expansion_info;
@@ -133,3 +135,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 
     return expansion_info;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_definitions,
+                   loongarch_query_cpu_definitions);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_model_expansion,
+                   loongarch_query_cpu_model_expansion);
diff --git a/target/mips/system/mips-qmp-cmds.c b/target/mips/system/mips-qmp-cmds.c
index b6a2874f2dd..ff78487423b 100644
--- a/target/mips/system/mips-qmp-cmds.c
+++ b/target/mips/system/mips-qmp-cmds.c
@@ -11,15 +11,7 @@
 #include "qapi/error.h"
 #include "qapi/qapi-commands-machine.h"
 #include "cpu.h"
-
-CpuModelExpansionInfo *
-qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                              CpuModelInfo *model,
-                              Error **errp)
-{
-    error_setg(errp, "CPU model expansion is not supported on this target");
-    return NULL;
-}
+#include "qemu/target-info-qom.h"
 
 static void mips_cpu_add_definition(gpointer data, gpointer user_data)
 {
@@ -36,7 +28,7 @@ static void mips_cpu_add_definition(gpointer data, gpointer user_data)
     QAPI_LIST_PREPEND(*cpu_list, info);
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+static CpuDefinitionInfoList *mips_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
@@ -47,3 +39,6 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 
     return cpu_list;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_definitions,
+                   mips_query_cpu_definitions);
diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c
index 80ac6c3e320..07f0c75c45e 100644
--- a/target/ppc/arch_dump.c
+++ b/target/ppc/arch_dump.c
@@ -17,6 +17,7 @@
 #include "elf.h"
 #include "system/dump.h"
 #include "system/kvm.h"
+#include "qemu/target-info-qom.h"
 
 #ifdef TARGET_PPC64
 #define ELFCLASS ELFCLASS64
@@ -229,7 +230,7 @@ static const struct NoteFuncDescStruct {
 
 typedef struct NoteFuncDescStruct NoteFuncDesc;
 
-int cpu_get_dump_info(ArchDumpInfo *info,
+static int ppc_get_dump_info(ArchDumpInfo *info,
                       const struct GuestPhysBlockList *guest_phys_blocks)
 {
     PowerPCCPU *cpu;
@@ -257,7 +258,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
     return 0;
 }
 
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+static ssize_t ppc_get_note_size(int class, int machine, int nr_cpus)
 {
     int name_size = 8; /* "CORE" or "QEMU" rounded */
     size_t elf_note_size = 0;
@@ -313,3 +314,6 @@ int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, s);
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_dump_info, ppc_get_dump_info);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_note_size, ppc_get_note_size);
diff --git a/target/ppc/ppc-qmp-cmds.c b/target/ppc/ppc-qmp-cmds.c
index 96228919966..70fca0170b1 100644
--- a/target/ppc/ppc-qmp-cmds.c
+++ b/target/ppc/ppc-qmp-cmds.c
@@ -29,15 +29,7 @@
 #include "qapi/qapi-commands-machine.h"
 #include "cpu-models.h"
 #include "cpu-qom.h"
-
-CpuModelExpansionInfo *
-qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                              CpuModelInfo *model,
-                              Error **errp)
-{
-    error_setg(errp, "CPU model expansion is not supported on this target");
-    return NULL;
-}
+#include "qemu/target-info-qom.h"
 
 static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
 {
@@ -53,7 +45,7 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
     QAPI_LIST_PREPEND(*first, info);
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+static CpuDefinitionInfoList *ppc_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
@@ -82,3 +74,6 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 
     return cpu_list;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_definitions,
+                   ppc_query_cpu_definitions);
diff --git a/target/riscv/arch_dump.c b/target/riscv/arch_dump.c
index 12b68799070..7e4b584faa0 100644
--- a/target/riscv/arch_dump.c
+++ b/target/riscv/arch_dump.c
@@ -20,6 +20,7 @@
 #include "cpu.h"
 #include "elf.h"
 #include "system/dump.h"
+#include "qemu/target-info-qom.h"
 
 /* struct user_regs_struct from arch/riscv/include/uapi/asm/ptrace.h */
 struct riscv64_user_regs {
@@ -161,7 +162,7 @@ int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
     return ret;
 }
 
-int cpu_get_dump_info(ArchDumpInfo *info,
+static int riscv_get_dump_info(ArchDumpInfo *info,
                       const GuestPhysBlockList *guest_phys_blocks)
 {
     RISCVCPU *cpu;
@@ -187,7 +188,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
     return 0;
 }
 
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+static ssize_t riscv_get_note_size(int class, int machine, int nr_cpus)
 {
     size_t note_size;
 
@@ -199,3 +200,6 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 
     return note_size * nr_cpus;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_dump_info, riscv_get_dump_info);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_note_size, riscv_get_note_size);
diff --git a/target/riscv/common-semi-target.c b/target/riscv/common-semi-target.c
index aeaeb88d536..aed9dfc5b68 100644
--- a/target/riscv/common-semi-target.c
+++ b/target/riscv/common-semi-target.c
@@ -12,38 +12,49 @@
 #include "cpu.h"
 #include "semihosting/common-semi.h"
 
-uint64_t common_semi_arg(CPUState *cs, int argno)
+static uint64_t riscv_common_semi_arg(CPUState *cs, int argno)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
     return env->gpr[xA0 + argno];
 }
 
-void common_semi_set_ret(CPUState *cs, uint64_t ret)
+static void riscv_common_semi_set_ret(CPUState *cs, uint64_t ret)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
     env->gpr[xA0] = ret;
 }
 
-bool is_64bit_semihosting(CPUArchState *env)
+static bool riscv_is_64bit_semihosting(CPUArchState *env)
 {
     return riscv_cpu_mxl(env) != MXL_RV32;
 }
 
-bool common_semi_sys_exit_is_extended(CPUState *cs)
+static bool riscv_common_semi_sys_exit_is_extended(CPUState *cs)
 {
-    return is_64bit_semihosting(cpu_env(cs));
+    return riscv_is_64bit_semihosting(cpu_env(cs));
 }
 
-uint64_t common_semi_stack_bottom(CPUState *cs)
+static uint64_t riscv_common_semi_stack_bottom(CPUState *cs)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
     return env->gpr[xSP];
 }
 
-bool common_semi_has_synccache(CPUArchState *env)
+static bool riscv_common_semi_has_synccache(CPUArchState *env)
 {
     return true;
 }
+
+static const CPUSemihostingOps riscv_semihosting_ops = {
+    .arg = riscv_common_semi_arg,
+    .set_ret = riscv_common_semi_set_ret,
+    .is_64bit = riscv_is_64bit_semihosting,
+    .sys_exit_is_extended = riscv_common_semi_sys_exit_is_extended,
+    .stack_bottom = riscv_common_semi_stack_bottom,
+    .has_synccache = riscv_common_semi_has_synccache,
+};
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, semihosting, riscv_semihosting_ops);
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 42d0f6d538a..5adb6d1c9e7 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -11,12 +11,10 @@ gen = [
 riscv_ss = ss.source_set()
 riscv_ss.add(gen)
 
-riscv_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING',
-		     if_true: files('common-semi-target.c'))
-
 riscv_ss.add(files(
   'cpu.c',
   'gdbstub.c',
+  'common-semi-target.c',
 ))
 
 riscv_system_ss = ss.source_set()
diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c
index 2647deef916..248e6a0eaf0 100644
--- a/target/riscv/riscv-qmp-cmds.c
+++ b/target/riscv/riscv-qmp-cmds.c
@@ -36,6 +36,7 @@
 #include "cpu-qom.h"
 #include "cpu.h"
 #include "target/riscv/tcg/csr.h"
+#include "qemu/target-info-qom.h"
 
 static void riscv_cpu_add_definition(gpointer data, gpointer user_data)
 {
@@ -54,7 +55,7 @@ static void riscv_cpu_add_definition(gpointer data, gpointer user_data)
     QAPI_LIST_PREPEND(*cpu_list, info);
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+static CpuDefinitionInfoList *riscv_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list = object_class_get_list(TYPE_RISCV_CPU, false);
@@ -154,9 +155,10 @@ err:
     visit_free(visitor);
 }
 
-CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                                                     CpuModelInfo *model,
-                                                     Error **errp)
+static CpuModelExpansionInfo *
+riscv_query_cpu_model_expansion(CpuModelExpansionType type,
+                                CpuModelInfo *model,
+                                Error **errp)
 {
     CpuModelExpansionInfo *expansion_info;
     QDict *qdict_out;
@@ -225,3 +227,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 
     return expansion_info;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_definitions,
+                   riscv_query_cpu_definitions);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_model_expansion,
+                   riscv_query_cpu_model_expansion);
diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c
index 2c26e992959..c0334baa72f 100644
--- a/target/s390x/arch_dump.c
+++ b/target/s390x/arch_dump.c
@@ -18,6 +18,7 @@
 #include "elf.h"
 #include "system/dump.h"
 #include "kvm/kvm_s390x.h"
+#include "qemu/target-info-qom.h"
 #include "target/s390x/kvm/pv.h"
 
 struct S390xUserRegsStruct {
@@ -449,7 +450,7 @@ static void arch_cleanup(DumpState *s)
     }
 }
 
-int cpu_get_dump_info(ArchDumpInfo *info,
+static int s390_get_dump_info(ArchDumpInfo *info,
                       const struct GuestPhysBlockList *guest_phys_blocks)
 {
     info->d_machine = EM_S390;
@@ -469,7 +470,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
     return 0;
 }
 
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+static ssize_t s390_get_note_size(int class, int machine, int nr_cpus)
 {
     int name_size = 8; /* "LINUX" or "CORE" + pad */
     size_t elf_note_size = 0;
@@ -495,3 +496,6 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 
     return (elf_note_size) * nr_cpus;
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_dump_info, s390_get_dump_info);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, get_note_size, s390_get_note_size);
diff --git a/target/s390x/cpu_models_system.c b/target/s390x/cpu_models_system.c
index 5b846048675..5470bf55e20 100644
--- a/target/s390x/cpu_models_system.c
+++ b/target/s390x/cpu_models_system.c
@@ -20,6 +20,7 @@
 #include "qapi/qobject-input-visitor.h"
 #include "qobject/qdict.h"
 #include "qapi/qapi-commands-machine.h"
+#include "qemu/target-info-qom.h"
 
 static void list_add_feat(const char *name, void *opaque);
 
@@ -82,7 +83,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
     QAPI_LIST_PREPEND(*cpu_list, info);
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+static CpuDefinitionInfoList *s390_query_cpu_definitions(Error **errp)
 {
     struct CpuDefinitionInfoListData list_data = {
         .list = NULL,
@@ -208,9 +209,10 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
     }
 }
 
-CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                                                      CpuModelInfo *model,
-                                                      Error **errp)
+static CpuModelExpansionInfo *
+s390_query_cpu_model_expansion(CpuModelExpansionType type,
+                               CpuModelInfo *model,
+                               Error **errp)
 {
     Error *err = NULL;
     CpuModelExpansionInfo *expansion_info = NULL;
@@ -434,3 +436,8 @@ void apply_cpu_model(const S390CPUModel *model, Error **errp)
         applied_model = *model;
     }
 }
+
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_definitions,
+                   s390_query_cpu_definitions);
+TARGET_INFO_CPU_OP(CPU_RESOLVING_TYPE, query_cpu_model_expansion,
+                   s390_query_cpu_model_expansion);
-- 
2.52.0.windows.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.