All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] qom: pass TargetInfo to the is_available callback
@ 2026-10-07 11:47 Yonggang Luo
  2026-10-07 11:47 ` [PATCH 1/8] configs/targets: remove target info definitions Yonggang Luo
                   ` (9 more replies)
  0 siblings, 10 replies; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

This allows a combined binary to register machine types from all its targets.
Consequently, QMP `query-machines` can return machine entries from every
target, even when `none` is selected. For example, a client can query the
combined machine list with:

```json
{ "execute": "query-machines" }
```

The returned list includes the registered machine classes from all linked
targets. This is separate from selecting a machine: with `-target none`,
`-M virt` reports the targets that provide `virt` instead of choosing one
arbitrarily:

```text
qemu-system -target none -M virt
unsupported machine type: "virt" for target "none"
Available for targets:
  aarch64
  arm
```

It moves target_info() to a shared location so object.c can call it when
checking machine availability. The series also replaces QOM-based target-info
registration with a constructor list and passes TargetInfo to the
is_available callback.

Target metadata and architecture checks are generated from the configured
targets, there is too much arch to write biiolperate code. doing this for easier
Add TargetInfo* to is_available

The target-info API and implementation are shared, rather than compiled
separately for every target.

This series removes the per-target source files "configs/targets/*.c".
Their target-specific parameters are collected in a generated
target-info-def.c for each softmmu target. This lays the groundwork for
QEMU system builds in which target-info-def.c is the only target-specific
source file compiled for each target. Using the same filename lets
meson.build handle these definitions uniformly.

The series adds unit-test coverage for target info and multi-target builds.

Pierrick Bouvier (2):
  configs/targets: remove target info definitions
  target-info: rename target-info-stub.c in target-info-def.c

Yonggang Luo (6):
  target-info: rename target-info-impl.h to target-info-def.h
  target-info: replace QOM registration with a constructor list
  tests/unit: add target-info coverage for multi-target builds
  meson: load all target .mak files into target_mak_all
  target-info: Replace handwritten architecture checks with generated
    code
  qom: pass TargetInfo to is_available for later use

 MAINTAINERS                             |   2 +-
 configs/targets/aarch64-softmmu.c       |  25 ------
 configs/targets/arm-softmmu.c           |  25 ------
 configs/targets/meson.build             |   6 --
 configs/targets/riscv32-softmmu.c       |  24 -----
 configs/targets/riscv64-softmmu.c       |  24 -----
 hw/arm/aspeed_ast27x0-fc.c              |   2 +-
 hw/arm/aspeed_ast27x0_evb.c             |   4 +-
 hw/arm/raspi.c                          |   4 +-
 hw/arm/raspi4b.c                        |   2 +-
 hw/arm/virt.c                           |   4 +-
 hw/m68k/virt.c                          |   4 +-
 hw/or1k/virt.c                          |   2 +-
 include/hw/core/cpu.h                   |   2 +-
 include/qemu/module.h                   |   1 -
 include/qemu/target-info-def.h          |  88 ++++++++++++++++++
 include/qemu/target-info-impl.h         |  42 ---------
 include/qemu/target-info-init.h         |  53 -----------
 include/qemu/target-info-qom.h          |  31 -------
 include/qemu/target-info.h              |  87 ++++--------------
 include/qom/object.h                    |  12 ++-
 meson.build                             |  52 ++++++++---
 page-vary-common.c                      |   2 +-
 page-vary-system.c                      |   2 +-
 qom/object.c                            |   3 +-
 scripts/gen-target-info.py              |  99 ++++++++++++++++++++
 system/vl.c                             |   4 -
 target-info-stub.c => target-info-def.c |   3 +-
 target-info-qom.c                       |  60 -------------
 target-info.c                           | 115 ++++++++++++------------
 tests/qtest/fuzz/fuzz.c                 |   3 -
 tests/unit/meson.build                  |   4 +
 tests/unit/test-multi-target.c          |  12 +--
 tests/unit/test-target-info.c           |  38 ++++++++
 34 files changed, 379 insertions(+), 462 deletions(-)
 delete mode 100644 configs/targets/aarch64-softmmu.c
 delete mode 100644 configs/targets/arm-softmmu.c
 delete mode 100644 configs/targets/meson.build
 delete mode 100644 configs/targets/riscv32-softmmu.c
 delete mode 100644 configs/targets/riscv64-softmmu.c
 create mode 100644 include/qemu/target-info-def.h
 delete mode 100644 include/qemu/target-info-impl.h
 delete mode 100644 include/qemu/target-info-init.h
 delete mode 100644 include/qemu/target-info-qom.h
 create mode 100644 scripts/gen-target-info.py
 rename target-info-stub.c => target-info-def.c (94%)
 delete mode 100644 target-info-qom.c
 create mode 100644 tests/unit/test-target-info.c

-- 
2.55.0.windows.3



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

* [PATCH 1/8] configs/targets: remove target info definitions
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
@ 2026-10-07 11:47 ` Yonggang Luo
  2026-10-07 20:26   ` Pierrick Bouvier
  2026-10-07 11:47 ` [PATCH 2/8] target-info: rename target-info-stub.c in target-info-def.c Yonggang Luo
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>

Now that we remove machine_typename, we don't need to keep duplicated
file per target anymore. So we can just rely on target-info-stub.c.

Signed-off-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 MAINTAINERS                       |  1 -
 configs/targets/aarch64-softmmu.c | 25 -------------------------
 configs/targets/arm-softmmu.c     | 25 -------------------------
 configs/targets/meson.build       |  6 ------
 configs/targets/riscv32-softmmu.c | 24 ------------------------
 configs/targets/riscv64-softmmu.c | 24 ------------------------
 meson.build                       |  7 +------
 7 files changed, 1 insertion(+), 111 deletions(-)
 delete mode 100644 configs/targets/aarch64-softmmu.c
 delete mode 100644 configs/targets/arm-softmmu.c
 delete mode 100644 configs/targets/meson.build
 delete mode 100644 configs/targets/riscv32-softmmu.c
 delete mode 100644 configs/targets/riscv64-softmmu.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1312bbd1bd8..cfe39dc2883 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2148,7 +2148,6 @@ M: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
 S: Supported
 F: include/qemu/target-info*.h
 F: target-info*.c
-F: configs/targets/*.c
 F: tests/unit/test-multi-targets.c
 
 Xtensa Machines
diff --git a/configs/targets/aarch64-softmmu.c b/configs/targets/aarch64-softmmu.c
deleted file mode 100644
index fdebdcc3582..00000000000
--- a/configs/targets/aarch64-softmmu.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * QEMU binary/target API (qemu-system-aarch64)
- *
- *  Copyright (c) Linaro
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#include "qemu/osdep.h"
-#include "qemu/target-info-impl.h"
-#include "qemu/target-info-init.h"
-#include "target/arm/cpu-qom.h"
-#include "target/arm/cpu-param.h"
-
-static const TargetInfo target_info_aarch64_system = {
-    .target_name = "aarch64",
-    .target_arch = SYS_EMU_TARGET_AARCH64,
-    .long_bits = 64,
-    .cpu_type = TYPE_ARM_CPU,
-    .endianness = ENDIAN_MODE_LITTLE,
-    .page_bits_vary = true,
-    .page_bits_init = TARGET_PAGE_BITS_LEGACY,
-};
-
-target_info_init(target_info_aarch64_system)
diff --git a/configs/targets/arm-softmmu.c b/configs/targets/arm-softmmu.c
deleted file mode 100644
index 2b98f65a0f8..00000000000
--- a/configs/targets/arm-softmmu.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * QEMU binary/target API (qemu-system-arm)
- *
- *  Copyright (c) Linaro
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#include "qemu/osdep.h"
-#include "qemu/target-info-impl.h"
-#include "qemu/target-info-init.h"
-#include "target/arm/cpu-qom.h"
-#include "target/arm/cpu-param.h"
-
-static const TargetInfo target_info_arm_system = {
-    .target_name = "arm",
-    .target_arch = SYS_EMU_TARGET_ARM,
-    .long_bits = 32,
-    .cpu_type = TYPE_ARM_CPU,
-    .endianness = ENDIAN_MODE_LITTLE,
-    .page_bits_vary = true,
-    .page_bits_init = TARGET_PAGE_BITS_LEGACY,
-};
-
-target_info_init(target_info_arm_system)
diff --git a/configs/targets/meson.build b/configs/targets/meson.build
deleted file mode 100644
index 2ab4d27eaf5..00000000000
--- a/configs/targets/meson.build
+++ /dev/null
@@ -1,6 +0,0 @@
-foreach target : [
-      'arm-softmmu', 'aarch64-softmmu',
-      'riscv32-softmmu', 'riscv64-softmmu'
-  ]
-  config_target_info += {target : files(target + '.c')}
-endforeach
diff --git a/configs/targets/riscv32-softmmu.c b/configs/targets/riscv32-softmmu.c
deleted file mode 100644
index 0829ab84de5..00000000000
--- a/configs/targets/riscv32-softmmu.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * QEMU binary/target API (qemu-system-riscv32)
- *
- *  Copyright (c) rev.ng Labs Srl.
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#include "qemu/osdep.h"
-#include "qemu/target-info-impl.h"
-#include "qemu/target-info-init.h"
-#include "target/riscv/cpu-qom.h"
-#include "target/riscv/cpu-param.h"
-
-static const TargetInfo target_info_riscv32_system = {
-    .target_name = "riscv32",
-    .target_arch = SYS_EMU_TARGET_RISCV32,
-    .long_bits = 32,
-    .cpu_type = TYPE_RISCV_CPU,
-    .endianness = ENDIAN_MODE_LITTLE,
-    .page_bits_init = TARGET_PAGE_BITS,
-};
-
-target_info_init(target_info_riscv32_system)
diff --git a/configs/targets/riscv64-softmmu.c b/configs/targets/riscv64-softmmu.c
deleted file mode 100644
index 553bd1f75fe..00000000000
--- a/configs/targets/riscv64-softmmu.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * QEMU binary/target API (qemu-system-riscv64)
- *
- *  Copyright (c) rev.ng Labs Srl.
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#include "qemu/osdep.h"
-#include "qemu/target-info-impl.h"
-#include "qemu/target-info-init.h"
-#include "target/riscv/cpu-qom.h"
-#include "target/riscv/cpu-param.h"
-
-static const TargetInfo target_info_riscv64_system = {
-    .target_name = "riscv64",
-    .target_arch = SYS_EMU_TARGET_RISCV64,
-    .long_bits = 64,
-    .cpu_type = TYPE_RISCV_CPU,
-    .endianness = ENDIAN_MODE_LITTLE,
-    .page_bits_init = TARGET_PAGE_BITS,
-};
-
-target_info_init(target_info_riscv64_system)
diff --git a/meson.build b/meson.build
index 828100de816..64d3f7675f7 100644
--- a/meson.build
+++ b/meson.build
@@ -3754,7 +3754,6 @@ subdir('dump')
 subdir('accel')
 
 subdir('backends')
-subdir('configs/targets')
 subdir('disas')
 subdir('migration')
 subdir('monitor')
@@ -4346,11 +4345,7 @@ foreach target : target_dirs
     endif
   endif
 
-  if target in config_target_info
-    arch_srcs += config_target_info[target]
-  else
-    arch_srcs += files('target-info-stub.c')
-  endif
+  arch_srcs += files('target-info-stub.c')
 
   if target_base_arch in target_arch
     t = target_arch[target_base_arch].apply(config_target, strict: false)
-- 
2.55.0.windows.3



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

* [PATCH 2/8] target-info: rename target-info-stub.c in target-info-def.c
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
  2026-10-07 11:47 ` [PATCH 1/8] configs/targets: remove target info definitions Yonggang Luo
@ 2026-10-07 11:47 ` Yonggang Luo
  2026-10-07 11:48 ` [PATCH 3/8] target-info: rename target-info-impl.h to target-info-def.h Yonggang Luo
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>

Now it's the only file left to define target info, we call it def to
make the intent more clear.

Signed-off-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 include/hw/core/cpu.h                   | 2 +-
 meson.build                             | 2 +-
 target-info-stub.c => target-info-def.c | 0
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename target-info-stub.c => target-info-def.c (100%)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 328e30045ce..ae66f5e33e3 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -601,7 +601,7 @@ QEMU_BUILD_BUG_ON(offsetof(CPUState, neg) !=
  * Return the CPUArchState associated with the CPU.
  */
 #define cpu_env(cpu) _Generic(cpu, \
-    /* We validate that CPUArchState follows CPUState in target-info-stub.c */ \
+    /* We validate that CPUArchState follows CPUState in target-info-def.c */ \
     CPUState *: \
         (CPUArchState *)((cpu) + 1), \
     const CPUState *: \
diff --git a/meson.build b/meson.build
index 64d3f7675f7..ac78c58cb91 100644
--- a/meson.build
+++ b/meson.build
@@ -4345,7 +4345,7 @@ foreach target : target_dirs
     endif
   endif
 
-  arch_srcs += files('target-info-stub.c')
+  arch_srcs += files('target-info-def.c')
 
   if target_base_arch in target_arch
     t = target_arch[target_base_arch].apply(config_target, strict: false)
diff --git a/target-info-stub.c b/target-info-def.c
similarity index 100%
rename from target-info-stub.c
rename to target-info-def.c
-- 
2.55.0.windows.3



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

* [PATCH 3/8] target-info: rename target-info-impl.h to target-info-def.h
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
  2026-10-07 11:47 ` [PATCH 1/8] configs/targets: remove target info definitions Yonggang Luo
  2026-10-07 11:47 ` [PATCH 2/8] target-info: rename target-info-stub.c in target-info-def.c Yonggang Luo
@ 2026-10-07 11:48 ` Yonggang Luo
  2026-10-07 20:27   ` Pierrick Bouvier
  2026-10-07 11:48 ` [PATCH 4/8] target-info: replace QOM registration with a constructor list Yonggang Luo
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

Rename the TargetInfo structure header and its include guard.

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 include/qemu/{target-info-impl.h => target-info-def.h} | 4 ++--
 include/qemu/target-info-qom.h                         | 2 +-
 page-vary-common.c                                     | 2 +-
 page-vary-system.c                                     | 2 +-
 target-info-def.c                                      | 2 +-
 target-info-qom.c                                      | 2 +-
 target-info.c                                          | 2 +-
 7 files changed, 8 insertions(+), 8 deletions(-)
 rename include/qemu/{target-info-impl.h => target-info-def.h} (94%)

diff --git a/include/qemu/target-info-impl.h b/include/qemu/target-info-def.h
similarity index 94%
rename from include/qemu/target-info-impl.h
rename to include/qemu/target-info-def.h
index cf42aabbc8b..8019d2c7196 100644
--- a/include/qemu/target-info-impl.h
+++ b/include/qemu/target-info-def.h
@@ -6,8 +6,8 @@
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
-#ifndef QEMU_TARGET_INFO_IMPL_H
-#define QEMU_TARGET_INFO_IMPL_H
+#ifndef QEMU_TARGET_INFO_DEF_H
+#define QEMU_TARGET_INFO_DEF_H
 
 #include "qapi/qapi-types-common.h"
 #include "qapi/qapi-types-machine.h"
diff --git a/include/qemu/target-info-qom.h b/include/qemu/target-info-qom.h
index 8b6e1ece969..ba2e4370afb 100644
--- a/include/qemu/target-info-qom.h
+++ b/include/qemu/target-info-qom.h
@@ -9,7 +9,7 @@
 #ifndef QEMU_TARGET_INFO_QOM_H
 #define QEMU_TARGET_INFO_QOM_H
 
-#include "qemu/target-info-impl.h"
+#include "qemu/target-info-def.h"
 #include "qom/object.h"
 
 #define TYPE_TARGET_INFO "target-info"
diff --git a/page-vary-common.c b/page-vary-common.c
index ddd08633788..5a4654725a8 100644
--- a/page-vary-common.c
+++ b/page-vary-common.c
@@ -20,7 +20,7 @@
 #define IN_PAGE_VARY 1
 
 #include "qemu/osdep.h"
-#include "qemu/target-info-impl.h"
+#include "qemu/target-info-def.h"
 #include "exec/page-vary.h"
 
 /* WARNING: This file must *not* be complied with -flto. */
diff --git a/page-vary-system.c b/page-vary-system.c
index 6c49c10e23b..9773685dc16 100644
--- a/page-vary-system.c
+++ b/page-vary-system.c
@@ -20,7 +20,7 @@
 #include "qemu/osdep.h"
 #include "exec/page-vary.h"
 #include "exec/tlb-flags.h"
-#include "qemu/target-info-impl.h"
+#include "qemu/target-info-def.h"
 
 QEMU_BUILD_BUG_ON(TLB_FLAGS_MASK & ((1u < TARGET_PAGE_BITS_MIN) - 1));
 
diff --git a/target-info-def.c b/target-info-def.c
index d121b8c0170..fa19cabc55f 100644
--- a/target-info-def.c
+++ b/target-info-def.c
@@ -8,7 +8,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/target-info.h"
-#include "qemu/target-info-impl.h"
+#include "qemu/target-info-def.h"
 #include "qemu/target-info-init.h"
 #include "hw/core/boards.h"
 #include "cpu.h"
diff --git a/target-info-qom.c b/target-info-qom.c
index 3ae1627b8fb..aeeedb7e818 100644
--- a/target-info-qom.c
+++ b/target-info-qom.c
@@ -9,7 +9,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qom/object.h"
-#include "qemu/target-info-impl.h"
+#include "qemu/target-info-def.h"
 #include "qemu/target-info-init.h"
 #include "qemu/target-info-qom.h"
 
diff --git a/target-info.c b/target-info.c
index ab43c9f802c..6b365113955 100644
--- a/target-info.c
+++ b/target-info.c
@@ -9,7 +9,7 @@
 #include "qemu/osdep.h"
 #include "qemu/target-info.h"
 #include "qemu/target-info-qapi.h"
-#include "qemu/target-info-impl.h"
+#include "qemu/target-info-def.h"
 #include "qapi/error.h"
 
 const char *target_name(void)
-- 
2.55.0.windows.3



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

* [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
                   ` (2 preceding siblings ...)
  2026-10-07 11:48 ` [PATCH 3/8] target-info: rename target-info-impl.h to target-info-def.h Yonggang Luo
@ 2026-10-07 11:48 ` Yonggang Luo
  2026-10-07 20:29   ` Pierrick Bouvier
  2026-10-07 11:48 ` [PATCH 5/8] tests/unit: add target-info coverage for multi-target builds Yonggang Luo
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

Register target definitions through constructors instead of
MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
available on entry to main(), without explicit initialization or a
call to module_call_init(MODULE_INIT_QOM).

Keep the target list sorted by target_arch and default to its first
entry. Provide an unknown TargetInfo fallback for target-independent
tools such as qemu-img and unit tests that link no target-info-def.c
objects.

Remove the obsolete QOM target-info registration infrastructure and
update the multi-target test to inspect target information before
initializing QOM.

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 include/qemu/module.h           |  1 -
 include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
 include/qemu/target-info-init.h | 53 ----------------------------
 include/qemu/target-info-qom.h  | 31 -----------------
 include/qemu/target-info.h      |  9 +++++
 meson.build                     |  6 ++--
 system/vl.c                     |  4 ---
 target-info-def.c               |  1 -
 target-info-qom.c               | 60 --------------------------------
 target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
 tests/qtest/fuzz/fuzz.c         |  3 --
 tests/unit/test-multi-target.c  | 12 +++----
 12 files changed, 129 insertions(+), 168 deletions(-)
 delete mode 100644 include/qemu/target-info-init.h
 delete mode 100644 include/qemu/target-info-qom.h
 delete mode 100644 target-info-qom.c

diff --git a/include/qemu/module.h b/include/qemu/module.h
index fccf017bf9e..9885ac9afb3 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -43,7 +43,6 @@ typedef enum {
     MODULE_INIT_MIGRATION,
     MODULE_INIT_BLOCK,
     MODULE_INIT_OPTS,
-    MODULE_INIT_TARGET_INFO,
     MODULE_INIT_QOM,
     MODULE_INIT_TRACE,
     MODULE_INIT_XEN_BACKEND,
diff --git a/include/qemu/target-info-def.h b/include/qemu/target-info-def.h
index 8019d2c7196..080e30a5b0e 100644
--- a/include/qemu/target-info-def.h
+++ b/include/qemu/target-info-def.h
@@ -11,8 +11,10 @@
 
 #include "qapi/qapi-types-common.h"
 #include "qapi/qapi-types-machine.h"
+#include "qemu/queue.h"
+#include "qemu/target-info.h"
 
-typedef struct TargetInfo {
+struct TargetInfo {
     /* runtime equivalent of TARGET_NAME definition */
     const char *target_name;
     /* related to TARGET_ARCH definition */
@@ -30,13 +32,57 @@ typedef struct TargetInfo {
     unsigned page_bits_init;
     /* runtime equivalent of TARGET_PAGE_BITS_VARY definition */
     bool page_bits_vary;
-} TargetInfo;
+};
+
+typedef struct TargetInfoNode TargetInfoNode;
+typedef QLIST_HEAD(, TargetInfoNode) TargetInfoList;
+
+struct TargetInfoNode {
+    const TargetInfo *info;
+    QLIST_ENTRY(TargetInfoNode) next;
+};
+
+/**
+ * target_info_list:
+ *
+ * TargetInfo is a static list, not a QOM type. Constructors insert
+ * entries before main(), so type_init can use it.
+ *
+ * Returns: registered TargetInfoNode list head, sorted by
+ *          info->target_arch. The list is owned by target-info
+ *          and must not be modified. Iterate with
+ *          QLIST_FOREACH(..., next) and use node->info.
+ */
+const TargetInfoList *target_info_list(void);
 
 /**
- * target_info:
+ * target_info_select:
+ * @ti: TargetInfo to make current
  *
- * Returns: The TargetInfo structure definition for this target binary.
+ * Sets target_info() to @ti.
+ */
+void target_info_select(const TargetInfo *ti);
+
+/**
+ * target_info_list_add:
+ * @node: static TargetInfoNode whose info points at a const TargetInfo
+ *
+ * Inserts @node into target_info_list(), sorted by info->target_arch.
+ * Sets target_info() to the first list entry.
+ */
+void target_info_list_add(TargetInfoNode *node);
+
+/*
+ * Register @ti before main(). Linked into the executable, not a DSO.
+ * @ti is a unique identifier in this translation unit.
  */
-const TargetInfo *target_info(void);
+#define target_info_init(ti)                                            \
+    static TargetInfoNode ti##_node = {                                 \
+        .info = &(ti),                                                  \
+    };                                                                  \
+    static void __attribute__((constructor)) do_qemu_init_##ti(void)    \
+    {                                                                   \
+        target_info_list_add(&ti##_node);                               \
+    }
 
 #endif
diff --git a/include/qemu/target-info-init.h b/include/qemu/target-info-init.h
deleted file mode 100644
index b7024c9faef..00000000000
--- a/include/qemu/target-info-init.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * QEMU target info initialization
- *
- * Copyright (c) Qualcomm
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- *
- * This file is included by each file defining a TargetInfo structure and is
- * responsible for registering it.
- */
-
-#ifndef QEMU_TARGET_INFO_INIT_H
-#define QEMU_TARGET_INFO_INIT_H
-
-#define DEFINE_TARGET_INFO_TYPE(info)                                       \
-static void do_qemu_init_target_info(void)                                  \
-{                                                                           \
-    type_register_static(&info);                                            \
-}                                                                           \
-module_init(do_qemu_init_target_info, MODULE_INIT_TARGET_INFO)
-
-#ifdef COMPILING_PER_TARGET
-#ifdef CONFIG_USER_ONLY
-
-/*
- * User mode does not support multiple targets in the same binary, so just
- * define target_info().
- */
-#define target_info_init(ti_var)        \
-const TargetInfo *target_info(void)     \
-{                                       \
-    return &ti_var;                     \
-}
-
-#else /* CONFIG_USER_ONLY */
-
-#include "qemu/target-info-qom.h"
-#include "qom/object.h"
-
-#define target_info_init(ti_var)                                            \
-static const TypeInfo target_info_qom_target_type_info = {                  \
-    .name =  TYPE_TARGET_INFO"-"TARGET_NAME,                                \
-    .parent = TYPE_TARGET_INFO,                                             \
-    .instance_size = sizeof(TargetInfoQom),                                 \
-    .class_size = sizeof(TargetInfoQomClass),                               \
-    .class_data = &ti_var,                                                  \
-};                                                                          \
-DEFINE_TARGET_INFO_TYPE(target_info_qom_target_type_info)
-
-#endif /* CONFIG_USER_ONLY */
-#endif /* COMPILING_PER_TARGET */
-
-#endif /* QEMU_TARGET_INFO_INIT_H */
diff --git a/include/qemu/target-info-qom.h b/include/qemu/target-info-qom.h
deleted file mode 100644
index ba2e4370afb..00000000000
--- a/include/qemu/target-info-qom.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * QEMU target info QOM types
- *
- * Copyright (c) Qualcomm
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#ifndef QEMU_TARGET_INFO_QOM_H
-#define QEMU_TARGET_INFO_QOM_H
-
-#include "qemu/target-info-def.h"
-#include "qom/object.h"
-
-#define TYPE_TARGET_INFO "target-info"
-
-typedef struct TargetInfoQom {
-    Object parent_obj;
-} TargetInfoQom;
-
-typedef struct TargetInfoQomClass {
-    ObjectClass parent_class;
-    const TargetInfo *target_info;
-} TargetInfoQomClass;
-
-OBJECT_DECLARE_TYPE(TargetInfoQom, TargetInfoQomClass, TARGET_INFO)
-
-void target_info_qom_set_target(void);
-void target_info_qom_set_target_info(const TargetInfo *ti);
-
-#endif /* QEMU_TARGET_INFO_QOM_H */
diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
index adda363ac39..d1928cecf84 100644
--- a/include/qemu/target-info.h
+++ b/include/qemu/target-info.h
@@ -9,6 +9,15 @@
 #ifndef QEMU_TARGET_INFO_H
 #define QEMU_TARGET_INFO_H
 
+typedef struct TargetInfo TargetInfo;
+
+/**
+ * target_info:
+ *
+ * Returns: The TargetInfo structure definition for the selected target.
+ */
+const TargetInfo *target_info(void);
+
 /**
  * target_name:
  *
diff --git a/meson.build b/meson.build
index ac78c58cb91..4097784e7a2 100644
--- a/meson.build
+++ b/meson.build
@@ -3777,6 +3777,9 @@ if enable_modules
   modulecommon = declare_dependency(objects: libmodulecommon.extract_all_objects(recursive: false), compile_args: '-DBUILD_DSO')
 endif
 
+qom_ss.add(files(
+  'target-info.c',
+))
 qom_ss = qom_ss.apply({})
 libqom = static_library('qom', qom_ss.sources() + genh,
                         dependencies: [qom_ss.dependencies()],
@@ -3869,9 +3872,6 @@ endif
 common_ss.add(pagevary)
 system_ss.add(files('page-vary-system.c'))
 
-common_ss.add(files('target-info.c'))
-system_ss.add(files('target-info-qom.c'))
-
 if 'CONFIG_TCG' in config_all_accel
   subdir('contrib/plugins')
 endif
diff --git a/system/vl.c b/system/vl.c
index 468a9fc247a..2c50aa01a2e 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -28,7 +28,6 @@
 #include "qemu/units.h"
 #include "qemu/module.h"
 #include "qemu/target-info.h"
-#include "qemu/target-info-qom.h"
 #include "exec/cpu-common.h"
 #include "exec/page-vary.h"
 #include "hw/core/qdev-properties.h"
@@ -2914,9 +2913,6 @@ void qemu_init(int argc, char **argv)
 
     os_setup_limits();
 
-    module_call_init(MODULE_INIT_TARGET_INFO);
-    target_info_qom_set_target();
-
     module_init_info(qemu_modinfo);
     module_allow_arch(target_name());
 
diff --git a/target-info-def.c b/target-info-def.c
index fa19cabc55f..3041d64ccd2 100644
--- a/target-info-def.c
+++ b/target-info-def.c
@@ -9,7 +9,6 @@
 #include "qemu/osdep.h"
 #include "qemu/target-info.h"
 #include "qemu/target-info-def.h"
-#include "qemu/target-info-init.h"
 #include "hw/core/boards.h"
 #include "cpu.h"
 #include "exec/cpu-defs.h"
diff --git a/target-info-qom.c b/target-info-qom.c
deleted file mode 100644
index aeeedb7e818..00000000000
--- a/target-info-qom.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * QEMU binary/target API (QOM types)
- *
- *  Copyright (c) Linaro
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qom/object.h"
-#include "qemu/target-info-def.h"
-#include "qemu/target-info-init.h"
-#include "qemu/target-info-qom.h"
-
-static void target_info_qom_class_init(ObjectClass *oc, const void * data)
-{
-    TargetInfoQomClass *klass = TARGET_INFO_CLASS(oc);
-    klass->target_info = data;
-}
-
-static const TypeInfo target_info_parent_type = {
-    .name = TYPE_TARGET_INFO,
-    .parent = TYPE_OBJECT,
-    .instance_size = sizeof(TargetInfoQom),
-    .class_size = sizeof(TargetInfoQomClass),
-    /* use class_base_init so children classes can set class_data accordingly */
-    .class_base_init = target_info_qom_class_init,
-    /* children classes will be concrete, which allows to easily query them
-     * without listing this parent class also */
-    .abstract = true,
-};
-
-DEFINE_TARGET_INFO_TYPE(target_info_parent_type)
-
-static const TargetInfo *target_info_ptr;
-
-const TargetInfo *target_info(void)
-{
-    return target_info_ptr;
-}
-
-void target_info_qom_set_target(void)
-{
-    g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
-
-    size_t num_found = g_slist_length(targets);
-    if (num_found != 1) {
-        error_setg(&error_fatal, num_found == 0 ?
-                                 "no target-info is available" :
-                                 "more than one target-info is available");
-    }
-
-    target_info_ptr = TARGET_INFO_CLASS(targets->data)->target_info;
-}
-
-void target_info_qom_set_target_info(const TargetInfo *ti)
-{
-    target_info_ptr = ti;
-}
diff --git a/target-info.c b/target-info.c
index 6b365113955..8ccb333e365 100644
--- a/target-info.c
+++ b/target-info.c
@@ -10,7 +10,66 @@
 #include "qemu/target-info.h"
 #include "qemu/target-info-qapi.h"
 #include "qemu/target-info-def.h"
-#include "qapi/error.h"
+#include "exec/page-vary.h"
+
+/*
+ * Tools such as qemu-img and unit tests may link target-info.c without any
+ * target-info-def.c objects. Their target list remains empty, so use this
+ * fallback.
+ */
+static const TargetInfo target_info_default = {
+    .target_arch = SYS_EMU_TARGET__MAX,
+    .target_name = "unknown",
+    .long_bits = 64,
+    .endianness = ENDIAN_MODE_LITTLE,
+    .page_bits_init = TARGET_PAGE_BITS_MIN,
+};
+
+static const TargetInfo *target_info_ptr = &target_info_default;
+static TargetInfoList target_infos = QLIST_HEAD_INITIALIZER(target_infos);
+
+const TargetInfo *target_info(void)
+{
+    g_assert(target_info_ptr != NULL);
+    return target_info_ptr;
+}
+
+const TargetInfoList *target_info_list(void)
+{
+    return &target_infos;
+}
+
+void target_info_select(const TargetInfo *ti)
+{
+    g_assert(ti != NULL);
+    target_info_ptr = ti;
+}
+
+void target_info_list_add(TargetInfoNode *node)
+{
+    const TargetInfo *info;
+    TargetInfoNode *cur, *prev = NULL;
+
+    g_assert(node && node->info);
+    info = node->info;
+    QLIST_FOREACH(cur, &target_infos, next) {
+        if (info->target_arch < cur->info->target_arch) {
+            QLIST_INSERT_BEFORE(cur, node, next);
+            break;
+        }
+        prev = cur;
+    }
+    if (!cur) {
+        if (prev) {
+            QLIST_INSERT_AFTER(prev, node, next);
+        } else {
+            QLIST_INSERT_HEAD(&target_infos, node, next);
+        }
+    }
+
+    /* Default to the first entry in the target_arch-sorted list. */
+    target_info_select(QLIST_FIRST(&target_infos)->info);
+}
 
 const char *target_name(void)
 {
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
index a3a131c80f8..d2355989616 100644
--- a/tests/qtest/fuzz/fuzz.c
+++ b/tests/qtest/fuzz/fuzz.c
@@ -22,7 +22,6 @@
 #include "system/runstate.h"
 #include "qemu/main-loop.h"
 #include "qemu/rcu.h"
-#include "qemu/target-info-qom.h"
 #include "tests/qtest/libqtest.h"
 #include "tests/qtest/libqos/qgraph.h"
 #include "fuzz.h"
@@ -173,8 +172,6 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
 
     /* Initialize qgraph and modules */
     qos_graph_init();
-    module_call_init(MODULE_INIT_TARGET_INFO);
-    target_info_qom_set_target();
     module_call_init(MODULE_INIT_FUZZ_TARGET);
     module_call_init(MODULE_INIT_QOM);
     module_call_init(MODULE_INIT_LIBQOS);
diff --git a/tests/unit/test-multi-target.c b/tests/unit/test-multi-target.c
index 89b55bb1632..150254a3ba3 100644
--- a/tests/unit/test-multi-target.c
+++ b/tests/unit/test-multi-target.c
@@ -15,7 +15,7 @@
 #include "qemu/osdep.h"
 #include "qemu/module.h"
 #include "qemu/target-info.h"
-#include "qemu/target-info-qom.h"
+#include "qemu/target-info-def.h"
 #include "qom/object.h"
 
 #ifdef CONFIG_SDL
@@ -32,11 +32,11 @@ int (*qemu_main)(void);
 
 static void test_qom_types_are_unique(void)
 {
-    module_call_init(MODULE_INIT_TARGET_INFO);
-    g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
-    g_assert(targets);
-    const TargetInfo *first_ti = TARGET_INFO_CLASS(targets->data)->target_info;
-    target_info_qom_set_target_info(first_ti);
+    const TargetInfoList *targets = target_info_list();
+
+    g_assert_nonnull(QLIST_FIRST(targets));
+
+    g_assert_nonnull(target_info());
 
     /* register all types */
     module_call_init(MODULE_INIT_QOM);
-- 
2.55.0.windows.3



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

* [PATCH 5/8] tests/unit: add target-info coverage for multi-target builds
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
                   ` (3 preceding siblings ...)
  2026-10-07 11:48 ` [PATCH 4/8] target-info: replace QOM registration with a constructor list Yonggang Luo
@ 2026-10-07 11:48 ` Yonggang Luo
  2026-10-07 11:48 ` [PATCH 6/8] meson: load all target .mak files into target_mak_all Yonggang Luo
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

Link target-info-def.c objects from supported multi-target libraries into
test-target-info. Verify target_info() is non-NULL and that
target_info_list() contains one entry for each linked target.

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 MAINTAINERS                   |  1 +
 meson.build                   |  5 ++++-
 tests/unit/meson.build        |  4 ++++
 tests/unit/test-target-info.c | 38 +++++++++++++++++++++++++++++++++++
 4 files changed, 47 insertions(+), 1 deletion(-)
 create mode 100644 tests/unit/test-target-info.c

diff --git a/MAINTAINERS b/MAINTAINERS
index cfe39dc2883..418c4e472a9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2149,6 +2149,7 @@ S: Supported
 F: include/qemu/target-info*.h
 F: target-info*.c
 F: tests/unit/test-multi-targets.c
+F: tests/unit/test-target-info.c
 
 Xtensa Machines
 ---------------
diff --git a/meson.build b/meson.build
index 4097784e7a2..fd7a4f68389 100644
--- a/meson.build
+++ b/meson.build
@@ -4259,6 +4259,7 @@ endif
 traceable = []
 multi_target_libs = []
 multi_target_deps = []
+multi_target_target_info_objects = []
 multi_target_crates = []
 multi_target_supported_targets = [
   'aarch64-softmmu',
@@ -4274,6 +4275,7 @@ multi_target_supported_targets = [
 ]
 
 emulators = {}
+target_info_def = files('target-info-def.c')
 foreach target : target_dirs
   config_target = config_target_mak[target]
   target_name = config_target['TARGET_NAME']
@@ -4345,7 +4347,7 @@ foreach target : target_dirs
     endif
   endif
 
-  arch_srcs += files('target-info-def.c')
+  arch_srcs += target_info_def
 
   if target_base_arch in target_arch
     t = target_arch[target_base_arch].apply(config_target, strict: false)
@@ -4428,6 +4430,7 @@ foreach target : target_dirs
       multi_target_libs += lib
       multi_target_deps += arch_deps
       multi_target_deps += target_stubs
+      multi_target_target_info_objects += lib.extract_objects(target_info_def)
       multi_target_crates += main_rs
     endif
     execs = [{
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index d17435c1877..b2e8be24b05 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -43,6 +43,10 @@ tests = {
   'test-qgraph': ['../qtest/libqos/qgraph.c'],
   'check-qom-interface': [qom],
   'check-qom-proplist': [qom],
+  'test-target-info': [qom, declare_dependency(
+    objects: multi_target_target_info_objects,
+    compile_args: ['-DTARGET_INFO_DEF_COUNT=@0@'.format(
+      multi_target_target_info_objects.length())])],
   'test-qemu-opts': [],
   'test-keyval': [testqapi],
   'test-logging': [],
diff --git a/tests/unit/test-target-info.c b/tests/unit/test-target-info.c
new file mode 100644
index 00000000000..e6de9b259e8
--- /dev/null
+++ b/tests/unit/test-target-info.c
@@ -0,0 +1,38 @@
+/*
+ * TargetInfo unit tests
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/target-info.h"
+#include "qemu/target-info-def.h"
+
+static int target_info_list_count(void)
+{
+    TargetInfoNode *node;
+    int n = 0;
+
+    QLIST_FOREACH(node, target_info_list(), next) {
+        n++;
+    }
+    return n;
+}
+
+static void test_target_info_not_null(void)
+{
+    g_assert_nonnull(target_info());
+}
+
+static void test_target_info_list_count(void)
+{
+    g_assert_cmpint(target_info_list_count(), ==, TARGET_INFO_DEF_COUNT);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/target-info/not-null", test_target_info_not_null);
+    g_test_add_func("/target-info/list-count", test_target_info_list_count);
+    return g_test_run();
+}
-- 
2.55.0.windows.3



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

* [PATCH 6/8] meson: load all target .mak files into target_mak_all
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
                   ` (4 preceding siblings ...)
  2026-10-07 11:48 ` [PATCH 5/8] tests/unit: add target-info coverage for multi-target builds Yonggang Luo
@ 2026-10-07 11:48 ` Yonggang Luo
  2026-10-07 20:30   ` Pierrick Bouvier
  2026-10-07 11:48 ` [PATCH 7/8] target-info: Replace handwritten architecture checks with generated code Yonggang Luo
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

Load every configs/targets/*.mak once into target_mak_all, keyed by
target_dirs_all, with TARGET_BASE_ARCH defaulted to TARGET_ARCH. The
per-target loop now takes its config from target_mak_all instead of
loading the file again.

target_dirs is still the --target-list filtered subset and is the only
list built. target_mak_all is for later use by code that needs target
properties independent of --target-list, such as generating
TargetInfo helpers for every target.

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 meson.build | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/meson.build b/meson.build
index fd7a4f68389..d070dafe2a9 100644
--- a/meson.build
+++ b/meson.build
@@ -3239,6 +3239,21 @@ config_target_mak = {}
 config_base_arch_mak = {}
 config_target_info = {}
 
+# Load every configs/targets/*.mak unconditionally; target_dirs is the
+# --target-list filtered subset of target_dirs_all.
+target_dirs_all = run_command(python, '-c',
+  'import os, sys; print(" ".join(sorted(f[:-4] for f in os.listdir(sys.argv[1]) if f.endswith(".mak"))))',
+  meson.current_source_dir() / 'configs/targets',
+  check: true).stdout().split()
+target_mak_all = {}
+foreach target : target_dirs_all
+  mak = keyval.load('configs/targets' / target + '.mak')
+  if 'TARGET_BASE_ARCH' not in mak
+    mak += {'TARGET_BASE_ARCH': mak['TARGET_ARCH']}
+  endif
+  target_mak_all += {target: mak}
+endforeach
+
 disassemblers = {
   'alpha' : ['CONFIG_ALPHA_DIS'],
   'avr' : ['CONFIG_AVR_DIS'],
@@ -3318,7 +3333,7 @@ foreach target : target_dirs
     }
   endif
 
-  config_target += keyval.load('configs/targets' / target + '.mak')
+  config_target += target_mak_all[target]
 
   target_kconfig = []
   foreach sym: accelerators
@@ -3348,9 +3363,6 @@ foreach target : target_dirs
 
   # Add default keys
   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
-  if 'TARGET_BASE_ARCH' not in config_target
-    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
-  endif
   if 'TARGET_ABI_DIR' not in config_target
     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
   endif
-- 
2.55.0.windows.3



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

* [PATCH 7/8] target-info: Replace handwritten architecture checks with generated code
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
                   ` (5 preceding siblings ...)
  2026-10-07 11:48 ` [PATCH 6/8] meson: load all target .mak files into target_mak_all Yonggang Luo
@ 2026-10-07 11:48 ` Yonggang Luo
  2026-10-07 20:36   ` Pierrick Bouvier
  2026-10-07 11:48 ` [PATCH 8/8] qom: pass TargetInfo to is_available for later use Yonggang Luo
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

Add scripts/gen-target-info.py to generate declarations and definitions
for exact-target and base-family architecture checks from system target
names and their TARGET_BASE_ARCH values.

Provide target_is_<arch>() and target_is_base_<family>() checks for an
explicit TargetInfo. Retain target_<arch>() and target_base_<family>()
as wrappers using the current target.

Wire the generator into Meson using all system target definitions so
the available checks do not depend on --target-list.

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 include/qemu/target-info.h | 76 ++++-------------------------
 meson.build                | 16 ++++++
 scripts/gen-target-info.py | 99 ++++++++++++++++++++++++++++++++++++++
 target-info.c              | 62 +-----------------------
 4 files changed, 125 insertions(+), 128 deletions(-)
 create mode 100644 scripts/gen-target-info.py

diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
index d1928cecf84..88aa80e918c 100644
--- a/include/qemu/target-info.h
+++ b/include/qemu/target-info.h
@@ -51,74 +51,16 @@ const char *target_cpu_type(void);
  */
 bool target_big_endian(void);
 
-/**
- * target_base_arm:
- *
- * Returns whether the target architecture is ARM or Aarch64.
- */
-bool target_base_arm(void);
-
-/**
- * target_arm:
- *
- * Returns whether the target architecture is ARM (32-bit, not Aarch64).
- */
-bool target_arm(void);
-
-/**
- * target_aarch64:
- *
- * Returns whether the target architecture is Aarch64.
- */
-bool target_aarch64(void);
-
-/**
- * target_m68k:
- *
- * Returns whether the target architecture is M68K.
- */
-bool target_m68k(void);
-
-/**
- * target_or1k:
- *
- * Returns whether the target architecture is OpenRISC 1000.
- */
-bool target_or1k(void);
-
-/**
- * target_base_ppc:
- *
- * Returns whether the target architecture is PowerPC 32-bit or 64-bit.
- */
-bool target_base_ppc(void);
-
-/**
- * target_ppc:
- *
- * Returns whether the target architecture is PowerPC 32-bit.
- */
-bool target_ppc(void);
-
-/**
- * target_ppc64:
- *
- * Returns whether the target architecture is PowerPC 64-bit.
- */
-bool target_ppc64(void);
-
-/**
- * target_s390x:
- *
- * Returns whether the target architecture is S390x.
- */
-bool target_s390x(void);
-
-/**
- * target_riscv64:
+/*
+ * Exact-target and base-family helpers, generated by
+ * scripts/gen-target-info.py from the TARGET_BASE_ARCH of every
+ * system target:
  *
- * Returns whether the target architecture is riscv64
+ *   bool target_is_<arch>(const TargetInfo *ti);
+ *   bool target_<arch>(void);
+ *   bool target_is_base_<family>(const TargetInfo *ti);
+ *   bool target_base_<family>(void);
  */
-bool target_riscv64(void);
+#include "target-info-gen.h"
 
 #endif
diff --git a/meson.build b/meson.build
index d070dafe2a9..8799b3f6d51 100644
--- a/meson.build
+++ b/meson.build
@@ -3581,6 +3581,22 @@ foreach d : hx_headers
 endforeach
 genh += hxdep
 
+# Use target_mak_all, not target_dirs, so the generated helpers do not
+# depend on --target-list.
+target_info_gen_args = []
+foreach target, mak : target_mak_all
+  if target.endswith('-softmmu')
+    target_info_gen_args += ['--target',
+      target.split('-')[0] + '=' + mak['TARGET_BASE_ARCH']]
+  endif
+endforeach
+target_info_gen = custom_target('target-info-gen',
+                      output: ['target-info-gen.h', 'target-info-gen.c.inc'],
+                      depend_files: files('scripts/qapi/common.py'),
+                      command: [python, files('scripts/gen-target-info.py'),
+                                target_info_gen_args, '@OUTDIR@'])
+genh += target_info_gen
+
 ###############
 # Trace files #
 ###############
diff --git a/scripts/gen-target-info.py b/scripts/gen-target-info.py
new file mode 100644
index 00000000000..a4c3474140f
--- /dev/null
+++ b/scripts/gen-target-info.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+"""Generate TargetInfo target helpers and abstract machine parents.
+
+meson passes every system target with its TARGET_BASE_ARCH, independent
+of --target-list, as --target <name>=<base>.  <name> is a SysEmuTarget
+member; a target without one fails to compile.
+
+For every target <arch> and every base family <family>:
+    bool target_is_<arch>(const TargetInfo *ti);
+    bool target_<arch>(void);
+    bool target_is_base_<family>(const TargetInfo *ti);
+    bool target_base_<family>(void);
+    TYPE_TARGET_<ARCH>_MACHINE        "target-<arch>-machine"
+    TYPE_TARGET_BASE_<FAMILY>_MACHINE "target-base-<family>-machine"
+
+Machine parents are abstract and only registered when available.
+<arch> parents inherit their <family> parent, which inherits TYPE_MACHINE.
+"""
+
+import argparse
+import os
+import re
+import sys
+from typing import Dict, List
+
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+from qapi.common import c_enum_const, c_name
+
+HEADER = "/* Generated by scripts/gen-target-info.py. Do not edit. */"
+C_IDENT = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
+
+
+def parse_targets(pairs: List[str]) -> Dict[str, List[str]]:
+    """Return {family: [target, ...]}, both sorted."""
+    seen = set()
+    families: Dict[str, List[str]] = {}
+    for pair in pairs:
+        name, _, family = pair.partition("=")
+        if not name or not C_IDENT.match(family) or name in seen:
+            sys.exit(f"{sys.argv[0]}: bad or duplicate --target '{pair}'")
+        seen.add(name)
+        families.setdefault(family, []).append(name)
+    return {f: sorted(t) for f, t in sorted(families.items())}
+
+
+def write(path: str, lines: List[str]) -> None:
+    with open(path, "w", encoding="utf-8", newline="\n") as fh:
+        fh.write("\n".join([HEADER, ""] + lines + [""]))
+
+
+def predicate(fn: str, cases: List[str]) -> List[str]:
+    body = (["    switch (ti->target_arch) {"]
+            + [f"    case {c}:" for c in cases]
+            + ["        return true;", "    default:",
+               "        return false;", "    }"])
+    return [f"bool target_is_{fn}(const TargetInfo *ti)", "{", *body, "}",
+            "", f"bool target_{fn}(void)", "{",
+            f"    return target_is_{fn}(target_info());", "}", ""]
+
+
+def main() -> None:
+    parser = argparse.ArgumentParser(description=__doc__.split("\n")[0])
+    parser.add_argument("--target", action="append", required=True,
+                        metavar="NAME=TARGET_BASE_ARCH")
+    parser.add_argument("outdir")
+    args = parser.parse_args()
+    families = parse_targets(args.target)
+
+    # (helper suffix, QOM name, enum constants, parent macro or None)
+    entries = []
+    for family, targets in families.items():
+        consts = [c_enum_const("SysEmuTarget", t) for t in targets]
+        entries.append((f"base_{family}", f"target-base-{family}",
+                        consts, None))
+    for family, targets in families.items():
+        for t in targets:
+            entries.append((c_name(t, False), f"target-{t}",
+                            [c_enum_const("SysEmuTarget", t)],
+                            f"TYPE_TARGET_BASE_{family.upper()}_MACHINE"))
+
+    def macro(fn: str) -> str:
+        return f"TYPE_TARGET_{fn.upper()}_MACHINE"
+
+    header = ["#ifndef TARGET_INFO_GEN_H", "#define TARGET_INFO_GEN_H", "",
+              "typedef struct TargetInfo TargetInfo;", ""]
+    for fn, _, _, _ in entries:
+        header += [f"bool target_is_{fn}(const TargetInfo *ti);",
+                   f"bool target_{fn}(void);", ""]
+    write(os.path.join(args.outdir, "target-info-gen.h"),
+          header + ["#endif"])
+
+    source = []
+    for fn, _, consts, _ in entries:
+        source += predicate(fn, consts)
+    write(os.path.join(args.outdir, "target-info-gen.c.inc"), source)
+
+if __name__ == "__main__":
+    main()
diff --git a/target-info.c b/target-info.c
index 8ccb333e365..fec8ee7c08e 100644
--- a/target-info.c
+++ b/target-info.c
@@ -101,64 +101,4 @@ bool target_big_endian(void)
     return target_endian_mode() == ENDIAN_MODE_BIG;
 }
 
-bool target_base_arm(void)
-{
-    switch (target_arch()) {
-    case SYS_EMU_TARGET_ARM:
-    case SYS_EMU_TARGET_AARCH64:
-        return true;
-    default:
-        return false;
-    }
-}
-
-bool target_arm(void)
-{
-    return target_arch() == SYS_EMU_TARGET_ARM;
-}
-
-bool target_aarch64(void)
-{
-    return target_arch() == SYS_EMU_TARGET_AARCH64;
-}
-
-bool target_m68k(void)
-{
-    return target_arch() == SYS_EMU_TARGET_M68K;
-}
-
-bool target_or1k(void)
-{
-    return target_arch() == SYS_EMU_TARGET_OR1K;
-}
-
-bool target_base_ppc(void)
-{
-    switch (target_arch()) {
-    case SYS_EMU_TARGET_PPC:
-    case SYS_EMU_TARGET_PPC64:
-        return true;
-    default:
-        return false;
-    }
-}
-
-bool target_ppc(void)
-{
-    return target_arch() == SYS_EMU_TARGET_PPC;
-}
-
-bool target_ppc64(void)
-{
-    return target_arch() == SYS_EMU_TARGET_PPC64;
-}
-
-bool target_s390x(void)
-{
-    return target_arch() == SYS_EMU_TARGET_S390X;
-}
-
-bool target_riscv64(void)
-{
-    return target_arch() == SYS_EMU_TARGET_RISCV64;
-}
+#include "target-info-gen.c.inc"
-- 
2.55.0.windows.3



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

* [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
                   ` (6 preceding siblings ...)
  2026-10-07 11:48 ` [PATCH 7/8] target-info: Replace handwritten architecture checks with generated code Yonggang Luo
@ 2026-10-07 11:48 ` Yonggang Luo
  2026-10-07 20:44   ` Pierrick Bouvier
  2026-10-07 20:25 ` [PATCH 0/8] qom: pass TargetInfo to the is_available callback Pierrick Bouvier
  2026-10-07 20:46 ` Pierrick Bouvier
  9 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 11:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	Pierrick Bouvier, qemu-arm, Philippe Mathieu-Daude, Peter Maydell,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

Change TypeInfo.is_available to the new TypeIsAvailable type, which
takes a const TargetInfo *. Registration passes target_info(), so
behavior is unchanged. object.h only forward-declares TargetInfo.

Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
generated machine parents to the matching target_is_<arch> helpers.

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 hw/arm/aspeed_ast27x0-fc.c  |  2 +-
 hw/arm/aspeed_ast27x0_evb.c |  4 ++--
 hw/arm/raspi.c              |  4 ++--
 hw/arm/raspi4b.c            |  2 +-
 hw/arm/virt.c               |  4 ++--
 hw/m68k/virt.c              |  4 ++--
 hw/or1k/virt.c              |  2 +-
 include/qom/object.h        | 12 +++++++++++-
 qom/object.c                |  3 ++-
 9 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
index 73362b60d2a..8a7c6a116ac 100644
--- a/hw/arm/aspeed_ast27x0-fc.c
+++ b/hw/arm/aspeed_ast27x0-fc.c
@@ -234,7 +234,7 @@ static const TypeInfo ast2700fc_types[] = {
         .parent         = TYPE_MACHINE,
         .class_init     = ast2700fc_class_init,
         .instance_size  = sizeof(Ast2700FCState),
-        .is_available   = target_aarch64,
+        .is_available   = target_is_aarch64,
     },
 };
 
diff --git a/hw/arm/aspeed_ast27x0_evb.c b/hw/arm/aspeed_ast27x0_evb.c
index 460c9ff0d2e..02a8cff1d9d 100644
--- a/hw/arm/aspeed_ast27x0_evb.c
+++ b/hw/arm/aspeed_ast27x0_evb.c
@@ -75,13 +75,13 @@ static const TypeInfo aspeed_ast27x0_evb_types[] = {
         .name          = MACHINE_TYPE_NAME("ast2700a1-evb"),
         .parent        = TYPE_ASPEED_MACHINE,
         .class_init    = aspeed_machine_ast2700a1_evb_class_init,
-        .is_available  = target_aarch64,
+        .is_available  = target_is_aarch64,
     },
     {
         .name          = MACHINE_TYPE_NAME("ast2700a2-evb"),
         .parent        = TYPE_ASPEED_MACHINE,
         .class_init    = aspeed_machine_ast2700a2_evb_class_init,
-        .is_available  = target_aarch64,
+        .is_available  = target_is_aarch64,
     }
 };
 
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index fadbacb2534..22b06c6ca22 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -403,12 +403,12 @@ static const TypeInfo raspi_machine_types[] = {
         .name           = MACHINE_TYPE_NAME("raspi3ap"),
         .parent         = TYPE_RASPI_MACHINE,
         .class_init     = raspi3ap_machine_class_init,
-        .is_available   = target_aarch64,
+        .is_available   = target_is_aarch64,
     }, {
         .name           = MACHINE_TYPE_NAME("raspi3b"),
         .parent         = TYPE_RASPI_MACHINE,
         .class_init     = raspi3b_machine_class_init,
-        .is_available   = target_aarch64,
+        .is_available   = target_is_aarch64,
     }, {
         .name           = TYPE_RASPI_MACHINE,
         .parent         = TYPE_RASPI_BASE_MACHINE,
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 566d64572db..a1dc477f25e 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -121,7 +121,7 @@ static const TypeInfo raspi4b_machine_type = {
     .parent         = TYPE_RASPI_BASE_MACHINE,
     .instance_size  = sizeof(Raspi4bMachineState),
     .class_init     = raspi4b_machine_class_init,
-    .is_available   = target_aarch64,
+    .is_available   = target_is_aarch64,
 };
 
 static void raspi4b_machine_register_type(void)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 9d192515d85..18160f7fad3 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -132,7 +132,7 @@ static void arm_virt_compat_default_set(MachineClass *mc)
         .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
         .parent = TYPE_VIRT_MACHINE, \
         .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
-        .is_available = target_base_arm, \
+        .is_available = target_is_base_arm, \
     }; \
     static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
     { \
@@ -4430,7 +4430,7 @@ static const TypeInfo virt_machine_info = {
          { TYPE_HOTPLUG_HANDLER },
          { }
     },
-    .is_available = target_base_arm,
+    .is_available = target_is_base_arm,
 };
 
 static void machvirt_machine_init(void)
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index e52546e4fab..ad2a43ef3fb 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -327,7 +327,7 @@ static const TypeInfo virt_machine_info = {
     .parent       = TYPE_MACHINE,
     .abstract     = true,
     .class_init   = virt_machine_class_init,
-    .is_available = target_m68k,
+    .is_available = target_is_m68k,
 };
 
 static void virt_machine_register_types(void)
@@ -355,7 +355,7 @@ type_init(virt_machine_register_types)
         .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
         .parent = MACHINE_TYPE_NAME("virt"), \
         .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
-        .is_available = target_m68k, \
+        .is_available = target_is_m68k, \
     }; \
     static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
     { \
diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
index a3ff903839b..89fb786641f 100644
--- a/hw/or1k/virt.c
+++ b/hw/or1k/virt.c
@@ -559,7 +559,7 @@ static const TypeInfo or1ksim_machine_typeinfo = {
     .parent     = TYPE_MACHINE,
     .class_init = openrisc_virt_machine_init,
     .instance_size = sizeof(OR1KVirtState),
-    .is_available = target_or1k,
+    .is_available = target_is_or1k,
 };
 
 static void or1ksim_machine_init_register_types(void)
diff --git a/include/qom/object.h b/include/qom/object.h
index 4c0645817a5..7d52a15f6b8 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -17,6 +17,7 @@
 #include "qapi/qapi-builtin-types.h"
 #include "qemu/module.h"
 
+typedef struct TargetInfo TargetInfo;
 struct TypeImpl;
 typedef struct TypeImpl *Type;
 
@@ -117,6 +118,15 @@ typedef void (ObjectUnparent)(Object *obj);
  */
 typedef void (ObjectFree)(void *obj);
 
+/**
+ * typedef TypeIsAvailable:
+ * @ti: TargetInfo to test.
+ *
+ * Returns whether a type is available for @ti. Typical implementations
+ * are target_is_*().
+ */
+typedef bool (TypeIsAvailable)(const TargetInfo *ti);
+
 #define OBJECT_CLASS_CAST_CACHE 4
 
 /**
@@ -498,7 +508,7 @@ struct TypeInfo
     void (*class_base_init)(ObjectClass *klass, const void *data);
     const void *class_data;
 
-    bool (*is_available)(void);
+    TypeIsAvailable *is_available;
     const InterfaceInfo *interfaces;
 };
 
diff --git a/qom/object.c b/qom/object.c
index 96498f3d001..253b9562b41 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -15,6 +15,7 @@
 #include "qom/compat-properties.h"
 #include "qom/object.h"
 #include "qom/object_interfaces.h"
+#include "qemu/target-info.h"
 #include "qemu/cutils.h"
 #include "qemu/memalign.h"
 #include "qapi/visitor.h"
@@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
         abort();
     }
 
-    if (info->is_available && !info->is_available()) {
+    if (info->is_available && !info->is_available(target_info())) {
         return NULL;
     }
 
-- 
2.55.0.windows.3



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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
                   ` (7 preceding siblings ...)
  2026-10-07 11:48 ` [PATCH 8/8] qom: pass TargetInfo to is_available for later use Yonggang Luo
@ 2026-10-07 20:25 ` Pierrick Bouvier
  2026-10-08  9:42   ` Daniel P. Berrangé
  2026-10-07 20:46 ` Pierrick Bouvier
  9 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 20:25 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> This allows a combined binary to register machine types from all its targets.
> Consequently, QMP `query-machines` can return machine entries from every
> target, even when `none` is selected. For example, a client can query the
> combined machine list with:
> 
> ```json
> { "execute": "query-machines" }
> ```
> 
> The returned list includes the registered machine classes from all linked
> targets. This is separate from selecting a machine: with `-target none`,
> `-M virt` reports the targets that provide `virt` instead of choosing one
> arbitrarily:
> 
> ```text
> qemu-system -target none -M virt
> unsupported machine type: "virt" for target "none"
> Available for targets:
>   aarch64
>   arm
> ```
>

From the long conversation on a previous thread, I thought we reached
the conclusion that if we didn't expose any ambiguous name, then -target
option is unnecessary, or maybe I got lost on track of this thread.

https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/

I'm not sure which semantic we want to have with -target none. If there
is no ambiguous name registered, we just don't need it at all. It's a
win-win IMHO.

> It moves target_info() to a shared location so object.c can call it when
> checking machine availability. The series also replaces QOM-based target-info
> registration with a constructor list and passes TargetInfo to the
> is_available callback.
> 
> Target metadata and architecture checks are generated from the configured
> targets, there is too much arch to write biiolperate code. doing this for easier
> Add TargetInfo* to is_available
> 
> The target-info API and implementation are shared, rather than compiled
> separately for every target.
> 
> This series removes the per-target source files "configs/targets/*.c".
> Their target-specific parameters are collected in a generated
> target-info-def.c for each softmmu target. This lays the groundwork for
> QEMU system builds in which target-info-def.c is the only target-specific
> source file compiled for each target. Using the same filename lets
> meson.build handle these definitions uniformly.
> 
> The series adds unit-test coverage for target info and multi-target builds.
> 
> Pierrick Bouvier (2):
>   configs/targets: remove target info definitions
>   target-info: rename target-info-stub.c in target-info-def.c
> 
> Yonggang Luo (6):
>   target-info: rename target-info-impl.h to target-info-def.h
>   target-info: replace QOM registration with a constructor list
>   tests/unit: add target-info coverage for multi-target builds
>   meson: load all target .mak files into target_mak_all
>   target-info: Replace handwritten architecture checks with generated
>     code
>   qom: pass TargetInfo to is_available for later use
> 
>  MAINTAINERS                             |   2 +-
>  configs/targets/aarch64-softmmu.c       |  25 ------
>  configs/targets/arm-softmmu.c           |  25 ------
>  configs/targets/meson.build             |   6 --
>  configs/targets/riscv32-softmmu.c       |  24 -----
>  configs/targets/riscv64-softmmu.c       |  24 -----
>  hw/arm/aspeed_ast27x0-fc.c              |   2 +-
>  hw/arm/aspeed_ast27x0_evb.c             |   4 +-
>  hw/arm/raspi.c                          |   4 +-
>  hw/arm/raspi4b.c                        |   2 +-
>  hw/arm/virt.c                           |   4 +-
>  hw/m68k/virt.c                          |   4 +-
>  hw/or1k/virt.c                          |   2 +-
>  include/hw/core/cpu.h                   |   2 +-
>  include/qemu/module.h                   |   1 -
>  include/qemu/target-info-def.h          |  88 ++++++++++++++++++
>  include/qemu/target-info-impl.h         |  42 ---------
>  include/qemu/target-info-init.h         |  53 -----------
>  include/qemu/target-info-qom.h          |  31 -------
>  include/qemu/target-info.h              |  87 ++++--------------
>  include/qom/object.h                    |  12 ++-
>  meson.build                             |  52 ++++++++---
>  page-vary-common.c                      |   2 +-
>  page-vary-system.c                      |   2 +-
>  qom/object.c                            |   3 +-
>  scripts/gen-target-info.py              |  99 ++++++++++++++++++++
>  system/vl.c                             |   4 -
>  target-info-stub.c => target-info-def.c |   3 +-
>  target-info-qom.c                       |  60 -------------
>  target-info.c                           | 115 ++++++++++++------------
>  tests/qtest/fuzz/fuzz.c                 |   3 -
>  tests/unit/meson.build                  |   4 +
>  tests/unit/test-multi-target.c          |  12 +--
>  tests/unit/test-target-info.c           |  38 ++++++++
>  34 files changed, 379 insertions(+), 462 deletions(-)
>  delete mode 100644 configs/targets/aarch64-softmmu.c
>  delete mode 100644 configs/targets/arm-softmmu.c
>  delete mode 100644 configs/targets/meson.build
>  delete mode 100644 configs/targets/riscv32-softmmu.c
>  delete mode 100644 configs/targets/riscv64-softmmu.c
>  create mode 100644 include/qemu/target-info-def.h
>  delete mode 100644 include/qemu/target-info-impl.h
>  delete mode 100644 include/qemu/target-info-init.h
>  delete mode 100644 include/qemu/target-info-qom.h
>  create mode 100644 scripts/gen-target-info.py
>  rename target-info-stub.c => target-info-def.c (94%)
>  delete mode 100644 target-info-qom.c
>  create mode 100644 tests/unit/test-target-info.c
> 



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

* Re: [PATCH 1/8] configs/targets: remove target info definitions
  2026-10-07 11:47 ` [PATCH 1/8] configs/targets: remove target info definitions Yonggang Luo
@ 2026-10-07 20:26   ` Pierrick Bouvier
  2026-10-08  9:46     ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 20:26 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
> 
> Now that we remove machine_typename, we don't need to keep duplicated
> file per target anymore. So we can just rely on target-info-stub.c.
> 
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
>  MAINTAINERS                       |  1 -
>  configs/targets/aarch64-softmmu.c | 25 -------------------------
>  configs/targets/arm-softmmu.c     | 25 -------------------------
>  configs/targets/meson.build       |  6 ------
>  configs/targets/riscv32-softmmu.c | 24 ------------------------
>  configs/targets/riscv64-softmmu.c | 24 ------------------------
>  meson.build                       |  7 +------
>  7 files changed, 1 insertion(+), 111 deletions(-)
>  delete mode 100644 configs/targets/aarch64-softmmu.c
>  delete mode 100644 configs/targets/arm-softmmu.c
>  delete mode 100644 configs/targets/meson.build
>  delete mode 100644 configs/targets/riscv32-softmmu.c
>  delete mode 100644 configs/targets/riscv64-softmmu.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1312bbd1bd8..cfe39dc2883 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2148,7 +2148,6 @@ M: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
>  S: Supported
>  F: include/qemu/target-info*.h
>  F: target-info*.c
> -F: configs/targets/*.c
>  F: tests/unit/test-multi-targets.c
>  
>  Xtensa Machines
> diff --git a/configs/targets/aarch64-softmmu.c b/configs/targets/aarch64-softmmu.c
> deleted file mode 100644
> index fdebdcc3582..00000000000
> --- a/configs/targets/aarch64-softmmu.c
> +++ /dev/null
> @@ -1,25 +0,0 @@
> -/*
> - * QEMU binary/target API (qemu-system-aarch64)
> - *
> - *  Copyright (c) Linaro
> - *
> - * SPDX-License-Identifier: GPL-2.0-or-later
> - */
> -
> -#include "qemu/osdep.h"
> -#include "qemu/target-info-impl.h"
> -#include "qemu/target-info-init.h"
> -#include "target/arm/cpu-qom.h"
> -#include "target/arm/cpu-param.h"
> -
> -static const TargetInfo target_info_aarch64_system = {
> -    .target_name = "aarch64",
> -    .target_arch = SYS_EMU_TARGET_AARCH64,
> -    .long_bits = 64,
> -    .cpu_type = TYPE_ARM_CPU,
> -    .endianness = ENDIAN_MODE_LITTLE,
> -    .page_bits_vary = true,
> -    .page_bits_init = TARGET_PAGE_BITS_LEGACY,
> -};
> -
> -target_info_init(target_info_aarch64_system)
> diff --git a/configs/targets/arm-softmmu.c b/configs/targets/arm-softmmu.c
> deleted file mode 100644
> index 2b98f65a0f8..00000000000
> --- a/configs/targets/arm-softmmu.c
> +++ /dev/null
> @@ -1,25 +0,0 @@
> -/*
> - * QEMU binary/target API (qemu-system-arm)
> - *
> - *  Copyright (c) Linaro
> - *
> - * SPDX-License-Identifier: GPL-2.0-or-later
> - */
> -
> -#include "qemu/osdep.h"
> -#include "qemu/target-info-impl.h"
> -#include "qemu/target-info-init.h"
> -#include "target/arm/cpu-qom.h"
> -#include "target/arm/cpu-param.h"
> -
> -static const TargetInfo target_info_arm_system = {
> -    .target_name = "arm",
> -    .target_arch = SYS_EMU_TARGET_ARM,
> -    .long_bits = 32,
> -    .cpu_type = TYPE_ARM_CPU,
> -    .endianness = ENDIAN_MODE_LITTLE,
> -    .page_bits_vary = true,
> -    .page_bits_init = TARGET_PAGE_BITS_LEGACY,
> -};
> -
> -target_info_init(target_info_arm_system)
> diff --git a/configs/targets/meson.build b/configs/targets/meson.build
> deleted file mode 100644
> index 2ab4d27eaf5..00000000000
> --- a/configs/targets/meson.build
> +++ /dev/null
> @@ -1,6 +0,0 @@
> -foreach target : [
> -      'arm-softmmu', 'aarch64-softmmu',
> -      'riscv32-softmmu', 'riscv64-softmmu'
> -  ]
> -  config_target_info += {target : files(target + '.c')}
> -endforeach
> diff --git a/configs/targets/riscv32-softmmu.c b/configs/targets/riscv32-softmmu.c
> deleted file mode 100644
> index 0829ab84de5..00000000000
> --- a/configs/targets/riscv32-softmmu.c
> +++ /dev/null
> @@ -1,24 +0,0 @@
> -/*
> - * QEMU binary/target API (qemu-system-riscv32)
> - *
> - *  Copyright (c) rev.ng Labs Srl.
> - *
> - * SPDX-License-Identifier: GPL-2.0-or-later
> - */
> -
> -#include "qemu/osdep.h"
> -#include "qemu/target-info-impl.h"
> -#include "qemu/target-info-init.h"
> -#include "target/riscv/cpu-qom.h"
> -#include "target/riscv/cpu-param.h"
> -
> -static const TargetInfo target_info_riscv32_system = {
> -    .target_name = "riscv32",
> -    .target_arch = SYS_EMU_TARGET_RISCV32,
> -    .long_bits = 32,
> -    .cpu_type = TYPE_RISCV_CPU,
> -    .endianness = ENDIAN_MODE_LITTLE,
> -    .page_bits_init = TARGET_PAGE_BITS,
> -};
> -
> -target_info_init(target_info_riscv32_system)
> diff --git a/configs/targets/riscv64-softmmu.c b/configs/targets/riscv64-softmmu.c
> deleted file mode 100644
> index 553bd1f75fe..00000000000
> --- a/configs/targets/riscv64-softmmu.c
> +++ /dev/null
> @@ -1,24 +0,0 @@
> -/*
> - * QEMU binary/target API (qemu-system-riscv64)
> - *
> - *  Copyright (c) rev.ng Labs Srl.
> - *
> - * SPDX-License-Identifier: GPL-2.0-or-later
> - */
> -
> -#include "qemu/osdep.h"
> -#include "qemu/target-info-impl.h"
> -#include "qemu/target-info-init.h"
> -#include "target/riscv/cpu-qom.h"
> -#include "target/riscv/cpu-param.h"
> -
> -static const TargetInfo target_info_riscv64_system = {
> -    .target_name = "riscv64",
> -    .target_arch = SYS_EMU_TARGET_RISCV64,
> -    .long_bits = 64,
> -    .cpu_type = TYPE_RISCV_CPU,
> -    .endianness = ENDIAN_MODE_LITTLE,
> -    .page_bits_init = TARGET_PAGE_BITS,
> -};
> -
> -target_info_init(target_info_riscv64_system)
> diff --git a/meson.build b/meson.build
> index 828100de816..64d3f7675f7 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -3754,7 +3754,6 @@ subdir('dump')
>  subdir('accel')
>  
>  subdir('backends')
> -subdir('configs/targets')
>  subdir('disas')
>  subdir('migration')
>  subdir('monitor')
> @@ -4346,11 +4345,7 @@ foreach target : target_dirs
>      endif
>    endif
>  
> -  if target in config_target_info
> -    arch_srcs += config_target_info[target]
> -  else
> -    arch_srcs += files('target-info-stub.c')
> -  endif
> +  arch_srcs += files('target-info-stub.c')
>  
>    if target_base_arch in target_arch
>      t = target_arch[target_base_arch].apply(config_target, strict: false)

We delayed this patch because initially we thought we might need to add
other things in this struct (per target). However, it was not proven it
was needed, thus I'll pull this.

Thanks,
Pierrick


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

* Re: [PATCH 3/8] target-info: rename target-info-impl.h to target-info-def.h
  2026-10-07 11:48 ` [PATCH 3/8] target-info: rename target-info-impl.h to target-info-def.h Yonggang Luo
@ 2026-10-07 20:27   ` Pierrick Bouvier
  0 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 20:27 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> Rename the TargetInfo structure header and its include guard.
> 
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
>  include/qemu/{target-info-impl.h => target-info-def.h} | 4 ++--
>  include/qemu/target-info-qom.h                         | 2 +-
>  page-vary-common.c                                     | 2 +-
>  page-vary-system.c                                     | 2 +-
>  target-info-def.c                                      | 2 +-
>  target-info-qom.c                                      | 2 +-
>  target-info.c                                          | 2 +-
>  7 files changed, 8 insertions(+), 8 deletions(-)
>  rename include/qemu/{target-info-impl.h => target-info-def.h} (94%)
> 

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 11:48 ` [PATCH 4/8] target-info: replace QOM registration with a constructor list Yonggang Luo
@ 2026-10-07 20:29   ` Pierrick Bouvier
  2026-10-07 20:50     ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 20:29 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> Register target definitions through constructors instead of
> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
> available on entry to main(), without explicit initialization or a
> call to module_call_init(MODULE_INIT_QOM).
> 
> Keep the target list sorted by target_arch and default to its first
> entry. Provide an unknown TargetInfo fallback for target-independent
> tools such as qemu-img and unit tests that link no target-info-def.c
> objects.
> 
> Remove the obsolete QOM target-info registration infrastructure and
> update the multi-target test to inspect target information before
> initializing QOM.
> 
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
>  include/qemu/module.h           |  1 -
>  include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
>  include/qemu/target-info-init.h | 53 ----------------------------
>  include/qemu/target-info-qom.h  | 31 -----------------
>  include/qemu/target-info.h      |  9 +++++
>  meson.build                     |  6 ++--
>  system/vl.c                     |  4 ---
>  target-info-def.c               |  1 -
>  target-info-qom.c               | 60 --------------------------------
>  target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
>  tests/qtest/fuzz/fuzz.c         |  3 --
>  tests/unit/test-multi-target.c  | 12 +++----
>  12 files changed, 129 insertions(+), 168 deletions(-)
>  delete mode 100644 include/qemu/target-info-init.h
>  delete mode 100644 include/qemu/target-info-qom.h
>  delete mode 100644 target-info-qom.c
> 

This approach (custom list based) was considered before implementing
things with QOM Types. The rationale I followed was that if everything
is in QOM, we might better follow that for consistency sake.
Yes, the compromise if that we need an extra init step, but it was not a
problem to add it.

Is there another good value this list approach brings compared to what
exists?

Regards,
Pierrick


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

* Re: [PATCH 6/8] meson: load all target .mak files into target_mak_all
  2026-10-07 11:48 ` [PATCH 6/8] meson: load all target .mak files into target_mak_all Yonggang Luo
@ 2026-10-07 20:30   ` Pierrick Bouvier
  0 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 20:30 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> Load every configs/targets/*.mak once into target_mak_all, keyed by
> target_dirs_all, with TARGET_BASE_ARCH defaulted to TARGET_ARCH. The
> per-target loop now takes its config from target_mak_all instead of
> loading the file again.
> 
> target_dirs is still the --target-list filtered subset and is the only
> list built. target_mak_all is for later use by code that needs target
> properties independent of --target-list, such as generating
> TargetInfo helpers for every target.
> 
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
>  meson.build | 20 ++++++++++++++++----
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/meson.build b/meson.build
> index fd7a4f68389..d070dafe2a9 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -3239,6 +3239,21 @@ config_target_mak = {}
>  config_base_arch_mak = {}
>  config_target_info = {}
>  
> +# Load every configs/targets/*.mak unconditionally; target_dirs is the
> +# --target-list filtered subset of target_dirs_all.
> +target_dirs_all = run_command(python, '-c',
> +  'import os, sys; print(" ".join(sorted(f[:-4] for f in os.listdir(sys.argv[1]) if f.endswith(".mak"))))',
> +  meson.current_source_dir() / 'configs/targets',
> +  check: true).stdout().split()
> +target_mak_all = {}
> +foreach target : target_dirs_all
> +  mak = keyval.load('configs/targets' / target + '.mak')
> +  if 'TARGET_BASE_ARCH' not in mak
> +    mak += {'TARGET_BASE_ARCH': mak['TARGET_ARCH']}
> +  endif
> +  target_mak_all += {target: mak}
> +endforeach
> +
>  disassemblers = {
>    'alpha' : ['CONFIG_ALPHA_DIS'],
>    'avr' : ['CONFIG_AVR_DIS'],
> @@ -3318,7 +3333,7 @@ foreach target : target_dirs
>      }
>    endif
>  
> -  config_target += keyval.load('configs/targets' / target + '.mak')
> +  config_target += target_mak_all[target]
>  
>    target_kconfig = []
>    foreach sym: accelerators
> @@ -3348,9 +3363,6 @@ foreach target : target_dirs
>  
>    # Add default keys
>    config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
> -  if 'TARGET_BASE_ARCH' not in config_target
> -    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
> -  endif
>    if 'TARGET_ABI_DIR' not in config_target
>      config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
>    endif

What is the goal of this patch?
In case it's to simplify further patches, if a script can read one .mak
files, it can probably read several also.

Regards,
Pierrick


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

* Re: [PATCH 7/8] target-info: Replace handwritten architecture checks with generated code
  2026-10-07 11:48 ` [PATCH 7/8] target-info: Replace handwritten architecture checks with generated code Yonggang Luo
@ 2026-10-07 20:36   ` Pierrick Bouvier
  0 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 20:36 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> Add scripts/gen-target-info.py to generate declarations and definitions
> for exact-target and base-family architecture checks from system target
> names and their TARGET_BASE_ARCH values.
> 
> Provide target_is_<arch>() and target_is_base_<family>() checks for an
> explicit TargetInfo. Retain target_<arch>() and target_base_<family>()
> as wrappers using the current target.
> 
> Wire the generator into Meson using all system target definitions so
> the available checks do not depend on --target-list.
> 
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
>  include/qemu/target-info.h | 76 ++++-------------------------
>  meson.build                | 16 ++++++
>  scripts/gen-target-info.py | 99 ++++++++++++++++++++++++++++++++++++++
>  target-info.c              | 62 +-----------------------
>  4 files changed, 125 insertions(+), 128 deletions(-)
>  create mode 100644 scripts/gen-target-info.py
> 

If I had to pick between simple and manual boilerplate, and a python
script generating C code, I would tend to choose the former.
In this case, the set of targets is bounded, so manual code is really
the way to go for me.

If the repetition is really unbearable, macros are a way to deal with
this. However, note that we will not need all the target_X to be
defined, so I would prefer to not see any new variant added as long as
it's not used.

Regards,
Pierrick


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-07 11:48 ` [PATCH 8/8] qom: pass TargetInfo to is_available for later use Yonggang Luo
@ 2026-10-07 20:44   ` Pierrick Bouvier
  2026-10-07 21:42     ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 20:44 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> Change TypeInfo.is_available to the new TypeIsAvailable type, which
> takes a const TargetInfo *. Registration passes target_info(), so
> behavior is unchanged. object.h only forward-declares TargetInfo.
> 
> Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
> generated machine parents to the matching target_is_<arch> helpers.
> 
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
>  hw/arm/aspeed_ast27x0-fc.c  |  2 +-
>  hw/arm/aspeed_ast27x0_evb.c |  4 ++--
>  hw/arm/raspi.c              |  4 ++--
>  hw/arm/raspi4b.c            |  2 +-
>  hw/arm/virt.c               |  4 ++--
>  hw/m68k/virt.c              |  4 ++--
>  hw/or1k/virt.c              |  2 +-
>  include/qom/object.h        | 12 +++++++++++-
>  qom/object.c                |  3 ++-
>  9 files changed, 24 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
> index 73362b60d2a..8a7c6a116ac 100644
> --- a/hw/arm/aspeed_ast27x0-fc.c
> +++ b/hw/arm/aspeed_ast27x0-fc.c
> @@ -234,7 +234,7 @@ static const TypeInfo ast2700fc_types[] = {
>          .parent         = TYPE_MACHINE,
>          .class_init     = ast2700fc_class_init,
>          .instance_size  = sizeof(Ast2700FCState),
> -        .is_available   = target_aarch64,
> +        .is_available   = target_is_aarch64,
>      },
>  };
>  
> diff --git a/hw/arm/aspeed_ast27x0_evb.c b/hw/arm/aspeed_ast27x0_evb.c
> index 460c9ff0d2e..02a8cff1d9d 100644
> --- a/hw/arm/aspeed_ast27x0_evb.c
> +++ b/hw/arm/aspeed_ast27x0_evb.c
> @@ -75,13 +75,13 @@ static const TypeInfo aspeed_ast27x0_evb_types[] = {
>          .name          = MACHINE_TYPE_NAME("ast2700a1-evb"),
>          .parent        = TYPE_ASPEED_MACHINE,
>          .class_init    = aspeed_machine_ast2700a1_evb_class_init,
> -        .is_available  = target_aarch64,
> +        .is_available  = target_is_aarch64,
>      },
>      {
>          .name          = MACHINE_TYPE_NAME("ast2700a2-evb"),
>          .parent        = TYPE_ASPEED_MACHINE,
>          .class_init    = aspeed_machine_ast2700a2_evb_class_init,
> -        .is_available  = target_aarch64,
> +        .is_available  = target_is_aarch64,
>      }
>  };
>  
> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
> index fadbacb2534..22b06c6ca22 100644
> --- a/hw/arm/raspi.c
> +++ b/hw/arm/raspi.c
> @@ -403,12 +403,12 @@ static const TypeInfo raspi_machine_types[] = {
>          .name           = MACHINE_TYPE_NAME("raspi3ap"),
>          .parent         = TYPE_RASPI_MACHINE,
>          .class_init     = raspi3ap_machine_class_init,
> -        .is_available   = target_aarch64,
> +        .is_available   = target_is_aarch64,
>      }, {
>          .name           = MACHINE_TYPE_NAME("raspi3b"),
>          .parent         = TYPE_RASPI_MACHINE,
>          .class_init     = raspi3b_machine_class_init,
> -        .is_available   = target_aarch64,
> +        .is_available   = target_is_aarch64,
>      }, {
>          .name           = TYPE_RASPI_MACHINE,
>          .parent         = TYPE_RASPI_BASE_MACHINE,
> diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
> index 566d64572db..a1dc477f25e 100644
> --- a/hw/arm/raspi4b.c
> +++ b/hw/arm/raspi4b.c
> @@ -121,7 +121,7 @@ static const TypeInfo raspi4b_machine_type = {
>      .parent         = TYPE_RASPI_BASE_MACHINE,
>      .instance_size  = sizeof(Raspi4bMachineState),
>      .class_init     = raspi4b_machine_class_init,
> -    .is_available   = target_aarch64,
> +    .is_available   = target_is_aarch64,
>  };
>  
>  static void raspi4b_machine_register_type(void)
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 9d192515d85..18160f7fad3 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -132,7 +132,7 @@ static void arm_virt_compat_default_set(MachineClass *mc)
>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
>          .parent = TYPE_VIRT_MACHINE, \
>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
> -        .is_available = target_base_arm, \
> +        .is_available = target_is_base_arm, \
>      }; \
>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
>      { \
> @@ -4430,7 +4430,7 @@ static const TypeInfo virt_machine_info = {
>           { TYPE_HOTPLUG_HANDLER },
>           { }
>      },
> -    .is_available = target_base_arm,
> +    .is_available = target_is_base_arm,
>  };
>  
>  static void machvirt_machine_init(void)
> diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
> index e52546e4fab..ad2a43ef3fb 100644
> --- a/hw/m68k/virt.c
> +++ b/hw/m68k/virt.c
> @@ -327,7 +327,7 @@ static const TypeInfo virt_machine_info = {
>      .parent       = TYPE_MACHINE,
>      .abstract     = true,
>      .class_init   = virt_machine_class_init,
> -    .is_available = target_m68k,
> +    .is_available = target_is_m68k,
>  };
>  
>  static void virt_machine_register_types(void)
> @@ -355,7 +355,7 @@ type_init(virt_machine_register_types)
>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
>          .parent = MACHINE_TYPE_NAME("virt"), \
>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
> -        .is_available = target_m68k, \
> +        .is_available = target_is_m68k, \
>      }; \
>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
>      { \
> diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
> index a3ff903839b..89fb786641f 100644
> --- a/hw/or1k/virt.c
> +++ b/hw/or1k/virt.c
> @@ -559,7 +559,7 @@ static const TypeInfo or1ksim_machine_typeinfo = {
>      .parent     = TYPE_MACHINE,
>      .class_init = openrisc_virt_machine_init,
>      .instance_size = sizeof(OR1KVirtState),
> -    .is_available = target_or1k,
> +    .is_available = target_is_or1k,
>  };
>  
>  static void or1ksim_machine_init_register_types(void)
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 4c0645817a5..7d52a15f6b8 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -17,6 +17,7 @@
>  #include "qapi/qapi-builtin-types.h"
>  #include "qemu/module.h"
>  
> +typedef struct TargetInfo TargetInfo;
>  struct TypeImpl;
>  typedef struct TypeImpl *Type;
>  
> @@ -117,6 +118,15 @@ typedef void (ObjectUnparent)(Object *obj);
>   */
>  typedef void (ObjectFree)(void *obj);
>  
> +/**
> + * typedef TypeIsAvailable:
> + * @ti: TargetInfo to test.
> + *
> + * Returns whether a type is available for @ti. Typical implementations
> + * are target_is_*().
> + */
> +typedef bool (TypeIsAvailable)(const TargetInfo *ti);
> +
>  #define OBJECT_CLASS_CAST_CACHE 4
>  
>  /**
> @@ -498,7 +508,7 @@ struct TypeInfo
>      void (*class_base_init)(ObjectClass *klass, const void *data);
>      const void *class_data;
>  
> -    bool (*is_available)(void);
> +    TypeIsAvailable *is_available;
>      const InterfaceInfo *interfaces;
>  };
>  
> diff --git a/qom/object.c b/qom/object.c
> index 96498f3d001..253b9562b41 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -15,6 +15,7 @@
>  #include "qom/compat-properties.h"
>  #include "qom/object.h"
>  #include "qom/object_interfaces.h"
> +#include "qemu/target-info.h"
>  #include "qemu/cutils.h"
>  #include "qemu/memalign.h"
>  #include "qapi/visitor.h"
> @@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
>          abort();
>      }
>  
> -    if (info->is_available && !info->is_available()) {
> +    if (info->is_available && !info->is_available(target_info())) {
>          return NULL;
>      }
>  

```
info->is_available(target_info())
```

or

```
is_available() {
  TargetInfo ti * = target_info();
  ...
}
```

Are doing the exact same thing today.

So what is the future goal requiring to introduce this?

It's something we asked multiple times, and until we don't have a short
series doing this change + a single and minimal modification showing the
reason, I will still be asking.

If the goal is to implement some sort of classification for
machines/cpus, I would suggest to just send a simple series doing this
change (and only this - no additional cleanups/refactoring), and an
example for a single machine + cpu, so we can talk about it.

Regards,
Pierrick


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
                   ` (8 preceding siblings ...)
  2026-10-07 20:25 ` [PATCH 0/8] qom: pass TargetInfo to the is_available callback Pierrick Bouvier
@ 2026-10-07 20:46 ` Pierrick Bouvier
  2026-10-09 21:58   ` Pierrick Bouvier
  9 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 20:46 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> This allows a combined binary to register machine types from all its targets.
> Consequently, QMP `query-machines` can return machine entries from every
> target, even when `none` is selected. For example, a client can query the
> combined machine list with:
> 
> ```json
> { "execute": "query-machines" }
> ```
> 
> The returned list includes the registered machine classes from all linked
> targets. This is separate from selecting a machine: with `-target none`,
> `-M virt` reports the targets that provide `virt` instead of choosing one
> arbitrarily:
> 
> ```text
> qemu-system -target none -M virt
> unsupported machine type: "virt" for target "none"
> Available for targets:
>   aarch64
>   arm
> ```
> 
> It moves target_info() to a shared location so object.c can call it when
> checking machine availability. The series also replaces QOM-based target-info
> registration with a constructor list and passes TargetInfo to the
> is_available callback.
> 
> Target metadata and architecture checks are generated from the configured
> targets, there is too much arch to write biiolperate code. doing this for easier
> Add TargetInfo* to is_available
> 
> The target-info API and implementation are shared, rather than compiled
> separately for every target.
> 
> This series removes the per-target source files "configs/targets/*.c".
> Their target-specific parameters are collected in a generated
> target-info-def.c for each softmmu target. This lays the groundwork for
> QEMU system builds in which target-info-def.c is the only target-specific
> source file compiled for each target. Using the same filename lets
> meson.build handle these definitions uniformly.
> 
> The series adds unit-test coverage for target info and multi-target builds.
> 
> Pierrick Bouvier (2):
>   configs/targets: remove target info definitions
>   target-info: rename target-info-stub.c in target-info-def.c
> 
> Yonggang Luo (6):
>   target-info: rename target-info-impl.h to target-info-def.h
>   target-info: replace QOM registration with a constructor list
>   tests/unit: add target-info coverage for multi-target builds
>   meson: load all target .mak files into target_mak_all
>   target-info: Replace handwritten architecture checks with generated
>     code
>   qom: pass TargetInfo to is_available for later use
> 
>  MAINTAINERS                             |   2 +-
>  configs/targets/aarch64-softmmu.c       |  25 ------
>  configs/targets/arm-softmmu.c           |  25 ------
>  configs/targets/meson.build             |   6 --
>  configs/targets/riscv32-softmmu.c       |  24 -----
>  configs/targets/riscv64-softmmu.c       |  24 -----
>  hw/arm/aspeed_ast27x0-fc.c              |   2 +-
>  hw/arm/aspeed_ast27x0_evb.c             |   4 +-
>  hw/arm/raspi.c                          |   4 +-
>  hw/arm/raspi4b.c                        |   2 +-
>  hw/arm/virt.c                           |   4 +-
>  hw/m68k/virt.c                          |   4 +-
>  hw/or1k/virt.c                          |   2 +-
>  include/hw/core/cpu.h                   |   2 +-
>  include/qemu/module.h                   |   1 -
>  include/qemu/target-info-def.h          |  88 ++++++++++++++++++
>  include/qemu/target-info-impl.h         |  42 ---------
>  include/qemu/target-info-init.h         |  53 -----------
>  include/qemu/target-info-qom.h          |  31 -------
>  include/qemu/target-info.h              |  87 ++++--------------
>  include/qom/object.h                    |  12 ++-
>  meson.build                             |  52 ++++++++---
>  page-vary-common.c                      |   2 +-
>  page-vary-system.c                      |   2 +-
>  qom/object.c                            |   3 +-
>  scripts/gen-target-info.py              |  99 ++++++++++++++++++++
>  system/vl.c                             |   4 -
>  target-info-stub.c => target-info-def.c |   3 +-
>  target-info-qom.c                       |  60 -------------
>  target-info.c                           | 115 ++++++++++++------------
>  tests/qtest/fuzz/fuzz.c                 |   3 -
>  tests/unit/meson.build                  |   4 +
>  tests/unit/test-multi-target.c          |  12 +--
>  tests/unit/test-target-info.c           |  38 ++++++++
>  34 files changed, 379 insertions(+), 462 deletions(-)
>  delete mode 100644 configs/targets/aarch64-softmmu.c
>  delete mode 100644 configs/targets/arm-softmmu.c
>  delete mode 100644 configs/targets/meson.build
>  delete mode 100644 configs/targets/riscv32-softmmu.c
>  delete mode 100644 configs/targets/riscv64-softmmu.c
>  create mode 100644 include/qemu/target-info-def.h
>  delete mode 100644 include/qemu/target-info-impl.h
>  delete mode 100644 include/qemu/target-info-init.h
>  delete mode 100644 include/qemu/target-info-qom.h
>  create mode 100644 scripts/gen-target-info.py
>  rename target-info-stub.c => target-info-def.c (94%)
>  delete mode 100644 target-info-qom.c
>  create mode 100644 tests/unit/test-target-info.c
> 

I'll pull the first three patches.

Regards,
Pierrick


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 20:29   ` Pierrick Bouvier
@ 2026-10-07 20:50     ` Yonggang Luo
  2026-10-07 22:31       ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 20:50 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> > Register target definitions through constructors instead of
> > MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
> > available on entry to main(), without explicit initialization or a
> > call to module_call_init(MODULE_INIT_QOM).
> >
> > Keep the target list sorted by target_arch and default to its first
> > entry. Provide an unknown TargetInfo fallback for target-independent
> > tools such as qemu-img and unit tests that link no target-info-def.c
> > objects.
> >
> > Remove the obsolete QOM target-info registration infrastructure and
> > update the multi-target test to inspect target information before
> > initializing QOM.
> >
> > Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> > ---
> >  include/qemu/module.h           |  1 -
> >  include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
> >  include/qemu/target-info-init.h | 53 ----------------------------
> >  include/qemu/target-info-qom.h  | 31 -----------------
> >  include/qemu/target-info.h      |  9 +++++
> >  meson.build                     |  6 ++--
> >  system/vl.c                     |  4 ---
> >  target-info-def.c               |  1 -
> >  target-info-qom.c               | 60 --------------------------------
> >  target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
> >  tests/qtest/fuzz/fuzz.c         |  3 --
> >  tests/unit/test-multi-target.c  | 12 +++----
> >  12 files changed, 129 insertions(+), 168 deletions(-)
> >  delete mode 100644 include/qemu/target-info-init.h
> >  delete mode 100644 include/qemu/target-info-qom.h
> >  delete mode 100644 target-info-qom.c
> >
>
> This approach (custom list based) was considered before implementing
> things with QOM Types. The rationale I followed was that if everything
> is in QOM, we might better follow that for consistency sake.
> Yes, the compromise if that we need an extra init step, but it was not a
> problem to add it.
I have issue to add the init step for unit-tests, and hard to write the -target
parse procedure and get it right. Not means this won't work. but for
me, too much
coupled.

If we treat target_info as a QOM, but QOM needs target_info to set
up(is_avaible). That makes
the init sequence too much of a burden.


is_available is depends on target_arch
And before this patch, target_arch depends on QOM, pulls user/softmmu because
target_info_init. By moving target-info to be a custom list based, we
can decouple
target-info from qom/softmmu/user. and target-info will always
available once "main(argv, argc)" is entered. We also have the
advantage of doing all sorts
of tests against it.


Tools such as qemu-img and unit tests may link target-info.c without any
target-info-def.c objects. Their target list remains empty, so use this
fallback.


static TypeImpl *type_register_internal(const TypeInfo *info)
{
    TypeImpl *ti;

    if (!type_name_is_valid(info->name)) {
        fprintf(stderr, "Registering '%s' with illegal type name\n",
info->name);
        abort();
    }

    if (info->is_available && !info->is_available()) {
        return NULL;
    }

    ti = type_new(info);

    type_table_add(ti);
    return ti;
}

>
> Is there another good value this list approach brings compared to what
> exists?
>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-07 20:44   ` Pierrick Bouvier
@ 2026-10-07 21:42     ` Yonggang Luo
  2026-10-08  0:00       ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 21:42 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Thu, Oct 8, 2026 at 4:44 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> > Change TypeInfo.is_available to the new TypeIsAvailable type, which
> > takes a const TargetInfo *. Registration passes target_info(), so
> > behavior is unchanged. object.h only forward-declares TargetInfo.
> >
> > Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
> > generated machine parents to the matching target_is_<arch> helpers.
> >
> > Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> > ---
> >  hw/arm/aspeed_ast27x0-fc.c  |  2 +-
> >  hw/arm/aspeed_ast27x0_evb.c |  4 ++--
> >  hw/arm/raspi.c              |  4 ++--
> >  hw/arm/raspi4b.c            |  2 +-
> >  hw/arm/virt.c               |  4 ++--
> >  hw/m68k/virt.c              |  4 ++--
> >  hw/or1k/virt.c              |  2 +-
> >  include/qom/object.h        | 12 +++++++++++-
> >  qom/object.c                |  3 ++-
> >  9 files changed, 24 insertions(+), 13 deletions(-)
> >
> > diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
> > index 73362b60d2a..8a7c6a116ac 100644
> > --- a/hw/arm/aspeed_ast27x0-fc.c
> > +++ b/hw/arm/aspeed_ast27x0-fc.c
> > @@ -234,7 +234,7 @@ static const TypeInfo ast2700fc_types[] = {
> >          .parent         = TYPE_MACHINE,
> >          .class_init     = ast2700fc_class_init,
> >          .instance_size  = sizeof(Ast2700FCState),
> > -        .is_available   = target_aarch64,
> > +        .is_available   = target_is_aarch64,
> >      },
> >  };
> >
> > diff --git a/hw/arm/aspeed_ast27x0_evb.c b/hw/arm/aspeed_ast27x0_evb.c
> > index 460c9ff0d2e..02a8cff1d9d 100644
> > --- a/hw/arm/aspeed_ast27x0_evb.c
> > +++ b/hw/arm/aspeed_ast27x0_evb.c
> > @@ -75,13 +75,13 @@ static const TypeInfo aspeed_ast27x0_evb_types[] = {
> >          .name          = MACHINE_TYPE_NAME("ast2700a1-evb"),
> >          .parent        = TYPE_ASPEED_MACHINE,
> >          .class_init    = aspeed_machine_ast2700a1_evb_class_init,
> > -        .is_available  = target_aarch64,
> > +        .is_available  = target_is_aarch64,
> >      },
> >      {
> >          .name          = MACHINE_TYPE_NAME("ast2700a2-evb"),
> >          .parent        = TYPE_ASPEED_MACHINE,
> >          .class_init    = aspeed_machine_ast2700a2_evb_class_init,
> > -        .is_available  = target_aarch64,
> > +        .is_available  = target_is_aarch64,
> >      }
> >  };
> >
> > diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
> > index fadbacb2534..22b06c6ca22 100644
> > --- a/hw/arm/raspi.c
> > +++ b/hw/arm/raspi.c
> > @@ -403,12 +403,12 @@ static const TypeInfo raspi_machine_types[] = {
> >          .name           = MACHINE_TYPE_NAME("raspi3ap"),
> >          .parent         = TYPE_RASPI_MACHINE,
> >          .class_init     = raspi3ap_machine_class_init,
> > -        .is_available   = target_aarch64,
> > +        .is_available   = target_is_aarch64,
> >      }, {
> >          .name           = MACHINE_TYPE_NAME("raspi3b"),
> >          .parent         = TYPE_RASPI_MACHINE,
> >          .class_init     = raspi3b_machine_class_init,
> > -        .is_available   = target_aarch64,
> > +        .is_available   = target_is_aarch64,
> >      }, {
> >          .name           = TYPE_RASPI_MACHINE,
> >          .parent         = TYPE_RASPI_BASE_MACHINE,
> > diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
> > index 566d64572db..a1dc477f25e 100644
> > --- a/hw/arm/raspi4b.c
> > +++ b/hw/arm/raspi4b.c
> > @@ -121,7 +121,7 @@ static const TypeInfo raspi4b_machine_type = {
> >      .parent         = TYPE_RASPI_BASE_MACHINE,
> >      .instance_size  = sizeof(Raspi4bMachineState),
> >      .class_init     = raspi4b_machine_class_init,
> > -    .is_available   = target_aarch64,
> > +    .is_available   = target_is_aarch64,
> >  };
> >
> >  static void raspi4b_machine_register_type(void)
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index 9d192515d85..18160f7fad3 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -132,7 +132,7 @@ static void arm_virt_compat_default_set(MachineClass *mc)
> >          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
> >          .parent = TYPE_VIRT_MACHINE, \
> >          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
> > -        .is_available = target_base_arm, \
> > +        .is_available = target_is_base_arm, \
> >      }; \
> >      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
> >      { \
> > @@ -4430,7 +4430,7 @@ static const TypeInfo virt_machine_info = {
> >           { TYPE_HOTPLUG_HANDLER },
> >           { }
> >      },
> > -    .is_available = target_base_arm,
> > +    .is_available = target_is_base_arm,
> >  };
> >
> >  static void machvirt_machine_init(void)
> > diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
> > index e52546e4fab..ad2a43ef3fb 100644
> > --- a/hw/m68k/virt.c
> > +++ b/hw/m68k/virt.c
> > @@ -327,7 +327,7 @@ static const TypeInfo virt_machine_info = {
> >      .parent       = TYPE_MACHINE,
> >      .abstract     = true,
> >      .class_init   = virt_machine_class_init,
> > -    .is_available = target_m68k,
> > +    .is_available = target_is_m68k,
> >  };
> >
> >  static void virt_machine_register_types(void)
> > @@ -355,7 +355,7 @@ type_init(virt_machine_register_types)
> >          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
> >          .parent = MACHINE_TYPE_NAME("virt"), \
> >          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
> > -        .is_available = target_m68k, \
> > +        .is_available = target_is_m68k, \
> >      }; \
> >      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
> >      { \
> > diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
> > index a3ff903839b..89fb786641f 100644
> > --- a/hw/or1k/virt.c
> > +++ b/hw/or1k/virt.c
> > @@ -559,7 +559,7 @@ static const TypeInfo or1ksim_machine_typeinfo = {
> >      .parent     = TYPE_MACHINE,
> >      .class_init = openrisc_virt_machine_init,
> >      .instance_size = sizeof(OR1KVirtState),
> > -    .is_available = target_or1k,
> > +    .is_available = target_is_or1k,
> >  };
> >
> >  static void or1ksim_machine_init_register_types(void)
> > diff --git a/include/qom/object.h b/include/qom/object.h
> > index 4c0645817a5..7d52a15f6b8 100644
> > --- a/include/qom/object.h
> > +++ b/include/qom/object.h
> > @@ -17,6 +17,7 @@
> >  #include "qapi/qapi-builtin-types.h"
> >  #include "qemu/module.h"
> >
> > +typedef struct TargetInfo TargetInfo;
> >  struct TypeImpl;
> >  typedef struct TypeImpl *Type;
> >
> > @@ -117,6 +118,15 @@ typedef void (ObjectUnparent)(Object *obj);
> >   */
> >  typedef void (ObjectFree)(void *obj);
> >
> > +/**
> > + * typedef TypeIsAvailable:
> > + * @ti: TargetInfo to test.
> > + *
> > + * Returns whether a type is available for @ti. Typical implementations
> > + * are target_is_*().
> > + */
> > +typedef bool (TypeIsAvailable)(const TargetInfo *ti);
> > +
> >  #define OBJECT_CLASS_CAST_CACHE 4
> >
> >  /**
> > @@ -498,7 +508,7 @@ struct TypeInfo
> >      void (*class_base_init)(ObjectClass *klass, const void *data);
> >      const void *class_data;
> >
> > -    bool (*is_available)(void);
> > +    TypeIsAvailable *is_available;
> >      const InterfaceInfo *interfaces;
> >  };
> >
> > diff --git a/qom/object.c b/qom/object.c
> > index 96498f3d001..253b9562b41 100644
> > --- a/qom/object.c
> > +++ b/qom/object.c
> > @@ -15,6 +15,7 @@
> >  #include "qom/compat-properties.h"
> >  #include "qom/object.h"
> >  #include "qom/object_interfaces.h"
> > +#include "qemu/target-info.h"
> >  #include "qemu/cutils.h"
> >  #include "qemu/memalign.h"
> >  #include "qapi/visitor.h"
> > @@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
> >          abort();
> >      }
> >
> > -    if (info->is_available && !info->is_available()) {
> > +    if (info->is_available && !info->is_available(target_info())) {
> >          return NULL;
> >      }
> >
>
> ```
> info->is_available(target_info())
> ```
>
> or
>
> ```
> is_available() {
>   TargetInfo ti * = target_info();
>   ...
> }
> ```
>
> Are doing the exact same thing today.
>
> So what is the future goal requiring to introduce this?

From Daniel P. Berrangé's
requesthttps://lore.kernel.org/qemu-devel/apAszS1ewxM0Y1XU@redhat.com/
        I forgot to mention that this is also pretty important for making
        introspection work, as we need to be able to say

          'qemu-system --machine none -qmp ...'

        and connect to QMP to introspect the binary. Having to add a
        '--target <name>' into that mix is undesirable, as it creates
        a chicken & egg problem. You don't know what targets are built
        into qemu-system without introspecting it and you can't
        introspect it without selecting a target to introspect.

From Pierrick's review
https://lore.kernel.org/qemu-devel/557262df-b8e7-49b5-a245-ae46b8885b30@oss.qualcomm.com/So,
for existing binary: -M virt works as before.

        For new multi binary:
        $ qemu-system -M virt:
        Multiple machines were found, select one among:
        - aarch64-virt
        - riscv64-virt

        Does it matches what you would expect?

From Daniel's review
https://lore.kernel.org/qemu-devel/aro93NuZBXYGbD33@redhat.com/
        We already have  'QemuTargetInfo' struct which is used
        with 'query-target', that should also be used with the
        new 'query-targets' command.

        We need to add the 'endianness' field to QemuTargetInfo.

        I don't think that we need to report machines though.
        We already have 'query-machines' which gives much broader
        information on the machines. "MachineInfo" needs to
        gain

        "targets": ["SysEmuTarget"]

        to list which target(s) a machine can be used with.


To achieve these, we needs add TypeInfo parameter to it so that we can do

static void report_unsupported_machine_type(const char *name, Error **errp)
{
    g_autoptr(GSList) machines = machine_class_get_list(true);
    g_autoptr(GString) targets = g_string_new(NULL);
    TargetInfoNode *node;
    GSList *el;

    error_setg(errp, "unsupported machine type: \"%s\" for target \"%s\"",
               name, target_name());
    QLIST_FOREACH(node, target_info_list(), next) {
        for (el = machines; el; el = el->next) {
            MachineClass *mc = el->data;

            if ((!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) &&
                object_class_get_is_available(OBJECT_CLASS(mc))(node->info)) {
                g_string_append_printf(targets, "  %s\n",
                                       node->info->target_name);
                break;
            }
        }
    }
    if (targets->len) {
        error_append_hint(errp, "Available for targets:\n%s", targets->str);
    }
}

That is we can iterate on all target-list, and check if it's can be fitlered.


>
> It's something we asked multiple times, and until we don't have a short
> series doing this change + a single and minimal modification showing the
> reason, I will still be asking.
>
> If the goal is to implement some sort of classification for
> machines/cpus, I would suggest to just send a simple series doing this
> change (and only this - no additional cleanups/refactoring), and an
> example for a single machine + cpu, so we can talk about it.
>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 20:50     ` Yonggang Luo
@ 2026-10-07 22:31       ` Pierrick Bouvier
  2026-10-07 22:54         ` Yonggang Luo
  2026-10-07 23:02         ` Yonggang Luo
  0 siblings, 2 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 22:31 UTC (permalink / raw)
  To: luoyonggang
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 1:50 PM, Yonggang Luo wrote:
> On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
>>> Register target definitions through constructors instead of
>>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
>>> available on entry to main(), without explicit initialization or a
>>> call to module_call_init(MODULE_INIT_QOM).
>>>
>>> Keep the target list sorted by target_arch and default to its first
>>> entry. Provide an unknown TargetInfo fallback for target-independent
>>> tools such as qemu-img and unit tests that link no target-info-def.c
>>> objects.
>>>
>>> Remove the obsolete QOM target-info registration infrastructure and
>>> update the multi-target test to inspect target information before
>>> initializing QOM.
>>>
>>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
>>> ---
>>>  include/qemu/module.h           |  1 -
>>>  include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
>>>  include/qemu/target-info-init.h | 53 ----------------------------
>>>  include/qemu/target-info-qom.h  | 31 -----------------
>>>  include/qemu/target-info.h      |  9 +++++
>>>  meson.build                     |  6 ++--
>>>  system/vl.c                     |  4 ---
>>>  target-info-def.c               |  1 -
>>>  target-info-qom.c               | 60 --------------------------------
>>>  target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
>>>  tests/qtest/fuzz/fuzz.c         |  3 --
>>>  tests/unit/test-multi-target.c  | 12 +++----
>>>  12 files changed, 129 insertions(+), 168 deletions(-)
>>>  delete mode 100644 include/qemu/target-info-init.h
>>>  delete mode 100644 include/qemu/target-info-qom.h
>>>  delete mode 100644 target-info-qom.c
>>>
>>
>> This approach (custom list based) was considered before implementing
>> things with QOM Types. The rationale I followed was that if everything
>> is in QOM, we might better follow that for consistency sake.
>> Yes, the compromise if that we need an extra init step, but it was not a
>> problem to add it.
> I have issue to add the init step for unit-tests, and hard to write the -target
> parse procedure and get it right. Not means this won't work. but for
> me, too much
> coupled.
>

We already have such a test upstream:
https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35

The init sequence is quite straightforward:

```
/* initialize target types, and only them */
module_call_init(MODULE_INIT_TARGET_INFO);

/* we can get the list if we want, for -target or any other purpose */
g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);

/* set the global target info from any element in this list */
TargetInfo* ti = ...;
target_info_qom_set_target_info(ti);

/* register rest of QOM types */
module_call_init(MODULE_INIT_QOM);
```

It works fine to implement -target (if we would like to do it), since I
implemented it myself. That was also my initial motivation by the way.

Also, I appreciate that target-info is NULL by default, it crashes
loudly when it has not been set, and make it easy to find who depends on it.

> If we treat target_info as a QOM, but QOM needs target_info to set
> up(is_avaible). That makes
> the init sequence too much of a burden.
>

See sequence above, the solution is to initialize TARGET_INFO first,
before the rest of QOM. You end up with the same result than with a
statically initialized list.

> 
> is_available is depends on target_arch
> And before this patch, target_arch depends on QOM, pulls user/softmmu because
> target_info_init. By moving target-info to be a custom list based, we
> can decouple
> target-info from qom/softmmu/user. and target-info will always
> available once "main(argv, argc)" is entered. We also have the
> advantage of doing all sorts
> of tests against it.
>

Which kind of tests are you trying to add?

For now, the exact list of places where we need to do this initialize
target dance are:
- system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
- tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
- tests/unit/test-multi-target.c:
module_call_init(MODULE_INIT_TARGET_INFO);

If we want more tests, I'm totally ok to move this init code to
target-info.c, and replace call sites if needed.

> 
> Tools such as qemu-img and unit tests may link target-info.c without any
> target-info-def.c objects. Their target list remains empty, so use this
> fallback.
>

Why should this tool get access to target list? qemu-img deals with disk
images, and is unrelated to targets.

> 
> static TypeImpl *type_register_internal(const TypeInfo *info)
> {
>     TypeImpl *ti;
> 
>     if (!type_name_is_valid(info->name)) {
>         fprintf(stderr, "Registering '%s' with illegal type name\n",
> info->name);
>         abort();
>     }
> 
>     if (info->is_available && !info->is_available()) {
>         return NULL;
>     }
> 
>     ti = type_new(info);
> 
>     type_table_add(ti);
>     return ti;
> }
> 
>>
>> Is there another good value this list approach brings compared to what
>> exists?
>>
>> Regards,
>> Pierrick
> 
> 
> 



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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 22:31       ` Pierrick Bouvier
@ 2026-10-07 22:54         ` Yonggang Luo
  2026-10-07 23:24           ` Pierrick Bouvier
  2026-10-07 23:02         ` Yonggang Luo
  1 sibling, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 22:54 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Thu, Oct 8, 2026 at 6:31 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/7/2026 1:50 PM, Yonggang Luo wrote:
> > On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> >>> Register target definitions through constructors instead of
> >>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
> >>> available on entry to main(), without explicit initialization or a
> >>> call to module_call_init(MODULE_INIT_QOM).
> >>>
> >>> Keep the target list sorted by target_arch and default to its first
> >>> entry. Provide an unknown TargetInfo fallback for target-independent
> >>> tools such as qemu-img and unit tests that link no target-info-def.c
> >>> objects.
> >>>
> >>> Remove the obsolete QOM target-info registration infrastructure and
> >>> update the multi-target test to inspect target information before
> >>> initializing QOM.
> >>>
> >>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> >>> ---
> >>>  include/qemu/module.h           |  1 -
> >>>  include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
> >>>  include/qemu/target-info-init.h | 53 ----------------------------
> >>>  include/qemu/target-info-qom.h  | 31 -----------------
> >>>  include/qemu/target-info.h      |  9 +++++
> >>>  meson.build                     |  6 ++--
> >>>  system/vl.c                     |  4 ---
> >>>  target-info-def.c               |  1 -
> >>>  target-info-qom.c               | 60 --------------------------------
> >>>  target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
> >>>  tests/qtest/fuzz/fuzz.c         |  3 --
> >>>  tests/unit/test-multi-target.c  | 12 +++----
> >>>  12 files changed, 129 insertions(+), 168 deletions(-)
> >>>  delete mode 100644 include/qemu/target-info-init.h
> >>>  delete mode 100644 include/qemu/target-info-qom.h
> >>>  delete mode 100644 target-info-qom.c
> >>>
> >>
> >> This approach (custom list based) was considered before implementing
> >> things with QOM Types. The rationale I followed was that if everything
> >> is in QOM, we might better follow that for consistency sake.
> >> Yes, the compromise if that we need an extra init step, but it was not a
> >> problem to add it.
> > I have issue to add the init step for unit-tests, and hard to write the -target
> > parse procedure and get it right. Not means this won't work. but for
> > me, too much
> > coupled.
> >
>
> We already have such a test upstream:
> https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35
>
> The init sequence is quite straightforward:
>
> ```
> /* initialize target types, and only them */
> module_call_init(MODULE_INIT_TARGET_INFO);
>
> /* we can get the list if we want, for -target or any other purpose */
> g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
>
> /* set the global target info from any element in this list */
> TargetInfo* ti = ...;
> target_info_qom_set_target_info(ti);
>
> /* register rest of QOM types */
> module_call_init(MODULE_INIT_QOM);
> ```
>
> It works fine to implement -target (if we would like to do it), since I
> implemented it myself. That was also my initial motivation by the way.
>
> Also, I appreciate that target-info is NULL by default, it crashes
> loudly when it has not been set, and make it easy to find who depends on it.
>
> > If we treat target_info as a QOM, but QOM needs target_info to set
> > up(is_avaible). That makes
> > the init sequence too much of a burden.
> >
>
> See sequence above, the solution is to initialize TARGET_INFO first,
> before the rest of QOM. You end up with the same result than with a
> statically initialized list.
>
> >
> > is_available is depends on target_arch
> > And before this patch, target_arch depends on QOM, pulls user/softmmu because
> > target_info_init. By moving target-info to be a custom list based, we
> > can decouple
> > target-info from qom/softmmu/user. and target-info will always
> > available once "main(argv, argc)" is entered. We also have the
> > advantage of doing all sorts
> > of tests against it.
> >
>
> Which kind of tests are you trying to add?
>
> For now, the exact list of places where we need to do this initialize
> target dance are:
> - system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> - tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> - tests/unit/test-multi-target.c:
> module_call_init(MODULE_INIT_TARGET_INFO);
>
> If we want more tests, I'm totally ok to move this init code to
> target-info.c, and replace call sites if needed.
>
> >
> > Tools such as qemu-img and unit tests may link target-info.c without any
> > target-info-def.c objects. Their target list remains empty, so use this
> > fallback.
> >
>
> Why should this tool get access to target list? qemu-img deals with disk
> images, and is unrelated to targets.
>
> >
> > static TypeImpl *type_register_internal(const TypeInfo *info)
> > {
> >     TypeImpl *ti;
> >
> >     if (!type_name_is_valid(info->name)) {
> >         fprintf(stderr, "Registering '%s' with illegal type name\n",
> > info->name);
> >         abort();
> >     }
> >
> >     if (info->is_available && !info->is_available()) {
> >         return NULL;
> >     }
> >
> >     ti = type_new(info);
> >
> >     type_table_add(ti);
> >     return ti;
> > }
> >
> >>
> >> Is there another good value this list approach brings compared to what
> >> exists?

Sorry, I have to wait for your work to be done first.
I have too many patches depending on this, and it seems hard to
convince you. Let's just keep it as is.
Maybe you can work them out in an easier way.

My work is here.
https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
I am afraid of posting 300 pathces into threads to flood it(and
disturbing yours). So I'll wait for your work first. and resolving
conflicts later, that's really time-consuming.

I did many explanations before. seems my explanation is too bad and
not to give a clean picture for you, let's delay these first.

I only sent these 8 patches for easier review. because too many
patches won't be accepted either.

> >>
> >> Regards,
> >> Pierrick
> >
> >
> >
>


-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 22:31       ` Pierrick Bouvier
  2026-10-07 22:54         ` Yonggang Luo
@ 2026-10-07 23:02         ` Yonggang Luo
  2026-10-07 23:28           ` Pierrick Bouvier
  1 sibling, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-07 23:02 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Thu, Oct 8, 2026 at 6:31 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/7/2026 1:50 PM, Yonggang Luo wrote:
> > On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> >>> Register target definitions through constructors instead of
> >>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
> >>> available on entry to main(), without explicit initialization or a
> >>> call to module_call_init(MODULE_INIT_QOM).
> >>>
> >>> Keep the target list sorted by target_arch and default to its first
> >>> entry. Provide an unknown TargetInfo fallback for target-independent
> >>> tools such as qemu-img and unit tests that link no target-info-def.c
> >>> objects.
> >>>
> >>> Remove the obsolete QOM target-info registration infrastructure and
> >>> update the multi-target test to inspect target information before
> >>> initializing QOM.
> >>>
> >>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> >>> ---
> >>>  include/qemu/module.h           |  1 -
> >>>  include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
> >>>  include/qemu/target-info-init.h | 53 ----------------------------
> >>>  include/qemu/target-info-qom.h  | 31 -----------------
> >>>  include/qemu/target-info.h      |  9 +++++
> >>>  meson.build                     |  6 ++--
> >>>  system/vl.c                     |  4 ---
> >>>  target-info-def.c               |  1 -
> >>>  target-info-qom.c               | 60 --------------------------------
> >>>  target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
> >>>  tests/qtest/fuzz/fuzz.c         |  3 --
> >>>  tests/unit/test-multi-target.c  | 12 +++----
> >>>  12 files changed, 129 insertions(+), 168 deletions(-)
> >>>  delete mode 100644 include/qemu/target-info-init.h
> >>>  delete mode 100644 include/qemu/target-info-qom.h
> >>>  delete mode 100644 target-info-qom.c
> >>>
> >>
> >> This approach (custom list based) was considered before implementing
> >> things with QOM Types. The rationale I followed was that if everything
> >> is in QOM, we might better follow that for consistency sake.
> >> Yes, the compromise if that we need an extra init step, but it was not a
> >> problem to add it.
> > I have issue to add the init step for unit-tests, and hard to write the -target
> > parse procedure and get it right. Not means this won't work. but for
> > me, too much
> > coupled.
> >
>
> We already have such a test upstream:
> https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35
>
> The init sequence is quite straightforward:
>
> ```
> /* initialize target types, and only them */
> module_call_init(MODULE_INIT_TARGET_INFO);
>
> /* we can get the list if we want, for -target or any other purpose */
> g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
>
> /* set the global target info from any element in this list */
> TargetInfo* ti = ...;
> target_info_qom_set_target_info(ti);
>
> /* register rest of QOM types */
> module_call_init(MODULE_INIT_QOM);
> ```
>
> It works fine to implement -target (if we would like to do it), since I
> implemented it myself. That was also my initial motivation by the way.
>
> Also, I appreciate that target-info is NULL by default, it crashes
> loudly when it has not been set, and make it easy to find who depends on it.
>
> > If we treat target_info as a QOM, but QOM needs target_info to set
> > up(is_avaible). That makes
> > the init sequence too much of a burden.
> >
>
> See sequence above, the solution is to initialize TARGET_INFO first,
> before the rest of QOM. You end up with the same result than with a
> statically initialized list.
>
> >
> > is_available is depends on target_arch
> > And before this patch, target_arch depends on QOM, pulls user/softmmu because
> > target_info_init. By moving target-info to be a custom list based, we
> > can decouple
> > target-info from qom/softmmu/user. and target-info will always
> > available once "main(argv, argc)" is entered. We also have the
> > advantage of doing all sorts
> > of tests against it.
> >
>
> Which kind of tests are you trying to add?
>
> For now, the exact list of places where we need to do this initialize
> target dance are:
> - system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> - tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> - tests/unit/test-multi-target.c:

# Multi targets test
if multi_target_objects != []
  test('test-multi-target',
       executable('test-multi-target',
                  sources: [multi_target_crates, files('test-multi-target.c')],
                  dependencies: multi_target_deps,
                  objects: multi_target_objects,
                  link_depends: [block_syms, qemu_syms],
                  link_args: multi_target_link_args),
       suite: ['unit'])
endif

I see this test, I am trying to add tests that do not pull so many
multi_target_objects, as it would be huge.
Just pull qom only.  And I am trying to call target_info() in
object.c, as inspect machines with
qemu-system is rejected, so maybe that's not an issue anymore


I means Subject: [PATCH v3 00/10] machine: uniquify virt QOM names
https://lore.kernel.org/qemu-devel/20260926081551.29-1-luoyonggang@gmail.com/#r

So the current design always rejects types that do not belong to the
current target. Listing them
all is not an option at all. With this restriction, then these are
indeed not needed.
So I'll wait for your work first, otherwise it's always conflicting.


> module_call_init(MODULE_INIT_TARGET_INFO);
>
> If we want more tests, I'm totally ok to move this init code to
> target-info.c, and replace call sites if needed.
>
> >
> > Tools such as qemu-img and unit tests may link target-info.c without any
> > target-info-def.c objects. Their target list remains empty, so use this
> > fallback.
> >
>
> Why should this tool get access to target list? qemu-img deals with disk
> images, and is unrelated to targets.
>
> >
> > static TypeImpl *type_register_internal(const TypeInfo *info)
> > {
> >     TypeImpl *ti;
> >
> >     if (!type_name_is_valid(info->name)) {
> >         fprintf(stderr, "Registering '%s' with illegal type name\n",
> > info->name);
> >         abort();
> >     }
> >
> >     if (info->is_available && !info->is_available()) {
> >         return NULL;
> >     }
> >
> >     ti = type_new(info);
> >
> >     type_table_add(ti);
> >     return ti;
> > }
> >
> >>
> >> Is there another good value this list approach brings compared to what
> >> exists?
> >>
> >> Regards,
> >> Pierrick
> >
> >
> >
>


-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 22:54         ` Yonggang Luo
@ 2026-10-07 23:24           ` Pierrick Bouvier
  2026-10-13  9:26             ` Daniel P. Berrangé
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 23:24 UTC (permalink / raw)
  To: luoyonggang
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 3:54 PM, Yonggang Luo wrote:
> On Thu, Oct 8, 2026 at 6:31 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/7/2026 1:50 PM, Yonggang Luo wrote:
>>> On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>
>>>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
>>>>> Register target definitions through constructors instead of
>>>>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
>>>>> available on entry to main(), without explicit initialization or a
>>>>> call to module_call_init(MODULE_INIT_QOM).
>>>>>
>>>>> Keep the target list sorted by target_arch and default to its first
>>>>> entry. Provide an unknown TargetInfo fallback for target-independent
>>>>> tools such as qemu-img and unit tests that link no target-info-def.c
>>>>> objects.
>>>>>
>>>>> Remove the obsolete QOM target-info registration infrastructure and
>>>>> update the multi-target test to inspect target information before
>>>>> initializing QOM.
>>>>>
>>>>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
>>>>> ---
>>>>>  include/qemu/module.h           |  1 -
>>>>>  include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
>>>>>  include/qemu/target-info-init.h | 53 ----------------------------
>>>>>  include/qemu/target-info-qom.h  | 31 -----------------
>>>>>  include/qemu/target-info.h      |  9 +++++
>>>>>  meson.build                     |  6 ++--
>>>>>  system/vl.c                     |  4 ---
>>>>>  target-info-def.c               |  1 -
>>>>>  target-info-qom.c               | 60 --------------------------------
>>>>>  target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
>>>>>  tests/qtest/fuzz/fuzz.c         |  3 --
>>>>>  tests/unit/test-multi-target.c  | 12 +++----
>>>>>  12 files changed, 129 insertions(+), 168 deletions(-)
>>>>>  delete mode 100644 include/qemu/target-info-init.h
>>>>>  delete mode 100644 include/qemu/target-info-qom.h
>>>>>  delete mode 100644 target-info-qom.c
>>>>>
>>>>
>>>> This approach (custom list based) was considered before implementing
>>>> things with QOM Types. The rationale I followed was that if everything
>>>> is in QOM, we might better follow that for consistency sake.
>>>> Yes, the compromise if that we need an extra init step, but it was not a
>>>> problem to add it.
>>> I have issue to add the init step for unit-tests, and hard to write the -target
>>> parse procedure and get it right. Not means this won't work. but for
>>> me, too much
>>> coupled.
>>>
>>
>> We already have such a test upstream:
>> https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35
>>
>> The init sequence is quite straightforward:
>>
>> ```
>> /* initialize target types, and only them */
>> module_call_init(MODULE_INIT_TARGET_INFO);
>>
>> /* we can get the list if we want, for -target or any other purpose */
>> g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
>>
>> /* set the global target info from any element in this list */
>> TargetInfo* ti = ...;
>> target_info_qom_set_target_info(ti);
>>
>> /* register rest of QOM types */
>> module_call_init(MODULE_INIT_QOM);
>> ```
>>
>> It works fine to implement -target (if we would like to do it), since I
>> implemented it myself. That was also my initial motivation by the way.
>>
>> Also, I appreciate that target-info is NULL by default, it crashes
>> loudly when it has not been set, and make it easy to find who depends on it.
>>
>>> If we treat target_info as a QOM, but QOM needs target_info to set
>>> up(is_avaible). That makes
>>> the init sequence too much of a burden.
>>>
>>
>> See sequence above, the solution is to initialize TARGET_INFO first,
>> before the rest of QOM. You end up with the same result than with a
>> statically initialized list.
>>
>>>
>>> is_available is depends on target_arch
>>> And before this patch, target_arch depends on QOM, pulls user/softmmu because
>>> target_info_init. By moving target-info to be a custom list based, we
>>> can decouple
>>> target-info from qom/softmmu/user. and target-info will always
>>> available once "main(argv, argc)" is entered. We also have the
>>> advantage of doing all sorts
>>> of tests against it.
>>>
>>
>> Which kind of tests are you trying to add?
>>
>> For now, the exact list of places where we need to do this initialize
>> target dance are:
>> - system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
>> - tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
>> - tests/unit/test-multi-target.c:
>> module_call_init(MODULE_INIT_TARGET_INFO);
>>
>> If we want more tests, I'm totally ok to move this init code to
>> target-info.c, and replace call sites if needed.
>>
>>>
>>> Tools such as qemu-img and unit tests may link target-info.c without any
>>> target-info-def.c objects. Their target list remains empty, so use this
>>> fallback.
>>>
>>
>> Why should this tool get access to target list? qemu-img deals with disk
>> images, and is unrelated to targets.
>>
>>>
>>> static TypeImpl *type_register_internal(const TypeInfo *info)
>>> {
>>>     TypeImpl *ti;
>>>
>>>     if (!type_name_is_valid(info->name)) {
>>>         fprintf(stderr, "Registering '%s' with illegal type name\n",
>>> info->name);
>>>         abort();
>>>     }
>>>
>>>     if (info->is_available && !info->is_available()) {
>>>         return NULL;
>>>     }
>>>
>>>     ti = type_new(info);
>>>
>>>     type_table_add(ti);
>>>     return ti;
>>> }
>>>
>>>>
>>>> Is there another good value this list approach brings compared to what
>>>> exists?
> 
> Sorry, I have to wait for your work to be done first.
> I have too many patches depending on this, and it seems hard to
> convince you. Let's just keep it as is.
> Maybe you can work them out in an easier way.
>

I quit the effort of upstreaming a qemu-system binary some time ago,
because it was not easy to get a consensus on what the new binary should
be, and I'm happy you took the relay there. I try my best to help on the
issues you bring, some of them being interesting problems that we need
to solve.

Thanks to your work and persistence, it seems like conversation is
starting to converge towards something: qemu-system with all
devices/machines/cpus available.

It's not what I had in my mind originally, but I'm happy to see progress
on this, and open to accept this alternative!

> My work is here.
> https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
> I am afraid of posting 300 pathces into threads to flood it(and
> disturbing yours). So I'll wait for your work first. and resolving
> conflicts later, that's really time-consuming.
>

It's indeed not possible to send 300 patches and expect this to work,
whether it's on this mailing list, or any software forge also.
It's also not possible to send a link, and expect anyone to take a look
at the 373 commits sitting it on top of master. My name is not Claude.
Instead, humans have to progress step by step, based on feedback. Yes it
takes time and it can be frustrating. And yes, I've been there (and
frustrated) also, I feel sorry for you.

At the moment, if we want to make it move on, we need to focus on one
single thing:
"How to document/specify which targets a machine support".

> I did many explanations before. seems my explanation is too bad and
> not to give a clean picture for you, let's delay these first.
>

If I can suggest something politely here, IMHO, alternating between
genuinely human written messages, and AI content sent as it is on email
or commit messages is not helping on the receiver side.

I would prefer anytime to deal with imperfect english (mine is imperfect
too, I'm not a native speaker neither), compared to read what
Claude/GPT/Deepseek generated that was pasted as it is.
I understand it's a good tool for helping on the language side, and
that's ok to fix grammar and sentence structure.
But asking "Please generate a summary from those email threads and
explain what the current series is doing", and paste this is doomed to fail.

It also has a very detrimental side effect: it makes me start to wonder
where the code is coming from also. Especially when seeing boilerplates
with lengthy comments written in perfect english. My 2 cents is, use AI
if you want/need, but make sure the result has this *human* touch.

> I only sent these 8 patches for easier review. because too many
> patches won't be accepted either.
>

This series is useful, thanks to your answer on last patch, I finally
see where you're headed. I'll answer there to keep this moving forward.

Regards,
Pierrick


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 23:02         ` Yonggang Luo
@ 2026-10-07 23:28           ` Pierrick Bouvier
  2026-10-12 21:27             ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-07 23:28 UTC (permalink / raw)
  To: luoyonggang
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 4:02 PM, Yonggang Luo wrote:
> On Thu, Oct 8, 2026 at 6:31 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/7/2026 1:50 PM, Yonggang Luo wrote:
>>> On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>
>>>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
>>>>> Register target definitions through constructors instead of
>>>>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
>>>>> available on entry to main(), without explicit initialization or a
>>>>> call to module_call_init(MODULE_INIT_QOM).
>>>>>
>>>>> Keep the target list sorted by target_arch and default to its first
>>>>> entry. Provide an unknown TargetInfo fallback for target-independent
>>>>> tools such as qemu-img and unit tests that link no target-info-def.c
>>>>> objects.
>>>>>
>>>>> Remove the obsolete QOM target-info registration infrastructure and
>>>>> update the multi-target test to inspect target information before
>>>>> initializing QOM.
>>>>>
>>>>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
>>>>> ---
>>>>>  include/qemu/module.h           |  1 -
>>>>>  include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
>>>>>  include/qemu/target-info-init.h | 53 ----------------------------
>>>>>  include/qemu/target-info-qom.h  | 31 -----------------
>>>>>  include/qemu/target-info.h      |  9 +++++
>>>>>  meson.build                     |  6 ++--
>>>>>  system/vl.c                     |  4 ---
>>>>>  target-info-def.c               |  1 -
>>>>>  target-info-qom.c               | 60 --------------------------------
>>>>>  target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
>>>>>  tests/qtest/fuzz/fuzz.c         |  3 --
>>>>>  tests/unit/test-multi-target.c  | 12 +++----
>>>>>  12 files changed, 129 insertions(+), 168 deletions(-)
>>>>>  delete mode 100644 include/qemu/target-info-init.h
>>>>>  delete mode 100644 include/qemu/target-info-qom.h
>>>>>  delete mode 100644 target-info-qom.c
>>>>>
>>>>
>>>> This approach (custom list based) was considered before implementing
>>>> things with QOM Types. The rationale I followed was that if everything
>>>> is in QOM, we might better follow that for consistency sake.
>>>> Yes, the compromise if that we need an extra init step, but it was not a
>>>> problem to add it.
>>> I have issue to add the init step for unit-tests, and hard to write the -target
>>> parse procedure and get it right. Not means this won't work. but for
>>> me, too much
>>> coupled.
>>>
>>
>> We already have such a test upstream:
>> https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35
>>
>> The init sequence is quite straightforward:
>>
>> ```
>> /* initialize target types, and only them */
>> module_call_init(MODULE_INIT_TARGET_INFO);
>>
>> /* we can get the list if we want, for -target or any other purpose */
>> g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
>>
>> /* set the global target info from any element in this list */
>> TargetInfo* ti = ...;
>> target_info_qom_set_target_info(ti);
>>
>> /* register rest of QOM types */
>> module_call_init(MODULE_INIT_QOM);
>> ```
>>
>> It works fine to implement -target (if we would like to do it), since I
>> implemented it myself. That was also my initial motivation by the way.
>>
>> Also, I appreciate that target-info is NULL by default, it crashes
>> loudly when it has not been set, and make it easy to find who depends on it.
>>
>>> If we treat target_info as a QOM, but QOM needs target_info to set
>>> up(is_avaible). That makes
>>> the init sequence too much of a burden.
>>>
>>
>> See sequence above, the solution is to initialize TARGET_INFO first,
>> before the rest of QOM. You end up with the same result than with a
>> statically initialized list.
>>
>>>
>>> is_available is depends on target_arch
>>> And before this patch, target_arch depends on QOM, pulls user/softmmu because
>>> target_info_init. By moving target-info to be a custom list based, we
>>> can decouple
>>> target-info from qom/softmmu/user. and target-info will always
>>> available once "main(argv, argc)" is entered. We also have the
>>> advantage of doing all sorts
>>> of tests against it.
>>>
>>
>> Which kind of tests are you trying to add?
>>
>> For now, the exact list of places where we need to do this initialize
>> target dance are:
>> - system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
>> - tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
>> - tests/unit/test-multi-target.c:
> 
> # Multi targets test
> if multi_target_objects != []
>   test('test-multi-target',
>        executable('test-multi-target',
>                   sources: [multi_target_crates, files('test-multi-target.c')],
>                   dependencies: multi_target_deps,
>                   objects: multi_target_objects,
>                   link_depends: [block_syms, qemu_syms],
>                   link_args: multi_target_link_args),
>        suite: ['unit'])
> endif
> 
> I see this test, I am trying to add tests that do not pull so many
> multi_target_objects, as it would be huge.

Agree, we should not add more binary.
If you need truly multi targets test, this existing binary is a good
place to start: just add a second test in it.

> Just pull qom only.  And I am trying to call target_info() in
> object.c, as inspect machines with
> qemu-system is rejected, so maybe that's not an issue anymore
>

Seems like a good candidate for the multi-target.c test.

> 
> I means Subject: [PATCH v3 00/10] machine: uniquify virt QOM names
> https://lore.kernel.org/qemu-devel/20260926081551.29-1-luoyonggang@gmail.com/#r
> 
> So the current design always rejects types that do not belong to the
> current target. Listing them
> all is not an option at all. With this restriction, then these are
> indeed not needed.
> So I'll wait for your work first, otherwise it's always conflicting.
> 
> 
>> module_call_init(MODULE_INIT_TARGET_INFO);
>>
>> If we want more tests, I'm totally ok to move this init code to
>> target-info.c, and replace call sites if needed.
>>
>>>
>>> Tools such as qemu-img and unit tests may link target-info.c without any
>>> target-info-def.c objects. Their target list remains empty, so use this
>>> fallback.
>>>
>>
>> Why should this tool get access to target list? qemu-img deals with disk
>> images, and is unrelated to targets.
>>
>>>
>>> static TypeImpl *type_register_internal(const TypeInfo *info)
>>> {
>>>     TypeImpl *ti;
>>>
>>>     if (!type_name_is_valid(info->name)) {
>>>         fprintf(stderr, "Registering '%s' with illegal type name\n",
>>> info->name);
>>>         abort();
>>>     }
>>>
>>>     if (info->is_available && !info->is_available()) {
>>>         return NULL;
>>>     }
>>>
>>>     ti = type_new(info);
>>>
>>>     type_table_add(ti);
>>>     return ti;
>>> }
>>>
>>>>
>>>> Is there another good value this list approach brings compared to what
>>>> exists?
>>>>
>>>> Regards,
>>>> Pierrick
>>>
>>>
>>>
>>
> 
> 



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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-07 21:42     ` Yonggang Luo
@ 2026-10-08  0:00       ` Pierrick Bouvier
  2026-10-08  0:03         ` Pierrick Bouvier
                           ` (2 more replies)
  0 siblings, 3 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-08  0:00 UTC (permalink / raw)
  To: luoyonggang
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 2:42 PM, Yonggang Luo wrote:
> On Thu, Oct 8, 2026 at 4:44 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
>>> Change TypeInfo.is_available to the new TypeIsAvailable type, which
>>> takes a const TargetInfo *. Registration passes target_info(), so
>>> behavior is unchanged. object.h only forward-declares TargetInfo.
>>>
>>> Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
>>> generated machine parents to the matching target_is_<arch> helpers.
>>>
>>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
>>> ---
>>>  hw/arm/aspeed_ast27x0-fc.c  |  2 +-
>>>  hw/arm/aspeed_ast27x0_evb.c |  4 ++--
>>>  hw/arm/raspi.c              |  4 ++--
>>>  hw/arm/raspi4b.c            |  2 +-
>>>  hw/arm/virt.c               |  4 ++--
>>>  hw/m68k/virt.c              |  4 ++--
>>>  hw/or1k/virt.c              |  2 +-
>>>  include/qom/object.h        | 12 +++++++++++-
>>>  qom/object.c                |  3 ++-
>>>  9 files changed, 24 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
>>> index 73362b60d2a..8a7c6a116ac 100644
>>> --- a/hw/arm/aspeed_ast27x0-fc.c
>>> +++ b/hw/arm/aspeed_ast27x0-fc.c
>>> @@ -234,7 +234,7 @@ static const TypeInfo ast2700fc_types[] = {
>>>          .parent         = TYPE_MACHINE,
>>>          .class_init     = ast2700fc_class_init,
>>>          .instance_size  = sizeof(Ast2700FCState),
>>> -        .is_available   = target_aarch64,
>>> +        .is_available   = target_is_aarch64,
>>>      },
>>>  };
>>>
>>> diff --git a/hw/arm/aspeed_ast27x0_evb.c b/hw/arm/aspeed_ast27x0_evb.c
>>> index 460c9ff0d2e..02a8cff1d9d 100644
>>> --- a/hw/arm/aspeed_ast27x0_evb.c
>>> +++ b/hw/arm/aspeed_ast27x0_evb.c
>>> @@ -75,13 +75,13 @@ static const TypeInfo aspeed_ast27x0_evb_types[] = {
>>>          .name          = MACHINE_TYPE_NAME("ast2700a1-evb"),
>>>          .parent        = TYPE_ASPEED_MACHINE,
>>>          .class_init    = aspeed_machine_ast2700a1_evb_class_init,
>>> -        .is_available  = target_aarch64,
>>> +        .is_available  = target_is_aarch64,
>>>      },
>>>      {
>>>          .name          = MACHINE_TYPE_NAME("ast2700a2-evb"),
>>>          .parent        = TYPE_ASPEED_MACHINE,
>>>          .class_init    = aspeed_machine_ast2700a2_evb_class_init,
>>> -        .is_available  = target_aarch64,
>>> +        .is_available  = target_is_aarch64,
>>>      }
>>>  };
>>>
>>> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
>>> index fadbacb2534..22b06c6ca22 100644
>>> --- a/hw/arm/raspi.c
>>> +++ b/hw/arm/raspi.c
>>> @@ -403,12 +403,12 @@ static const TypeInfo raspi_machine_types[] = {
>>>          .name           = MACHINE_TYPE_NAME("raspi3ap"),
>>>          .parent         = TYPE_RASPI_MACHINE,
>>>          .class_init     = raspi3ap_machine_class_init,
>>> -        .is_available   = target_aarch64,
>>> +        .is_available   = target_is_aarch64,
>>>      }, {
>>>          .name           = MACHINE_TYPE_NAME("raspi3b"),
>>>          .parent         = TYPE_RASPI_MACHINE,
>>>          .class_init     = raspi3b_machine_class_init,
>>> -        .is_available   = target_aarch64,
>>> +        .is_available   = target_is_aarch64,
>>>      }, {
>>>          .name           = TYPE_RASPI_MACHINE,
>>>          .parent         = TYPE_RASPI_BASE_MACHINE,
>>> diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
>>> index 566d64572db..a1dc477f25e 100644
>>> --- a/hw/arm/raspi4b.c
>>> +++ b/hw/arm/raspi4b.c
>>> @@ -121,7 +121,7 @@ static const TypeInfo raspi4b_machine_type = {
>>>      .parent         = TYPE_RASPI_BASE_MACHINE,
>>>      .instance_size  = sizeof(Raspi4bMachineState),
>>>      .class_init     = raspi4b_machine_class_init,
>>> -    .is_available   = target_aarch64,
>>> +    .is_available   = target_is_aarch64,
>>>  };
>>>
>>>  static void raspi4b_machine_register_type(void)
>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>>> index 9d192515d85..18160f7fad3 100644
>>> --- a/hw/arm/virt.c
>>> +++ b/hw/arm/virt.c
>>> @@ -132,7 +132,7 @@ static void arm_virt_compat_default_set(MachineClass *mc)
>>>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
>>>          .parent = TYPE_VIRT_MACHINE, \
>>>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
>>> -        .is_available = target_base_arm, \
>>> +        .is_available = target_is_base_arm, \
>>>      }; \
>>>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
>>>      { \
>>> @@ -4430,7 +4430,7 @@ static const TypeInfo virt_machine_info = {
>>>           { TYPE_HOTPLUG_HANDLER },
>>>           { }
>>>      },
>>> -    .is_available = target_base_arm,
>>> +    .is_available = target_is_base_arm,
>>>  };
>>>
>>>  static void machvirt_machine_init(void)
>>> diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
>>> index e52546e4fab..ad2a43ef3fb 100644
>>> --- a/hw/m68k/virt.c
>>> +++ b/hw/m68k/virt.c
>>> @@ -327,7 +327,7 @@ static const TypeInfo virt_machine_info = {
>>>      .parent       = TYPE_MACHINE,
>>>      .abstract     = true,
>>>      .class_init   = virt_machine_class_init,
>>> -    .is_available = target_m68k,
>>> +    .is_available = target_is_m68k,
>>>  };
>>>
>>>  static void virt_machine_register_types(void)
>>> @@ -355,7 +355,7 @@ type_init(virt_machine_register_types)
>>>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
>>>          .parent = MACHINE_TYPE_NAME("virt"), \
>>>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
>>> -        .is_available = target_m68k, \
>>> +        .is_available = target_is_m68k, \
>>>      }; \
>>>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
>>>      { \
>>> diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
>>> index a3ff903839b..89fb786641f 100644
>>> --- a/hw/or1k/virt.c
>>> +++ b/hw/or1k/virt.c
>>> @@ -559,7 +559,7 @@ static const TypeInfo or1ksim_machine_typeinfo = {
>>>      .parent     = TYPE_MACHINE,
>>>      .class_init = openrisc_virt_machine_init,
>>>      .instance_size = sizeof(OR1KVirtState),
>>> -    .is_available = target_or1k,
>>> +    .is_available = target_is_or1k,
>>>  };
>>>
>>>  static void or1ksim_machine_init_register_types(void)
>>> diff --git a/include/qom/object.h b/include/qom/object.h
>>> index 4c0645817a5..7d52a15f6b8 100644
>>> --- a/include/qom/object.h
>>> +++ b/include/qom/object.h
>>> @@ -17,6 +17,7 @@
>>>  #include "qapi/qapi-builtin-types.h"
>>>  #include "qemu/module.h"
>>>
>>> +typedef struct TargetInfo TargetInfo;
>>>  struct TypeImpl;
>>>  typedef struct TypeImpl *Type;
>>>
>>> @@ -117,6 +118,15 @@ typedef void (ObjectUnparent)(Object *obj);
>>>   */
>>>  typedef void (ObjectFree)(void *obj);
>>>
>>> +/**
>>> + * typedef TypeIsAvailable:
>>> + * @ti: TargetInfo to test.
>>> + *
>>> + * Returns whether a type is available for @ti. Typical implementations
>>> + * are target_is_*().
>>> + */
>>> +typedef bool (TypeIsAvailable)(const TargetInfo *ti);
>>> +
>>>  #define OBJECT_CLASS_CAST_CACHE 4
>>>
>>>  /**
>>> @@ -498,7 +508,7 @@ struct TypeInfo
>>>      void (*class_base_init)(ObjectClass *klass, const void *data);
>>>      const void *class_data;
>>>
>>> -    bool (*is_available)(void);
>>> +    TypeIsAvailable *is_available;
>>>      const InterfaceInfo *interfaces;
>>>  };
>>>
>>> diff --git a/qom/object.c b/qom/object.c
>>> index 96498f3d001..253b9562b41 100644
>>> --- a/qom/object.c
>>> +++ b/qom/object.c
>>> @@ -15,6 +15,7 @@
>>>  #include "qom/compat-properties.h"
>>>  #include "qom/object.h"
>>>  #include "qom/object_interfaces.h"
>>> +#include "qemu/target-info.h"
>>>  #include "qemu/cutils.h"
>>>  #include "qemu/memalign.h"
>>>  #include "qapi/visitor.h"
>>> @@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
>>>          abort();
>>>      }
>>>
>>> -    if (info->is_available && !info->is_available()) {
>>> +    if (info->is_available && !info->is_available(target_info())) {
>>>          return NULL;
>>>      }
>>>
>>
>> ```
>> info->is_available(target_info())
>> ```
>>
>> or
>>
>> ```
>> is_available() {
>>   TargetInfo ti * = target_info();
>>   ...
>> }
>> ```
>>
>> Are doing the exact same thing today.
>>
>> So what is the future goal requiring to introduce this?
> 
> From Daniel P. Berrangé's
> requesthttps://lore.kernel.org/qemu-devel/apAszS1ewxM0Y1XU@redhat.com/
>         I forgot to mention that this is also pretty important for making
>         introspection work, as we need to be able to say
> 
>           'qemu-system --machine none -qmp ...'
> 
>         and connect to QMP to introspect the binary. Having to add a
>         '--target <name>' into that mix is undesirable, as it creates
>         a chicken & egg problem. You don't know what targets are built
>         into qemu-system without introspecting it and you can't
>         introspect it without selecting a target to introspect.
> 
> From Pierrick's review
> https://lore.kernel.org/qemu-devel/557262df-b8e7-49b5-a245-ae46b8885b30@oss.qualcomm.com/So,
> for existing binary: -M virt works as before.
> 
>         For new multi binary:
>         $ qemu-system -M virt:
>         Multiple machines were found, select one among:
>         - aarch64-virt
>         - riscv64-virt
> 
>         Does it matches what you would expect?
> 
> From Daniel's review
> https://lore.kernel.org/qemu-devel/aro93NuZBXYGbD33@redhat.com/
>         We already have  'QemuTargetInfo' struct which is used
>         with 'query-target', that should also be used with the
>         new 'query-targets' command.
> 
>         We need to add the 'endianness' field to QemuTargetInfo.
> 
>         I don't think that we need to report machines though.
>         We already have 'query-machines' which gives much broader
>         information on the machines. "MachineInfo" needs to
>         gain
> 
>         "targets": ["SysEmuTarget"]
> 
>         to list which target(s) a machine can be used with.
> 
> 
> To achieve these, we needs add TypeInfo parameter to it so that we can do
> 
> static void report_unsupported_machine_type(const char *name, Error **errp)
> {
>     g_autoptr(GSList) machines = machine_class_get_list(true);
>     g_autoptr(GString) targets = g_string_new(NULL);
>     TargetInfoNode *node;
>     GSList *el;
> 
>     error_setg(errp, "unsupported machine type: \"%s\" for target \"%s\"",
>                name, target_name());
>     QLIST_FOREACH(node, target_info_list(), next) {
>         for (el = machines; el; el = el->next) {
>             MachineClass *mc = el->data;
> 
>             if ((!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) &&
>                 object_class_get_is_available(OBJECT_CLASS(mc))(node->info)) {
>                 g_string_append_printf(targets, "  %s\n",
>                                        node->info->target_name);
>                 break;
>             }
>         }
>     }
>     if (targets->len) {
>         error_append_hint(errp, "Available for targets:\n%s", targets->str);
>     }
> }
> 
> That is we can iterate on all target-list, and check if it's can be fitlered.
>

Ok, I finally see where this is going.

So, based on all the previous conversations, we agreed to have a
qemu-system binary with all the QOM types available (for all targets).

I personally think that if we go this way, we should not have any
-target option, and even less a -target none option.

The current is_available() approach was made with filtering per target
in mind, which predates where things are now. So, it's a good time to
reevaluate how to do it.

This leaves us with (at least) two options:
- keep the callback and add TargetInfo parameter (what is done here)
- remove is_available, and adopt a more declarative approach

How about we (re)-explore the second one?

It's what we did in the past
(https://gitlab.com/qemu-project/qemu/-/commit/5de9216064d32eaac125dac4de1878486c16d73e),
and that I removed recently, in favor of is_available.
My rationale was that it was incomplete, since we needed to filter types
per config also, and not only target.
Now that direction is to not filter anything, filter per config is
unneeded, and switching back to declarative instead of callback makes
total sense. Using interfaces like we did has its own issues, and I
would not like to see this coming back.

I'll do one very concrete proposal:

```
How about letting machines (and machines only first), have a new field
'targets', being a uint32_t mask with an array of EMU_TARGET?
machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
```

@Daniel, IIUC, this is exactly the approach you proposed a few weeks
ago, just before I got frustrated and lost my patience against you. I
think it's more clear for me where you wanted to go. Sorry it took such
a large detour.

Yonggang, does that sounds good for you?
Daniel, does that sounds good for you also?

Regards,
Pierrick


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08  0:00       ` Pierrick Bouvier
@ 2026-10-08  0:03         ` Pierrick Bouvier
  2026-10-08  2:08         ` Yonggang Luo
  2026-10-08  9:36         ` Daniel P. Berrangé
  2 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-08  0:03 UTC (permalink / raw)
  To: luoyonggang
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 5:00 PM, Pierrick Bouvier wrote:
> On 10/7/2026 2:42 PM, Yonggang Luo wrote:
>> On Thu, Oct 8, 2026 at 4:44 AM Pierrick Bouvier
>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>
>>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
>>>> Change TypeInfo.is_available to the new TypeIsAvailable type, which
>>>> takes a const TargetInfo *. Registration passes target_info(), so
>>>> behavior is unchanged. object.h only forward-declares TargetInfo.
>>>>
>>>> Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
>>>> generated machine parents to the matching target_is_<arch> helpers.
>>>>
>>>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
>>>> ---
>>>>  hw/arm/aspeed_ast27x0-fc.c  |  2 +-
>>>>  hw/arm/aspeed_ast27x0_evb.c |  4 ++--
>>>>  hw/arm/raspi.c              |  4 ++--
>>>>  hw/arm/raspi4b.c            |  2 +-
>>>>  hw/arm/virt.c               |  4 ++--
>>>>  hw/m68k/virt.c              |  4 ++--
>>>>  hw/or1k/virt.c              |  2 +-
>>>>  include/qom/object.h        | 12 +++++++++++-
>>>>  qom/object.c                |  3 ++-
>>>>  9 files changed, 24 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
>>>> index 73362b60d2a..8a7c6a116ac 100644
>>>> --- a/hw/arm/aspeed_ast27x0-fc.c
>>>> +++ b/hw/arm/aspeed_ast27x0-fc.c
>>>> @@ -234,7 +234,7 @@ static const TypeInfo ast2700fc_types[] = {
>>>>          .parent         = TYPE_MACHINE,
>>>>          .class_init     = ast2700fc_class_init,
>>>>          .instance_size  = sizeof(Ast2700FCState),
>>>> -        .is_available   = target_aarch64,
>>>> +        .is_available   = target_is_aarch64,
>>>>      },
>>>>  };
>>>>
>>>> diff --git a/hw/arm/aspeed_ast27x0_evb.c b/hw/arm/aspeed_ast27x0_evb.c
>>>> index 460c9ff0d2e..02a8cff1d9d 100644
>>>> --- a/hw/arm/aspeed_ast27x0_evb.c
>>>> +++ b/hw/arm/aspeed_ast27x0_evb.c
>>>> @@ -75,13 +75,13 @@ static const TypeInfo aspeed_ast27x0_evb_types[] = {
>>>>          .name          = MACHINE_TYPE_NAME("ast2700a1-evb"),
>>>>          .parent        = TYPE_ASPEED_MACHINE,
>>>>          .class_init    = aspeed_machine_ast2700a1_evb_class_init,
>>>> -        .is_available  = target_aarch64,
>>>> +        .is_available  = target_is_aarch64,
>>>>      },
>>>>      {
>>>>          .name          = MACHINE_TYPE_NAME("ast2700a2-evb"),
>>>>          .parent        = TYPE_ASPEED_MACHINE,
>>>>          .class_init    = aspeed_machine_ast2700a2_evb_class_init,
>>>> -        .is_available  = target_aarch64,
>>>> +        .is_available  = target_is_aarch64,
>>>>      }
>>>>  };
>>>>
>>>> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
>>>> index fadbacb2534..22b06c6ca22 100644
>>>> --- a/hw/arm/raspi.c
>>>> +++ b/hw/arm/raspi.c
>>>> @@ -403,12 +403,12 @@ static const TypeInfo raspi_machine_types[] = {
>>>>          .name           = MACHINE_TYPE_NAME("raspi3ap"),
>>>>          .parent         = TYPE_RASPI_MACHINE,
>>>>          .class_init     = raspi3ap_machine_class_init,
>>>> -        .is_available   = target_aarch64,
>>>> +        .is_available   = target_is_aarch64,
>>>>      }, {
>>>>          .name           = MACHINE_TYPE_NAME("raspi3b"),
>>>>          .parent         = TYPE_RASPI_MACHINE,
>>>>          .class_init     = raspi3b_machine_class_init,
>>>> -        .is_available   = target_aarch64,
>>>> +        .is_available   = target_is_aarch64,
>>>>      }, {
>>>>          .name           = TYPE_RASPI_MACHINE,
>>>>          .parent         = TYPE_RASPI_BASE_MACHINE,
>>>> diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
>>>> index 566d64572db..a1dc477f25e 100644
>>>> --- a/hw/arm/raspi4b.c
>>>> +++ b/hw/arm/raspi4b.c
>>>> @@ -121,7 +121,7 @@ static const TypeInfo raspi4b_machine_type = {
>>>>      .parent         = TYPE_RASPI_BASE_MACHINE,
>>>>      .instance_size  = sizeof(Raspi4bMachineState),
>>>>      .class_init     = raspi4b_machine_class_init,
>>>> -    .is_available   = target_aarch64,
>>>> +    .is_available   = target_is_aarch64,
>>>>  };
>>>>
>>>>  static void raspi4b_machine_register_type(void)
>>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>>>> index 9d192515d85..18160f7fad3 100644
>>>> --- a/hw/arm/virt.c
>>>> +++ b/hw/arm/virt.c
>>>> @@ -132,7 +132,7 @@ static void arm_virt_compat_default_set(MachineClass *mc)
>>>>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
>>>>          .parent = TYPE_VIRT_MACHINE, \
>>>>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
>>>> -        .is_available = target_base_arm, \
>>>> +        .is_available = target_is_base_arm, \
>>>>      }; \
>>>>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
>>>>      { \
>>>> @@ -4430,7 +4430,7 @@ static const TypeInfo virt_machine_info = {
>>>>           { TYPE_HOTPLUG_HANDLER },
>>>>           { }
>>>>      },
>>>> -    .is_available = target_base_arm,
>>>> +    .is_available = target_is_base_arm,
>>>>  };
>>>>
>>>>  static void machvirt_machine_init(void)
>>>> diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
>>>> index e52546e4fab..ad2a43ef3fb 100644
>>>> --- a/hw/m68k/virt.c
>>>> +++ b/hw/m68k/virt.c
>>>> @@ -327,7 +327,7 @@ static const TypeInfo virt_machine_info = {
>>>>      .parent       = TYPE_MACHINE,
>>>>      .abstract     = true,
>>>>      .class_init   = virt_machine_class_init,
>>>> -    .is_available = target_m68k,
>>>> +    .is_available = target_is_m68k,
>>>>  };
>>>>
>>>>  static void virt_machine_register_types(void)
>>>> @@ -355,7 +355,7 @@ type_init(virt_machine_register_types)
>>>>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
>>>>          .parent = MACHINE_TYPE_NAME("virt"), \
>>>>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
>>>> -        .is_available = target_m68k, \
>>>> +        .is_available = target_is_m68k, \
>>>>      }; \
>>>>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
>>>>      { \
>>>> diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
>>>> index a3ff903839b..89fb786641f 100644
>>>> --- a/hw/or1k/virt.c
>>>> +++ b/hw/or1k/virt.c
>>>> @@ -559,7 +559,7 @@ static const TypeInfo or1ksim_machine_typeinfo = {
>>>>      .parent     = TYPE_MACHINE,
>>>>      .class_init = openrisc_virt_machine_init,
>>>>      .instance_size = sizeof(OR1KVirtState),
>>>> -    .is_available = target_or1k,
>>>> +    .is_available = target_is_or1k,
>>>>  };
>>>>
>>>>  static void or1ksim_machine_init_register_types(void)
>>>> diff --git a/include/qom/object.h b/include/qom/object.h
>>>> index 4c0645817a5..7d52a15f6b8 100644
>>>> --- a/include/qom/object.h
>>>> +++ b/include/qom/object.h
>>>> @@ -17,6 +17,7 @@
>>>>  #include "qapi/qapi-builtin-types.h"
>>>>  #include "qemu/module.h"
>>>>
>>>> +typedef struct TargetInfo TargetInfo;
>>>>  struct TypeImpl;
>>>>  typedef struct TypeImpl *Type;
>>>>
>>>> @@ -117,6 +118,15 @@ typedef void (ObjectUnparent)(Object *obj);
>>>>   */
>>>>  typedef void (ObjectFree)(void *obj);
>>>>
>>>> +/**
>>>> + * typedef TypeIsAvailable:
>>>> + * @ti: TargetInfo to test.
>>>> + *
>>>> + * Returns whether a type is available for @ti. Typical implementations
>>>> + * are target_is_*().
>>>> + */
>>>> +typedef bool (TypeIsAvailable)(const TargetInfo *ti);
>>>> +
>>>>  #define OBJECT_CLASS_CAST_CACHE 4
>>>>
>>>>  /**
>>>> @@ -498,7 +508,7 @@ struct TypeInfo
>>>>      void (*class_base_init)(ObjectClass *klass, const void *data);
>>>>      const void *class_data;
>>>>
>>>> -    bool (*is_available)(void);
>>>> +    TypeIsAvailable *is_available;
>>>>      const InterfaceInfo *interfaces;
>>>>  };
>>>>
>>>> diff --git a/qom/object.c b/qom/object.c
>>>> index 96498f3d001..253b9562b41 100644
>>>> --- a/qom/object.c
>>>> +++ b/qom/object.c
>>>> @@ -15,6 +15,7 @@
>>>>  #include "qom/compat-properties.h"
>>>>  #include "qom/object.h"
>>>>  #include "qom/object_interfaces.h"
>>>> +#include "qemu/target-info.h"
>>>>  #include "qemu/cutils.h"
>>>>  #include "qemu/memalign.h"
>>>>  #include "qapi/visitor.h"
>>>> @@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
>>>>          abort();
>>>>      }
>>>>
>>>> -    if (info->is_available && !info->is_available()) {
>>>> +    if (info->is_available && !info->is_available(target_info())) {
>>>>          return NULL;
>>>>      }
>>>>
>>>
>>> ```
>>> info->is_available(target_info())
>>> ```
>>>
>>> or
>>>
>>> ```
>>> is_available() {
>>>   TargetInfo ti * = target_info();
>>>   ...
>>> }
>>> ```
>>>
>>> Are doing the exact same thing today.
>>>
>>> So what is the future goal requiring to introduce this?
>>
>> From Daniel P. Berrangé's
>> requesthttps://lore.kernel.org/qemu-devel/apAszS1ewxM0Y1XU@redhat.com/
>>         I forgot to mention that this is also pretty important for making
>>         introspection work, as we need to be able to say
>>
>>           'qemu-system --machine none -qmp ...'
>>
>>         and connect to QMP to introspect the binary. Having to add a
>>         '--target <name>' into that mix is undesirable, as it creates
>>         a chicken & egg problem. You don't know what targets are built
>>         into qemu-system without introspecting it and you can't
>>         introspect it without selecting a target to introspect.
>>
>> From Pierrick's review
>> https://lore.kernel.org/qemu-devel/557262df-b8e7-49b5-a245-ae46b8885b30@oss.qualcomm.com/So,
>> for existing binary: -M virt works as before.
>>
>>         For new multi binary:
>>         $ qemu-system -M virt:
>>         Multiple machines were found, select one among:
>>         - aarch64-virt
>>         - riscv64-virt
>>
>>         Does it matches what you would expect?
>>
>> From Daniel's review
>> https://lore.kernel.org/qemu-devel/aro93NuZBXYGbD33@redhat.com/
>>         We already have  'QemuTargetInfo' struct which is used
>>         with 'query-target', that should also be used with the
>>         new 'query-targets' command.
>>
>>         We need to add the 'endianness' field to QemuTargetInfo.
>>
>>         I don't think that we need to report machines though.
>>         We already have 'query-machines' which gives much broader
>>         information on the machines. "MachineInfo" needs to
>>         gain
>>
>>         "targets": ["SysEmuTarget"]
>>
>>         to list which target(s) a machine can be used with.
>>
>>
>> To achieve these, we needs add TypeInfo parameter to it so that we can do
>>
>> static void report_unsupported_machine_type(const char *name, Error **errp)
>> {
>>     g_autoptr(GSList) machines = machine_class_get_list(true);
>>     g_autoptr(GString) targets = g_string_new(NULL);
>>     TargetInfoNode *node;
>>     GSList *el;
>>
>>     error_setg(errp, "unsupported machine type: \"%s\" for target \"%s\"",
>>                name, target_name());
>>     QLIST_FOREACH(node, target_info_list(), next) {
>>         for (el = machines; el; el = el->next) {
>>             MachineClass *mc = el->data;
>>
>>             if ((!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) &&
>>                 object_class_get_is_available(OBJECT_CLASS(mc))(node->info)) {
>>                 g_string_append_printf(targets, "  %s\n",
>>                                        node->info->target_name);
>>                 break;
>>             }
>>         }
>>     }
>>     if (targets->len) {
>>         error_append_hint(errp, "Available for targets:\n%s", targets->str);
>>     }
>> }
>>
>> That is we can iterate on all target-list, and check if it's can be fitlered.
>>
> 
> Ok, I finally see where this is going.
> 
> So, based on all the previous conversations, we agreed to have a
> qemu-system binary with all the QOM types available (for all targets).
> 
> I personally think that if we go this way, we should not have any
> -target option, and even less a -target none option.
> 
> The current is_available() approach was made with filtering per target
> in mind, which predates where things are now. So, it's a good time to
> reevaluate how to do it.
> 
> This leaves us with (at least) two options:
> - keep the callback and add TargetInfo parameter (what is done here)
> - remove is_available, and adopt a more declarative approach
> 
> How about we (re)-explore the second one?
> 
> It's what we did in the past
> (https://gitlab.com/qemu-project/qemu/-/commit/5de9216064d32eaac125dac4de1878486c16d73e),
> and that I removed recently, in favor of is_available.
> My rationale was that it was incomplete, since we needed to filter types
> per config also, and not only target.
> Now that direction is to not filter anything, filter per config is
> unneeded, and switching back to declarative instead of callback makes
> total sense. Using interfaces like we did has its own issues, and I
> would not like to see this coming back.
> 
> I'll do one very concrete proposal:
> 
> ```
> How about letting machines (and machines only first), have a new field
> 'targets', being a uint32_t mask with an array of EMU_TARGET?
> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
> ```
>

Machine class more exactly: mc->targets
See mc->desc for a concrete example of where it should be set.

> @Daniel, IIUC, this is exactly the approach you proposed a few weeks
> ago, just before I got frustrated and lost my patience against you. I
> think it's more clear for me where you wanted to go. Sorry it took such
> a large detour.
> 
> Yonggang, does that sounds good for you?
> Daniel, does that sounds good for you also?
> 
> Regards,
> Pierrick



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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08  0:00       ` Pierrick Bouvier
  2026-10-08  0:03         ` Pierrick Bouvier
@ 2026-10-08  2:08         ` Yonggang Luo
  2026-10-08 15:58           ` Pierrick Bouvier
  2026-10-08  9:36         ` Daniel P. Berrangé
  2 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-08  2:08 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Thu, Oct 8, 2026 at 8:00 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/7/2026 2:42 PM, Yonggang Luo wrote:
> > On Thu, Oct 8, 2026 at 4:44 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> >>> Change TypeInfo.is_available to the new TypeIsAvailable type, which
> >>> takes a const TargetInfo *. Registration passes target_info(), so
> >>> behavior is unchanged. object.h only forward-declares TargetInfo.
> >>>
> >>> Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
> >>> generated machine parents to the matching target_is_<arch> helpers.
> >>>
> >>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> >>> ---
> >>>  hw/arm/aspeed_ast27x0-fc.c  |  2 +-
> >>>  hw/arm/aspeed_ast27x0_evb.c |  4 ++--
> >>>  hw/arm/raspi.c              |  4 ++--
> >>>  hw/arm/raspi4b.c            |  2 +-
> >>>  hw/arm/virt.c               |  4 ++--
> >>>  hw/m68k/virt.c              |  4 ++--
> >>>  hw/or1k/virt.c              |  2 +-
> >>>  include/qom/object.h        | 12 +++++++++++-
> >>>  qom/object.c                |  3 ++-
> >>>  9 files changed, 24 insertions(+), 13 deletions(-)
> >>>
> >>> diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
> >>> index 73362b60d2a..8a7c6a116ac 100644
> >>> --- a/hw/arm/aspeed_ast27x0-fc.c
> >>> +++ b/hw/arm/aspeed_ast27x0-fc.c
> >>> @@ -234,7 +234,7 @@ static const TypeInfo ast2700fc_types[] = {
> >>>          .parent         = TYPE_MACHINE,
> >>>          .class_init     = ast2700fc_class_init,
> >>>          .instance_size  = sizeof(Ast2700FCState),
> >>> -        .is_available   = target_aarch64,
> >>> +        .is_available   = target_is_aarch64,
> >>>      },
> >>>  };
> >>>
> >>> diff --git a/hw/arm/aspeed_ast27x0_evb.c b/hw/arm/aspeed_ast27x0_evb.c
> >>> index 460c9ff0d2e..02a8cff1d9d 100644
> >>> --- a/hw/arm/aspeed_ast27x0_evb.c
> >>> +++ b/hw/arm/aspeed_ast27x0_evb.c
> >>> @@ -75,13 +75,13 @@ static const TypeInfo aspeed_ast27x0_evb_types[] = {
> >>>          .name          = MACHINE_TYPE_NAME("ast2700a1-evb"),
> >>>          .parent        = TYPE_ASPEED_MACHINE,
> >>>          .class_init    = aspeed_machine_ast2700a1_evb_class_init,
> >>> -        .is_available  = target_aarch64,
> >>> +        .is_available  = target_is_aarch64,
> >>>      },
> >>>      {
> >>>          .name          = MACHINE_TYPE_NAME("ast2700a2-evb"),
> >>>          .parent        = TYPE_ASPEED_MACHINE,
> >>>          .class_init    = aspeed_machine_ast2700a2_evb_class_init,
> >>> -        .is_available  = target_aarch64,
> >>> +        .is_available  = target_is_aarch64,
> >>>      }
> >>>  };
> >>>
> >>> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
> >>> index fadbacb2534..22b06c6ca22 100644
> >>> --- a/hw/arm/raspi.c
> >>> +++ b/hw/arm/raspi.c
> >>> @@ -403,12 +403,12 @@ static const TypeInfo raspi_machine_types[] = {
> >>>          .name           = MACHINE_TYPE_NAME("raspi3ap"),
> >>>          .parent         = TYPE_RASPI_MACHINE,
> >>>          .class_init     = raspi3ap_machine_class_init,
> >>> -        .is_available   = target_aarch64,
> >>> +        .is_available   = target_is_aarch64,
> >>>      }, {
> >>>          .name           = MACHINE_TYPE_NAME("raspi3b"),
> >>>          .parent         = TYPE_RASPI_MACHINE,
> >>>          .class_init     = raspi3b_machine_class_init,
> >>> -        .is_available   = target_aarch64,
> >>> +        .is_available   = target_is_aarch64,
> >>>      }, {
> >>>          .name           = TYPE_RASPI_MACHINE,
> >>>          .parent         = TYPE_RASPI_BASE_MACHINE,
> >>> diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
> >>> index 566d64572db..a1dc477f25e 100644
> >>> --- a/hw/arm/raspi4b.c
> >>> +++ b/hw/arm/raspi4b.c
> >>> @@ -121,7 +121,7 @@ static const TypeInfo raspi4b_machine_type = {
> >>>      .parent         = TYPE_RASPI_BASE_MACHINE,
> >>>      .instance_size  = sizeof(Raspi4bMachineState),
> >>>      .class_init     = raspi4b_machine_class_init,
> >>> -    .is_available   = target_aarch64,
> >>> +    .is_available   = target_is_aarch64,
> >>>  };
> >>>
> >>>  static void raspi4b_machine_register_type(void)
> >>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> >>> index 9d192515d85..18160f7fad3 100644
> >>> --- a/hw/arm/virt.c
> >>> +++ b/hw/arm/virt.c
> >>> @@ -132,7 +132,7 @@ static void arm_virt_compat_default_set(MachineClass *mc)
> >>>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
> >>>          .parent = TYPE_VIRT_MACHINE, \
> >>>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
> >>> -        .is_available = target_base_arm, \
> >>> +        .is_available = target_is_base_arm, \
> >>>      }; \
> >>>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
> >>>      { \
> >>> @@ -4430,7 +4430,7 @@ static const TypeInfo virt_machine_info = {
> >>>           { TYPE_HOTPLUG_HANDLER },
> >>>           { }
> >>>      },
> >>> -    .is_available = target_base_arm,
> >>> +    .is_available = target_is_base_arm,
> >>>  };
> >>>
> >>>  static void machvirt_machine_init(void)
> >>> diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
> >>> index e52546e4fab..ad2a43ef3fb 100644
> >>> --- a/hw/m68k/virt.c
> >>> +++ b/hw/m68k/virt.c
> >>> @@ -327,7 +327,7 @@ static const TypeInfo virt_machine_info = {
> >>>      .parent       = TYPE_MACHINE,
> >>>      .abstract     = true,
> >>>      .class_init   = virt_machine_class_init,
> >>> -    .is_available = target_m68k,
> >>> +    .is_available = target_is_m68k,
> >>>  };
> >>>
> >>>  static void virt_machine_register_types(void)
> >>> @@ -355,7 +355,7 @@ type_init(virt_machine_register_types)
> >>>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
> >>>          .parent = MACHINE_TYPE_NAME("virt"), \
> >>>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
> >>> -        .is_available = target_m68k, \
> >>> +        .is_available = target_is_m68k, \
> >>>      }; \
> >>>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
> >>>      { \
> >>> diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
> >>> index a3ff903839b..89fb786641f 100644
> >>> --- a/hw/or1k/virt.c
> >>> +++ b/hw/or1k/virt.c
> >>> @@ -559,7 +559,7 @@ static const TypeInfo or1ksim_machine_typeinfo = {
> >>>      .parent     = TYPE_MACHINE,
> >>>      .class_init = openrisc_virt_machine_init,
> >>>      .instance_size = sizeof(OR1KVirtState),
> >>> -    .is_available = target_or1k,
> >>> +    .is_available = target_is_or1k,
> >>>  };
> >>>
> >>>  static void or1ksim_machine_init_register_types(void)
> >>> diff --git a/include/qom/object.h b/include/qom/object.h
> >>> index 4c0645817a5..7d52a15f6b8 100644
> >>> --- a/include/qom/object.h
> >>> +++ b/include/qom/object.h
> >>> @@ -17,6 +17,7 @@
> >>>  #include "qapi/qapi-builtin-types.h"
> >>>  #include "qemu/module.h"
> >>>
> >>> +typedef struct TargetInfo TargetInfo;
> >>>  struct TypeImpl;
> >>>  typedef struct TypeImpl *Type;
> >>>
> >>> @@ -117,6 +118,15 @@ typedef void (ObjectUnparent)(Object *obj);
> >>>   */
> >>>  typedef void (ObjectFree)(void *obj);
> >>>
> >>> +/**
> >>> + * typedef TypeIsAvailable:
> >>> + * @ti: TargetInfo to test.
> >>> + *
> >>> + * Returns whether a type is available for @ti. Typical implementations
> >>> + * are target_is_*().
> >>> + */
> >>> +typedef bool (TypeIsAvailable)(const TargetInfo *ti);
> >>> +
> >>>  #define OBJECT_CLASS_CAST_CACHE 4
> >>>
> >>>  /**
> >>> @@ -498,7 +508,7 @@ struct TypeInfo
> >>>      void (*class_base_init)(ObjectClass *klass, const void *data);
> >>>      const void *class_data;
> >>>
> >>> -    bool (*is_available)(void);
> >>> +    TypeIsAvailable *is_available;
> >>>      const InterfaceInfo *interfaces;
> >>>  };
> >>>
> >>> diff --git a/qom/object.c b/qom/object.c
> >>> index 96498f3d001..253b9562b41 100644
> >>> --- a/qom/object.c
> >>> +++ b/qom/object.c
> >>> @@ -15,6 +15,7 @@
> >>>  #include "qom/compat-properties.h"
> >>>  #include "qom/object.h"
> >>>  #include "qom/object_interfaces.h"
> >>> +#include "qemu/target-info.h"
> >>>  #include "qemu/cutils.h"
> >>>  #include "qemu/memalign.h"
> >>>  #include "qapi/visitor.h"
> >>> @@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
> >>>          abort();
> >>>      }
> >>>
> >>> -    if (info->is_available && !info->is_available()) {
> >>> +    if (info->is_available && !info->is_available(target_info())) {
> >>>          return NULL;
> >>>      }
> >>>
> >>
> >> ```
> >> info->is_available(target_info())
> >> ```
> >>
> >> or
> >>
> >> ```
> >> is_available() {
> >>   TargetInfo ti * = target_info();
> >>   ...
> >> }
> >> ```
> >>
> >> Are doing the exact same thing today.
> >>
> >> So what is the future goal requiring to introduce this?
> >
> > From Daniel P. Berrangé's
> > requesthttps://lore.kernel.org/qemu-devel/apAszS1ewxM0Y1XU@redhat.com/
> >         I forgot to mention that this is also pretty important for making
> >         introspection work, as we need to be able to say
> >
> >           'qemu-system --machine none -qmp ...'
> >
> >         and connect to QMP to introspect the binary. Having to add a
> >         '--target <name>' into that mix is undesirable, as it creates
> >         a chicken & egg problem. You don't know what targets are built
> >         into qemu-system without introspecting it and you can't
> >         introspect it without selecting a target to introspect.
> >
> > From Pierrick's review
> > https://lore.kernel.org/qemu-devel/557262df-b8e7-49b5-a245-ae46b8885b30@oss.qualcomm.com/So,
> > for existing binary: -M virt works as before.
> >
> >         For new multi binary:
> >         $ qemu-system -M virt:
> >         Multiple machines were found, select one among:
> >         - aarch64-virt
> >         - riscv64-virt
> >
> >         Does it matches what you would expect?
> >
> > From Daniel's review
> > https://lore.kernel.org/qemu-devel/aro93NuZBXYGbD33@redhat.com/
> >         We already have  'QemuTargetInfo' struct which is used
> >         with 'query-target', that should also be used with the
> >         new 'query-targets' command.
> >
> >         We need to add the 'endianness' field to QemuTargetInfo.
> >
> >         I don't think that we need to report machines though.
> >         We already have 'query-machines' which gives much broader
> >         information on the machines. "MachineInfo" needs to
> >         gain
> >
> >         "targets": ["SysEmuTarget"]
> >
> >         to list which target(s) a machine can be used with.
> >
> >
> > To achieve these, we needs add TypeInfo parameter to it so that we can do
> >
> > static void report_unsupported_machine_type(const char *name, Error **errp)
> > {
> >     g_autoptr(GSList) machines = machine_class_get_list(true);
> >     g_autoptr(GString) targets = g_string_new(NULL);
> >     TargetInfoNode *node;
> >     GSList *el;
> >
> >     error_setg(errp, "unsupported machine type: \"%s\" for target \"%s\"",
> >                name, target_name());
> >     QLIST_FOREACH(node, target_info_list(), next) {
> >         for (el = machines; el; el = el->next) {
> >             MachineClass *mc = el->data;
> >
> >             if ((!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) &&
> >                 object_class_get_is_available(OBJECT_CLASS(mc))(node->info)) {
> >                 g_string_append_printf(targets, "  %s\n",
> >                                        node->info->target_name);
> >                 break;
> >             }
> >         }
> >     }
> >     if (targets->len) {
> >         error_append_hint(errp, "Available for targets:\n%s", targets->str);
> >     }
> > }
> >
> > That is we can iterate on all target-list, and check if it's can be fitlered.
> >
>
> Ok, I finally see where this is going.
>
> So, based on all the previous conversations, we agreed to have a
> qemu-system binary with all the QOM types available (for all targets).
>
> I personally think that if we go this way, we should not have any
> -target option, and even less a -target none option.
>
> The current is_available() approach was made with filtering per target
> in mind, which predates where things are now. So, it's a good time to
> reevaluate how to do it.
>
> This leaves us with (at least) two options:
> - keep the callback and add TargetInfo parameter (what is done here)
> - remove is_available, and adopt a more declarative approach
>
> How about we (re)-explore the second one?

Indeed, I am doing

- preserve is_available(TargetInfo*), and adopt a more declarative approach

/* Generated by scripts/gen-target-info.py. Do not edit. */

static const TypeInfo target_machine_types[] = {
    {
        .name = TYPE_TARGET_BASE_ALPHA_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_alpha,
    },
    {
        .name = TYPE_TARGET_BASE_ARM_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_arm,
    },
    {
        .name = TYPE_TARGET_BASE_AVR_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_avr,
    },
    {
        .name = TYPE_TARGET_BASE_HEXAGON_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_hexagon,
    },
    {
        .name = TYPE_TARGET_BASE_HPPA_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_hppa,
    },
    {
        .name = TYPE_TARGET_BASE_I386_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_i386,
    },
    {
        .name = TYPE_TARGET_BASE_LOONGARCH_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_loongarch,
    },
    {
        .name = TYPE_TARGET_BASE_M68K_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_m68k,
    },
    {
        .name = TYPE_TARGET_BASE_MICROBLAZE_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_microblaze,
    },
    {
        .name = TYPE_TARGET_BASE_MIPS_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_mips,
    },
    {
        .name = TYPE_TARGET_BASE_NONE_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_none,
    },
    {
        .name = TYPE_TARGET_BASE_OR1K_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_or1k,
    },
    {
        .name = TYPE_TARGET_BASE_PPC_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_ppc,
    },
    {
        .name = TYPE_TARGET_BASE_RISCV_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_riscv,
    },
    {
        .name = TYPE_TARGET_BASE_RX_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_rx,
    },
    {
        .name = TYPE_TARGET_BASE_S390X_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_s390x,
    },
    {
        .name = TYPE_TARGET_BASE_SH4_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_sh4,
    },
    {
        .name = TYPE_TARGET_BASE_SPARC_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_sparc,
    },
    {
        .name = TYPE_TARGET_BASE_TRICORE_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_tricore,
    },
    {
        .name = TYPE_TARGET_BASE_XTENSA_MACHINE,
        .parent = TYPE_MACHINE,
        .abstract = true,
        .is_available = target_is_base_xtensa,
    },
    {
        .name = TYPE_TARGET_ALPHA_MACHINE,
        .parent = TYPE_TARGET_BASE_ALPHA_MACHINE,
        .abstract = true,
        .is_available = target_is_alpha,
    },
    {
        .name = TYPE_TARGET_AARCH64_MACHINE,
        .parent = TYPE_TARGET_BASE_ARM_MACHINE,
        .abstract = true,
        .is_available = target_is_aarch64,
    },
    {
        .name = TYPE_TARGET_ARM_MACHINE,
        .parent = TYPE_TARGET_BASE_ARM_MACHINE,
        .abstract = true,
        .is_available = target_is_arm,
    },
    {
        .name = TYPE_TARGET_AVR_MACHINE,
        .parent = TYPE_TARGET_BASE_AVR_MACHINE,
        .abstract = true,
        .is_available = target_is_avr,
    },
    {
        .name = TYPE_TARGET_HEXAGON_MACHINE,
        .parent = TYPE_TARGET_BASE_HEXAGON_MACHINE,
        .abstract = true,
        .is_available = target_is_hexagon,
    },
    {
        .name = TYPE_TARGET_HPPA_MACHINE,
        .parent = TYPE_TARGET_BASE_HPPA_MACHINE,
        .abstract = true,
        .is_available = target_is_hppa,
    },
    {
        .name = TYPE_TARGET_I386_MACHINE,
        .parent = TYPE_TARGET_BASE_I386_MACHINE,
        .abstract = true,
        .is_available = target_is_i386,
    },
    {
        .name = TYPE_TARGET_X86_64_MACHINE,
        .parent = TYPE_TARGET_BASE_I386_MACHINE,
        .abstract = true,
        .is_available = target_is_x86_64,
    },
    {
        .name = TYPE_TARGET_LOONGARCH64_MACHINE,
        .parent = TYPE_TARGET_BASE_LOONGARCH_MACHINE,
        .abstract = true,
        .is_available = target_is_loongarch64,
    },
    {
        .name = TYPE_TARGET_M68K_MACHINE,
        .parent = TYPE_TARGET_BASE_M68K_MACHINE,
        .abstract = true,
        .is_available = target_is_m68k,
    },
    {
        .name = TYPE_TARGET_MICROBLAZE_MACHINE,
        .parent = TYPE_TARGET_BASE_MICROBLAZE_MACHINE,
        .abstract = true,
        .is_available = target_is_microblaze,
    },
    {
        .name = TYPE_TARGET_MIPS_MACHINE,
        .parent = TYPE_TARGET_BASE_MIPS_MACHINE,
        .abstract = true,
        .is_available = target_is_mips,
    },
    {
        .name = TYPE_TARGET_MIPS64_MACHINE,
        .parent = TYPE_TARGET_BASE_MIPS_MACHINE,
        .abstract = true,
        .is_available = target_is_mips64,
    },
    {
        .name = TYPE_TARGET_MIPS64EL_MACHINE,
        .parent = TYPE_TARGET_BASE_MIPS_MACHINE,
        .abstract = true,
        .is_available = target_is_mips64el,
    },
    {
        .name = TYPE_TARGET_MIPSEL_MACHINE,
        .parent = TYPE_TARGET_BASE_MIPS_MACHINE,
        .abstract = true,
        .is_available = target_is_mipsel,
    },
    {
        .name = TYPE_TARGET_NONE_MACHINE,
        .parent = TYPE_TARGET_BASE_NONE_MACHINE,
        .abstract = true,
        .is_available = target_is_none,
    },
    {
        .name = TYPE_TARGET_OR1K_MACHINE,
        .parent = TYPE_TARGET_BASE_OR1K_MACHINE,
        .abstract = true,
        .is_available = target_is_or1k,
    },
    {
        .name = TYPE_TARGET_PPC_MACHINE,
        .parent = TYPE_TARGET_BASE_PPC_MACHINE,
        .abstract = true,
        .is_available = target_is_ppc,
    },
    {
        .name = TYPE_TARGET_PPC64_MACHINE,
        .parent = TYPE_TARGET_BASE_PPC_MACHINE,
        .abstract = true,
        .is_available = target_is_ppc64,
    },
    {
        .name = TYPE_TARGET_RISCV32_MACHINE,
        .parent = TYPE_TARGET_BASE_RISCV_MACHINE,
        .abstract = true,
        .is_available = target_is_riscv32,
    },
    {
        .name = TYPE_TARGET_RISCV64_MACHINE,
        .parent = TYPE_TARGET_BASE_RISCV_MACHINE,
        .abstract = true,
        .is_available = target_is_riscv64,
    },
    {
        .name = TYPE_TARGET_RX_MACHINE,
        .parent = TYPE_TARGET_BASE_RX_MACHINE,
        .abstract = true,
        .is_available = target_is_rx,
    },
    {
        .name = TYPE_TARGET_S390X_MACHINE,
        .parent = TYPE_TARGET_BASE_S390X_MACHINE,
        .abstract = true,
        .is_available = target_is_s390x,
    },
    {
        .name = TYPE_TARGET_SH4_MACHINE,
        .parent = TYPE_TARGET_BASE_SH4_MACHINE,
        .abstract = true,
        .is_available = target_is_sh4,
    },
    {
        .name = TYPE_TARGET_SH4EB_MACHINE,
        .parent = TYPE_TARGET_BASE_SH4_MACHINE,
        .abstract = true,
        .is_available = target_is_sh4eb,
    },
    {
        .name = TYPE_TARGET_SPARC_MACHINE,
        .parent = TYPE_TARGET_BASE_SPARC_MACHINE,
        .abstract = true,
        .is_available = target_is_sparc,
    },
    {
        .name = TYPE_TARGET_SPARC64_MACHINE,
        .parent = TYPE_TARGET_BASE_SPARC_MACHINE,
        .abstract = true,
        .is_available = target_is_sparc64,
    },
    {
        .name = TYPE_TARGET_TRICORE_MACHINE,
        .parent = TYPE_TARGET_BASE_TRICORE_MACHINE,
        .abstract = true,
        .is_available = target_is_tricore,
    },
    {
        .name = TYPE_TARGET_XTENSA_MACHINE,
        .parent = TYPE_TARGET_BASE_XTENSA_MACHINE,
        .abstract = true,
        .is_available = target_is_xtensa,
    },
    {
        .name = TYPE_TARGET_XTENSAEB_MACHINE,
        .parent = TYPE_TARGET_BASE_XTENSA_MACHINE,
        .abstract = true,
        .is_available = target_is_xtensaeb,
    },
};
Other than these base machines, other machines are children of these
base machines.

See these changes
https://gitlab.com/lygstate-qemu/qemu/-/commit/c71da20c2483cdf577fd2a5548a80ca1e5099676
https://gitlab.com/lygstate-qemu/qemu/-/commit/252b8763fd74ec57f5762bf9c57e19d8d9e5a146
https://gitlab.com/lygstate-qemu/qemu/-/commit/252b8763fd74ec57f5762bf9c57e19d8d9e5a146
https://gitlab.com/lygstate-qemu/qemu/-/commit/252b8763fd74ec57f5762bf9c57e19d8d9e5a146
For ARM:
https://gitlab.com/lygstate-qemu/qemu/-/commit/c42d5eb333fd3a7cab899c8df95375dfc79aba40

These base machine type is auto-generated in this MR.
You can see at the branch
https://gitlab.com/lygstate-qemu/qemu/-/commits/single-binary-arm-riscv?ref_type=heads

And the inherit is done by commits
qom: inherit is_available and filter after MODULE_INIT_QOM:
https://gitlab.com/lygstate-qemu/qemu/-/commit/cb66474a36e03b4353c2f525ce7821f2af779ea1
qom: register late types through module_call_init_fn:
https://gitlab.com/lygstate-qemu/qemu/-/commit/ba6a3d3fb6e4bfe35d88d3845abf7b0ec8fbc337
module: add before/after hooks and module_call_init_fn:
https://gitlab.com/lygstate-qemu/qemu/-/commit/86c635f45e283b6d0f714a1a3a9d9521b17d5152

And the gitlab-ci is already passed


>
> It's what we did in the past
> (https://gitlab.com/qemu-project/qemu/-/commit/5de9216064d32eaac125dac4de1878486c16d73e),

Somewhat alike except I do not introduce many interface types. Just
base machine types.

> and that I removed recently, in favor of is_available.
> My rationale was that it was incomplete, since we needed to filter types
> per config also, and not only target.
> Now that direction is to not filter anything, filter per config is
> unneeded, and switching back to declarative instead of callback makes
> total sense. Using interfaces like we did has its own issues, and I
> would not like to see this coming back.
>
> I'll do one very concrete proposal:
>
> ```
> How about letting machines (and machines only first), have a new field
> 'targets', being a uint32_t mask with an array of EMU_TARGET?
> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
> ```

From my experience at
https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
this is not enough, we still needs is_avaible, because for those
machines that binding to
KVM/WHPX and other accels, we need to use target_kconfig to handle
them. That's why I choose to use a unified
is_avaible(TargetInfo*).

This new field only works if is_availbe still be a member of TypeInfo.
machine->targets are not generic. Indeed CPU and ACCEL(kvm/whpx/hyp)
types also need filtering.

>
> @Daniel, IIUC, this is exactly the approach you proposed a few weeks
> ago, just before I got frustrated and lost my patience against you. I
> think it's more clear for me where you wanted to go. Sorry it took such
> a large detour.
>
> Yonggang, does that sounds good for you?
> Daniel, does that sounds good for you also?
>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08  0:00       ` Pierrick Bouvier
  2026-10-08  0:03         ` Pierrick Bouvier
  2026-10-08  2:08         ` Yonggang Luo
@ 2026-10-08  9:36         ` Daniel P. Berrangé
  2026-10-08  9:56           ` Yonggang Luo
  2 siblings, 1 reply; 62+ messages in thread
From: Daniel P. Berrangé @ 2026-10-08  9:36 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: luoyonggang, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Wed, Oct 07, 2026 at 05:00:06PM -0700, Pierrick Bouvier wrote:
> On 10/7/2026 2:42 PM, Yonggang Luo wrote:
> > On Thu, Oct 8, 2026 at 4:44 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> >>> Change TypeInfo.is_available to the new TypeIsAvailable type, which
> >>> takes a const TargetInfo *. Registration passes target_info(), so
> >>> behavior is unchanged. object.h only forward-declares TargetInfo.
> >>>
> >>> Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
> >>> generated machine parents to the matching target_is_<arch> helpers.
> >>>
> >>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> >>> ---
> >>>  hw/arm/aspeed_ast27x0-fc.c  |  2 +-
> >>>  hw/arm/aspeed_ast27x0_evb.c |  4 ++--
> >>>  hw/arm/raspi.c              |  4 ++--
> >>>  hw/arm/raspi4b.c            |  2 +-
> >>>  hw/arm/virt.c               |  4 ++--
> >>>  hw/m68k/virt.c              |  4 ++--
> >>>  hw/or1k/virt.c              |  2 +-
> >>>  include/qom/object.h        | 12 +++++++++++-
> >>>  qom/object.c                |  3 ++-
> >>>  9 files changed, 24 insertions(+), 13 deletions(-)

snip

> >>> @@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
> >>>          abort();
> >>>      }
> >>>
> >>> -    if (info->is_available && !info->is_available()) {
> >>> +    if (info->is_available && !info->is_available(target_info())) {
> >>>          return NULL;
> >>>      }
> >>>
> >>
> >> ```
> >> info->is_available(target_info())
> >> ```
> >>
> >> or
> >>
> >> ```
> >> is_available() {
> >>   TargetInfo ti * = target_info();
> >>   ...
> >> }
> >> ```
> >>
> >> Are doing the exact same thing today.
> >>
> >> So what is the future goal requiring to introduce this?
> > 
> > From Daniel P. Berrangé's
> > requesthttps://lore.kernel.org/qemu-devel/apAszS1ewxM0Y1XU@redhat.com/
> >         I forgot to mention that this is also pretty important for making
> >         introspection work, as we need to be able to say
> > 
> >           'qemu-system --machine none -qmp ...'
> > 
> >         and connect to QMP to introspect the binary. Having to add a
> >         '--target <name>' into that mix is undesirable, as it creates
> >         a chicken & egg problem. You don't know what targets are built
> >         into qemu-system without introspecting it and you can't
> >         introspect it without selecting a target to introspect.
> > 
> > From Pierrick's review
> > https://lore.kernel.org/qemu-devel/557262df-b8e7-49b5-a245-ae46b8885b30@oss.qualcomm.com/So,
> > for existing binary: -M virt works as before.
> > 
> >         For new multi binary:
> >         $ qemu-system -M virt:
> >         Multiple machines were found, select one among:
> >         - aarch64-virt
> >         - riscv64-virt
> > 
> >         Does it matches what you would expect?
> > 
> > From Daniel's review
> > https://lore.kernel.org/qemu-devel/aro93NuZBXYGbD33@redhat.com/
> >         We already have  'QemuTargetInfo' struct which is used
> >         with 'query-target', that should also be used with the
> >         new 'query-targets' command.
> > 
> >         We need to add the 'endianness' field to QemuTargetInfo.
> > 
> >         I don't think that we need to report machines though.
> >         We already have 'query-machines' which gives much broader
> >         information on the machines. "MachineInfo" needs to
> >         gain
> > 
> >         "targets": ["SysEmuTarget"]
> > 
> >         to list which target(s) a machine can be used with.
> > 
> > 
> > To achieve these, we needs add TypeInfo parameter to it so that we can do
> > 
> > static void report_unsupported_machine_type(const char *name, Error **errp)
> > {
> >     g_autoptr(GSList) machines = machine_class_get_list(true);
> >     g_autoptr(GString) targets = g_string_new(NULL);
> >     TargetInfoNode *node;
> >     GSList *el;
> > 
> >     error_setg(errp, "unsupported machine type: \"%s\" for target \"%s\"",
> >                name, target_name());
> >     QLIST_FOREACH(node, target_info_list(), next) {
> >         for (el = machines; el; el = el->next) {
> >             MachineClass *mc = el->data;
> > 
> >             if ((!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) &&
> >                 object_class_get_is_available(OBJECT_CLASS(mc))(node->info)) {
> >                 g_string_append_printf(targets, "  %s\n",
> >                                        node->info->target_name);
> >                 break;
> >             }
> >         }
> >     }
> >     if (targets->len) {
> >         error_append_hint(errp, "Available for targets:\n%s", targets->str);
> >     }
> > }
> > 
> > That is we can iterate on all target-list, and check if it's can be fitlered.
> >
> 
> Ok, I finally see where this is going.
> 
> So, based on all the previous conversations, we agreed to have a
> qemu-system binary with all the QOM types available (for all targets).

ack.

> I personally think that if we go this way, we should not have any
> -target option, and even less a -target none option.

If we don't have a compelling need for -target to exist now, then
dropping it as a concept is good.

> The current is_available() approach was made with filtering per target
> in mind, which predates where things are now. So, it's a good time to
> reevaluate how to do it.
> 
> This leaves us with (at least) two options:
> - keep the callback and add TargetInfo parameter (what is done here)
> - remove is_available, and adopt a more declarative approach
> 
> How about we (re)-explore the second one?
> 
> It's what we did in the past
> (https://gitlab.com/qemu-project/qemu/-/commit/5de9216064d32eaac125dac4de1878486c16d73e),
> and that I removed recently, in favor of is_available.
> My rationale was that it was incomplete, since we needed to filter types
> per config also, and not only target.
> Now that direction is to not filter anything, filter per config is
> unneeded, and switching back to declarative instead of callback makes
> total sense. Using interfaces like we did has its own issues, and I
> would not like to see this coming back.
> 
> I'll do one very concrete proposal:
> 
> ```
> How about letting machines (and machines only first), have a new field
> 'targets', being a uint32_t mask with an array of EMU_TARGET?
> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
> ```
> 
> @Daniel, IIUC, this is exactly the approach you proposed a few weeks
> ago, just before I got frustrated and lost my patience against you. I
> think it's more clear for me where you wanted to go. Sorry it took such
> a large detour.

Not a problem. We were coming at the debate with different ideas of
where we were heading, so talking past each other at times.

> 
> Yonggang, does that sounds good for you?
> Daniel, does that sounds good for you also?

Works for me.

With regards,
Daniel
-- 
|: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
|: https://libvirt.org          ~~          https://entangle-photo.org :|
|: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|



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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-07 20:25 ` [PATCH 0/8] qom: pass TargetInfo to the is_available callback Pierrick Bouvier
@ 2026-10-08  9:42   ` Daniel P. Berrangé
  2026-10-08  9:46     ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Daniel P. Berrangé @ 2026-10-08  9:42 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Yonggang Luo, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> > This allows a combined binary to register machine types from all its targets.
> > Consequently, QMP `query-machines` can return machine entries from every
> > target, even when `none` is selected. For example, a client can query the
> > combined machine list with:
> > 
> > ```json
> > { "execute": "query-machines" }
> > ```
> > 
> > The returned list includes the registered machine classes from all linked
> > targets. This is separate from selecting a machine: with `-target none`,
> > `-M virt` reports the targets that provide `virt` instead of choosing one
> > arbitrarily:
> > 
> > ```text
> > qemu-system -target none -M virt
> > unsupported machine type: "virt" for target "none"
> > Available for targets:
> >   aarch64
> >   arm
> > ```
> >
> 
> From the long conversation on a previous thread, I thought we reached
> the conclusion that if we didn't expose any ambiguous name, then -target
> option is unnecessary, or maybe I got lost on track of this thread.
> 
> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> 
> I'm not sure which semantic we want to have with -target none. If there
> is no ambiguous name registered, we just don't need it at all. It's a
> win-win IMHO.

Yes, if we expose unique names for every machine, then -target is then
redundant.

With regards,
Daniel
-- 
|: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
|: https://libvirt.org          ~~          https://entangle-photo.org :|
|: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|



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

* Re: [PATCH 1/8] configs/targets: remove target info definitions
  2026-10-07 20:26   ` Pierrick Bouvier
@ 2026-10-08  9:46     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 62+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-08  9:46 UTC (permalink / raw)
  To: Pierrick Bouvier, Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Marc-André Lureau, Steven Lee, Alexander Bulekov,
	Darren Kenny

On 7/10/26 22:26, Pierrick Bouvier wrote:
> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>> From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
>>
>> Now that we remove machine_typename, we don't need to keep duplicated
>> file per target anymore. So we can just rely on target-info-stub.c.
>>
>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
>> ---
>>   MAINTAINERS                       |  1 -
>>   configs/targets/aarch64-softmmu.c | 25 -------------------------
>>   configs/targets/arm-softmmu.c     | 25 -------------------------
>>   configs/targets/meson.build       |  6 ------
>>   configs/targets/riscv32-softmmu.c | 24 ------------------------
>>   configs/targets/riscv64-softmmu.c | 24 ------------------------
>>   meson.build                       |  7 +------
>>   7 files changed, 1 insertion(+), 111 deletions(-)
>>   delete mode 100644 configs/targets/aarch64-softmmu.c
>>   delete mode 100644 configs/targets/arm-softmmu.c
>>   delete mode 100644 configs/targets/meson.build
>>   delete mode 100644 configs/targets/riscv32-softmmu.c
>>   delete mode 100644 configs/targets/riscv64-softmmu.c
>> diff --git a/configs/targets/riscv64-softmmu.c b/configs/targets/riscv64-softmmu.c
>> deleted file mode 100644
>> index 553bd1f75fe..00000000000
>> --- a/configs/targets/riscv64-softmmu.c
>> +++ /dev/null
>> @@ -1,24 +0,0 @@
>> -/*
>> - * QEMU binary/target API (qemu-system-riscv64)
>> - *
>> - *  Copyright (c) rev.ng Labs Srl.
>> - *
>> - * SPDX-License-Identifier: GPL-2.0-or-later
>> - */
>> -
>> -#include "qemu/osdep.h"
>> -#include "qemu/target-info-impl.h"
>> -#include "qemu/target-info-init.h"
>> -#include "target/riscv/cpu-qom.h"
>> -#include "target/riscv/cpu-param.h"
>> -
>> -static const TargetInfo target_info_riscv64_system = {
>> -    .target_name = "riscv64",
>> -    .target_arch = SYS_EMU_TARGET_RISCV64,
>> -    .long_bits = 64,
>> -    .cpu_type = TYPE_RISCV_CPU,
>> -    .endianness = ENDIAN_MODE_LITTLE,
>> -    .page_bits_init = TARGET_PAGE_BITS,
>> -};
>> -
>> -target_info_init(target_info_riscv64_system)
>> diff --git a/meson.build b/meson.build
>> index 828100de816..64d3f7675f7 100644
>> --- a/meson.build
>> +++ b/meson.build
>> @@ -3754,7 +3754,6 @@ subdir('dump')
>>   subdir('accel')
>>   
>>   subdir('backends')
>> -subdir('configs/targets')
>>   subdir('disas')
>>   subdir('migration')
>>   subdir('monitor')
>> @@ -4346,11 +4345,7 @@ foreach target : target_dirs
>>       endif
>>     endif
>>   
>> -  if target in config_target_info
>> -    arch_srcs += config_target_info[target]
>> -  else
>> -    arch_srcs += files('target-info-stub.c')
>> -  endif
>> +  arch_srcs += files('target-info-stub.c')
>>   
>>     if target_base_arch in target_arch
>>       t = target_arch[target_base_arch].apply(config_target, strict: false)
> 
> We delayed this patch because initially we thought we might need to add
> other things in this struct (per target). However, it was not proven it
> was needed, thus I'll pull this.

I think because in early prototype I was initializing manually
with a 2-target {&target_info_aarch64, &target_info_microblaze}
explicit set, but this predates target_info_init() which does the
QOM type registration, so today we can simply use a set of QOM
typenames IIUC.


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-08  9:42   ` Daniel P. Berrangé
@ 2026-10-08  9:46     ` Yonggang Luo
  2026-10-08 16:06       ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-08  9:46 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Pierrick Bouvier, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> > On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> > > This allows a combined binary to register machine types from all its targets.
> > > Consequently, QMP `query-machines` can return machine entries from every
> > > target, even when `none` is selected. For example, a client can query the
> > > combined machine list with:
> > >
> > > ```json
> > > { "execute": "query-machines" }
> > > ```
> > >
> > > The returned list includes the registered machine classes from all linked
> > > targets. This is separate from selecting a machine: with `-target none`,
> > > `-M virt` reports the targets that provide `virt` instead of choosing one
> > > arbitrarily:
> > >
> > > ```text
> > > qemu-system -target none -M virt
> > > unsupported machine type: "virt" for target "none"
> > > Available for targets:
> > >   aarch64
> > >   arm
> > > ```
> > >
> >
> > From the long conversation on a previous thread, I thought we reached
> > the conclusion that if we didn't expose any ambiguous name, then -target
> > option is unnecessary, or maybe I got lost on track of this thread.
> >
> > https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >
> > I'm not sure which semantic we want to have with -target none. If there
> > is no ambiguous name registered, we just don't need it at all. It's a
> > win-win IMHO.
>
> Yes, if we expose unique names for every machine, then -target is then
> redundant.

so how to diff riscv32-virt and risv64-virt? oh so for this machine we
needs two name?
"virt" needs register twice for it? or register only a single time,
but we prefix the target_name()
automatically? for example machine::name === "virt", but we can use
"riscv32-virt" "risv64-virt" to reach it?

>
> With regards,
> Daniel
> --
> |: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
> |: https://libvirt.org          ~~          https://entangle-photo.org :|
> |: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|
>


-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08  9:36         ` Daniel P. Berrangé
@ 2026-10-08  9:56           ` Yonggang Luo
  2026-10-08 16:01             ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-08  9:56 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Pierrick Bouvier, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Thu, Oct 8, 2026 at 5:36 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Wed, Oct 07, 2026 at 05:00:06PM -0700, Pierrick Bouvier wrote:
> > On 10/7/2026 2:42 PM, Yonggang Luo wrote:
> > > On Thu, Oct 8, 2026 at 4:44 AM Pierrick Bouvier
> > > <pierrick.bouvier@oss.qualcomm.com> wrote:
> > >>
> > >> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> > >>> Change TypeInfo.is_available to the new TypeIsAvailable type, which
> > >>> takes a const TargetInfo *. Registration passes target_info(), so
> > >>> behavior is unchanged. object.h only forward-declares TargetInfo.
> > >>>
> > >>> Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
> > >>> generated machine parents to the matching target_is_<arch> helpers.
> > >>>
> > >>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> > >>> ---
> > >>>  hw/arm/aspeed_ast27x0-fc.c  |  2 +-
> > >>>  hw/arm/aspeed_ast27x0_evb.c |  4 ++--
> > >>>  hw/arm/raspi.c              |  4 ++--
> > >>>  hw/arm/raspi4b.c            |  2 +-
> > >>>  hw/arm/virt.c               |  4 ++--
> > >>>  hw/m68k/virt.c              |  4 ++--
> > >>>  hw/or1k/virt.c              |  2 +-
> > >>>  include/qom/object.h        | 12 +++++++++++-
> > >>>  qom/object.c                |  3 ++-
> > >>>  9 files changed, 24 insertions(+), 13 deletions(-)
>
> snip
>
> > >>> @@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
> > >>>          abort();
> > >>>      }
> > >>>
> > >>> -    if (info->is_available && !info->is_available()) {
> > >>> +    if (info->is_available && !info->is_available(target_info())) {
> > >>>          return NULL;
> > >>>      }
> > >>>
> > >>
> > >> ```
> > >> info->is_available(target_info())
> > >> ```
> > >>
> > >> or
> > >>
> > >> ```
> > >> is_available() {
> > >>   TargetInfo ti * = target_info();
> > >>   ...
> > >> }
> > >> ```
> > >>
> > >> Are doing the exact same thing today.
> > >>
> > >> So what is the future goal requiring to introduce this?
> > >
> > > From Daniel P. Berrangé's
> > > requesthttps://lore.kernel.org/qemu-devel/apAszS1ewxM0Y1XU@redhat.com/
> > >         I forgot to mention that this is also pretty important for making
> > >         introspection work, as we need to be able to say
> > >
> > >           'qemu-system --machine none -qmp ...'
> > >
> > >         and connect to QMP to introspect the binary. Having to add a
> > >         '--target <name>' into that mix is undesirable, as it creates
> > >         a chicken & egg problem. You don't know what targets are built
> > >         into qemu-system without introspecting it and you can't
> > >         introspect it without selecting a target to introspect.
> > >
> > > From Pierrick's review
> > > https://lore.kernel.org/qemu-devel/557262df-b8e7-49b5-a245-ae46b8885b30@oss.qualcomm.com/So,
> > > for existing binary: -M virt works as before.
> > >
> > >         For new multi binary:
> > >         $ qemu-system -M virt:
> > >         Multiple machines were found, select one among:
> > >         - aarch64-virt
> > >         - riscv64-virt
> > >
> > >         Does it matches what you would expect?
> > >
> > > From Daniel's review
> > > https://lore.kernel.org/qemu-devel/aro93NuZBXYGbD33@redhat.com/
> > >         We already have  'QemuTargetInfo' struct which is used
> > >         with 'query-target', that should also be used with the
> > >         new 'query-targets' command.
> > >
> > >         We need to add the 'endianness' field to QemuTargetInfo.
> > >
> > >         I don't think that we need to report machines though.
> > >         We already have 'query-machines' which gives much broader
> > >         information on the machines. "MachineInfo" needs to
> > >         gain
> > >
> > >         "targets": ["SysEmuTarget"]
> > >
> > >         to list which target(s) a machine can be used with.
> > >
> > >
> > > To achieve these, we needs add TypeInfo parameter to it so that we can do
> > >
> > > static void report_unsupported_machine_type(const char *name, Error **errp)
> > > {
> > >     g_autoptr(GSList) machines = machine_class_get_list(true);
> > >     g_autoptr(GString) targets = g_string_new(NULL);
> > >     TargetInfoNode *node;
> > >     GSList *el;
> > >
> > >     error_setg(errp, "unsupported machine type: \"%s\" for target \"%s\"",
> > >                name, target_name());
> > >     QLIST_FOREACH(node, target_info_list(), next) {
> > >         for (el = machines; el; el = el->next) {
> > >             MachineClass *mc = el->data;
> > >
> > >             if ((!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) &&
> > >                 object_class_get_is_available(OBJECT_CLASS(mc))(node->info)) {
> > >                 g_string_append_printf(targets, "  %s\n",
> > >                                        node->info->target_name);
> > >                 break;
> > >             }
> > >         }
> > >     }
> > >     if (targets->len) {
> > >         error_append_hint(errp, "Available for targets:\n%s", targets->str);
> > >     }
> > > }
> > >
> > > That is we can iterate on all target-list, and check if it's can be fitlered.
> > >
> >
> > Ok, I finally see where this is going.
> >
> > So, based on all the previous conversations, we agreed to have a
> > qemu-system binary with all the QOM types available (for all targets).
>
> ack.
>
> > I personally think that if we go this way, we should not have any
> > -target option, and even less a -target none option.
>
> If we don't have a compelling need for -target to exist now, then
> dropping it as a concept is good.
>
> > The current is_available() approach was made with filtering per target
> > in mind, which predates where things are now. So, it's a good time to
> > reevaluate how to do it.
> >
> > This leaves us with (at least) two options:
> > - keep the callback and add TargetInfo parameter (what is done here)
> > - remove is_available, and adopt a more declarative approach
> >
> > How about we (re)-explore the second one?
> >
> > It's what we did in the past
> > (https://gitlab.com/qemu-project/qemu/-/commit/5de9216064d32eaac125dac4de1878486c16d73e),
> > and that I removed recently, in favor of is_available.
> > My rationale was that it was incomplete, since we needed to filter types
> > per config also, and not only target.
> > Now that direction is to not filter anything, filter per config is
> > unneeded, and switching back to declarative instead of callback makes
> > total sense. Using interfaces like we did has its own issues, and I
> > would not like to see this coming back.
> >
> > I'll do one very concrete proposal:
> >
> > ```
> > How about letting machines (and machines only first), have a new field
> > 'targets', being a uint32_t mask with an array of EMU_TARGET?
> > machine->targets = EMU_TARGET_X | EMU_TARGET_Y;

To be explicit state what, I give you a pseudo code to compute
machine->targets from TypeInfo::is_available(TargetInfo*)
let targets=0
foreach ti of TargetInfo list:
   if (machine::TypeImpl::is_avaible(ti))
         targets |= 1 << ti->target_arch
   fi
endif
So they basically have equivalent effect, and is_available will handle
other code-needed condition properly such as
CPU/AccelClass. not restrict to targets, we can also attach the
KConfig into TargetInfo, so is_available(TargetInfo*)
also works for Kconfig. that's why I insist this way, it's solved all
the issues around.

so  machine->targets = EMU_TARGET_X | EMU_TARGET_Y; is a good idea,
and it can be implemented with TypeInfo::is_available(TargetInfo*)
without much burden. and targets can be saved into a (machine or
TypeImpl) for fast access when needed, we can compute it
when the program starts.


> > ```
> >
> > @Daniel, IIUC, this is exactly the approach you proposed a few weeks
> > ago, just before I got frustrated and lost my patience against you. I
> > think it's more clear for me where you wanted to go. Sorry it took such
> > a large detour.
>
> Not a problem. We were coming at the debate with different ideas of
> where we were heading, so talking past each other at times.
>
> >
> > Yonggang, does that sounds good for you?
> > Daniel, does that sounds good for you also?
>
> Works for me.
>
> With regards,
> Daniel
> --
> |: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
> |: https://libvirt.org          ~~          https://entangle-photo.org :|
> |: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|
>


-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08  2:08         ` Yonggang Luo
@ 2026-10-08 15:58           ` Pierrick Bouvier
  0 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-08 15:58 UTC (permalink / raw)
  To: luoyonggang
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 7:08 PM, Yonggang Luo wrote:
>> So, based on all the previous conversations, we agreed to have a
>> qemu-system binary with all the QOM types available (for all targets).
>>
>> I personally think that if we go this way, we should not have any
>> -target option, and even less a -target none option.
>>
>> The current is_available() approach was made with filtering per target
>> in mind, which predates where things are now. So, it's a good time to
>> reevaluate how to do it.
>>
>> This leaves us with (at least) two options:
>> - keep the callback and add TargetInfo parameter (what is done here)
>> - remove is_available, and adopt a more declarative approach
>>
>> How about we (re)-explore the second one?
> 
> Indeed, I am doing
> 
> - preserve is_available(TargetInfo*), and adopt a more declarative approach
> 
> /* Generated by scripts/gen-target-info.py. Do not edit. */
> 

...

>     {
>         .name = TYPE_TARGET_BASE_ARM_MACHINE,
>         .parent = TYPE_MACHINE,
>         .abstract = true,
>         .is_available = target_is_base_arm,
>     },

>     {
>         .name = TYPE_TARGET_AARCH64_MACHINE,
>         .parent = TYPE_TARGET_BASE_ARM_MACHINE,
>         .abstract = true,
>         .is_available = target_is_aarch64,
>     },
>     {
>         .name = TYPE_TARGET_ARM_MACHINE,
>         .parent = TYPE_TARGET_BASE_ARM_MACHINE,
>         .abstract = true,
>         .is_available = target_is_arm,
>     },

...

> Other than these base machines, other machines are children of these
> base machines.
> 
> See these changes
> https://gitlab.com/lygstate-qemu/qemu/-/commit/c71da20c2483cdf577fd2a5548a80ca1e5099676
> https://gitlab.com/lygstate-qemu/qemu/-/commit/252b8763fd74ec57f5762bf9c57e19d8d9e5a146
> https://gitlab.com/lygstate-qemu/qemu/-/commit/252b8763fd74ec57f5762bf9c57e19d8d9e5a146
> https://gitlab.com/lygstate-qemu/qemu/-/commit/252b8763fd74ec57f5762bf9c57e19d8d9e5a146
> For ARM:
> https://gitlab.com/lygstate-qemu/qemu/-/commit/c42d5eb333fd3a7cab899c8df95375dfc79aba40
> 
> These base machine type is auto-generated in this MR.
> You can see at the branch
> https://gitlab.com/lygstate-qemu/qemu/-/commits/single-binary-arm-riscv?ref_type=heads
> 
> And the inherit is done by commits
> qom: inherit is_available and filter after MODULE_INIT_QOM:
> https://gitlab.com/lygstate-qemu/qemu/-/commit/cb66474a36e03b4353c2f525ce7821f2af779ea1
> qom: register late types through module_call_init_fn:
> https://gitlab.com/lygstate-qemu/qemu/-/commit/ba6a3d3fb6e4bfe35d88d3845abf7b0ec8fbc337
> module: add before/after hooks and module_call_init_fn:
> https://gitlab.com/lygstate-qemu/qemu/-/commit/86c635f45e283b6d0f714a1a3a9d9521b17d5152
> 
> And the gitlab-ci is already passed
> 
>

The hierarchy based approach (we considered that also at the time) has a
big caveat: a QOM type can only have one parent. There is no multi
inheritance in our model.

You can easily merge arm and aarch64 under a base_arm parent. However,
you can't express:
- this machine is available for target X and Y (x-remote, nitro, null)

That's why we chose interfaces based tagging 1.5 years ago, because they
allow multi inheritance in some ways.

>>
>> It's what we did in the past
>> (https://gitlab.com/qemu-project/qemu/-/commit/5de9216064d32eaac125dac4de1878486c16d73e),
> 
> Somewhat alike except I do not introduce many interface types. Just
> base machine types.
> 
>> and that I removed recently, in favor of is_available.
>> My rationale was that it was incomplete, since we needed to filter types
>> per config also, and not only target.
>> Now that direction is to not filter anything, filter per config is
>> unneeded, and switching back to declarative instead of callback makes
>> total sense. Using interfaces like we did has its own issues, and I
>> would not like to see this coming back.
>>
>> I'll do one very concrete proposal:
>>
>> ```
>> How about letting machines (and machines only first), have a new field
>> 'targets', being a uint32_t mask with an array of EMU_TARGET?
>> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
>>

For now, it's the best I can think of. I tried having an array of
EMU_TARGET but declaring it was a verbose mess.
The arch mask, that you or Daniel sugggested at some point IIRC, is the
best compromise here: it's compact and readable.

> 
> From my experience at
> https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
> this is not enough, we still needs is_avaible, because for those
> machines that binding to
> KVM/WHPX and other accels, we need to use target_kconfig to handle
> them. That's why I choose to use a unified
> is_avaible(TargetInfo*).
>

Given our base assumption to expose all types, why should we care about
kvm/whpx? If we don't have a proper message when user select a wrong
machine/cpu type, we can simply add one.

> This new field only works if is_availbe still be a member of TypeInfo.
> machine->targets are not generic. Indeed CPU and ACCEL(kvm/whpx/hyp)
> types also need filtering.
>

Yes, so CPU can have the same target field. Since we won't filter
devices, I don't see a need to have this in object.c. Also, it can
completely replace the existing is_available mechanic.

Also, in multi-target.c test, we can add a new test to ensure all
machines and all cpus that belongs to this binary have targets set.
This allows to leave the rest of architectures as they are for now, and
force to add this when we'll integrate them.

Regards,
Pierrick


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08  9:56           ` Yonggang Luo
@ 2026-10-08 16:01             ` Pierrick Bouvier
  2026-10-08 17:04               ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-08 16:01 UTC (permalink / raw)
  To: luoyonggang, Daniel P. Berrangé
  Cc: qemu-devel, Cleber Rosa, Stefan Hajnoczi, Cédric Le Goater,
	Laurent Vivier, Zhao Liu, John Snow, Laurent Vivier,
	Richard Henderson, Joel Stanley, Fabiano Rosas, Kane Chen,
	Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne, qemu-arm,
	Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/8/2026 2:56 AM, Yonggang Luo wrote:
>>> How about letting machines (and machines only first), have a new field
>>> 'targets', being a uint32_t mask with an array of EMU_TARGET?
>>> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
> 
> To be explicit state what, I give you a pseudo code to compute
> machine->targets from TypeInfo::is_available(TargetInfo*)
> let targets=0
> foreach ti of TargetInfo list:
>    if (machine::TypeImpl::is_avaible(ti))
>          targets |= 1 << ti->target_arch
>    fi
> endif
> So they basically have equivalent effect, and is_available will handle
> other code-needed condition properly such as
> CPU/AccelClass. not restrict to targets, we can also attach the
> KConfig into TargetInfo, so is_available(TargetInfo*)
> also works for Kconfig. that's why I insist this way, it's solved all
> the issues around.
> 
> so  machine->targets = EMU_TARGET_X | EMU_TARGET_Y; is a good idea,
> and it can be implemented with TypeInfo::is_available(TargetInfo*)
> without much burden. and targets can be saved into a (machine or
> TypeImpl) for fast access when needed, we can compute it
> when the program starts.
>

In what we described, there is no need to keep any kind of callback,
targets field is sufficient to filter any type declaratively.

For the KConfig related types, I would really be keen to leave that
available for now, and add a proper error message later.

Regards,
Pierrick


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-08  9:46     ` Yonggang Luo
@ 2026-10-08 16:06       ` Pierrick Bouvier
  2026-10-08 17:13         ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-08 16:06 UTC (permalink / raw)
  To: luoyonggang, Daniel P. Berrangé
  Cc: qemu-devel, Cleber Rosa, Stefan Hajnoczi, Cédric Le Goater,
	Laurent Vivier, Zhao Liu, John Snow, Laurent Vivier,
	Richard Henderson, Joel Stanley, Fabiano Rosas, Kane Chen,
	Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne, qemu-arm,
	Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>
>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>>>> This allows a combined binary to register machine types from all its targets.
>>>> Consequently, QMP `query-machines` can return machine entries from every
>>>> target, even when `none` is selected. For example, a client can query the
>>>> combined machine list with:
>>>>
>>>> ```json
>>>> { "execute": "query-machines" }
>>>> ```
>>>>
>>>> The returned list includes the registered machine classes from all linked
>>>> targets. This is separate from selecting a machine: with `-target none`,
>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
>>>> arbitrarily:
>>>>
>>>> ```text
>>>> qemu-system -target none -M virt
>>>> unsupported machine type: "virt" for target "none"
>>>> Available for targets:
>>>>   aarch64
>>>>   arm
>>>> ```
>>>>
>>>
>>> From the long conversation on a previous thread, I thought we reached
>>> the conclusion that if we didn't expose any ambiguous name, then -target
>>> option is unnecessary, or maybe I got lost on track of this thread.
>>>
>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
>>>
>>> I'm not sure which semantic we want to have with -target none. If there
>>> is no ambiguous name registered, we just don't need it at all. It's a
>>> win-win IMHO.
>>
>> Yes, if we expose unique names for every machine, then -target is then
>> redundant.
> 
> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> needs two name?
> "virt" needs register twice for it? or register only a single time,
> but we prefix the target_name()
> automatically? for example machine::name === "virt", but we can use
> "riscv32-virt" "risv64-virt" to reach it?
>

Yes, ideally we should have different variant of virt for 32/64 bit.
Same goes for cpu max types.

QOM type is always registered unambiguously ("$arch-virt"). Then, for
the "alias" name, which is virt, in case multiple matches are found,
command line can return an error with list of unambiguous names to call it.

$ qemu-system -M virt
Multiple virt machines are available. Please choose one of them:
- aarch64-virt
- riscv64-virt

There is no "parsing" of the argument, it's just the real QOM type. Then
we can find which target it implements from mc->targets.
And then, we can automatically choose which cpus should be available
based on that, thanks to cpu->targets.

For existing binaries, nothing change.

>>
>> With regards,
>> Daniel
>> --
>> |: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
>> |: https://libvirt.org          ~~          https://entangle-photo.org :|
>> |: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|
>>
> 
> 



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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08 16:01             ` Pierrick Bouvier
@ 2026-10-08 17:04               ` Yonggang Luo
  2026-10-08 18:26                 ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-08 17:04 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Fri, Oct 9, 2026 at 12:01 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/8/2026 2:56 AM, Yonggang Luo wrote:
> >>> How about letting machines (and machines only first), have a new field
> >>> 'targets', being a uint32_t mask with an array of EMU_TARGET?
> >>> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
> >
> > To be explicit state what, I give you a pseudo code to compute
> > machine->targets from TypeInfo::is_available(TargetInfo*)
> > let targets=0
> > foreach ti of TargetInfo list:
> >    if (machine::TypeImpl::is_avaible(ti))
> >          targets |= 1 << ti->target_arch
> >    fi
> > endif
> > So they basically have equivalent effect, and is_available will handle
> > other code-needed condition properly such as
> > CPU/AccelClass. not restrict to targets, we can also attach the
> > KConfig into TargetInfo, so is_available(TargetInfo*)
> > also works for Kconfig. that's why I insist this way, it's solved all
> > the issues around.
> >
> > so  machine->targets = EMU_TARGET_X | EMU_TARGET_Y; is a good idea,
> > and it can be implemented with TypeInfo::is_available(TargetInfo*)
> > without much burden. and targets can be saved into a (machine or
> > TypeImpl) for fast access when needed, we can compute it
> > when the program starts.
> >
>
> In what we described, there is no need to keep any kind of callback,
> targets field is sufficient to filter any type declaratively.
>
> For the KConfig related types, I would really be keen to leave that
> available for now, and add a proper error message later.

Thanks, much clearer now, I was working for full KConfig related types support
because I am trying to keep qemu-system-$arch to be a symlink to qemu-system
which will still work without breaking anything. If we do not keep this then
I machine::targets or TypeInfo::targets would be the best solution, I think
TypeInfo::targets is better, and copy it into TypeImpl::targets. and give a API
to retrieve it, for example:
uint64_t *object_class_get_targets(ObjectClass *klass);

Add "targets" struct members as TypeInfo::targets and TypeImpl::targets, and
copy from TypeInfo into TypeImpl for later access with
object_class_get_targets
Then we can use it for filtering machines and cpus without burden.

How to dealt with
https://lore.kernel.org/qemu-devel/20261007-rv-dedup-v2-6-8a2f0f296a7f@rev.ng/

It's using is_available.

Maybe all using the way like
Subject: [PATCH v2 07/18] target/riscv: Runtime register MAX and BARE CPUs
https://lore.kernel.org/qemu-devel/20261007-rv-dedup-v2-7-8a2f0f296a7f@rev.ng/
>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-08 16:06       ` Pierrick Bouvier
@ 2026-10-08 17:13         ` Yonggang Luo
  2026-10-08 18:34           ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-08 17:13 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> > On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>
> >> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> >>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> >>>> This allows a combined binary to register machine types from all its targets.
> >>>> Consequently, QMP `query-machines` can return machine entries from every
> >>>> target, even when `none` is selected. For example, a client can query the
> >>>> combined machine list with:
> >>>>
> >>>> ```json
> >>>> { "execute": "query-machines" }
> >>>> ```
> >>>>
> >>>> The returned list includes the registered machine classes from all linked
> >>>> targets. This is separate from selecting a machine: with `-target none`,
> >>>> `-M virt` reports the targets that provide `virt` instead of choosing one
> >>>> arbitrarily:
> >>>>
> >>>> ```text
> >>>> qemu-system -target none -M virt
> >>>> unsupported machine type: "virt" for target "none"
> >>>> Available for targets:
> >>>>   aarch64
> >>>>   arm
> >>>> ```
> >>>>
> >>>
> >>> From the long conversation on a previous thread, I thought we reached
> >>> the conclusion that if we didn't expose any ambiguous name, then -target
> >>> option is unnecessary, or maybe I got lost on track of this thread.
> >>>
> >>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >>>
> >>> I'm not sure which semantic we want to have with -target none. If there
> >>> is no ambiguous name registered, we just don't need it at all. It's a
> >>> win-win IMHO.
> >>
> >> Yes, if we expose unique names for every machine, then -target is then
> >> redundant.
> >
> > so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> > needs two name?
> > "virt" needs register twice for it? or register only a single time,
> > but we prefix the target_name()
> > automatically? for example machine::name === "virt", but we can use
> > "riscv32-virt" "risv64-virt" to reach it?
> >
>
> Yes, ideally we should have different variant of virt for 32/64 bit.
> Same goes for cpu max types.
>
> QOM type is always registered unambiguously ("$arch-virt"). Then, for
> the "alias" name, which is virt, in case multiple matches are found,
> command line can return an error with list of unambiguous names to call it.
>
> $ qemu-system -M virt
> Multiple virt machines are available. Please choose one of them:
> - aarch64-virt
> - riscv64-virt
>
> There is no "parsing" of the argument, it's just the real QOM type. Then
> we can find which target it implements from mc->targets.
> And then, we can automatically choose which cpus should be available
> based on that, thanks to cpu->targets.
>
> For existing binaries, nothing change.

Good, I think we found a clean way now, is_available should be
removed, and TypeInfo::targets and TypeImpl::targets should be added.
I think
for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
the $arch specific virt. so that we only have a single "virt" registered.
And it's
targets is
QEMU_ARCH_I386 |
QEMU_ARCH_ARM |
QEMU_ARCH_RISCV |
QEMU_ARCH_LOONGARCH |
QEMU_ARCH_M68K |
QEMU_ARCH_OR1K |
QEMU_ARCH_XTENSA |
QEMU_ARCH_HEXAGON

So that we won't have a list of conflict QOM names for "virt" machines.
As now we indeed have only a single "virt" machine that redirects to
different targets.


For other types also conflict can be handled in the same way, such as
"-cpu host" "-cpu max"
maybe others, but I think they all have the same way to deal with.


That's why  TypeInfo::targets and TypeImpl::targets better than sole
Machine::targets

>
> >>
> >> With regards,
> >> Daniel
> >> --
> >> |: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
> >> |: https://libvirt.org          ~~          https://entangle-photo.org :|
> >> |: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|
> >>
> >
> >
>


-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08 17:04               ` Yonggang Luo
@ 2026-10-08 18:26                 ` Pierrick Bouvier
  2026-10-08 18:33                   ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-08 18:26 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/8/2026 10:04 AM, Yonggang Luo wrote:
> On Fri, Oct 9, 2026 at 12:01 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/8/2026 2:56 AM, Yonggang Luo wrote:
>>>>> How about letting machines (and machines only first), have a new field
>>>>> 'targets', being a uint32_t mask with an array of EMU_TARGET?
>>>>> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
>>>
>>> To be explicit state what, I give you a pseudo code to compute
>>> machine->targets from TypeInfo::is_available(TargetInfo*)
>>> let targets=0
>>> foreach ti of TargetInfo list:
>>>    if (machine::TypeImpl::is_avaible(ti))
>>>          targets |= 1 << ti->target_arch
>>>    fi
>>> endif
>>> So they basically have equivalent effect, and is_available will handle
>>> other code-needed condition properly such as
>>> CPU/AccelClass. not restrict to targets, we can also attach the
>>> KConfig into TargetInfo, so is_available(TargetInfo*)
>>> also works for Kconfig. that's why I insist this way, it's solved all
>>> the issues around.
>>>
>>> so  machine->targets = EMU_TARGET_X | EMU_TARGET_Y; is a good idea,
>>> and it can be implemented with TypeInfo::is_available(TargetInfo*)
>>> without much burden. and targets can be saved into a (machine or
>>> TypeImpl) for fast access when needed, we can compute it
>>> when the program starts.
>>>
>>
>> In what we described, there is no need to keep any kind of callback,
>> targets field is sufficient to filter any type declaratively.
>>
>> For the KConfig related types, I would really be keen to leave that
>> available for now, and add a proper error message later.
> 
> Thanks, much clearer now, I was working for full KConfig related types support
> because I am trying to keep qemu-system-$arch to be a symlink to qemu-system
> which will still work without breaking anything. If we do not keep this then
> I machine::targets or TypeInfo::targets would be the best solution, I think
> TypeInfo::targets is better, and copy it into TypeImpl::targets. and give a API
> to retrieve it, for example:
> uint64_t *object_class_get_targets(ObjectClass *klass);
>

We can exclude the goal to replace existing binaries with a symlink for now.

Please do not add this to TypeInfo, but to MachineClass instead, as
explained in previous email.
If you want to reduce upcoming frustration, I would really recommend you
stick to this, and to a single machine to start. So we can validate the
series, review it, and then you can iterate.
 > Add "targets" struct members as TypeInfo::targets and
TypeImpl::targets, and
> copy from TypeInfo into TypeImpl for later access with
> object_class_get_targets
> Then we can use it for filtering machines and cpus without burden.
> 
> How to dealt with
> https://lore.kernel.org/qemu-devel/20261007-rv-dedup-v2-6-8a2f0f296a7f@rev.ng/
> 
> It's using is_available.
>

.targets field can be conditioned by ifdef for config vs user, since
what we have everything needed in build system allows to duplicate
objects between user and system.

#ifdef CONFIG_USER_ONLY
 .targets = ...
#else
 .targets = ...
#endif

If that's not enough, it means the type has to be duplicated in some
ways to resolve ambiguity (especially for 32 vs 64 bits variants).

> Maybe all using the way like
> Subject: [PATCH v2 07/18] target/riscv: Runtime register MAX and BARE CPUs
> https://lore.kernel.org/qemu-devel/20261007-rv-dedup-v2-7-8a2f0f296a7f@rev.ng/

I would invite you to focus on a *single* machine first. See how to
declare it, and how to query which target it supports. Then we can see
what works/doesn't work, and (in a future series) we can do the same
thing for cpus.

You'll see that this iterative approach works much better than sending
huge series. You have my word I'll be reactive and present to help
continue this effort.

Regards,
Pierrick


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08 18:26                 ` Pierrick Bouvier
@ 2026-10-08 18:33                   ` Yonggang Luo
  2026-10-08 18:40                     ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-08 18:33 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Fri, Oct 9, 2026 at 2:27 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/8/2026 10:04 AM, Yonggang Luo wrote:
> > On Fri, Oct 9, 2026 at 12:01 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/8/2026 2:56 AM, Yonggang Luo wrote:
> >>>>> How about letting machines (and machines only first), have a new field
> >>>>> 'targets', being a uint32_t mask with an array of EMU_TARGET?
> >>>>> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
> >>>
> >>> To be explicit state what, I give you a pseudo code to compute
> >>> machine->targets from TypeInfo::is_available(TargetInfo*)
> >>> let targets=0
> >>> foreach ti of TargetInfo list:
> >>>    if (machine::TypeImpl::is_avaible(ti))
> >>>          targets |= 1 << ti->target_arch
> >>>    fi
> >>> endif
> >>> So they basically have equivalent effect, and is_available will handle
> >>> other code-needed condition properly such as
> >>> CPU/AccelClass. not restrict to targets, we can also attach the
> >>> KConfig into TargetInfo, so is_available(TargetInfo*)
> >>> also works for Kconfig. that's why I insist this way, it's solved all
> >>> the issues around.
> >>>
> >>> so  machine->targets = EMU_TARGET_X | EMU_TARGET_Y; is a good idea,
> >>> and it can be implemented with TypeInfo::is_available(TargetInfo*)
> >>> without much burden. and targets can be saved into a (machine or
> >>> TypeImpl) for fast access when needed, we can compute it
> >>> when the program starts.
> >>>
> >>
> >> In what we described, there is no need to keep any kind of callback,
> >> targets field is sufficient to filter any type declaratively.
> >>
> >> For the KConfig related types, I would really be keen to leave that
> >> available for now, and add a proper error message later.
> >
> > Thanks, much clearer now, I was working for full KConfig related types support
> > because I am trying to keep qemu-system-$arch to be a symlink to qemu-system
> > which will still work without breaking anything. If we do not keep this then
> > I machine::targets or TypeInfo::targets would be the best solution, I think
> > TypeInfo::targets is better, and copy it into TypeImpl::targets. and give a API
> > to retrieve it, for example:
> > uint64_t *object_class_get_targets(ObjectClass *klass);
> >
>
> We can exclude the goal to replace existing binaries with a symlink for now.
>
> Please do not add this to TypeInfo, but to MachineClass instead, as
> explained in previous email.

I didn't see any simple way to do this, and don't know how, I am sorry.
MachineClass init procedure is scattered, how would that be? I am
afraid I am not
able to get this done. If you can give some prepare work would be appreciated

> If you want to reduce upcoming frustration, I would really recommend you
> stick to this, and to a single machine to start. So we can validate the
> series, review it, and then you can iterate.
>  > Add "targets" struct members as TypeInfo::targets and
> TypeImpl::targets, and
> > copy from TypeInfo into TypeImpl for later access with
> > object_class_get_targets
> > Then we can use it for filtering machines and cpus without burden.
> >
> > How to dealt with
> > https://lore.kernel.org/qemu-devel/20261007-rv-dedup-v2-6-8a2f0f296a7f@rev.ng/
> >
> > It's using is_available.
> >
>
> .targets field can be conditioned by ifdef for config vs user, since
> what we have everything needed in build system allows to duplicate
> objects between user and system.
>
> #ifdef CONFIG_USER_ONLY
>  .targets = ...
> #else
>  .targets = ...
> #endif
>
> If that's not enough, it means the type has to be duplicated in some
> ways to resolve ambiguity (especially for 32 vs 64 bits variants).
>
> > Maybe all using the way like
> > Subject: [PATCH v2 07/18] target/riscv: Runtime register MAX and BARE CPUs
> > https://lore.kernel.org/qemu-devel/20261007-rv-dedup-v2-7-8a2f0f296a7f@rev.ng/
>
> I would invite you to focus on a *single* machine first. See how to
> declare it, and how to query which target it supports. Then we can see
> what works/doesn't work, and (in a future series) we can do the same
> thing for cpus.
>
> You'll see that this iterative approach works much better than sending
> huge series. You have my word I'll be reactive and present to help
> continue this effort.
>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-08 17:13         ` Yonggang Luo
@ 2026-10-08 18:34           ` Pierrick Bouvier
  2026-10-08 18:48             ` Yonggang Luo
                               ` (2 more replies)
  0 siblings, 3 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-08 18:34 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/8/2026 10:13 AM, Yonggang Luo wrote:
> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>
>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>>>>>> This allows a combined binary to register machine types from all its targets.
>>>>>> Consequently, QMP `query-machines` can return machine entries from every
>>>>>> target, even when `none` is selected. For example, a client can query the
>>>>>> combined machine list with:
>>>>>>
>>>>>> ```json
>>>>>> { "execute": "query-machines" }
>>>>>> ```
>>>>>>
>>>>>> The returned list includes the registered machine classes from all linked
>>>>>> targets. This is separate from selecting a machine: with `-target none`,
>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
>>>>>> arbitrarily:
>>>>>>
>>>>>> ```text
>>>>>> qemu-system -target none -M virt
>>>>>> unsupported machine type: "virt" for target "none"
>>>>>> Available for targets:
>>>>>>   aarch64
>>>>>>   arm
>>>>>> ```
>>>>>>
>>>>>
>>>>> From the long conversation on a previous thread, I thought we reached
>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
>>>>> option is unnecessary, or maybe I got lost on track of this thread.
>>>>>
>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
>>>>>
>>>>> I'm not sure which semantic we want to have with -target none. If there
>>>>> is no ambiguous name registered, we just don't need it at all. It's a
>>>>> win-win IMHO.
>>>>
>>>> Yes, if we expose unique names for every machine, then -target is then
>>>> redundant.
>>>
>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
>>> needs two name?
>>> "virt" needs register twice for it? or register only a single time,
>>> but we prefix the target_name()
>>> automatically? for example machine::name === "virt", but we can use
>>> "riscv32-virt" "risv64-virt" to reach it?
>>>
>>
>> Yes, ideally we should have different variant of virt for 32/64 bit.
>> Same goes for cpu max types.
>>
>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
>> the "alias" name, which is virt, in case multiple matches are found,
>> command line can return an error with list of unambiguous names to call it.
>>
>> $ qemu-system -M virt
>> Multiple virt machines are available. Please choose one of them:
>> - aarch64-virt
>> - riscv64-virt
>>
>> There is no "parsing" of the argument, it's just the real QOM type. Then
>> we can find which target it implements from mc->targets.
>> And then, we can automatically choose which cpus should be available
>> based on that, thanks to cpu->targets.
>>
>> For existing binaries, nothing change.
> 
> Good, I think we found a clean way now, is_available should be
> removed, and TypeInfo::targets and TypeImpl::targets should be added.

It goes into MachineClass only for now.

> I think
> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
> the $arch specific virt. so that we only have a single "virt" registered.
> And it's
> targets is
> QEMU_ARCH_I386 |
> QEMU_ARCH_ARM |
> QEMU_ARCH_RISCV |
> QEMU_ARCH_LOONGARCH |
> QEMU_ARCH_M68K |
> QEMU_ARCH_OR1K |
> QEMU_ARCH_XTENSA |
> QEMU_ARCH_HEXAGON
> 
> So that we won't have a list of conflict QOM names for "virt" machines.
> As now we indeed have only a single "virt" machine that redirects to
> different targets.
>

The idea looks appealing, but I don't think it solves the problem to
have multiple virt variants available at the same time.

The "alias" idea you introduced before is good, we just need to add a
check if an alias is really unique, else return an error, as explained
previously.

If "-M aarch64-virt" works for both the new and existing binary, and -M
virt only for existing binaries (and ambiguous for new one), I think
that's a safe approach.

> 
> For other types also conflict can be handled in the same way, such as
> "-cpu host" "-cpu max"
> maybe others, but I think they all have the same way to deal with.
> 
> 
> That's why  TypeInfo::targets and TypeImpl::targets better than sole
> Machine::targets
>

One step at a time.
Let's keep focused on declaring targets for a single machine first.
Then we can iterate to solve the "virt" problem.
Then convert all the existing machines and add a check in machine-target.c
Then, and only then, we can see what happens with cpus.

Regards,
Pierrick


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

* Re: [PATCH 8/8] qom: pass TargetInfo to is_available for later use
  2026-10-08 18:33                   ` Yonggang Luo
@ 2026-10-08 18:40                     ` Pierrick Bouvier
  0 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-08 18:40 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/8/2026 11:33 AM, Yonggang Luo wrote:
> On Fri, Oct 9, 2026 at 2:27 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/8/2026 10:04 AM, Yonggang Luo wrote:
>>> On Fri, Oct 9, 2026 at 12:01 AM Pierrick Bouvier
>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>
>>>> On 10/8/2026 2:56 AM, Yonggang Luo wrote:
>>>>>>> How about letting machines (and machines only first), have a new field
>>>>>>> 'targets', being a uint32_t mask with an array of EMU_TARGET?
>>>>>>> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
>>>>>
>>>>> To be explicit state what, I give you a pseudo code to compute
>>>>> machine->targets from TypeInfo::is_available(TargetInfo*)
>>>>> let targets=0
>>>>> foreach ti of TargetInfo list:
>>>>>    if (machine::TypeImpl::is_avaible(ti))
>>>>>          targets |= 1 << ti->target_arch
>>>>>    fi
>>>>> endif
>>>>> So they basically have equivalent effect, and is_available will handle
>>>>> other code-needed condition properly such as
>>>>> CPU/AccelClass. not restrict to targets, we can also attach the
>>>>> KConfig into TargetInfo, so is_available(TargetInfo*)
>>>>> also works for Kconfig. that's why I insist this way, it's solved all
>>>>> the issues around.
>>>>>
>>>>> so  machine->targets = EMU_TARGET_X | EMU_TARGET_Y; is a good idea,
>>>>> and it can be implemented with TypeInfo::is_available(TargetInfo*)
>>>>> without much burden. and targets can be saved into a (machine or
>>>>> TypeImpl) for fast access when needed, we can compute it
>>>>> when the program starts.
>>>>>
>>>>
>>>> In what we described, there is no need to keep any kind of callback,
>>>> targets field is sufficient to filter any type declaratively.
>>>>
>>>> For the KConfig related types, I would really be keen to leave that
>>>> available for now, and add a proper error message later.
>>>
>>> Thanks, much clearer now, I was working for full KConfig related types support
>>> because I am trying to keep qemu-system-$arch to be a symlink to qemu-system
>>> which will still work without breaking anything. If we do not keep this then
>>> I machine::targets or TypeInfo::targets would be the best solution, I think
>>> TypeInfo::targets is better, and copy it into TypeImpl::targets. and give a API
>>> to retrieve it, for example:
>>> uint64_t *object_class_get_targets(ObjectClass *klass);
>>>
>>
>> We can exclude the goal to replace existing binaries with a symlink for now.
>>
>> Please do not add this to TypeInfo, but to MachineClass instead, as
>> explained in previous email.
> 
> I didn't see any simple way to do this, and don't know how, I am sorry.
> MachineClass init procedure is scattered, how would that be? I am
> afraid I am not
> able to get this done. If you can give some prepare work would be appreciated
>

You can take a look at "git grep mc->desc". That's where you want to set
targets. Also see MachineClass::desc, to see where to declare the field.

There might be some machine classes that lack a class_init function, and
thus will require to introduce it. If you find any occurrence that is
not easy to solve, let me know, I'll help on it.

>> If you want to reduce upcoming frustration, I would really recommend you
>> stick to this, and to a single machine to start. So we can validate the
>> series, review it, and then you can iterate.
>>  > Add "targets" struct members as TypeInfo::targets and
>> TypeImpl::targets, and
>>> copy from TypeInfo into TypeImpl for later access with
>>> object_class_get_targets
>>> Then we can use it for filtering machines and cpus without burden.
>>>
>>> How to dealt with
>>> https://lore.kernel.org/qemu-devel/20261007-rv-dedup-v2-6-8a2f0f296a7f@rev.ng/
>>>
>>> It's using is_available.
>>>
>>
>> .targets field can be conditioned by ifdef for config vs user, since
>> what we have everything needed in build system allows to duplicate
>> objects between user and system.
>>
>> #ifdef CONFIG_USER_ONLY
>>  .targets = ...
>> #else
>>  .targets = ...
>> #endif
>>
>> If that's not enough, it means the type has to be duplicated in some
>> ways to resolve ambiguity (especially for 32 vs 64 bits variants).
>>
>>> Maybe all using the way like
>>> Subject: [PATCH v2 07/18] target/riscv: Runtime register MAX and BARE CPUs
>>> https://lore.kernel.org/qemu-devel/20261007-rv-dedup-v2-7-8a2f0f296a7f@rev.ng/
>>
>> I would invite you to focus on a *single* machine first. See how to
>> declare it, and how to query which target it supports. Then we can see
>> what works/doesn't work, and (in a future series) we can do the same
>> thing for cpus.
>>
>> You'll see that this iterative approach works much better than sending
>> huge series. You have my word I'll be reactive and present to help
>> continue this effort.
>>
>> Regards,
>> Pierrick
> 
> 
> 



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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-08 18:34           ` Pierrick Bouvier
@ 2026-10-08 18:48             ` Yonggang Luo
  2026-10-11 20:22             ` Yonggang Luo
  2026-10-11 20:32             ` Yonggang Luo
  2 siblings, 0 replies; 62+ messages in thread
From: Yonggang Luo @ 2026-10-08 18:48 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
> > On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> >>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>>>
> >>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> >>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> >>>>>> This allows a combined binary to register machine types from all its targets.
> >>>>>> Consequently, QMP `query-machines` can return machine entries from every
> >>>>>> target, even when `none` is selected. For example, a client can query the
> >>>>>> combined machine list with:
> >>>>>>
> >>>>>> ```json
> >>>>>> { "execute": "query-machines" }
> >>>>>> ```
> >>>>>>
> >>>>>> The returned list includes the registered machine classes from all linked
> >>>>>> targets. This is separate from selecting a machine: with `-target none`,
> >>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
> >>>>>> arbitrarily:
> >>>>>>
> >>>>>> ```text
> >>>>>> qemu-system -target none -M virt
> >>>>>> unsupported machine type: "virt" for target "none"
> >>>>>> Available for targets:
> >>>>>>   aarch64
> >>>>>>   arm
> >>>>>> ```
> >>>>>>
> >>>>>
> >>>>> From the long conversation on a previous thread, I thought we reached
> >>>>> the conclusion that if we didn't expose any ambiguous name, then -target
> >>>>> option is unnecessary, or maybe I got lost on track of this thread.
> >>>>>
> >>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >>>>>
> >>>>> I'm not sure which semantic we want to have with -target none. If there
> >>>>> is no ambiguous name registered, we just don't need it at all. It's a
> >>>>> win-win IMHO.
> >>>>
> >>>> Yes, if we expose unique names for every machine, then -target is then
> >>>> redundant.
> >>>
> >>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> >>> needs two name?
> >>> "virt" needs register twice for it? or register only a single time,
> >>> but we prefix the target_name()
> >>> automatically? for example machine::name === "virt", but we can use
> >>> "riscv32-virt" "risv64-virt" to reach it?
> >>>
> >>
> >> Yes, ideally we should have different variant of virt for 32/64 bit.
> >> Same goes for cpu max types.
> >>
> >> QOM type is always registered unambiguously ("$arch-virt"). Then, for
> >> the "alias" name, which is virt, in case multiple matches are found,
> >> command line can return an error with list of unambiguous names to call it.
> >>
> >> $ qemu-system -M virt
> >> Multiple virt machines are available. Please choose one of them:
> >> - aarch64-virt
> >> - riscv64-virt
> >>
> >> There is no "parsing" of the argument, it's just the real QOM type. Then
> >> we can find which target it implements from mc->targets.
> >> And then, we can automatically choose which cpus should be available
> >> based on that, thanks to cpu->targets.
> >>
> >> For existing binaries, nothing change.
> >
> > Good, I think we found a clean way now, is_available should be
> > removed, and TypeInfo::targets and TypeImpl::targets should be added.
>
> It goes into MachineClass only for now.
>
> > I think
> > for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
> > the $arch specific virt. so that we only have a single "virt" registered.
> > And it's
> > targets is
> > QEMU_ARCH_I386 |
> > QEMU_ARCH_ARM |
> > QEMU_ARCH_RISCV |
> > QEMU_ARCH_LOONGARCH |
> > QEMU_ARCH_M68K |
> > QEMU_ARCH_OR1K |
> > QEMU_ARCH_XTENSA |
> > QEMU_ARCH_HEXAGON
> >
> > So that we won't have a list of conflict QOM names for "virt" machines.
> > As now we indeed have only a single "virt" machine that redirects to
> > different targets.
> >
>
> The idea looks appealing, but I don't think it solves the problem to
> have multiple virt variants available at the same time.
>
> The "alias" idea you introduced before is good, we just need to add a
> check if an alias is really unique, else return an error, as explained
> previously.
>
> If "-M aarch64-virt" works for both the new and existing binary, and -M
> virt only for existing binaries (and ambiguous for new one), I think
> that's a safe approach.
>
> >
> > For other types also conflict can be handled in the same way, such as
> > "-cpu host" "-cpu max"
> > maybe others, but I think they all have the same way to deal with.
> >
> >
> > That's why  TypeInfo::targets and TypeImpl::targets better than sole
> > Machine::targets
> >
>
> One step at a time.

That makes sense, I am afraid I have no time to trace it currently(at
least a month).
At least we now have a good agreement. So it should be much easier,
otherwise it's really frustrating.

> Let's keep focused on declaring targets for a single machine first.
> Then we can iterate to solve the "virt" problem.
> Then convert all the existing machines and add a check in machine-target.c
> Then, and only then, we can see what happens with cpus.
>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-07 20:46 ` Pierrick Bouvier
@ 2026-10-09 21:58   ` Pierrick Bouvier
  2026-10-09 22:08     ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-09 21:58 UTC (permalink / raw)
  To: Yonggang Luo, qemu-devel
  Cc: Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/7/2026 1:46 PM, Pierrick Bouvier wrote:
> 
> I'll pull the first three patches.
>

Now merged upstream (40ba85501c0b6ac2a7319d3804dab072edf67564)

Thanks,
Pierrick


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-09 21:58   ` Pierrick Bouvier
@ 2026-10-09 22:08     ` Yonggang Luo
  2026-10-09 22:21       ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-09 22:08 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Sat, Oct 10, 2026 at 5:58 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/7/2026 1:46 PM, Pierrick Bouvier wrote:
> >
> > I'll pull the first three patches.
> >
>
> Now merged upstream (40ba85501c0b6ac2a7319d3804dab072edf67564)
>

Hi Pierrick
Seems you post to the wrong place.

> Thanks,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-09 22:08     ` Yonggang Luo
@ 2026-10-09 22:21       ` Pierrick Bouvier
  0 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-09 22:21 UTC (permalink / raw)
  To: luoyonggang
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/9/2026 3:08 PM, Yonggang Luo wrote:
> On Sat, Oct 10, 2026 at 5:58 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/7/2026 1:46 PM, Pierrick Bouvier wrote:
>>>
>>> I'll pull the first three patches.
>>>
>>
>> Now merged upstream (40ba85501c0b6ac2a7319d3804dab072edf67564)
>>
> 
> Hi Pierrick
> Seems you post to the wrong place.
>

Hi Yonggang,
oops sorry indeed.
I was waiting for previous patches to be merged to send those ones.


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-08 18:34           ` Pierrick Bouvier
  2026-10-08 18:48             ` Yonggang Luo
@ 2026-10-11 20:22             ` Yonggang Luo
  2026-10-12  2:13               ` Pierrick Bouvier
  2026-10-11 20:32             ` Yonggang Luo
  2 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-11 20:22 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
> > On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> >>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>>>
> >>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> >>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> >>>>>> This allows a combined binary to register machine types from all its targets.
> >>>>>> Consequently, QMP `query-machines` can return machine entries from every
> >>>>>> target, even when `none` is selected. For example, a client can query the
> >>>>>> combined machine list with:
> >>>>>>
> >>>>>> ```json
> >>>>>> { "execute": "query-machines" }
> >>>>>> ```
> >>>>>>
> >>>>>> The returned list includes the registered machine classes from all linked
> >>>>>> targets. This is separate from selecting a machine: with `-target none`,
> >>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
> >>>>>> arbitrarily:
> >>>>>>
> >>>>>> ```text
> >>>>>> qemu-system -target none -M virt
> >>>>>> unsupported machine type: "virt" for target "none"
> >>>>>> Available for targets:
> >>>>>>   aarch64
> >>>>>>   arm
> >>>>>> ```
> >>>>>>
> >>>>>
> >>>>> From the long conversation on a previous thread, I thought we reached
> >>>>> the conclusion that if we didn't expose any ambiguous name, then -target
> >>>>> option is unnecessary, or maybe I got lost on track of this thread.
> >>>>>
> >>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >>>>>
> >>>>> I'm not sure which semantic we want to have with -target none. If there
> >>>>> is no ambiguous name registered, we just don't need it at all. It's a
> >>>>> win-win IMHO.
> >>>>
> >>>> Yes, if we expose unique names for every machine, then -target is then
> >>>> redundant.
> >>>
> >>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> >>> needs two name?
> >>> "virt" needs register twice for it? or register only a single time,
> >>> but we prefix the target_name()
> >>> automatically? for example machine::name === "virt", but we can use
> >>> "riscv32-virt" "risv64-virt" to reach it?
> >>>
> >>
> >> Yes, ideally we should have different variant of virt for 32/64 bit.
> >> Same goes for cpu max types.
> >>
> >> QOM type is always registered unambiguously ("$arch-virt"). Then, for
> >> the "alias" name, which is virt, in case multiple matches are found,
> >> command line can return an error with list of unambiguous names to call it.
> >>
> >> $ qemu-system -M virt
> >> Multiple virt machines are available. Please choose one of them:
> >> - aarch64-virt
> >> - riscv64-virt
> >>
> >> There is no "parsing" of the argument, it's just the real QOM type. Then
> >> we can find which target it implements from mc->targets.
> >> And then, we can automatically choose which cpus should be available
> >> based on that, thanks to cpu->targets.
> >>
> >> For existing binaries, nothing change.
> >
> > Good, I think we found a clean way now, is_available should be
> > removed, and TypeInfo::targets and TypeImpl::targets should be added.
>
> It goes into MachineClass only for now.
>
> > I think
> > for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
> > the $arch specific virt. so that we only have a single "virt" registered.
> > And it's
> > targets is
> > QEMU_ARCH_I386 |
> > QEMU_ARCH_ARM |
> > QEMU_ARCH_RISCV |
> > QEMU_ARCH_LOONGARCH |
> > QEMU_ARCH_M68K |
> > QEMU_ARCH_OR1K |
> > QEMU_ARCH_XTENSA |
> > QEMU_ARCH_HEXAGON
> >
> > So that we won't have a list of conflict QOM names for "virt" machines.
> > As now we indeed have only a single "virt" machine that redirects to
> > different targets.
> >
>
> The idea looks appealing, but I don't think it solves the problem to
> have multiple virt variants available at the same time.
>
> The "alias" idea you introduced before is good, we just need to add a
> check if an alias is really unique, else return an error, as explained
> previously.
>
> If "-M aarch64-virt" works for both the new and existing binary, and -M
> virt only for existing binaries (and ambiguous for new one), I think
> that's a safe approach.
>
> >
> > For other types also conflict can be handled in the same way, such as
> > "-cpu host" "-cpu max"
> > maybe others, but I think they all have the same way to deal with.
> >
> >
> > That's why  TypeInfo::targets and TypeImpl::targets better than sole
> > Machine::targets
> >
>
> One step at a time.
> Let's keep focused on declaring targets for a single machine first.
> Then we can iterate to solve the "virt" problem.
> Then convert all the existing machines and add a check in machine-target.c
> Then, and only then, we can see what happens with cpus.

I tried this idea, but I faced a fatal error, because the
target_info() is not available until
the machine selected(the target arch will be select just along with
the machine selected), so basically
all calls to target_info() would raise an error(null pointer), how to
deal with it?

>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-08 18:34           ` Pierrick Bouvier
  2026-10-08 18:48             ` Yonggang Luo
  2026-10-11 20:22             ` Yonggang Luo
@ 2026-10-11 20:32             ` Yonggang Luo
  2 siblings, 0 replies; 62+ messages in thread
From: Yonggang Luo @ 2026-10-11 20:32 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
> > On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> >>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>>>
> >>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> >>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> >>>>>> This allows a combined binary to register machine types from all its targets.
> >>>>>> Consequently, QMP `query-machines` can return machine entries from every
> >>>>>> target, even when `none` is selected. For example, a client can query the
> >>>>>> combined machine list with:
> >>>>>>
> >>>>>> ```json
> >>>>>> { "execute": "query-machines" }
> >>>>>> ```
> >>>>>>
> >>>>>> The returned list includes the registered machine classes from all linked
> >>>>>> targets. This is separate from selecting a machine: with `-target none`,
> >>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
> >>>>>> arbitrarily:
> >>>>>>
> >>>>>> ```text
> >>>>>> qemu-system -target none -M virt
> >>>>>> unsupported machine type: "virt" for target "none"
> >>>>>> Available for targets:
> >>>>>>   aarch64
> >>>>>>   arm
> >>>>>> ```
> >>>>>>
> >>>>>
> >>>>> From the long conversation on a previous thread, I thought we reached
> >>>>> the conclusion that if we didn't expose any ambiguous name, then -target
> >>>>> option is unnecessary, or maybe I got lost on track of this thread.
> >>>>>
> >>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >>>>>
> >>>>> I'm not sure which semantic we want to have with -target none. If there
> >>>>> is no ambiguous name registered, we just don't need it at all. It's a
> >>>>> win-win IMHO.
> >>>>
> >>>> Yes, if we expose unique names for every machine, then -target is then
> >>>> redundant.
> >>>
> >>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> >>> needs two name?
> >>> "virt" needs register twice for it? or register only a single time,
> >>> but we prefix the target_name()
> >>> automatically? for example machine::name === "virt", but we can use
> >>> "riscv32-virt" "risv64-virt" to reach it?
> >>>
> >>
> >> Yes, ideally we should have different variant of virt for 32/64 bit.
> >> Same goes for cpu max types.
> >>
> >> QOM type is always registered unambiguously ("$arch-virt"). Then, for
> >> the "alias" name, which is virt, in case multiple matches are found,
> >> command line can return an error with list of unambiguous names to call it.
> >>
> >> $ qemu-system -M virt
> >> Multiple virt machines are available. Please choose one of them:
> >> - aarch64-virt
> >> - riscv64-virt
> >>
> >> There is no "parsing" of the argument, it's just the real QOM type. Then
> >> we can find which target it implements from mc->targets.
> >> And then, we can automatically choose which cpus should be available
> >> based on that, thanks to cpu->targets.
> >>
> >> For existing binaries, nothing change.
> >
> > Good, I think we found a clean way now, is_available should be
> > removed, and TypeInfo::targets and TypeImpl::targets should be added.
>
> It goes into MachineClass only for now.
>
> > I think
> > for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
> > the $arch specific virt. so that we only have a single "virt" registered.
> > And it's
> > targets is
> > QEMU_ARCH_I386 |
> > QEMU_ARCH_ARM |
> > QEMU_ARCH_RISCV |
> > QEMU_ARCH_LOONGARCH |
> > QEMU_ARCH_M68K |
> > QEMU_ARCH_OR1K |
> > QEMU_ARCH_XTENSA |
> > QEMU_ARCH_HEXAGON
> >
> > So that we won't have a list of conflict QOM names for "virt" machines.
> > As now we indeed have only a single "virt" machine that redirects to
> > different targets.
> >
>
> The idea looks appealing, but I don't think it solves the problem to
> have multiple virt variants available at the same time.
>
> The "alias" idea you introduced before is good, we just need to add a
> check if an alias is really unique, else return an error, as explained
> previously.
>
> If "-M aarch64-virt" works for both the new and existing binary, and -M
> virt only for existing binaries (and ambiguous for new one), I think
> that's a safe approach.
>
> >
> > For other types also conflict can be handled in the same way, such as
> > "-cpu host" "-cpu max"
> > maybe others, but I think they all have the same way to deal with.
> >
> >
> > That's why  TypeInfo::targets and TypeImpl::targets better than sole
> > Machine::targets
> >
>
> One step at a time.
> Let's keep focused on declaring targets for a single machine first.
> Then we can iterate to solve the "virt" problem.
> Then convert all the existing machines and add a check in machine-target.c
> Then, and only then, we can see what happens with cpus.
>
> Regards,
> Pierrick

Hi Pierrick,
this is something I have to do, please have a look

 target-info.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/target-info.c b/target-info.c
index 6c5c732eba9..b5d0dce1a87 100644
--- a/target-info.c
+++ b/target-info.c
@@ -43,55 +43,61 @@ bool target_big_endian(void)
     return target_endian_mode() == ENDIAN_MODE_BIG;
 }

+static bool target_arch_matches(uint64_t mask)
+{
+    return target_combined_binary() ||
+           (mask & (1ULL << target_arch())) != 0;
+}
+
 bool target_base_arm(void)
 {
-    return (QEMU_ARCH_ARM & (1ULL << target_arch())) != 0;
+    return target_arch_matches(QEMU_ARCH_ARM);
 }

 bool target_arm(void)
 {
-    return target_arch() == EMU_TARGET_ARM ||
-           target_arch() == EMU_TARGET_ARMEB;
+    return target_arch_matches((1ULL << EMU_TARGET_ARM) |
+                               (1ULL << EMU_TARGET_ARMEB));
 }

 bool target_aarch64(void)
 {
-    return target_arch() == EMU_TARGET_AARCH64 ||
-           target_arch() == EMU_TARGET_AARCH64_BE;
+    return target_arch_matches((1ULL << EMU_TARGET_AARCH64) |
+                               (1ULL << EMU_TARGET_AARCH64_BE));
 }

 bool target_m68k(void)
 {
-    return target_arch() == EMU_TARGET_M68K;
+    return target_arch_matches(1ULL << EMU_TARGET_M68K);
 }

 bool target_or1k(void)
 {
-    return target_arch() == EMU_TARGET_OR1K;
+    return target_arch_matches(1ULL << EMU_TARGET_OR1K);
 }

 bool target_base_ppc(void)
 {
-    return (QEMU_ARCH_PPC & (1ULL << target_arch())) != 0;
+    return target_arch_matches(QEMU_ARCH_PPC);
 }

 bool target_ppc(void)
 {
-    return target_arch() == EMU_TARGET_PPC;
+    return target_arch_matches(1ULL << EMU_TARGET_PPC);
 }

 bool target_ppc64(void)
 {
-    return target_arch() == EMU_TARGET_PPC64 ||
-           target_arch() == EMU_TARGET_PPC64LE;
+    return target_arch_matches((1ULL << EMU_TARGET_PPC64) |
+                               (1ULL << EMU_TARGET_PPC64LE));
 }

 bool target_s390x(void)
 {
-    return target_arch() == EMU_TARGET_S390X;
+    return target_arch_matches(1ULL << EMU_TARGET_S390X);
 }

 bool target_riscv64(void)
 {
-    return target_arch() == EMU_TARGET_RISCV64;
+    return target_arch_matches(1ULL << EMU_TARGET_RISCV64);
 }


-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-11 20:22             ` Yonggang Luo
@ 2026-10-12  2:13               ` Pierrick Bouvier
  2026-10-12  2:21                 ` Yonggang Luo
  2026-10-12  2:25                 ` Pierrick Bouvier
  0 siblings, 2 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-12  2:13 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/11/26 1:22 PM, Yonggang Luo wrote:
> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>
>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>>
>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>>>>>>>> This allows a combined binary to register machine types from all its targets.
>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
>>>>>>>> target, even when `none` is selected. For example, a client can query the
>>>>>>>> combined machine list with:
>>>>>>>>
>>>>>>>> ```json
>>>>>>>> { "execute": "query-machines" }
>>>>>>>> ```
>>>>>>>>
>>>>>>>> The returned list includes the registered machine classes from all linked
>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
>>>>>>>> arbitrarily:
>>>>>>>>
>>>>>>>> ```text
>>>>>>>> qemu-system -target none -M virt
>>>>>>>> unsupported machine type: "virt" for target "none"
>>>>>>>> Available for targets:
>>>>>>>>    aarch64
>>>>>>>>    arm
>>>>>>>> ```
>>>>>>>>
>>>>>>>
>>>>>>>  From the long conversation on a previous thread, I thought we reached
>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
>>>>>>>
>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
>>>>>>>
>>>>>>> I'm not sure which semantic we want to have with -target none. If there
>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
>>>>>>> win-win IMHO.
>>>>>>
>>>>>> Yes, if we expose unique names for every machine, then -target is then
>>>>>> redundant.
>>>>>
>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
>>>>> needs two name?
>>>>> "virt" needs register twice for it? or register only a single time,
>>>>> but we prefix the target_name()
>>>>> automatically? for example machine::name === "virt", but we can use
>>>>> "riscv32-virt" "risv64-virt" to reach it?
>>>>>
>>>>
>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
>>>> Same goes for cpu max types.
>>>>
>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
>>>> the "alias" name, which is virt, in case multiple matches are found,
>>>> command line can return an error with list of unambiguous names to call it.
>>>>
>>>> $ qemu-system -M virt
>>>> Multiple virt machines are available. Please choose one of them:
>>>> - aarch64-virt
>>>> - riscv64-virt
>>>>
>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
>>>> we can find which target it implements from mc->targets.
>>>> And then, we can automatically choose which cpus should be available
>>>> based on that, thanks to cpu->targets.
>>>>
>>>> For existing binaries, nothing change.
>>>
>>> Good, I think we found a clean way now, is_available should be
>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
>>
>> It goes into MachineClass only for now.
>>
>>> I think
>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
>>> the $arch specific virt. so that we only have a single "virt" registered.
>>> And it's
>>> targets is
>>> QEMU_ARCH_I386 |
>>> QEMU_ARCH_ARM |
>>> QEMU_ARCH_RISCV |
>>> QEMU_ARCH_LOONGARCH |
>>> QEMU_ARCH_M68K |
>>> QEMU_ARCH_OR1K |
>>> QEMU_ARCH_XTENSA |
>>> QEMU_ARCH_HEXAGON
>>>
>>> So that we won't have a list of conflict QOM names for "virt" machines.
>>> As now we indeed have only a single "virt" machine that redirects to
>>> different targets.
>>>
>>
>> The idea looks appealing, but I don't think it solves the problem to
>> have multiple virt variants available at the same time.
>>
>> The "alias" idea you introduced before is good, we just need to add a
>> check if an alias is really unique, else return an error, as explained
>> previously.
>>
>> If "-M aarch64-virt" works for both the new and existing binary, and -M
>> virt only for existing binaries (and ambiguous for new one), I think
>> that's a safe approach.
>>
>>>
>>> For other types also conflict can be handled in the same way, such as
>>> "-cpu host" "-cpu max"
>>> maybe others, but I think they all have the same way to deal with.
>>>
>>>
>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
>>> Machine::targets
>>>
>>
>> One step at a time.
>> Let's keep focused on declaring targets for a single machine first.
>> Then we can iterate to solve the "virt" problem.
>> Then convert all the existing machines and add a check in machine-target.c
>> Then, and only then, we can see what happens with cpus.
> 
> I tried this idea, but I faced a fatal error, because the
> target_info() is not available until
> the machine selected(the target arch will be select just along with
> the machine selected), so basically
> all calls to target_info() would raise an error(null pointer), how to
> deal with it?
>

I see. Indeed, since we can't set a target before registering all types, 
it implies that all the types class_init can't use target_* functions.


- register_accel_target_type
- cpu_max_v8_register_type


>>
>> Regards,
>> Pierrick
> 
> 
> 



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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-12  2:13               ` Pierrick Bouvier
@ 2026-10-12  2:21                 ` Yonggang Luo
  2026-10-12  2:25                 ` Pierrick Bouvier
  1 sibling, 0 replies; 62+ messages in thread
From: Yonggang Luo @ 2026-10-12  2:21 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Mon, Oct 12, 2026 at 10:13 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/11/26 1:22 PM, Yonggang Luo wrote:
> > On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
> >>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
> >>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>
> >>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> >>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>>>>>
> >>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> >>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> >>>>>>>> This allows a combined binary to register machine types from all its targets.
> >>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
> >>>>>>>> target, even when `none` is selected. For example, a client can query the
> >>>>>>>> combined machine list with:
> >>>>>>>>
> >>>>>>>> ```json
> >>>>>>>> { "execute": "query-machines" }
> >>>>>>>> ```
> >>>>>>>>
> >>>>>>>> The returned list includes the registered machine classes from all linked
> >>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
> >>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
> >>>>>>>> arbitrarily:
> >>>>>>>>
> >>>>>>>> ```text
> >>>>>>>> qemu-system -target none -M virt
> >>>>>>>> unsupported machine type: "virt" for target "none"
> >>>>>>>> Available for targets:
> >>>>>>>>    aarch64
> >>>>>>>>    arm
> >>>>>>>> ```
> >>>>>>>>
> >>>>>>>
> >>>>>>>  From the long conversation on a previous thread, I thought we reached
> >>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
> >>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
> >>>>>>>
> >>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >>>>>>>
> >>>>>>> I'm not sure which semantic we want to have with -target none. If there
> >>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
> >>>>>>> win-win IMHO.
> >>>>>>
> >>>>>> Yes, if we expose unique names for every machine, then -target is then
> >>>>>> redundant.
> >>>>>
> >>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> >>>>> needs two name?
> >>>>> "virt" needs register twice for it? or register only a single time,
> >>>>> but we prefix the target_name()
> >>>>> automatically? for example machine::name === "virt", but we can use
> >>>>> "riscv32-virt" "risv64-virt" to reach it?
> >>>>>
> >>>>
> >>>> Yes, ideally we should have different variant of virt for 32/64 bit.
> >>>> Same goes for cpu max types.
> >>>>
> >>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
> >>>> the "alias" name, which is virt, in case multiple matches are found,
> >>>> command line can return an error with list of unambiguous names to call it.
> >>>>
> >>>> $ qemu-system -M virt
> >>>> Multiple virt machines are available. Please choose one of them:
> >>>> - aarch64-virt
> >>>> - riscv64-virt
> >>>>
> >>>> There is no "parsing" of the argument, it's just the real QOM type. Then
> >>>> we can find which target it implements from mc->targets.
> >>>> And then, we can automatically choose which cpus should be available
> >>>> based on that, thanks to cpu->targets.
> >>>>
> >>>> For existing binaries, nothing change.
> >>>
> >>> Good, I think we found a clean way now, is_available should be
> >>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
> >>
> >> It goes into MachineClass only for now.
> >>
> >>> I think
> >>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
> >>> the $arch specific virt. so that we only have a single "virt" registered.
> >>> And it's
> >>> targets is
> >>> QEMU_ARCH_I386 |
> >>> QEMU_ARCH_ARM |
> >>> QEMU_ARCH_RISCV |
> >>> QEMU_ARCH_LOONGARCH |
> >>> QEMU_ARCH_M68K |
> >>> QEMU_ARCH_OR1K |
> >>> QEMU_ARCH_XTENSA |
> >>> QEMU_ARCH_HEXAGON
> >>>
> >>> So that we won't have a list of conflict QOM names for "virt" machines.
> >>> As now we indeed have only a single "virt" machine that redirects to
> >>> different targets.
> >>>
> >>
> >> The idea looks appealing, but I don't think it solves the problem to
> >> have multiple virt variants available at the same time.
> >>
> >> The "alias" idea you introduced before is good, we just need to add a
> >> check if an alias is really unique, else return an error, as explained
> >> previously.
> >>
> >> If "-M aarch64-virt" works for both the new and existing binary, and -M
> >> virt only for existing binaries (and ambiguous for new one), I think
> >> that's a safe approach.
> >>
> >>>
> >>> For other types also conflict can be handled in the same way, such as
> >>> "-cpu host" "-cpu max"
> >>> maybe others, but I think they all have the same way to deal with.
> >>>
> >>>
> >>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
> >>> Machine::targets
> >>>
> >>
> >> One step at a time.
> >> Let's keep focused on declaring targets for a single machine first.
> >> Then we can iterate to solve the "virt" problem.
> >> Then convert all the existing machines and add a check in machine-target.c
> >> Then, and only then, we can see what happens with cpus.
> >
> > I tried this idea, but I faced a fatal error, because the
> > target_info() is not available until
> > the machine selected(the target arch will be select just along with
> > the machine selected), so basically
> > all calls to target_info() would raise an error(null pointer), how to
> > deal with it?
> >
>
> I see. Indeed, since we can't set a target before registering all types,
> it implies that all the types class_init can't use target_* functions.
>
>
> - register_accel_target_type
> - cpu_max_v8_register_type

Hi Pierrick

These two I can handle it properly, only for the "virt" machine I can
not handle it properly
What you suggest, it's a must-be requirement now.


for example, cpu_max_v8_register_type can be handle in such way:

 target/arm/tcg/cpu-max-v8.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/target/arm/tcg/cpu-max-v8.c b/target/arm/tcg/cpu-max-v8.c
index 65f851f2006..d7323ab431c 100644
--- a/target/arm/tcg/cpu-max-v8.c
+++ b/target/arm/tcg/cpu-max-v8.c
@@ -119,12 +119,21 @@ void aarch32_max_v8_tcg_initfn(Object *obj)
 #endif
 }

+static void max_v8_tcg_initfn(Object *obj)
+{
+    if (target_aarch64()) {
+        aarch64_max_v8_tcg_initfn(obj);
+    } else {
+        aarch32_max_v8_tcg_initfn(obj);
+    }
+}
+
 static void cpu_max_v8_register_type(void)
 {
-    static const ARMCPUInfo max_v8[2] = {
-        { .name = "max-v8", .initfn = aarch32_max_v8_tcg_initfn },
-        { .name = "max-v8", .initfn = aarch64_max_v8_tcg_initfn },
+    static const ARMCPUInfo max_v8 = {
+        .name = "max-v8",
+        .initfn = max_v8_tcg_initfn,
     };
-    arm_cpu_register(&max_v8[target_aarch64()]);
+    arm_cpu_register(&max_v8);
 }
 type_init(cpu_max_v8_register_type)



register_accel_target_type:

 accel/accel-common.c             | 21 ++++++---------------
 include/accel/accel-cpu-target.h |  3 +--
 include/accel/accel-cpu.h        |  2 ++
 3 files changed, 9 insertions(+), 17 deletions(-)

diff --git a/accel/accel-common.c b/accel/accel-common.c
index 00a400243f0..c4c365f38c7 100644
--- a/accel/accel-common.c
+++ b/accel/accel-common.c
@@ -126,21 +126,12 @@ static const TypeInfo accel_types[] = {
         .instance_size  = sizeof(AccelState),
         .abstract       = true,
     },
+    {
+        .name           = TYPE_ACCEL_CPU,
+        .parent         = TYPE_OBJECT,
+        .abstract       = true,
+        .class_size     = sizeof(AccelCPUClass),
+    },
 };

 DEFINE_TYPES(accel_types)
-
-static void register_accel_target_type(void)
-{
-    g_autofree char *name = g_strconcat("accel-", target_cpu_type(), NULL);
-    const TypeInfo accel_cpu_type = {
-        .name = name,
-        .parent = TYPE_OBJECT,
-        .abstract = true,
-        .class_size = sizeof(AccelCPUClass),
-    };
-
-    type_register_static(&accel_cpu_type);
-}
-
-type_init(register_accel_target_type);
diff --git a/include/accel/accel-cpu-target.h b/include/accel/accel-cpu-target.h
index 6feb344e29b..cf33ebd79fc 100644
--- a/include/accel/accel-cpu-target.h
+++ b/include/accel/accel-cpu-target.h
@@ -24,8 +24,7 @@
 #include "accel/accel-cpu.h"
 #include "cpu.h"

-#define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
-#define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
+#define ACCEL_CPU_NAME(name) (name "-accel-" CPU_RESOLVING_TYPE)
 DECLARE_CLASS_CHECKERS(AccelCPUClass, ACCEL_CPU, TYPE_ACCEL_CPU)

 #endif /* ACCEL_CPU_H */
diff --git a/include/accel/accel-cpu.h b/include/accel/accel-cpu.h
index 9e7eede7c3c..5cfc2b24223 100644
--- a/include/accel/accel-cpu.h
+++ b/include/accel/accel-cpu.h
@@ -12,6 +12,8 @@
 #include "qom/object.h"
 #include "hw/core/cpu.h"

+#define TYPE_ACCEL_CPU "accel-cpu"
+
 typedef struct AccelCPUClass {
     ObjectClass parent_class;


>
>
> >>
> >> Regards,
> >> Pierrick
> >
> >
> >
>


-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-12  2:13               ` Pierrick Bouvier
  2026-10-12  2:21                 ` Yonggang Luo
@ 2026-10-12  2:25                 ` Pierrick Bouvier
  2026-10-12  4:26                   ` Yonggang Luo
  1 sibling, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-12  2:25 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/11/26 7:13 PM, Pierrick Bouvier wrote:
> On 10/11/26 1:22 PM, Yonggang Luo wrote:
>> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>
>>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
>>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>
>>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
>>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>>>
>>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
>>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>>>>>>>>> This allows a combined binary to register machine types from all its targets.
>>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
>>>>>>>>> target, even when `none` is selected. For example, a client can query the
>>>>>>>>> combined machine list with:
>>>>>>>>>
>>>>>>>>> ```json
>>>>>>>>> { "execute": "query-machines" }
>>>>>>>>> ```
>>>>>>>>>
>>>>>>>>> The returned list includes the registered machine classes from all linked
>>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
>>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
>>>>>>>>> arbitrarily:
>>>>>>>>>
>>>>>>>>> ```text
>>>>>>>>> qemu-system -target none -M virt
>>>>>>>>> unsupported machine type: "virt" for target "none"
>>>>>>>>> Available for targets:
>>>>>>>>>     aarch64
>>>>>>>>>     arm
>>>>>>>>> ```
>>>>>>>>>
>>>>>>>>
>>>>>>>>   From the long conversation on a previous thread, I thought we reached
>>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
>>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
>>>>>>>>
>>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
>>>>>>>>
>>>>>>>> I'm not sure which semantic we want to have with -target none. If there
>>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
>>>>>>>> win-win IMHO.
>>>>>>>
>>>>>>> Yes, if we expose unique names for every machine, then -target is then
>>>>>>> redundant.
>>>>>>
>>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
>>>>>> needs two name?
>>>>>> "virt" needs register twice for it? or register only a single time,
>>>>>> but we prefix the target_name()
>>>>>> automatically? for example machine::name === "virt", but we can use
>>>>>> "riscv32-virt" "risv64-virt" to reach it?
>>>>>>
>>>>>
>>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
>>>>> Same goes for cpu max types.
>>>>>
>>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
>>>>> the "alias" name, which is virt, in case multiple matches are found,
>>>>> command line can return an error with list of unambiguous names to call it.
>>>>>
>>>>> $ qemu-system -M virt
>>>>> Multiple virt machines are available. Please choose one of them:
>>>>> - aarch64-virt
>>>>> - riscv64-virt
>>>>>
>>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
>>>>> we can find which target it implements from mc->targets.
>>>>> And then, we can automatically choose which cpus should be available
>>>>> based on that, thanks to cpu->targets.
>>>>>
>>>>> For existing binaries, nothing change.
>>>>
>>>> Good, I think we found a clean way now, is_available should be
>>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
>>>
>>> It goes into MachineClass only for now.
>>>
>>>> I think
>>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
>>>> the $arch specific virt. so that we only have a single "virt" registered.
>>>> And it's
>>>> targets is
>>>> QEMU_ARCH_I386 |
>>>> QEMU_ARCH_ARM |
>>>> QEMU_ARCH_RISCV |
>>>> QEMU_ARCH_LOONGARCH |
>>>> QEMU_ARCH_M68K |
>>>> QEMU_ARCH_OR1K |
>>>> QEMU_ARCH_XTENSA |
>>>> QEMU_ARCH_HEXAGON
>>>>
>>>> So that we won't have a list of conflict QOM names for "virt" machines.
>>>> As now we indeed have only a single "virt" machine that redirects to
>>>> different targets.
>>>>
>>>
>>> The idea looks appealing, but I don't think it solves the problem to
>>> have multiple virt variants available at the same time.
>>>
>>> The "alias" idea you introduced before is good, we just need to add a
>>> check if an alias is really unique, else return an error, as explained
>>> previously.
>>>
>>> If "-M aarch64-virt" works for both the new and existing binary, and -M
>>> virt only for existing binaries (and ambiguous for new one), I think
>>> that's a safe approach.
>>>
>>>>
>>>> For other types also conflict can be handled in the same way, such as
>>>> "-cpu host" "-cpu max"
>>>> maybe others, but I think they all have the same way to deal with.
>>>>
>>>>
>>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
>>>> Machine::targets
>>>>
>>>
>>> One step at a time.
>>> Let's keep focused on declaring targets for a single machine first.
>>> Then we can iterate to solve the "virt" problem.
>>> Then convert all the existing machines and add a check in machine-target.c
>>> Then, and only then, we can see what happens with cpus.
>>
>> I tried this idea, but I faced a fatal error, because the
>> target_info() is not available until
>> the machine selected(the target arch will be select just along with
>> the machine selected), so basically
>> all calls to target_info() would raise an error(null pointer), how to
>> deal with it?
>>
> 
> I see. Indeed, since we can't set a target before registering all types,
> it implies that all the types class_init can't use target_* functions.
> 
> 
> - register_accel_target_type
> - cpu_max_v8_register_type
>

Sorry, mail sent to early.

For the is_available callback usage, it should be easy to do the switch, 
since it's basically the same information that what we are trying to do 
- we can leave them for now.

Some types (like accel and max mentioned above), explicitly change their 
definition depending on the target. It's a behavior we can't rely on 
anymore, and it means we need proper distinct types instead of a single 
one with dynamic definition driven by target-info.

I think that's the preliminary work needed, before being able to go 
further: convert all existing usage in class_init with distinct types + 
is_available, and then we can do the switch from is_available to the new 
.targets approach.

It's probably worth having the conversion in its own series (only 
cleanup usage of target_* in class_init), before trying to get rid of 
is_available.

For the implementation, you can use the multi-targets.c binary test to 
drive the change. Remove the module init for target info (leaving no 
target set), and add a hacky patch to skip call to is_available (and 
return true instead) and allow double definition (which will rely on 
is_available). Then, fix all the segfault. Once it compiles and runs, 
only double definition will be left, which can be handled by inserting 
the right is_available callbacks. Then in a subsequent series, the 
switch to .targets can be made.

It's a work we'll need to do for heterogeneous anyway, I was just hoping 
to delay that until there, but seems we need to deal with it now.
A good thing is that it means target-info won't have to be registered 
before all QOM types anymore, so it's worth the effort IMHO.

Thanks,
Pierrick


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-12  2:25                 ` Pierrick Bouvier
@ 2026-10-12  4:26                   ` Yonggang Luo
  2026-10-12  7:11                     ` Pierrick Bouvier
  2026-10-13  1:26                     ` Pierrick Bouvier
  0 siblings, 2 replies; 62+ messages in thread
From: Yonggang Luo @ 2026-10-12  4:26 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Mon, Oct 12, 2026 at 10:25 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/11/26 7:13 PM, Pierrick Bouvier wrote:
> > On 10/11/26 1:22 PM, Yonggang Luo wrote:
> >> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
> >> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>
> >>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
> >>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
> >>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>>
> >>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> >>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>>>>>>
> >>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> >>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> >>>>>>>>> This allows a combined binary to register machine types from all its targets.
> >>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
> >>>>>>>>> target, even when `none` is selected. For example, a client can query the
> >>>>>>>>> combined machine list with:
> >>>>>>>>>
> >>>>>>>>> ```json
> >>>>>>>>> { "execute": "query-machines" }
> >>>>>>>>> ```
> >>>>>>>>>
> >>>>>>>>> The returned list includes the registered machine classes from all linked
> >>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
> >>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
> >>>>>>>>> arbitrarily:
> >>>>>>>>>
> >>>>>>>>> ```text
> >>>>>>>>> qemu-system -target none -M virt
> >>>>>>>>> unsupported machine type: "virt" for target "none"
> >>>>>>>>> Available for targets:
> >>>>>>>>>     aarch64
> >>>>>>>>>     arm
> >>>>>>>>> ```
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>>   From the long conversation on a previous thread, I thought we reached
> >>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
> >>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
> >>>>>>>>
> >>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >>>>>>>>
> >>>>>>>> I'm not sure which semantic we want to have with -target none. If there
> >>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
> >>>>>>>> win-win IMHO.
> >>>>>>>
> >>>>>>> Yes, if we expose unique names for every machine, then -target is then
> >>>>>>> redundant.
> >>>>>>
> >>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> >>>>>> needs two name?
> >>>>>> "virt" needs register twice for it? or register only a single time,
> >>>>>> but we prefix the target_name()
> >>>>>> automatically? for example machine::name === "virt", but we can use
> >>>>>> "riscv32-virt" "risv64-virt" to reach it?
> >>>>>>
> >>>>>
> >>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
> >>>>> Same goes for cpu max types.
> >>>>>
> >>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
> >>>>> the "alias" name, which is virt, in case multiple matches are found,
> >>>>> command line can return an error with list of unambiguous names to call it.
> >>>>>
> >>>>> $ qemu-system -M virt
> >>>>> Multiple virt machines are available. Please choose one of them:
> >>>>> - aarch64-virt
> >>>>> - riscv64-virt
> >>>>>
> >>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
> >>>>> we can find which target it implements from mc->targets.
> >>>>> And then, we can automatically choose which cpus should be available
> >>>>> based on that, thanks to cpu->targets.
> >>>>>
> >>>>> For existing binaries, nothing change.
> >>>>
> >>>> Good, I think we found a clean way now, is_available should be
> >>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
> >>>
> >>> It goes into MachineClass only for now.
> >>>
> >>>> I think
> >>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
> >>>> the $arch specific virt. so that we only have a single "virt" registered.
> >>>> And it's
> >>>> targets is
> >>>> QEMU_ARCH_I386 |
> >>>> QEMU_ARCH_ARM |
> >>>> QEMU_ARCH_RISCV |
> >>>> QEMU_ARCH_LOONGARCH |
> >>>> QEMU_ARCH_M68K |
> >>>> QEMU_ARCH_OR1K |
> >>>> QEMU_ARCH_XTENSA |
> >>>> QEMU_ARCH_HEXAGON
> >>>>
> >>>> So that we won't have a list of conflict QOM names for "virt" machines.
> >>>> As now we indeed have only a single "virt" machine that redirects to
> >>>> different targets.
> >>>>
> >>>
> >>> The idea looks appealing, but I don't think it solves the problem to
> >>> have multiple virt variants available at the same time.
> >>>
> >>> The "alias" idea you introduced before is good, we just need to add a
> >>> check if an alias is really unique, else return an error, as explained
> >>> previously.
> >>>
> >>> If "-M aarch64-virt" works for both the new and existing binary, and -M
> >>> virt only for existing binaries (and ambiguous for new one), I think
> >>> that's a safe approach.
> >>>
> >>>>
> >>>> For other types also conflict can be handled in the same way, such as
> >>>> "-cpu host" "-cpu max"
> >>>> maybe others, but I think they all have the same way to deal with.
> >>>>
> >>>>
> >>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
> >>>> Machine::targets
> >>>>
> >>>
> >>> One step at a time.
> >>> Let's keep focused on declaring targets for a single machine first.
> >>> Then we can iterate to solve the "virt" problem.
> >>> Then convert all the existing machines and add a check in machine-target.c
> >>> Then, and only then, we can see what happens with cpus.
> >>
> >> I tried this idea, but I faced a fatal error, because the
> >> target_info() is not available until
> >> the machine selected(the target arch will be select just along with
> >> the machine selected), so basically
> >> all calls to target_info() would raise an error(null pointer), how to
> >> deal with it?
> >>
> >
> > I see. Indeed, since we can't set a target before registering all types,
> > it implies that all the types class_init can't use target_* functions.
> >
> >
> > - register_accel_target_type
> > - cpu_max_v8_register_type
> >
>
> Sorry, mail sent to early.
>
> For the is_available callback usage, it should be easy to do the switch,
> since it's basically the same information that what we are trying to do
> - we can leave them for now.
>
> Some types (like accel and max mentioned above), explicitly change their
> definition depending on the target. It's a behavior we can't rely on
> anymore, and it means we need proper distinct types instead of a single
> one with dynamic definition driven by target-info.
>
> I think that's the preliminary work needed, before being able to go
> further: convert all existing usage in class_init with distinct types +
> is_available, and then we can do the switch from is_available to the new
> .targets approach.

Hi Pierrick,
I have already tried that introducing new QOM names just to make class_init
 target-independent is too broad(means all usage of it should be handled)
and could complicate compatibility(changed too much code).
Can we avoid new names by some new means(ideas welcome)?


>
> It's probably worth having the conversion in its own series (only
> cleanup usage of target_* in class_init), before trying to get rid of
> is_available.

>
> For the implementation, you can use the multi-targets.c binary test to
> drive the change. Remove the module init for target info (leaving no
> target set), and add a hacky patch to skip call to is_available (and
> return true instead) and allow double definition (which will rely on
> is_available). Then, fix all the segfault. Once it compiles and runs,
> only double definition will be left, which can be handled by inserting
> the right is_available callbacks. Then in a subsequent series, the
> switch to .targets can be made.


Still have no clean clue about how to remove is_available , as we have many
"virt" machines. Do you means all "virt" machines with "virt-machine" QOM names
are inserted to the table? How to get it working because the "key" is string.


>
> It's a work we'll need to do for heterogeneous anyway, I was just hoping
> to delay that until there, but seems we need to deal with it now.
> A good thing is that it means target-info won't have to be registered
> before all QOM types anymore, so it's worth the effort IMHO.
>
> Thanks,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-12  4:26                   ` Yonggang Luo
@ 2026-10-12  7:11                     ` Pierrick Bouvier
  2026-10-13  1:26                     ` Pierrick Bouvier
  1 sibling, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-12  7:11 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/11/26 9:26 PM, Yonggang Luo wrote:
> On Mon, Oct 12, 2026 at 10:25 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/11/26 7:13 PM, Pierrick Bouvier wrote:
>>> On 10/11/26 1:22 PM, Yonggang Luo wrote:
>>>> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>
>>>>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
>>>>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
>>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>>>
>>>>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
>>>>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>>>>>
>>>>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
>>>>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>>>>>>>>>>> This allows a combined binary to register machine types from all its targets.
>>>>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
>>>>>>>>>>> target, even when `none` is selected. For example, a client can query the
>>>>>>>>>>> combined machine list with:
>>>>>>>>>>>
>>>>>>>>>>> ```json
>>>>>>>>>>> { "execute": "query-machines" }
>>>>>>>>>>> ```
>>>>>>>>>>>
>>>>>>>>>>> The returned list includes the registered machine classes from all linked
>>>>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
>>>>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
>>>>>>>>>>> arbitrarily:
>>>>>>>>>>>
>>>>>>>>>>> ```text
>>>>>>>>>>> qemu-system -target none -M virt
>>>>>>>>>>> unsupported machine type: "virt" for target "none"
>>>>>>>>>>> Available for targets:
>>>>>>>>>>>      aarch64
>>>>>>>>>>>      arm
>>>>>>>>>>> ```
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>    From the long conversation on a previous thread, I thought we reached
>>>>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
>>>>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
>>>>>>>>>>
>>>>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
>>>>>>>>>>
>>>>>>>>>> I'm not sure which semantic we want to have with -target none. If there
>>>>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
>>>>>>>>>> win-win IMHO.
>>>>>>>>>
>>>>>>>>> Yes, if we expose unique names for every machine, then -target is then
>>>>>>>>> redundant.
>>>>>>>>
>>>>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
>>>>>>>> needs two name?
>>>>>>>> "virt" needs register twice for it? or register only a single time,
>>>>>>>> but we prefix the target_name()
>>>>>>>> automatically? for example machine::name === "virt", but we can use
>>>>>>>> "riscv32-virt" "risv64-virt" to reach it?
>>>>>>>>
>>>>>>>
>>>>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
>>>>>>> Same goes for cpu max types.
>>>>>>>
>>>>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
>>>>>>> the "alias" name, which is virt, in case multiple matches are found,
>>>>>>> command line can return an error with list of unambiguous names to call it.
>>>>>>>
>>>>>>> $ qemu-system -M virt
>>>>>>> Multiple virt machines are available. Please choose one of them:
>>>>>>> - aarch64-virt
>>>>>>> - riscv64-virt
>>>>>>>
>>>>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
>>>>>>> we can find which target it implements from mc->targets.
>>>>>>> And then, we can automatically choose which cpus should be available
>>>>>>> based on that, thanks to cpu->targets.
>>>>>>>
>>>>>>> For existing binaries, nothing change.
>>>>>>
>>>>>> Good, I think we found a clean way now, is_available should be
>>>>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
>>>>>
>>>>> It goes into MachineClass only for now.
>>>>>
>>>>>> I think
>>>>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
>>>>>> the $arch specific virt. so that we only have a single "virt" registered.
>>>>>> And it's
>>>>>> targets is
>>>>>> QEMU_ARCH_I386 |
>>>>>> QEMU_ARCH_ARM |
>>>>>> QEMU_ARCH_RISCV |
>>>>>> QEMU_ARCH_LOONGARCH |
>>>>>> QEMU_ARCH_M68K |
>>>>>> QEMU_ARCH_OR1K |
>>>>>> QEMU_ARCH_XTENSA |
>>>>>> QEMU_ARCH_HEXAGON
>>>>>>
>>>>>> So that we won't have a list of conflict QOM names for "virt" machines.
>>>>>> As now we indeed have only a single "virt" machine that redirects to
>>>>>> different targets.
>>>>>>
>>>>>
>>>>> The idea looks appealing, but I don't think it solves the problem to
>>>>> have multiple virt variants available at the same time.
>>>>>
>>>>> The "alias" idea you introduced before is good, we just need to add a
>>>>> check if an alias is really unique, else return an error, as explained
>>>>> previously.
>>>>>
>>>>> If "-M aarch64-virt" works for both the new and existing binary, and -M
>>>>> virt only for existing binaries (and ambiguous for new one), I think
>>>>> that's a safe approach.
>>>>>
>>>>>>
>>>>>> For other types also conflict can be handled in the same way, such as
>>>>>> "-cpu host" "-cpu max"
>>>>>> maybe others, but I think they all have the same way to deal with.
>>>>>>
>>>>>>
>>>>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
>>>>>> Machine::targets
>>>>>>
>>>>>
>>>>> One step at a time.
>>>>> Let's keep focused on declaring targets for a single machine first.
>>>>> Then we can iterate to solve the "virt" problem.
>>>>> Then convert all the existing machines and add a check in machine-target.c
>>>>> Then, and only then, we can see what happens with cpus.
>>>>
>>>> I tried this idea, but I faced a fatal error, because the
>>>> target_info() is not available until
>>>> the machine selected(the target arch will be select just along with
>>>> the machine selected), so basically
>>>> all calls to target_info() would raise an error(null pointer), how to
>>>> deal with it?
>>>>
>>>
>>> I see. Indeed, since we can't set a target before registering all types,
>>> it implies that all the types class_init can't use target_* functions.
>>>
>>>
>>> - register_accel_target_type
>>> - cpu_max_v8_register_type
>>>
>>
>> Sorry, mail sent to early.
>>
>> For the is_available callback usage, it should be easy to do the switch,
>> since it's basically the same information that what we are trying to do
>> - we can leave them for now.
>>
>> Some types (like accel and max mentioned above), explicitly change their
>> definition depending on the target. It's a behavior we can't rely on
>> anymore, and it means we need proper distinct types instead of a single
>> one with dynamic definition driven by target-info.
>>
>> I think that's the preliminary work needed, before being able to go
>> further: convert all existing usage in class_init with distinct types +
>> is_available, and then we can do the switch from is_available to the new
>> .targets approach.
> 
> Hi Pierrick,
> I have already tried that introducing new QOM names just to make class_init
>   target-independent is too broad(means all usage of it should be handled)
> and could complicate compatibility(changed too much code).
> Can we avoid new names by some new means(ideas welcome)?
>

We can use is_available as an intermediate step.
The good thing is that removing target_* from class_init can be done as 
much incrementally as we want: there is no need to do all the changes at 
once.

Once we get to the point where there is no target_* in class_init and 
all types are properly defined with is_available filters, we can see how 
to deal with the duplication. My point of view after our discussions is 
that we should keep current name for existing binaries, and should be 
free to force user to deal with ambiguity with new single-binary 
(machine type "X" is ambiguous, please choose among arch-X, arch-Y, ...).

> 
>>
>> It's probably worth having the conversion in its own series (only
>> cleanup usage of target_* in class_init), before trying to get rid of
>> is_available.
> 
>>
>> For the implementation, you can use the multi-targets.c binary test to
>> drive the change. Remove the module init for target info (leaving no
>> target set), and add a hacky patch to skip call to is_available (and
>> return true instead) and allow double definition (which will rely on
>> is_available). Then, fix all the segfault. Once it compiles and runs,
>> only double definition will be left, which can be handled by inserting
>> the right is_available callbacks. Then in a subsequent series, the
>> switch to .targets can be made.
> 
> 
> Still have no clean clue about how to remove is_available , as we have many
> "virt" machines. Do you means all "virt" machines with "virt-machine" QOM names
> are inserted to the table? How to get it working because the "key" is string.
>

The alias series you posted initially was good, with the addition to 
detect when multiple machines have the same alias (and report an error 
in this case).

I triggered the conversation we are having now because things have not 
been defined properly, and the direction to have -target + arch:machine 
was not really satisfactory. Now we settled on excluding -target, and 
embedding all types, I think it's clearer.

> 
>>
>> It's a work we'll need to do for heterogeneous anyway, I was just hoping
>> to delay that until there, but seems we need to deal with it now.
>> A good thing is that it means target-info won't have to be registered
>> before all QOM types anymore, so it's worth the effort IMHO.
>>
>> Thanks,
>> Pierrick
> 
> 
> 



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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 23:28           ` Pierrick Bouvier
@ 2026-10-12 21:27             ` Yonggang Luo
  2026-10-13  3:57               ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-12 21:27 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Thu, Oct 8, 2026 at 7:28 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/7/2026 4:02 PM, Yonggang Luo wrote:
> > On Thu, Oct 8, 2026 at 6:31 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/7/2026 1:50 PM, Yonggang Luo wrote:
> >>> On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
> >>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>
> >>>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> >>>>> Register target definitions through constructors instead of
> >>>>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
> >>>>> available on entry to main(), without explicit initialization or a
> >>>>> call to module_call_init(MODULE_INIT_QOM).
> >>>>>
> >>>>> Keep the target list sorted by target_arch and default to its first
> >>>>> entry. Provide an unknown TargetInfo fallback for target-independent
> >>>>> tools such as qemu-img and unit tests that link no target-info-def.c
> >>>>> objects.
> >>>>>
> >>>>> Remove the obsolete QOM target-info registration infrastructure and
> >>>>> update the multi-target test to inspect target information before
> >>>>> initializing QOM.
> >>>>>
> >>>>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> >>>>> ---
> >>>>>  include/qemu/module.h           |  1 -
> >>>>>  include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
> >>>>>  include/qemu/target-info-init.h | 53 ----------------------------
> >>>>>  include/qemu/target-info-qom.h  | 31 -----------------
> >>>>>  include/qemu/target-info.h      |  9 +++++
> >>>>>  meson.build                     |  6 ++--
> >>>>>  system/vl.c                     |  4 ---
> >>>>>  target-info-def.c               |  1 -
> >>>>>  target-info-qom.c               | 60 --------------------------------
> >>>>>  target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
> >>>>>  tests/qtest/fuzz/fuzz.c         |  3 --
> >>>>>  tests/unit/test-multi-target.c  | 12 +++----
> >>>>>  12 files changed, 129 insertions(+), 168 deletions(-)
> >>>>>  delete mode 100644 include/qemu/target-info-init.h
> >>>>>  delete mode 100644 include/qemu/target-info-qom.h
> >>>>>  delete mode 100644 target-info-qom.c
> >>>>>
> >>>>
> >>>> This approach (custom list based) was considered before implementing
> >>>> things with QOM Types. The rationale I followed was that if everything
> >>>> is in QOM, we might better follow that for consistency sake.
> >>>> Yes, the compromise if that we need an extra init step, but it was not a
> >>>> problem to add it.
> >>> I have issue to add the init step for unit-tests, and hard to write the -target
> >>> parse procedure and get it right. Not means this won't work. but for
> >>> me, too much
> >>> coupled.
> >>>
> >>
> >> We already have such a test upstream:
> >> https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35
> >>
> >> The init sequence is quite straightforward:
> >>
> >> ```
> >> /* initialize target types, and only them */
> >> module_call_init(MODULE_INIT_TARGET_INFO);
> >>
> >> /* we can get the list if we want, for -target or any other purpose */
> >> g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
> >>
> >> /* set the global target info from any element in this list */
> >> TargetInfo* ti = ...;
> >> target_info_qom_set_target_info(ti);
> >>
> >> /* register rest of QOM types */
> >> module_call_init(MODULE_INIT_QOM);
> >> ```
> >>
> >> It works fine to implement -target (if we would like to do it), since I
> >> implemented it myself. That was also my initial motivation by the way.
> >>
> >> Also, I appreciate that target-info is NULL by default, it crashes
> >> loudly when it has not been set, and make it easy to find who depends on it.
> >>
> >>> If we treat target_info as a QOM, but QOM needs target_info to set
> >>> up(is_avaible). That makes
> >>> the init sequence too much of a burden.
> >>>
> >>
> >> See sequence above, the solution is to initialize TARGET_INFO first,
> >> before the rest of QOM. You end up with the same result than with a
> >> statically initialized list.
> >>
> >>>
> >>> is_available is depends on target_arch
> >>> And before this patch, target_arch depends on QOM, pulls user/softmmu because
> >>> target_info_init. By moving target-info to be a custom list based, we
> >>> can decouple
> >>> target-info from qom/softmmu/user. and target-info will always
> >>> available once "main(argv, argc)" is entered. We also have the
> >>> advantage of doing all sorts
> >>> of tests against it.
> >>>
> >>
> >> Which kind of tests are you trying to add?
> >>
> >> For now, the exact list of places where we need to do this initialize
> >> target dance are:
> >> - system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> >> - tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> >> - tests/unit/test-multi-target.c:
> >
> > # Multi targets test
> > if multi_target_objects != []
> >   test('test-multi-target',
> >        executable('test-multi-target',
> >                   sources: [multi_target_crates, files('test-multi-target.c')],
> >                   dependencies: multi_target_deps,
> >                   objects: multi_target_objects,
> >                   link_depends: [block_syms, qemu_syms],
> >                   link_args: multi_target_link_args),
> >        suite: ['unit'])
> > endif
> >
> > I see this test, I am trying to add tests that do not pull so many
> > multi_target_objects, as it would be huge.
>
> Agree, we should not add more binary.
> If you need truly multi targets test, this existing binary is a good
> place to start: just add a second test in it.
>
> > Just pull qom only.  And I am trying to call target_info() in
> > object.c, as inspect machines with
> > qemu-system is rejected, so maybe that's not an issue anymore
> >
>
> Seems like a good candidate for the multi-target.c test.
>
> >
> > I means Subject: [PATCH v3 00/10] machine: uniquify virt QOM names
> > https://lore.kernel.org/qemu-devel/20260926081551.29-1-luoyonggang@gmail.com/#r
> >
> > So the current design always rejects types that do not belong to the
> > current target. Listing them
> > all is not an option at all. With this restriction, then these are
> > indeed not needed.
> > So I'll wait for your work first, otherwise it's always conflicting.
> >
> >
> >> module_call_init(MODULE_INIT_TARGET_INFO);
> >>
> >> If we want more tests, I'm totally ok to move this init code to
> >> target-info.c, and replace call sites if needed.
> >>
> >>>
> >>> Tools such as qemu-img and unit tests may link target-info.c without any
> >>> target-info-def.c objects. Their target list remains empty, so use this
> >>> fallback.
> >>>
> >>
> >> Why should this tool get access to target list? qemu-img deals with disk
> >> images, and is unrelated to targets.
> >>
> >>>
> >>> static TypeImpl *type_register_internal(const TypeInfo *info)
> >>> {
> >>>     TypeImpl *ti;
> >>>
> >>>     if (!type_name_is_valid(info->name)) {
> >>>         fprintf(stderr, "Registering '%s' with illegal type name\n",
> >>> info->name);
> >>>         abort();
> >>>     }
> >>>
> >>>     if (info->is_available && !info->is_available()) {
> >>>         return NULL;
> >>>     }
> >>>
> >>>     ti = type_new(info);
> >>>
> >>>     type_table_add(ti);
> >>>     return ti;
> >>> }
> >>>
> >>>>
> >>>> Is there another good value this list approach brings compared to what
> >>>> exists?
> >>>>
> >>>> Regards,
> >>>> Pierrick
> >>>
> >>>
> >>>
> >>
> >
> >
>


Hi, the cycle dependencies issue happened again, deal with it's a bit
nasty, there is workaround, but I think
the constructor list is the best, here is the rationale:


# Target discovery during QOM registration

## Problem

Machine registration needs the list of targets compiled into the binary.
Currently, it obtains that list through:

```c
object_class_get_list(TYPE_TARGET_INFO, false);
```

Despite the filter, QOM initializes every registered type before checking
whether it implements the requested type.

During `MODULE_INIT_QOM`, registration is only partially complete. A device
may already be registered while its parent's registration callback has not
run, causing failures such as:

```text
Type 'sys-bus-device' is missing its parent 'device'
```

The parent is linked into the binary. The problem is premature
initialization, not a missing library.

## Option 1: cache target-info QOM classes

Enumerate target-info classes once, before device registration starts.
Machine registration then reads the cache instead of enumerating QOM.

### Demo

Declare shared helpers:

```c
void target_info_qom_init(void);
const GSList *target_info_qom_get_targets(void);
```

Implement the cache:

```c
static GSList *target_info_classes;
static bool target_info_initialized;

void target_info_qom_init(void)
{
    if (target_info_initialized) {
        return;
    }

    module_call_init(MODULE_INIT_TARGET_INFO);
    target_info_classes = object_class_get_list(TYPE_TARGET_INFO, false);
    target_info_initialized = true;
}

const GSList *target_info_qom_get_targets(void)
{
    assert(target_info_initialized);
    return target_info_classes;
}
```

Initialize it before other QOM registration:

```c
target_info_qom_init();
module_call_init(MODULE_INIT_QOM);
```

Machine registration uses the borrowed cache:

```c
for (const GSList *l = target_info_qom_get_targets(); l; l = l->next) {
    const TargetInfo *ti = TARGET_INFO_CLASS(l->data)->target_info;

    machine_register_virt_type_for_target(info, name_suffix, arch_mask,
                                         latest, ti);
}
```

`target_info_qom_set_target()` should also use the cached list instead of
enumerating QOM again.

### Advantages

- Preserves the existing QOM-based representation.
- Avoids enumeration during incomplete device registration.
- Requires relatively small changes.

### Disadvantages

- Every relevant executable and test must initialize the cache before
  starting QOM registration.
- `object_class_get_list()` allocates list nodes.
- Callers borrow the list, so it cannot be freed while they are using it.
- Cleanup is possible after all consumers finish, but requires an explicit
  lifecycle policy. Keeping the cache until process exit is a lifetime
  allocation, not inherently an unreachable memory leak.
- Target-info types registered after cache creation are not included.
- Target discovery remains coupled to QOM class initialization.

## Option 2: constructor-populated TargetInfo registry

Each target registers its immutable `TargetInfo` pointer directly.
Machine registration later iterates the registry without querying QOM.

Use a statically allocated node per target so registration requires no
heap allocation.

### Demo

Define a registration node and accessors:

```c
typedef struct TargetInfoRegistration {
    const TargetInfo *info;
    struct TargetInfoRegistration *next;
} TargetInfoRegistration;

void target_info_register(TargetInfoRegistration *entry);
const TargetInfoRegistration *target_info_get_targets(void);
```

Implement the registry in shared code:

```c
static TargetInfoRegistration *target_info_targets;

void target_info_register(TargetInfoRegistration *entry)
{
    entry->next = target_info_targets;
    target_info_targets = entry;
}

const TargetInfoRegistration *target_info_get_targets(void)
{
    return target_info_targets;
}
```

Each target's translation unit provides its own static node and
constructor. For example:

```c
static TargetInfoRegistration target_info_registration = {
    .info = &target_info_stub,
};

static void __attribute__((constructor)) register_target_info(void)
{
    target_info_register(&target_info_registration);
}
```

The constructor must run exactly once per node. The existing target-info
initialization macro can generate this registration code alongside the
QOM registration code; user-mode target-info behavior should remain
unchanged.

Machine registration consumes the completed registry:

```c
for (const TargetInfoRegistration *entry = target_info_get_targets();
     entry;
     entry = entry->next) {
    machine_register_virt_type_for_target(info, name_suffix, arch_mask,
                                         latest, entry->info);
}
```

The sequence is:

```text
Target constructors register static metadata pointers
    ↓
Startup constructors finish
    ↓
Machine registration iterates the completed registry
```

QOM target-info classes can remain available for introspection.

### Advantages

- Makes target discovery independent of QOM initialization.
- Removes the explicit cache-initialization step from executables and tests.
- Avoids premature initialization of unrelated device types.
- Uses static storage: no allocated list nodes and no registry cleanup.
- Does not require ordering between target constructors.

### Constraints

- Constructors must only register metadata, not enumerate or initialize
  QOM classes.
- Consumers must run after startup constructors have completed.
- Each registration node must be inserted exactly once.
- Registry order must not be treated as a meaningful target ordering.
- This simple design assumes compiled-in targets; runtime loading or
  unloading would require additional lifecycle handling.

## Comparison

| Aspect | QOM class cache | Static constructor registry |
|---|---|---|
| Discovery mechanism | QOM enumeration | Direct metadata registration |
| Explicit startup initialization | Required | Not required |
| Heap allocation for list nodes | Yes | No |
| Cleanup policy | Required if releasing the cache | No registry cleanup |
| Dependency on QOM initialization | Yes | No |
| Registration-order sensitivity | Avoided through explicit sequencing
| Avoided by consuming after constructors |
| Late target registration | Cache needs updating | Requires a defined
runtime registration policy |

## Recommendation

Prefer the constructor-populated registry with statically allocated nodes.

`TargetInfo` describes the binary's compiled-in capabilities. Accessing
that metadata should not require initializing the device model or
maintaining an allocated cache of QOM classes.

The QOM cache fixes the immediate failure, but introduces an additional
startup contract and ownership policy. A static constructor registry
removes the underlying dependency and avoids heap allocation for the
registry itself.



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-12  4:26                   ` Yonggang Luo
  2026-10-12  7:11                     ` Pierrick Bouvier
@ 2026-10-13  1:26                     ` Pierrick Bouvier
  2026-10-13  2:43                       ` Yonggang Luo
  1 sibling, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-13  1:26 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/11/26 9:26 PM, Yonggang Luo wrote:
> On Mon, Oct 12, 2026 at 10:25 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/11/26 7:13 PM, Pierrick Bouvier wrote:
>>> On 10/11/26 1:22 PM, Yonggang Luo wrote:
>>>> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>
>>>>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
>>>>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
>>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>>>
>>>>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
>>>>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>>>>>
>>>>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
>>>>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>>>>>>>>>>> This allows a combined binary to register machine types from all its targets.
>>>>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
>>>>>>>>>>> target, even when `none` is selected. For example, a client can query the
>>>>>>>>>>> combined machine list with:
>>>>>>>>>>>
>>>>>>>>>>> ```json
>>>>>>>>>>> { "execute": "query-machines" }
>>>>>>>>>>> ```
>>>>>>>>>>>
>>>>>>>>>>> The returned list includes the registered machine classes from all linked
>>>>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
>>>>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
>>>>>>>>>>> arbitrarily:
>>>>>>>>>>>
>>>>>>>>>>> ```text
>>>>>>>>>>> qemu-system -target none -M virt
>>>>>>>>>>> unsupported machine type: "virt" for target "none"
>>>>>>>>>>> Available for targets:
>>>>>>>>>>>      aarch64
>>>>>>>>>>>      arm
>>>>>>>>>>> ```
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>    From the long conversation on a previous thread, I thought we reached
>>>>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
>>>>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
>>>>>>>>>>
>>>>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
>>>>>>>>>>
>>>>>>>>>> I'm not sure which semantic we want to have with -target none. If there
>>>>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
>>>>>>>>>> win-win IMHO.
>>>>>>>>>
>>>>>>>>> Yes, if we expose unique names for every machine, then -target is then
>>>>>>>>> redundant.
>>>>>>>>
>>>>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
>>>>>>>> needs two name?
>>>>>>>> "virt" needs register twice for it? or register only a single time,
>>>>>>>> but we prefix the target_name()
>>>>>>>> automatically? for example machine::name === "virt", but we can use
>>>>>>>> "riscv32-virt" "risv64-virt" to reach it?
>>>>>>>>
>>>>>>>
>>>>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
>>>>>>> Same goes for cpu max types.
>>>>>>>
>>>>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
>>>>>>> the "alias" name, which is virt, in case multiple matches are found,
>>>>>>> command line can return an error with list of unambiguous names to call it.
>>>>>>>
>>>>>>> $ qemu-system -M virt
>>>>>>> Multiple virt machines are available. Please choose one of them:
>>>>>>> - aarch64-virt
>>>>>>> - riscv64-virt
>>>>>>>
>>>>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
>>>>>>> we can find which target it implements from mc->targets.
>>>>>>> And then, we can automatically choose which cpus should be available
>>>>>>> based on that, thanks to cpu->targets.
>>>>>>>
>>>>>>> For existing binaries, nothing change.
>>>>>>
>>>>>> Good, I think we found a clean way now, is_available should be
>>>>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
>>>>>
>>>>> It goes into MachineClass only for now.
>>>>>
>>>>>> I think
>>>>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
>>>>>> the $arch specific virt. so that we only have a single "virt" registered.
>>>>>> And it's
>>>>>> targets is
>>>>>> QEMU_ARCH_I386 |
>>>>>> QEMU_ARCH_ARM |
>>>>>> QEMU_ARCH_RISCV |
>>>>>> QEMU_ARCH_LOONGARCH |
>>>>>> QEMU_ARCH_M68K |
>>>>>> QEMU_ARCH_OR1K |
>>>>>> QEMU_ARCH_XTENSA |
>>>>>> QEMU_ARCH_HEXAGON
>>>>>>
>>>>>> So that we won't have a list of conflict QOM names for "virt" machines.
>>>>>> As now we indeed have only a single "virt" machine that redirects to
>>>>>> different targets.
>>>>>>
>>>>>
>>>>> The idea looks appealing, but I don't think it solves the problem to
>>>>> have multiple virt variants available at the same time.
>>>>>
>>>>> The "alias" idea you introduced before is good, we just need to add a
>>>>> check if an alias is really unique, else return an error, as explained
>>>>> previously.
>>>>>
>>>>> If "-M aarch64-virt" works for both the new and existing binary, and -M
>>>>> virt only for existing binaries (and ambiguous for new one), I think
>>>>> that's a safe approach.
>>>>>
>>>>>>
>>>>>> For other types also conflict can be handled in the same way, such as
>>>>>> "-cpu host" "-cpu max"
>>>>>> maybe others, but I think they all have the same way to deal with.
>>>>>>
>>>>>>
>>>>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
>>>>>> Machine::targets
>>>>>>
>>>>>
>>>>> One step at a time.
>>>>> Let's keep focused on declaring targets for a single machine first.
>>>>> Then we can iterate to solve the "virt" problem.
>>>>> Then convert all the existing machines and add a check in machine-target.c
>>>>> Then, and only then, we can see what happens with cpus.
>>>>
>>>> I tried this idea, but I faced a fatal error, because the
>>>> target_info() is not available until
>>>> the machine selected(the target arch will be select just along with
>>>> the machine selected), so basically
>>>> all calls to target_info() would raise an error(null pointer), how to
>>>> deal with it?
>>>>
>>>
>>> I see. Indeed, since we can't set a target before registering all types,
>>> it implies that all the types class_init can't use target_* functions.
>>>
>>>
>>> - register_accel_target_type
>>> - cpu_max_v8_register_type
>>>
>>
>> Sorry, mail sent to early.
>>
>> For the is_available callback usage, it should be easy to do the switch,
>> since it's basically the same information that what we are trying to do
>> - we can leave them for now.
>>
>> Some types (like accel and max mentioned above), explicitly change their
>> definition depending on the target. It's a behavior we can't rely on
>> anymore, and it means we need proper distinct types instead of a single
>> one with dynamic definition driven by target-info.
>>
>> I think that's the preliminary work needed, before being able to go
>> further: convert all existing usage in class_init with distinct types +
>> is_available, and then we can do the switch from is_available to the new
>> .targets approach.
> 
> Hi Pierrick,
> I have already tried that introducing new QOM names just to make class_init
>   target-independent is too broad(means all usage of it should be handled)
> and could complicate compatibility(changed too much code).
> Can we avoid new names by some new means(ideas welcome)?
>

As a first step, I don't think we need new names, is_available can be 
used to selectively register one definition or another and avoid any 
clash. What is missing at the moment though, is that some types (like 
cpu max above) change their definition based on target definition.

So for cpu max, we would have two distinct types, both named max, but 
one with is_available(target_arm), and other one with 
is_available(target_aarch64), so they are never registered at the same time.

Same for virt machines. It's already what we have, duplication is 
handled at the moment with distinct is_available callbacks.

Then, see below.

> 
>>
>> It's probably worth having the conversion in its own series (only
>> cleanup usage of target_* in class_init), before trying to get rid of
>> is_available.
> 
>>
>> For the implementation, you can use the multi-targets.c binary test to
>> drive the change. Remove the module init for target info (leaving no
>> target set), and add a hacky patch to skip call to is_available (and
>> return true instead) and allow double definition (which will rely on
>> is_available). Then, fix all the segfault. Once it compiles and runs,
>> only double definition will be left, which can be handled by inserting
>> the right is_available callbacks. Then in a subsequent series, the
>> switch to .targets can be made.
> 
> 
> Still have no clean clue about how to remove is_available , as we have many
> "virt" machines. Do you means all "virt" machines with "virt-machine" QOM names
> are inserted to the table? How to get it working because the "key" is string.
>

Once we have type definition which only depends on is_available, we can 
convert this to .targets, which would contain the same information.
For the rest, I have some ideas, but I would like first we do the first 
part (convert to is_available), which is already a huge work in itself, 
and a series of its own.

Regards,
Pierrick


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-13  1:26                     ` Pierrick Bouvier
@ 2026-10-13  2:43                       ` Yonggang Luo
  2026-10-13  3:53                         ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-13  2:43 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Tue, Oct 13, 2026 at 9:26 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/11/26 9:26 PM, Yonggang Luo wrote:
> > On Mon, Oct 12, 2026 at 10:25 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/11/26 7:13 PM, Pierrick Bouvier wrote:
> >>> On 10/11/26 1:22 PM, Yonggang Luo wrote:
> >>>> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
> >>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>>
> >>>>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
> >>>>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
> >>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>>>>
> >>>>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> >>>>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>>>>>>>>
> >>>>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> >>>>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> >>>>>>>>>>> This allows a combined binary to register machine types from all its targets.
> >>>>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
> >>>>>>>>>>> target, even when `none` is selected. For example, a client can query the
> >>>>>>>>>>> combined machine list with:
> >>>>>>>>>>>
> >>>>>>>>>>> ```json
> >>>>>>>>>>> { "execute": "query-machines" }
> >>>>>>>>>>> ```
> >>>>>>>>>>>
> >>>>>>>>>>> The returned list includes the registered machine classes from all linked
> >>>>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
> >>>>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
> >>>>>>>>>>> arbitrarily:
> >>>>>>>>>>>
> >>>>>>>>>>> ```text
> >>>>>>>>>>> qemu-system -target none -M virt
> >>>>>>>>>>> unsupported machine type: "virt" for target "none"
> >>>>>>>>>>> Available for targets:
> >>>>>>>>>>>      aarch64
> >>>>>>>>>>>      arm
> >>>>>>>>>>> ```
> >>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>    From the long conversation on a previous thread, I thought we reached
> >>>>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
> >>>>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
> >>>>>>>>>>
> >>>>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >>>>>>>>>>
> >>>>>>>>>> I'm not sure which semantic we want to have with -target none. If there
> >>>>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
> >>>>>>>>>> win-win IMHO.
> >>>>>>>>>
> >>>>>>>>> Yes, if we expose unique names for every machine, then -target is then
> >>>>>>>>> redundant.
> >>>>>>>>
> >>>>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> >>>>>>>> needs two name?
> >>>>>>>> "virt" needs register twice for it? or register only a single time,
> >>>>>>>> but we prefix the target_name()
> >>>>>>>> automatically? for example machine::name === "virt", but we can use
> >>>>>>>> "riscv32-virt" "risv64-virt" to reach it?
> >>>>>>>>
> >>>>>>>
> >>>>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
> >>>>>>> Same goes for cpu max types.
> >>>>>>>
> >>>>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
> >>>>>>> the "alias" name, which is virt, in case multiple matches are found,
> >>>>>>> command line can return an error with list of unambiguous names to call it.
> >>>>>>>
> >>>>>>> $ qemu-system -M virt
> >>>>>>> Multiple virt machines are available. Please choose one of them:
> >>>>>>> - aarch64-virt
> >>>>>>> - riscv64-virt
> >>>>>>>
> >>>>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
> >>>>>>> we can find which target it implements from mc->targets.
> >>>>>>> And then, we can automatically choose which cpus should be available
> >>>>>>> based on that, thanks to cpu->targets.
> >>>>>>>
> >>>>>>> For existing binaries, nothing change.
> >>>>>>
> >>>>>> Good, I think we found a clean way now, is_available should be
> >>>>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
> >>>>>
> >>>>> It goes into MachineClass only for now.
> >>>>>
> >>>>>> I think
> >>>>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
> >>>>>> the $arch specific virt. so that we only have a single "virt" registered.
> >>>>>> And it's
> >>>>>> targets is
> >>>>>> QEMU_ARCH_I386 |
> >>>>>> QEMU_ARCH_ARM |
> >>>>>> QEMU_ARCH_RISCV |
> >>>>>> QEMU_ARCH_LOONGARCH |
> >>>>>> QEMU_ARCH_M68K |
> >>>>>> QEMU_ARCH_OR1K |
> >>>>>> QEMU_ARCH_XTENSA |
> >>>>>> QEMU_ARCH_HEXAGON
> >>>>>>
> >>>>>> So that we won't have a list of conflict QOM names for "virt" machines.
> >>>>>> As now we indeed have only a single "virt" machine that redirects to
> >>>>>> different targets.
> >>>>>>
> >>>>>
> >>>>> The idea looks appealing, but I don't think it solves the problem to
> >>>>> have multiple virt variants available at the same time.
> >>>>>
> >>>>> The "alias" idea you introduced before is good, we just need to add a
> >>>>> check if an alias is really unique, else return an error, as explained
> >>>>> previously.
> >>>>>
> >>>>> If "-M aarch64-virt" works for both the new and existing binary, and -M
> >>>>> virt only for existing binaries (and ambiguous for new one), I think
> >>>>> that's a safe approach.
> >>>>>
> >>>>>>
> >>>>>> For other types also conflict can be handled in the same way, such as
> >>>>>> "-cpu host" "-cpu max"
> >>>>>> maybe others, but I think they all have the same way to deal with.
> >>>>>>
> >>>>>>
> >>>>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
> >>>>>> Machine::targets
> >>>>>>
> >>>>>
> >>>>> One step at a time.
> >>>>> Let's keep focused on declaring targets for a single machine first.
> >>>>> Then we can iterate to solve the "virt" problem.
> >>>>> Then convert all the existing machines and add a check in machine-target.c
> >>>>> Then, and only then, we can see what happens with cpus.
> >>>>
> >>>> I tried this idea, but I faced a fatal error, because the
> >>>> target_info() is not available until
> >>>> the machine selected(the target arch will be select just along with
> >>>> the machine selected), so basically
> >>>> all calls to target_info() would raise an error(null pointer), how to
> >>>> deal with it?
> >>>>
> >>>
> >>> I see. Indeed, since we can't set a target before registering all types,
> >>> it implies that all the types class_init can't use target_* functions.
> >>>
> >>>
> >>> - register_accel_target_type
> >>> - cpu_max_v8_register_type
> >>>
> >>
> >> Sorry, mail sent to early.
> >>
> >> For the is_available callback usage, it should be easy to do the switch,
> >> since it's basically the same information that what we are trying to do
> >> - we can leave them for now.
> >>
> >> Some types (like accel and max mentioned above), explicitly change their
> >> definition depending on the target. It's a behavior we can't rely on
> >> anymore, and it means we need proper distinct types instead of a single
> >> one with dynamic definition driven by target-info.
> >>
> >> I think that's the preliminary work needed, before being able to go
> >> further: convert all existing usage in class_init with distinct types +
> >> is_available, and then we can do the switch from is_available to the new
> >> .targets approach.
> >
> > Hi Pierrick,
> > I have already tried that introducing new QOM names just to make class_init
> >   target-independent is too broad(means all usage of it should be handled)
> > and could complicate compatibility(changed too much code).
> > Can we avoid new names by some new means(ideas welcome)?
> >
>
> As a first step, I don't think we need new names, is_available can be
> used to selectively register one definition or another and avoid any
> clash. What is missing at the moment though, is that some types (like
> cpu max above) change their definition based on target definition.


>
> So for cpu max, we would have two distinct types, both named max, but
> one with is_available(target_arm), and other one with
> is_available(target_aarch64), so they are never registered at the same time.

>
> Same for virt machines. It's already what we have, duplication is
> handled at the moment with distinct is_available callbacks.
>
> Then, see below.
>
> >
> >>
> >> It's probably worth having the conversion in its own series (only
> >> cleanup usage of target_* in class_init), before trying to get rid of
> >> is_available.
> >
> >>
> >> For the implementation, you can use the multi-targets.c binary test to
> >> drive the change. Remove the module init for target info (leaving no
> >> target set), and add a hacky patch to skip call to is_available (and
> >> return true instead) and allow double definition (which will rely on
> >> is_available). Then, fix all the segfault. Once it compiles and runs,
> >> only double definition will be left, which can be handled by inserting
> >> the right is_available callbacks. Then in a subsequent series, the
> >> switch to .targets can be made.
> >
> >
> > Still have no clean clue about how to remove is_available , as we have many
> > "virt" machines. Do you means all "virt" machines with "virt-machine" QOM names
> > are inserted to the table? How to get it working because the "key" is string.
> >
>
> Once we have type definition which only depends on is_available, we can
> convert this to .targets, which would contain the same information.
> For the rest, I have some ideas, but I would like first we do the first
> part (convert to is_available), which is already a huge work in itself,
> and a series of its own.

Indeed I am confused .targets only exists on Machine, how is it
related to -cpu host -cpu max?


I already have a working copy that does not depend on target_info()
and selects target_info() when the machine
is selected, no QOM name introduced. only for machines, we will have
$target_name-$machine_name as a name for selecting
the exact machine.

The cpu max cpu host is dealt by moving the choose code out of
class_init, into object_init. I really did not get your idea by use
is_avaiable. because when I try to get all QOMs to be registered. then
I won't call is_available at all.
because "is_available" depends on target_info(),(we won't have
target_info() till the machine is selected).

>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-13  2:43                       ` Yonggang Luo
@ 2026-10-13  3:53                         ` Pierrick Bouvier
  2026-10-13  4:03                           ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-13  3:53 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/12/26 7:43 PM, Yonggang Luo wrote:
> On Tue, Oct 13, 2026 at 9:26 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/11/26 9:26 PM, Yonggang Luo wrote:
>>> On Mon, Oct 12, 2026 at 10:25 AM Pierrick Bouvier
>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>
>>>> On 10/11/26 7:13 PM, Pierrick Bouvier wrote:
>>>>> On 10/11/26 1:22 PM, Yonggang Luo wrote:
>>>>>> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
>>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>>>
>>>>>>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
>>>>>>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
>>>>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>>>>>
>>>>>>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
>>>>>>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
>>>>>>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>>>>>>>>>>>>> This allows a combined binary to register machine types from all its targets.
>>>>>>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
>>>>>>>>>>>>> target, even when `none` is selected. For example, a client can query the
>>>>>>>>>>>>> combined machine list with:
>>>>>>>>>>>>>
>>>>>>>>>>>>> ```json
>>>>>>>>>>>>> { "execute": "query-machines" }
>>>>>>>>>>>>> ```
>>>>>>>>>>>>>
>>>>>>>>>>>>> The returned list includes the registered machine classes from all linked
>>>>>>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
>>>>>>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
>>>>>>>>>>>>> arbitrarily:
>>>>>>>>>>>>>
>>>>>>>>>>>>> ```text
>>>>>>>>>>>>> qemu-system -target none -M virt
>>>>>>>>>>>>> unsupported machine type: "virt" for target "none"
>>>>>>>>>>>>> Available for targets:
>>>>>>>>>>>>>       aarch64
>>>>>>>>>>>>>       arm
>>>>>>>>>>>>> ```
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>     From the long conversation on a previous thread, I thought we reached
>>>>>>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
>>>>>>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
>>>>>>>>>>>>
>>>>>>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
>>>>>>>>>>>>
>>>>>>>>>>>> I'm not sure which semantic we want to have with -target none. If there
>>>>>>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
>>>>>>>>>>>> win-win IMHO.
>>>>>>>>>>>
>>>>>>>>>>> Yes, if we expose unique names for every machine, then -target is then
>>>>>>>>>>> redundant.
>>>>>>>>>>
>>>>>>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
>>>>>>>>>> needs two name?
>>>>>>>>>> "virt" needs register twice for it? or register only a single time,
>>>>>>>>>> but we prefix the target_name()
>>>>>>>>>> automatically? for example machine::name === "virt", but we can use
>>>>>>>>>> "riscv32-virt" "risv64-virt" to reach it?
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
>>>>>>>>> Same goes for cpu max types.
>>>>>>>>>
>>>>>>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
>>>>>>>>> the "alias" name, which is virt, in case multiple matches are found,
>>>>>>>>> command line can return an error with list of unambiguous names to call it.
>>>>>>>>>
>>>>>>>>> $ qemu-system -M virt
>>>>>>>>> Multiple virt machines are available. Please choose one of them:
>>>>>>>>> - aarch64-virt
>>>>>>>>> - riscv64-virt
>>>>>>>>>
>>>>>>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
>>>>>>>>> we can find which target it implements from mc->targets.
>>>>>>>>> And then, we can automatically choose which cpus should be available
>>>>>>>>> based on that, thanks to cpu->targets.
>>>>>>>>>
>>>>>>>>> For existing binaries, nothing change.
>>>>>>>>
>>>>>>>> Good, I think we found a clean way now, is_available should be
>>>>>>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
>>>>>>>
>>>>>>> It goes into MachineClass only for now.
>>>>>>>
>>>>>>>> I think
>>>>>>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
>>>>>>>> the $arch specific virt. so that we only have a single "virt" registered.
>>>>>>>> And it's
>>>>>>>> targets is
>>>>>>>> QEMU_ARCH_I386 |
>>>>>>>> QEMU_ARCH_ARM |
>>>>>>>> QEMU_ARCH_RISCV |
>>>>>>>> QEMU_ARCH_LOONGARCH |
>>>>>>>> QEMU_ARCH_M68K |
>>>>>>>> QEMU_ARCH_OR1K |
>>>>>>>> QEMU_ARCH_XTENSA |
>>>>>>>> QEMU_ARCH_HEXAGON
>>>>>>>>
>>>>>>>> So that we won't have a list of conflict QOM names for "virt" machines.
>>>>>>>> As now we indeed have only a single "virt" machine that redirects to
>>>>>>>> different targets.
>>>>>>>>
>>>>>>>
>>>>>>> The idea looks appealing, but I don't think it solves the problem to
>>>>>>> have multiple virt variants available at the same time.
>>>>>>>
>>>>>>> The "alias" idea you introduced before is good, we just need to add a
>>>>>>> check if an alias is really unique, else return an error, as explained
>>>>>>> previously.
>>>>>>>
>>>>>>> If "-M aarch64-virt" works for both the new and existing binary, and -M
>>>>>>> virt only for existing binaries (and ambiguous for new one), I think
>>>>>>> that's a safe approach.
>>>>>>>
>>>>>>>>
>>>>>>>> For other types also conflict can be handled in the same way, such as
>>>>>>>> "-cpu host" "-cpu max"
>>>>>>>> maybe others, but I think they all have the same way to deal with.
>>>>>>>>
>>>>>>>>
>>>>>>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
>>>>>>>> Machine::targets
>>>>>>>>
>>>>>>>
>>>>>>> One step at a time.
>>>>>>> Let's keep focused on declaring targets for a single machine first.
>>>>>>> Then we can iterate to solve the "virt" problem.
>>>>>>> Then convert all the existing machines and add a check in machine-target.c
>>>>>>> Then, and only then, we can see what happens with cpus.
>>>>>>
>>>>>> I tried this idea, but I faced a fatal error, because the
>>>>>> target_info() is not available until
>>>>>> the machine selected(the target arch will be select just along with
>>>>>> the machine selected), so basically
>>>>>> all calls to target_info() would raise an error(null pointer), how to
>>>>>> deal with it?
>>>>>>
>>>>>
>>>>> I see. Indeed, since we can't set a target before registering all types,
>>>>> it implies that all the types class_init can't use target_* functions.
>>>>>
>>>>>
>>>>> - register_accel_target_type
>>>>> - cpu_max_v8_register_type
>>>>>
>>>>
>>>> Sorry, mail sent to early.
>>>>
>>>> For the is_available callback usage, it should be easy to do the switch,
>>>> since it's basically the same information that what we are trying to do
>>>> - we can leave them for now.
>>>>
>>>> Some types (like accel and max mentioned above), explicitly change their
>>>> definition depending on the target. It's a behavior we can't rely on
>>>> anymore, and it means we need proper distinct types instead of a single
>>>> one with dynamic definition driven by target-info.
>>>>
>>>> I think that's the preliminary work needed, before being able to go
>>>> further: convert all existing usage in class_init with distinct types +
>>>> is_available, and then we can do the switch from is_available to the new
>>>> .targets approach.
>>>
>>> Hi Pierrick,
>>> I have already tried that introducing new QOM names just to make class_init
>>>    target-independent is too broad(means all usage of it should be handled)
>>> and could complicate compatibility(changed too much code).
>>> Can we avoid new names by some new means(ideas welcome)?
>>>
>>
>> As a first step, I don't think we need new names, is_available can be
>> used to selectively register one definition or another and avoid any
>> clash. What is missing at the moment though, is that some types (like
>> cpu max above) change their definition based on target definition.
> 
> 
>>
>> So for cpu max, we would have two distinct types, both named max, but
>> one with is_available(target_arm), and other one with
>> is_available(target_aarch64), so they are never registered at the same time.
> 
>>
>> Same for virt machines. It's already what we have, duplication is
>> handled at the moment with distinct is_available callbacks.
>>
>> Then, see below.
>>
>>>
>>>>
>>>> It's probably worth having the conversion in its own series (only
>>>> cleanup usage of target_* in class_init), before trying to get rid of
>>>> is_available.
>>>
>>>>
>>>> For the implementation, you can use the multi-targets.c binary test to
>>>> drive the change. Remove the module init for target info (leaving no
>>>> target set), and add a hacky patch to skip call to is_available (and
>>>> return true instead) and allow double definition (which will rely on
>>>> is_available). Then, fix all the segfault. Once it compiles and runs,
>>>> only double definition will be left, which can be handled by inserting
>>>> the right is_available callbacks. Then in a subsequent series, the
>>>> switch to .targets can be made.
>>>
>>>
>>> Still have no clean clue about how to remove is_available , as we have many
>>> "virt" machines. Do you means all "virt" machines with "virt-machine" QOM names
>>> are inserted to the table? How to get it working because the "key" is string.
>>>
>>
>> Once we have type definition which only depends on is_available, we can
>> convert this to .targets, which would contain the same information.
>> For the rest, I have some ideas, but I would like first we do the first
>> part (convert to is_available), which is already a huge work in itself,
>> and a series of its own.
> 
> Indeed I am confused .targets only exists on Machine, how is it
> related to -cpu host -cpu max?
>

We can introduce cpu.targets after machine.targets.
First step is just to get something that works with is_available and 
does not require any target info to be set.

> 
> I already have a working copy that does not depend on target_info()
> and selects target_info() when the machine
> is selected, no QOM name introduced. only for machines, we will have
> $target_name-$machine_name as a name for selecting
> the exact machine.
>
> The cpu max cpu host is dealt by moving the choose code out of
> class_init, into object_init. I really did not get your idea by use
> is_avaiable. because when I try to get all QOMs to be registered. then
> I won't call is_available at all.

As a first step, we rely on is_available, to work on distinguishing 
proper types per target and break the dependency of multiple class_init 
to target_info. Then, we can replace is_available with .targets.

> because "is_available" depends on target_info(),(we won't have
> target_info() till the machine is selected).
>

We can imagine registering types in different buckets per target, which 
would allow for duplication.

Regards,
Pierrick


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-12 21:27             ` Yonggang Luo
@ 2026-10-13  3:57               ` Pierrick Bouvier
  2026-10-13  8:58                 ` Yonggang Luo
  0 siblings, 1 reply; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-13  3:57 UTC (permalink / raw)
  To: luoyonggang
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/12/26 2:27 PM, Yonggang Luo wrote:
> On Thu, Oct 8, 2026 at 7:28 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/7/2026 4:02 PM, Yonggang Luo wrote:
>>> On Thu, Oct 8, 2026 at 6:31 AM Pierrick Bouvier
>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>
>>>> On 10/7/2026 1:50 PM, Yonggang Luo wrote:
>>>>> On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>>
>>>>>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
>>>>>>> Register target definitions through constructors instead of
>>>>>>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
>>>>>>> available on entry to main(), without explicit initialization or a
>>>>>>> call to module_call_init(MODULE_INIT_QOM).
>>>>>>>
>>>>>>> Keep the target list sorted by target_arch and default to its first
>>>>>>> entry. Provide an unknown TargetInfo fallback for target-independent
>>>>>>> tools such as qemu-img and unit tests that link no target-info-def.c
>>>>>>> objects.
>>>>>>>
>>>>>>> Remove the obsolete QOM target-info registration infrastructure and
>>>>>>> update the multi-target test to inspect target information before
>>>>>>> initializing QOM.
>>>>>>>
>>>>>>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
>>>>>>> ---
>>>>>>>   include/qemu/module.h           |  1 -
>>>>>>>   include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
>>>>>>>   include/qemu/target-info-init.h | 53 ----------------------------
>>>>>>>   include/qemu/target-info-qom.h  | 31 -----------------
>>>>>>>   include/qemu/target-info.h      |  9 +++++
>>>>>>>   meson.build                     |  6 ++--
>>>>>>>   system/vl.c                     |  4 ---
>>>>>>>   target-info-def.c               |  1 -
>>>>>>>   target-info-qom.c               | 60 --------------------------------
>>>>>>>   target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
>>>>>>>   tests/qtest/fuzz/fuzz.c         |  3 --
>>>>>>>   tests/unit/test-multi-target.c  | 12 +++----
>>>>>>>   12 files changed, 129 insertions(+), 168 deletions(-)
>>>>>>>   delete mode 100644 include/qemu/target-info-init.h
>>>>>>>   delete mode 100644 include/qemu/target-info-qom.h
>>>>>>>   delete mode 100644 target-info-qom.c
>>>>>>>
>>>>>>
>>>>>> This approach (custom list based) was considered before implementing
>>>>>> things with QOM Types. The rationale I followed was that if everything
>>>>>> is in QOM, we might better follow that for consistency sake.
>>>>>> Yes, the compromise if that we need an extra init step, but it was not a
>>>>>> problem to add it.
>>>>> I have issue to add the init step for unit-tests, and hard to write the -target
>>>>> parse procedure and get it right. Not means this won't work. but for
>>>>> me, too much
>>>>> coupled.
>>>>>
>>>>
>>>> We already have such a test upstream:
>>>> https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35
>>>>
>>>> The init sequence is quite straightforward:
>>>>
>>>> ```
>>>> /* initialize target types, and only them */
>>>> module_call_init(MODULE_INIT_TARGET_INFO);
>>>>
>>>> /* we can get the list if we want, for -target or any other purpose */
>>>> g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
>>>>
>>>> /* set the global target info from any element in this list */
>>>> TargetInfo* ti = ...;
>>>> target_info_qom_set_target_info(ti);
>>>>
>>>> /* register rest of QOM types */
>>>> module_call_init(MODULE_INIT_QOM);
>>>> ```
>>>>
>>>> It works fine to implement -target (if we would like to do it), since I
>>>> implemented it myself. That was also my initial motivation by the way.
>>>>
>>>> Also, I appreciate that target-info is NULL by default, it crashes
>>>> loudly when it has not been set, and make it easy to find who depends on it.
>>>>
>>>>> If we treat target_info as a QOM, but QOM needs target_info to set
>>>>> up(is_avaible). That makes
>>>>> the init sequence too much of a burden.
>>>>>
>>>>
>>>> See sequence above, the solution is to initialize TARGET_INFO first,
>>>> before the rest of QOM. You end up with the same result than with a
>>>> statically initialized list.
>>>>
>>>>>
>>>>> is_available is depends on target_arch
>>>>> And before this patch, target_arch depends on QOM, pulls user/softmmu because
>>>>> target_info_init. By moving target-info to be a custom list based, we
>>>>> can decouple
>>>>> target-info from qom/softmmu/user. and target-info will always
>>>>> available once "main(argv, argc)" is entered. We also have the
>>>>> advantage of doing all sorts
>>>>> of tests against it.
>>>>>
>>>>
>>>> Which kind of tests are you trying to add?
>>>>
>>>> For now, the exact list of places where we need to do this initialize
>>>> target dance are:
>>>> - system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
>>>> - tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
>>>> - tests/unit/test-multi-target.c:
>>>
>>> # Multi targets test
>>> if multi_target_objects != []
>>>    test('test-multi-target',
>>>         executable('test-multi-target',
>>>                    sources: [multi_target_crates, files('test-multi-target.c')],
>>>                    dependencies: multi_target_deps,
>>>                    objects: multi_target_objects,
>>>                    link_depends: [block_syms, qemu_syms],
>>>                    link_args: multi_target_link_args),
>>>         suite: ['unit'])
>>> endif
>>>
>>> I see this test, I am trying to add tests that do not pull so many
>>> multi_target_objects, as it would be huge.
>>
>> Agree, we should not add more binary.
>> If you need truly multi targets test, this existing binary is a good
>> place to start: just add a second test in it.
>>
>>> Just pull qom only.  And I am trying to call target_info() in
>>> object.c, as inspect machines with
>>> qemu-system is rejected, so maybe that's not an issue anymore
>>>
>>
>> Seems like a good candidate for the multi-target.c test.
>>
>>>
>>> I means Subject: [PATCH v3 00/10] machine: uniquify virt QOM names
>>> https://lore.kernel.org/qemu-devel/20260926081551.29-1-luoyonggang@gmail.com/#r
>>>
>>> So the current design always rejects types that do not belong to the
>>> current target. Listing them
>>> all is not an option at all. With this restriction, then these are
>>> indeed not needed.
>>> So I'll wait for your work first, otherwise it's always conflicting.
>>>
>>>
>>>> module_call_init(MODULE_INIT_TARGET_INFO);
>>>>
>>>> If we want more tests, I'm totally ok to move this init code to
>>>> target-info.c, and replace call sites if needed.
>>>>
>>>>>
>>>>> Tools such as qemu-img and unit tests may link target-info.c without any
>>>>> target-info-def.c objects. Their target list remains empty, so use this
>>>>> fallback.
>>>>>
>>>>
>>>> Why should this tool get access to target list? qemu-img deals with disk
>>>> images, and is unrelated to targets.
>>>>
>>>>>
>>>>> static TypeImpl *type_register_internal(const TypeInfo *info)
>>>>> {
>>>>>      TypeImpl *ti;
>>>>>
>>>>>      if (!type_name_is_valid(info->name)) {
>>>>>          fprintf(stderr, "Registering '%s' with illegal type name\n",
>>>>> info->name);
>>>>>          abort();
>>>>>      }
>>>>>
>>>>>      if (info->is_available && !info->is_available()) {
>>>>>          return NULL;
>>>>>      }
>>>>>
>>>>>      ti = type_new(info);
>>>>>
>>>>>      type_table_add(ti);
>>>>>      return ti;
>>>>> }
>>>>>
>>>>>>
>>>>>> Is there another good value this list approach brings compared to what
>>>>>> exists?
>>>>>>
>>>>>> Regards,
>>>>>> Pierrick
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>
> 
> 
> Hi, the cycle dependencies issue happened again, deal with it's a bit
> nasty, there is workaround, but I think
> the constructor list is the best, here is the rationale:
> 
> 
> # Target discovery during QOM registration
> 
> ## Problem
> 
> Machine registration needs the list of targets compiled into the binary.
> Currently, it obtains that list through:
> 
> ```c
> object_class_get_list(TYPE_TARGET_INFO, false);
> ```
> 
> Despite the filter, QOM initializes every registered type before checking
> whether it implements the requested type.
> 
> During `MODULE_INIT_QOM`, registration is only partially complete. A device
> may already be registered while its parent's registration callback has not
> run, causing failures such as:
> 
> ```text
> Type 'sys-bus-device' is missing its parent 'device'
> ```
> 
> The parent is linked into the binary. The problem is premature
> initialization, not a missing library.
> 
> ## Option 1: cache target-info QOM classes
> 
> Enumerate target-info classes once, before device registration starts.
> Machine registration then reads the cache instead of enumerating QOM.
> 
> ### Demo
> 
> Declare shared helpers:
> 
> ```c
> void target_info_qom_init(void);
> const GSList *target_info_qom_get_targets(void);
> ```
> 
> Implement the cache:
> 
> ```c
> static GSList *target_info_classes;
> static bool target_info_initialized;
> 
> void target_info_qom_init(void)
> {
>      if (target_info_initialized) {
>          return;
>      }
> 
>      module_call_init(MODULE_INIT_TARGET_INFO);
>      target_info_classes = object_class_get_list(TYPE_TARGET_INFO, false);
>      target_info_initialized = true;
> }
> 
> const GSList *target_info_qom_get_targets(void)
> {
>      assert(target_info_initialized);
>      return target_info_classes;
> }
> ```
> 
> Initialize it before other QOM registration:
> 
> ```c
> target_info_qom_init();
> module_call_init(MODULE_INIT_QOM);
> ```
> 
> Machine registration uses the borrowed cache:
> 
> ```c
> for (const GSList *l = target_info_qom_get_targets(); l; l = l->next) {
>      const TargetInfo *ti = TARGET_INFO_CLASS(l->data)->target_info;
> 
>      machine_register_virt_type_for_target(info, name_suffix, arch_mask,
>                                           latest, ti);
> }
> ```
> 
> `target_info_qom_set_target()` should also use the cached list instead of
> enumerating QOM again.
> 
> ### Advantages
> 
> - Preserves the existing QOM-based representation.
> - Avoids enumeration during incomplete device registration.
> - Requires relatively small changes.
> 
> ### Disadvantages
> 
> - Every relevant executable and test must initialize the cache before
>    starting QOM registration.
> - `object_class_get_list()` allocates list nodes.
> - Callers borrow the list, so it cannot be freed while they are using it.
> - Cleanup is possible after all consumers finish, but requires an explicit
>    lifecycle policy. Keeping the cache until process exit is a lifetime
>    allocation, not inherently an unreachable memory leak.
> - Target-info types registered after cache creation are not included.
> - Target discovery remains coupled to QOM class initialization.
> 
> ## Option 2: constructor-populated TargetInfo registry
> 
> Each target registers its immutable `TargetInfo` pointer directly.
> Machine registration later iterates the registry without querying QOM.
> 
> Use a statically allocated node per target so registration requires no
> heap allocation.
> 
> ### Demo
> 
> Define a registration node and accessors:
> 
> ```c
> typedef struct TargetInfoRegistration {
>      const TargetInfo *info;
>      struct TargetInfoRegistration *next;
> } TargetInfoRegistration;
> 
> void target_info_register(TargetInfoRegistration *entry);
> const TargetInfoRegistration *target_info_get_targets(void);
> ```
> 
> Implement the registry in shared code:
> 
> ```c
> static TargetInfoRegistration *target_info_targets;
> 
> void target_info_register(TargetInfoRegistration *entry)
> {
>      entry->next = target_info_targets;
>      target_info_targets = entry;
> }
> 
> const TargetInfoRegistration *target_info_get_targets(void)
> {
>      return target_info_targets;
> }
> ```
> 
> Each target's translation unit provides its own static node and
> constructor. For example:
> 
> ```c
> static TargetInfoRegistration target_info_registration = {
>      .info = &target_info_stub,
> };
> 
> static void __attribute__((constructor)) register_target_info(void)
> {
>      target_info_register(&target_info_registration);
> }
> ```
> 
> The constructor must run exactly once per node. The existing target-info
> initialization macro can generate this registration code alongside the
> QOM registration code; user-mode target-info behavior should remain
> unchanged.
> 
> Machine registration consumes the completed registry:
> 
> ```c
> for (const TargetInfoRegistration *entry = target_info_get_targets();
>       entry;
>       entry = entry->next) {
>      machine_register_virt_type_for_target(info, name_suffix, arch_mask,
>                                           latest, entry->info);
> }
> ```
> 
> The sequence is:
> 
> ```text
> Target constructors register static metadata pointers
>      ↓
> Startup constructors finish
>      ↓
> Machine registration iterates the completed registry
> ```
> 
> QOM target-info classes can remain available for introspection.
> 
> ### Advantages
> 
> - Makes target discovery independent of QOM initialization.
> - Removes the explicit cache-initialization step from executables and tests.
> - Avoids premature initialization of unrelated device types.
> - Uses static storage: no allocated list nodes and no registry cleanup.
> - Does not require ordering between target constructors.
> 
> ### Constraints
> 
> - Constructors must only register metadata, not enumerate or initialize
>    QOM classes.
> - Consumers must run after startup constructors have completed.
> - Each registration node must be inserted exactly once.
> - Registry order must not be treated as a meaningful target ordering.
> - This simple design assumes compiled-in targets; runtime loading or
>    unloading would require additional lifecycle handling.
> 
> ## Comparison
> 
> | Aspect | QOM class cache | Static constructor registry |
> |---|---|---|
> | Discovery mechanism | QOM enumeration | Direct metadata registration |
> | Explicit startup initialization | Required | Not required |
> | Heap allocation for list nodes | Yes | No |
> | Cleanup policy | Required if releasing the cache | No registry cleanup |
> | Dependency on QOM initialization | Yes | No |
> | Registration-order sensitivity | Avoided through explicit sequencing
> | Avoided by consuming after constructors |
> | Late target registration | Cache needs updating | Requires a defined
> runtime registration policy |
> 
> ## Recommendation
> 
> Prefer the constructor-populated registry with statically allocated nodes.
> 
> `TargetInfo` describes the binary's compiled-in capabilities. Accessing
> that metadata should not require initializing the device model or
> maintaining an allocated cache of QOM classes.
> 
> The QOM cache fixes the immediate failure, but introduces an additional
> startup contract and ownership policy. A static constructor registry
> removes the underlying dependency and avoids heap allocation for the
> registry itself.
>

I will politely say one last time (and ignore this in the future): 
please do not copy paste AI summary to motivate any kind of design.
Also, please do not post inline patches. In case you would like to 
develop an idea, send a minimal series (with one or two patches) 
presenting the concept and implementation, it's more efficient for 
collaboration.

Regards,
Pierrick


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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-13  3:53                         ` Pierrick Bouvier
@ 2026-10-13  4:03                           ` Yonggang Luo
  2026-10-13 15:56                             ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Yonggang Luo @ 2026-10-13  4:03 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Tue, Oct 13, 2026 at 11:53 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/12/26 7:43 PM, Yonggang Luo wrote:
> > On Tue, Oct 13, 2026 at 9:26 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/11/26 9:26 PM, Yonggang Luo wrote:
> >>> On Mon, Oct 12, 2026 at 10:25 AM Pierrick Bouvier
> >>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>
> >>>> On 10/11/26 7:13 PM, Pierrick Bouvier wrote:
> >>>>> On 10/11/26 1:22 PM, Yonggang Luo wrote:
> >>>>>> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
> >>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>>>>
> >>>>>>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
> >>>>>>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
> >>>>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>>>>>>
> >>>>>>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
> >>>>>>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>>>>>>>>>>
> >>>>>>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
> >>>>>>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
> >>>>>>>>>>>>> This allows a combined binary to register machine types from all its targets.
> >>>>>>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
> >>>>>>>>>>>>> target, even when `none` is selected. For example, a client can query the
> >>>>>>>>>>>>> combined machine list with:
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> ```json
> >>>>>>>>>>>>> { "execute": "query-machines" }
> >>>>>>>>>>>>> ```
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> The returned list includes the registered machine classes from all linked
> >>>>>>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
> >>>>>>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
> >>>>>>>>>>>>> arbitrarily:
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> ```text
> >>>>>>>>>>>>> qemu-system -target none -M virt
> >>>>>>>>>>>>> unsupported machine type: "virt" for target "none"
> >>>>>>>>>>>>> Available for targets:
> >>>>>>>>>>>>>       aarch64
> >>>>>>>>>>>>>       arm
> >>>>>>>>>>>>> ```
> >>>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>>     From the long conversation on a previous thread, I thought we reached
> >>>>>>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
> >>>>>>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
> >>>>>>>>>>>>
> >>>>>>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
> >>>>>>>>>>>>
> >>>>>>>>>>>> I'm not sure which semantic we want to have with -target none. If there
> >>>>>>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
> >>>>>>>>>>>> win-win IMHO.
> >>>>>>>>>>>
> >>>>>>>>>>> Yes, if we expose unique names for every machine, then -target is then
> >>>>>>>>>>> redundant.
> >>>>>>>>>>
> >>>>>>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
> >>>>>>>>>> needs two name?
> >>>>>>>>>> "virt" needs register twice for it? or register only a single time,
> >>>>>>>>>> but we prefix the target_name()
> >>>>>>>>>> automatically? for example machine::name === "virt", but we can use
> >>>>>>>>>> "riscv32-virt" "risv64-virt" to reach it?
> >>>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
> >>>>>>>>> Same goes for cpu max types.
> >>>>>>>>>
> >>>>>>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
> >>>>>>>>> the "alias" name, which is virt, in case multiple matches are found,
> >>>>>>>>> command line can return an error with list of unambiguous names to call it.
> >>>>>>>>>
> >>>>>>>>> $ qemu-system -M virt
> >>>>>>>>> Multiple virt machines are available. Please choose one of them:
> >>>>>>>>> - aarch64-virt
> >>>>>>>>> - riscv64-virt
> >>>>>>>>>
> >>>>>>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
> >>>>>>>>> we can find which target it implements from mc->targets.
> >>>>>>>>> And then, we can automatically choose which cpus should be available
> >>>>>>>>> based on that, thanks to cpu->targets.
> >>>>>>>>>
> >>>>>>>>> For existing binaries, nothing change.
> >>>>>>>>
> >>>>>>>> Good, I think we found a clean way now, is_available should be
> >>>>>>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
> >>>>>>>
> >>>>>>> It goes into MachineClass only for now.
> >>>>>>>
> >>>>>>>> I think
> >>>>>>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
> >>>>>>>> the $arch specific virt. so that we only have a single "virt" registered.
> >>>>>>>> And it's
> >>>>>>>> targets is
> >>>>>>>> QEMU_ARCH_I386 |
> >>>>>>>> QEMU_ARCH_ARM |
> >>>>>>>> QEMU_ARCH_RISCV |
> >>>>>>>> QEMU_ARCH_LOONGARCH |
> >>>>>>>> QEMU_ARCH_M68K |
> >>>>>>>> QEMU_ARCH_OR1K |
> >>>>>>>> QEMU_ARCH_XTENSA |
> >>>>>>>> QEMU_ARCH_HEXAGON
> >>>>>>>>
> >>>>>>>> So that we won't have a list of conflict QOM names for "virt" machines.
> >>>>>>>> As now we indeed have only a single "virt" machine that redirects to
> >>>>>>>> different targets.
> >>>>>>>>
> >>>>>>>
> >>>>>>> The idea looks appealing, but I don't think it solves the problem to
> >>>>>>> have multiple virt variants available at the same time.
> >>>>>>>
> >>>>>>> The "alias" idea you introduced before is good, we just need to add a
> >>>>>>> check if an alias is really unique, else return an error, as explained
> >>>>>>> previously.
> >>>>>>>
> >>>>>>> If "-M aarch64-virt" works for both the new and existing binary, and -M
> >>>>>>> virt only for existing binaries (and ambiguous for new one), I think
> >>>>>>> that's a safe approach.
> >>>>>>>
> >>>>>>>>
> >>>>>>>> For other types also conflict can be handled in the same way, such as
> >>>>>>>> "-cpu host" "-cpu max"
> >>>>>>>> maybe others, but I think they all have the same way to deal with.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
> >>>>>>>> Machine::targets
> >>>>>>>>
> >>>>>>>
> >>>>>>> One step at a time.
> >>>>>>> Let's keep focused on declaring targets for a single machine first.
> >>>>>>> Then we can iterate to solve the "virt" problem.
> >>>>>>> Then convert all the existing machines and add a check in machine-target.c
> >>>>>>> Then, and only then, we can see what happens with cpus.
> >>>>>>
> >>>>>> I tried this idea, but I faced a fatal error, because the
> >>>>>> target_info() is not available until
> >>>>>> the machine selected(the target arch will be select just along with
> >>>>>> the machine selected), so basically
> >>>>>> all calls to target_info() would raise an error(null pointer), how to
> >>>>>> deal with it?
> >>>>>>
> >>>>>
> >>>>> I see. Indeed, since we can't set a target before registering all types,
> >>>>> it implies that all the types class_init can't use target_* functions.
> >>>>>
> >>>>>
> >>>>> - register_accel_target_type
> >>>>> - cpu_max_v8_register_type
> >>>>>
> >>>>
> >>>> Sorry, mail sent to early.
> >>>>
> >>>> For the is_available callback usage, it should be easy to do the switch,
> >>>> since it's basically the same information that what we are trying to do
> >>>> - we can leave them for now.
> >>>>
> >>>> Some types (like accel and max mentioned above), explicitly change their
> >>>> definition depending on the target. It's a behavior we can't rely on
> >>>> anymore, and it means we need proper distinct types instead of a single
> >>>> one with dynamic definition driven by target-info.
> >>>>
> >>>> I think that's the preliminary work needed, before being able to go
> >>>> further: convert all existing usage in class_init with distinct types +
> >>>> is_available, and then we can do the switch from is_available to the new
> >>>> .targets approach.
> >>>
> >>> Hi Pierrick,
> >>> I have already tried that introducing new QOM names just to make class_init
> >>>    target-independent is too broad(means all usage of it should be handled)
> >>> and could complicate compatibility(changed too much code).
> >>> Can we avoid new names by some new means(ideas welcome)?
> >>>
> >>
> >> As a first step, I don't think we need new names, is_available can be
> >> used to selectively register one definition or another and avoid any
> >> clash. What is missing at the moment though, is that some types (like
> >> cpu max above) change their definition based on target definition.
> >
> >
> >>
> >> So for cpu max, we would have two distinct types, both named max, but
> >> one with is_available(target_arm), and other one with
> >> is_available(target_aarch64), so they are never registered at the same time.
> >
> >>
> >> Same for virt machines. It's already what we have, duplication is
> >> handled at the moment with distinct is_available callbacks.
> >>
> >> Then, see below.
> >>
> >>>
> >>>>
> >>>> It's probably worth having the conversion in its own series (only
> >>>> cleanup usage of target_* in class_init), before trying to get rid of
> >>>> is_available.
> >>>
> >>>>
> >>>> For the implementation, you can use the multi-targets.c binary test to
> >>>> drive the change. Remove the module init for target info (leaving no
> >>>> target set), and add a hacky patch to skip call to is_available (and
> >>>> return true instead) and allow double definition (which will rely on
> >>>> is_available). Then, fix all the segfault. Once it compiles and runs,
> >>>> only double definition will be left, which can be handled by inserting
> >>>> the right is_available callbacks. Then in a subsequent series, the
> >>>> switch to .targets can be made.
> >>>
> >>>
> >>> Still have no clean clue about how to remove is_available , as we have many
> >>> "virt" machines. Do you means all "virt" machines with "virt-machine" QOM names
> >>> are inserted to the table? How to get it working because the "key" is string.
> >>>
> >>
> >> Once we have type definition which only depends on is_available, we can
> >> convert this to .targets, which would contain the same information.
> >> For the rest, I have some ideas, but I would like first we do the first
> >> part (convert to is_available), which is already a huge work in itself,
> >> and a series of its own.
> >
> > Indeed I am confused .targets only exists on Machine, how is it
> > related to -cpu host -cpu max?
> >
>
> We can introduce cpu.targets after machine.targets.
> First step is just to get something that works with is_available and
> does not require any target info to be set.

Feels weird, what's wrong with this method:
 target/arm/tcg/cpu-max-v8.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/target/arm/tcg/cpu-max-v8.c b/target/arm/tcg/cpu-max-v8.c
index 65f851f2006..d7323ab431c 100644
--- a/target/arm/tcg/cpu-max-v8.c
+++ b/target/arm/tcg/cpu-max-v8.c
@@ -119,12 +119,21 @@ void aarch32_max_v8_tcg_initfn(Object *obj)
 #endif
 }

+static void max_v8_tcg_initfn(Object *obj)
+{
+    if (target_aarch64()) {
+        aarch64_max_v8_tcg_initfn(obj);
+    } else {
+        aarch32_max_v8_tcg_initfn(obj);
+    }
+}
+
 static void cpu_max_v8_register_type(void)
 {
-    static const ARMCPUInfo max_v8[2] = {
-        { .name = "max-v8", .initfn = aarch32_max_v8_tcg_initfn },
-        { .name = "max-v8", .initfn = aarch64_max_v8_tcg_initfn },
+    static const ARMCPUInfo max_v8 = {
+        .name = "max-v8",
+        .initfn = max_v8_tcg_initfn,
     };
-    arm_cpu_register(&max_v8[target_aarch64()]);
+    arm_cpu_register(&max_v8);
 }
 type_init(cpu_max_v8_register_type)


>
> >
> > I already have a working copy that does not depend on target_info()
> > and selects target_info() when the machine
> > is selected, no QOM name introduced. only for machines, we will have
> > $target_name-$machine_name as a name for selecting
> > the exact machine.
> >
> > The cpu max cpu host is dealt by moving the choose code out of
> > class_init, into object_init. I really did not get your idea by use
> > is_avaiable. because when I try to get all QOMs to be registered. then
> > I won't call is_available at all.
>
> As a first step, we rely on is_available, to work on distinguishing
> proper types per target and break the dependency of multiple class_init
> to target_info. Then, we can replace is_available with .targets.
>
> > because "is_available" depends on target_info(),(we won't have
> > target_info() till the machine is selected).
> >
>
> We can imagine registering types in different buckets per target, which
> would allow for duplication.


So your idea is multiple hash-tables for QOM types? key is the target_arch?

>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-13  3:57               ` Pierrick Bouvier
@ 2026-10-13  8:58                 ` Yonggang Luo
  0 siblings, 0 replies; 62+ messages in thread
From: Yonggang Luo @ 2026-10-13  8:58 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: qemu-devel, Daniel P. Berrangé, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Tue, Oct 13, 2026 at 11:57 AM Pierrick Bouvier
<pierrick.bouvier@oss.qualcomm.com> wrote:
>
> On 10/12/26 2:27 PM, Yonggang Luo wrote:
> > On Thu, Oct 8, 2026 at 7:28 AM Pierrick Bouvier
> > <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>
> >> On 10/7/2026 4:02 PM, Yonggang Luo wrote:
> >>> On Thu, Oct 8, 2026 at 6:31 AM Pierrick Bouvier
> >>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>
> >>>> On 10/7/2026 1:50 PM, Yonggang Luo wrote:
> >>>>> On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
> >>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
> >>>>>>
> >>>>>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> >>>>>>> Register target definitions through constructors instead of
> >>>>>>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
> >>>>>>> available on entry to main(), without explicit initialization or a
> >>>>>>> call to module_call_init(MODULE_INIT_QOM).
> >>>>>>>
> >>>>>>> Keep the target list sorted by target_arch and default to its first
> >>>>>>> entry. Provide an unknown TargetInfo fallback for target-independent
> >>>>>>> tools such as qemu-img and unit tests that link no target-info-def.c
> >>>>>>> objects.
> >>>>>>>
> >>>>>>> Remove the obsolete QOM target-info registration infrastructure and
> >>>>>>> update the multi-target test to inspect target information before
> >>>>>>> initializing QOM.
> >>>>>>>
> >>>>>>> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> >>>>>>> ---
> >>>>>>>   include/qemu/module.h           |  1 -
> >>>>>>>   include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
> >>>>>>>   include/qemu/target-info-init.h | 53 ----------------------------
> >>>>>>>   include/qemu/target-info-qom.h  | 31 -----------------
> >>>>>>>   include/qemu/target-info.h      |  9 +++++
> >>>>>>>   meson.build                     |  6 ++--
> >>>>>>>   system/vl.c                     |  4 ---
> >>>>>>>   target-info-def.c               |  1 -
> >>>>>>>   target-info-qom.c               | 60 --------------------------------
> >>>>>>>   target-info.c                   | 61 ++++++++++++++++++++++++++++++++-
> >>>>>>>   tests/qtest/fuzz/fuzz.c         |  3 --
> >>>>>>>   tests/unit/test-multi-target.c  | 12 +++----
> >>>>>>>   12 files changed, 129 insertions(+), 168 deletions(-)
> >>>>>>>   delete mode 100644 include/qemu/target-info-init.h
> >>>>>>>   delete mode 100644 include/qemu/target-info-qom.h
> >>>>>>>   delete mode 100644 target-info-qom.c
> >>>>>>>
> >>>>>>
> >>>>>> This approach (custom list based) was considered before implementing
> >>>>>> things with QOM Types. The rationale I followed was that if everything
> >>>>>> is in QOM, we might better follow that for consistency sake.
> >>>>>> Yes, the compromise if that we need an extra init step, but it was not a
> >>>>>> problem to add it.
> >>>>> I have issue to add the init step for unit-tests, and hard to write the -target
> >>>>> parse procedure and get it right. Not means this won't work. but for
> >>>>> me, too much
> >>>>> coupled.
> >>>>>
> >>>>
> >>>> We already have such a test upstream:
> >>>> https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35
> >>>>
> >>>> The init sequence is quite straightforward:
> >>>>
> >>>> ```
> >>>> /* initialize target types, and only them */
> >>>> module_call_init(MODULE_INIT_TARGET_INFO);
> >>>>
> >>>> /* we can get the list if we want, for -target or any other purpose */
> >>>> g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, false);
> >>>>
> >>>> /* set the global target info from any element in this list */
> >>>> TargetInfo* ti = ...;
> >>>> target_info_qom_set_target_info(ti);
> >>>>
> >>>> /* register rest of QOM types */
> >>>> module_call_init(MODULE_INIT_QOM);
> >>>> ```
> >>>>
> >>>> It works fine to implement -target (if we would like to do it), since I
> >>>> implemented it myself. That was also my initial motivation by the way.
> >>>>
> >>>> Also, I appreciate that target-info is NULL by default, it crashes
> >>>> loudly when it has not been set, and make it easy to find who depends on it.
> >>>>
> >>>>> If we treat target_info as a QOM, but QOM needs target_info to set
> >>>>> up(is_avaible). That makes
> >>>>> the init sequence too much of a burden.
> >>>>>
> >>>>
> >>>> See sequence above, the solution is to initialize TARGET_INFO first,
> >>>> before the rest of QOM. You end up with the same result than with a
> >>>> statically initialized list.
> >>>>
> >>>>>
> >>>>> is_available is depends on target_arch
> >>>>> And before this patch, target_arch depends on QOM, pulls user/softmmu because
> >>>>> target_info_init. By moving target-info to be a custom list based, we
> >>>>> can decouple
> >>>>> target-info from qom/softmmu/user. and target-info will always
> >>>>> available once "main(argv, argc)" is entered. We also have the
> >>>>> advantage of doing all sorts
> >>>>> of tests against it.
> >>>>>
> >>>>
> >>>> Which kind of tests are you trying to add?
> >>>>
> >>>> For now, the exact list of places where we need to do this initialize
> >>>> target dance are:
> >>>> - system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> >>>> - tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> >>>> - tests/unit/test-multi-target.c:
> >>>
> >>> # Multi targets test
> >>> if multi_target_objects != []
> >>>    test('test-multi-target',
> >>>         executable('test-multi-target',
> >>>                    sources: [multi_target_crates, files('test-multi-target.c')],
> >>>                    dependencies: multi_target_deps,
> >>>                    objects: multi_target_objects,
> >>>                    link_depends: [block_syms, qemu_syms],
> >>>                    link_args: multi_target_link_args),
> >>>         suite: ['unit'])
> >>> endif
> >>>
> >>> I see this test, I am trying to add tests that do not pull so many
> >>> multi_target_objects, as it would be huge.
> >>
> >> Agree, we should not add more binary.
> >> If you need truly multi targets test, this existing binary is a good
> >> place to start: just add a second test in it.
> >>
> >>> Just pull qom only.  And I am trying to call target_info() in
> >>> object.c, as inspect machines with
> >>> qemu-system is rejected, so maybe that's not an issue anymore
> >>>
> >>
> >> Seems like a good candidate for the multi-target.c test.
> >>
> >>>
> >>> I means Subject: [PATCH v3 00/10] machine: uniquify virt QOM names
> >>> https://lore.kernel.org/qemu-devel/20260926081551.29-1-luoyonggang@gmail.com/#r
> >>>
> >>> So the current design always rejects types that do not belong to the
> >>> current target. Listing them
> >>> all is not an option at all. With this restriction, then these are
> >>> indeed not needed.
> >>> So I'll wait for your work first, otherwise it's always conflicting.
> >>>
> >>>
> >>>> module_call_init(MODULE_INIT_TARGET_INFO);
> >>>>
> >>>> If we want more tests, I'm totally ok to move this init code to
> >>>> target-info.c, and replace call sites if needed.
> >>>>
> >>>>>
> >>>>> Tools such as qemu-img and unit tests may link target-info.c without any
> >>>>> target-info-def.c objects. Their target list remains empty, so use this
> >>>>> fallback.
> >>>>>
> >>>>
> >>>> Why should this tool get access to target list? qemu-img deals with disk
> >>>> images, and is unrelated to targets.
> >>>>
> >>>>>
> >>>>> static TypeImpl *type_register_internal(const TypeInfo *info)
> >>>>> {
> >>>>>      TypeImpl *ti;
> >>>>>
> >>>>>      if (!type_name_is_valid(info->name)) {
> >>>>>          fprintf(stderr, "Registering '%s' with illegal type name\n",
> >>>>> info->name);
> >>>>>          abort();
> >>>>>      }
> >>>>>
> >>>>>      if (info->is_available && !info->is_available()) {
> >>>>>          return NULL;
> >>>>>      }
> >>>>>
> >>>>>      ti = type_new(info);
> >>>>>
> >>>>>      type_table_add(ti);
> >>>>>      return ti;
> >>>>> }
> >>>>>
> >>>>>>
> >>>>>> Is there another good value this list approach brings compared to what
> >>>>>> exists?
> >>>>>>
> >>>>>> Regards,
> >>>>>> Pierrick
> >>>>>
> >>>>>
> >>>>>
> >>>>
> >>>
> >>>
> >>
> >
> >
> > Hi, the cycle dependencies issue happened again, deal with it's a bit
> > nasty, there is workaround, but I think
> > the constructor list is the best, here is the rationale:
> >
> >
> > # Target discovery during QOM registration
> >
> > ## Problem
> >
> > Machine registration needs the list of targets compiled into the binary.
> > Currently, it obtains that list through:
> >
> > ```c
> > object_class_get_list(TYPE_TARGET_INFO, false);
> > ```
> >
> > Despite the filter, QOM initializes every registered type before checking
> > whether it implements the requested type.
> >
> > During `MODULE_INIT_QOM`, registration is only partially complete. A device
> > may already be registered while its parent's registration callback has not
> > run, causing failures such as:
> >
> > ```text
> > Type 'sys-bus-device' is missing its parent 'device'
> > ```
> >
> > The parent is linked into the binary. The problem is premature
> > initialization, not a missing library.
> >
> > ## Option 1: cache target-info QOM classes
> >
> > Enumerate target-info classes once, before device registration starts.
> > Machine registration then reads the cache instead of enumerating QOM.
> >
> > ### Demo
> >
> > Declare shared helpers:
> >
> > ```c
> > void target_info_qom_init(void);
> > const GSList *target_info_qom_get_targets(void);
> > ```
> >
> > Implement the cache:
> >
> > ```c
> > static GSList *target_info_classes;
> > static bool target_info_initialized;
> >
> > void target_info_qom_init(void)
> > {
> >      if (target_info_initialized) {
> >          return;
> >      }
> >
> >      module_call_init(MODULE_INIT_TARGET_INFO);
> >      target_info_classes = object_class_get_list(TYPE_TARGET_INFO, false);
> >      target_info_initialized = true;
> > }
> >
> > const GSList *target_info_qom_get_targets(void)
> > {
> >      assert(target_info_initialized);
> >      return target_info_classes;
> > }
> > ```
> >
> > Initialize it before other QOM registration:
> >
> > ```c
> > target_info_qom_init();
> > module_call_init(MODULE_INIT_QOM);
> > ```
> >
> > Machine registration uses the borrowed cache:
> >
> > ```c
> > for (const GSList *l = target_info_qom_get_targets(); l; l = l->next) {
> >      const TargetInfo *ti = TARGET_INFO_CLASS(l->data)->target_info;
> >
> >      machine_register_virt_type_for_target(info, name_suffix, arch_mask,
> >                                           latest, ti);
> > }
> > ```
> >
> > `target_info_qom_set_target()` should also use the cached list instead of
> > enumerating QOM again.
> >
> > ### Advantages
> >
> > - Preserves the existing QOM-based representation.
> > - Avoids enumeration during incomplete device registration.
> > - Requires relatively small changes.
> >
> > ### Disadvantages
> >
> > - Every relevant executable and test must initialize the cache before
> >    starting QOM registration.
> > - `object_class_get_list()` allocates list nodes.
> > - Callers borrow the list, so it cannot be freed while they are using it.
> > - Cleanup is possible after all consumers finish, but requires an explicit
> >    lifecycle policy. Keeping the cache until process exit is a lifetime
> >    allocation, not inherently an unreachable memory leak.
> > - Target-info types registered after cache creation are not included.
> > - Target discovery remains coupled to QOM class initialization.
> >
> > ## Option 2: constructor-populated TargetInfo registry
> >
> > Each target registers its immutable `TargetInfo` pointer directly.
> > Machine registration later iterates the registry without querying QOM.
> >
> > Use a statically allocated node per target so registration requires no
> > heap allocation.
> >
> > ### Demo
> >
> > Define a registration node and accessors:
> >
> > ```c
> > typedef struct TargetInfoRegistration {
> >      const TargetInfo *info;
> >      struct TargetInfoRegistration *next;
> > } TargetInfoRegistration;
> >
> > void target_info_register(TargetInfoRegistration *entry);
> > const TargetInfoRegistration *target_info_get_targets(void);
> > ```
> >
> > Implement the registry in shared code:
> >
> > ```c
> > static TargetInfoRegistration *target_info_targets;
> >
> > void target_info_register(TargetInfoRegistration *entry)
> > {
> >      entry->next = target_info_targets;
> >      target_info_targets = entry;
> > }
> >
> > const TargetInfoRegistration *target_info_get_targets(void)
> > {
> >      return target_info_targets;
> > }
> > ```
> >
> > Each target's translation unit provides its own static node and
> > constructor. For example:
> >
> > ```c
> > static TargetInfoRegistration target_info_registration = {
> >      .info = &target_info_stub,
> > };
> >
> > static void __attribute__((constructor)) register_target_info(void)
> > {
> >      target_info_register(&target_info_registration);
> > }
> > ```
> >
> > The constructor must run exactly once per node. The existing target-info
> > initialization macro can generate this registration code alongside the
> > QOM registration code; user-mode target-info behavior should remain
> > unchanged.
> >
> > Machine registration consumes the completed registry:
> >
> > ```c
> > for (const TargetInfoRegistration *entry = target_info_get_targets();
> >       entry;
> >       entry = entry->next) {
> >      machine_register_virt_type_for_target(info, name_suffix, arch_mask,
> >                                           latest, entry->info);
> > }
> > ```
> >
> > The sequence is:
> >
> > ```text
> > Target constructors register static metadata pointers
> >      ↓
> > Startup constructors finish
> >      ↓
> > Machine registration iterates the completed registry
> > ```
> >
> > QOM target-info classes can remain available for introspection.
> >
> > ### Advantages
> >
> > - Makes target discovery independent of QOM initialization.
> > - Removes the explicit cache-initialization step from executables and tests.
> > - Avoids premature initialization of unrelated device types.
> > - Uses static storage: no allocated list nodes and no registry cleanup.
> > - Does not require ordering between target constructors.
> >
> > ### Constraints
> >
> > - Constructors must only register metadata, not enumerate or initialize
> >    QOM classes.
> > - Consumers must run after startup constructors have completed.
> > - Each registration node must be inserted exactly once.
> > - Registry order must not be treated as a meaningful target ordering.
> > - This simple design assumes compiled-in targets; runtime loading or
> >    unloading would require additional lifecycle handling.
> >
> > ## Comparison
> >
> > | Aspect | QOM class cache | Static constructor registry |
> > |---|---|---|
> > | Discovery mechanism | QOM enumeration | Direct metadata registration |
> > | Explicit startup initialization | Required | Not required |
> > | Heap allocation for list nodes | Yes | No |
> > | Cleanup policy | Required if releasing the cache | No registry cleanup |
> > | Dependency on QOM initialization | Yes | No |
> > | Registration-order sensitivity | Avoided through explicit sequencing
> > | Avoided by consuming after constructors |
> > | Late target registration | Cache needs updating | Requires a defined
> > runtime registration policy |
> >
> > ## Recommendation
> >
> > Prefer the constructor-populated registry with statically allocated nodes.
> >
> > `TargetInfo` describes the binary's compiled-in capabilities. Accessing
> > that metadata should not require initializing the device model or
> > maintaining an allocated cache of QOM classes.
> >
> > The QOM cache fixes the immediate failure, but introduces an additional
> > startup contract and ownership policy. A static constructor registry
> > removes the underlying dependency and avoids heap allocation for the
> > registry itself.
> >
>
> I will politely say one last time (and ignore this in the future):

apologize, I am doing this mainly because my poor English, I am post a
small patches instead.


> please do not copy paste AI summary to motivate any kind of design.
> Also, please do not post inline patches. In case you would like to
> develop an idea, send a minimal series (with one or two patches)
> presenting the concept and implementation, it's more efficient for
> collaboration.
>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-07 23:24           ` Pierrick Bouvier
@ 2026-10-13  9:26             ` Daniel P. Berrangé
  2026-10-13 15:53               ` Pierrick Bouvier
  0 siblings, 1 reply; 62+ messages in thread
From: Daniel P. Berrangé @ 2026-10-13  9:26 UTC (permalink / raw)
  To: Pierrick Bouvier
  Cc: luoyonggang, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On Wed, Oct 07, 2026 at 04:24:07PM -0700, Pierrick Bouvier wrote:
> On 10/7/2026 3:54 PM, Yonggang Luo wrote:
> > My work is here.
> > https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
> > I am afraid of posting 300 pathces into threads to flood it(and
> > disturbing yours). So I'll wait for your work first. and resolving
> > conflicts later, that's really time-consuming.
> >
> 
> It's indeed not possible to send 300 patches and expect this to work,
> whether it's on this mailing list, or any software forge also.
> It's also not possible to send a link, and expect anyone to take a look
> at the 373 commits sitting it on top of master. My name is not Claude.
> Instead, humans have to progress step by step, based on feedback. Yes it
> takes time and it can be frustrating. And yes, I've been there (and
> frustrated) also, I feel sorry for you.
> 
> At the moment, if we want to make it move on, we need to focus on one
> single thing:
> "How to document/specify which targets a machine support".
> 
> > I did many explanations before. seems my explanation is too bad and
> > not to give a clean picture for you, let's delay these first.
> >
> 
> If I can suggest something politely here, IMHO, alternating between
> genuinely human written messages, and AI content sent as it is on email
> or commit messages is not helping on the receiver side.
> 
> I would prefer anytime to deal with imperfect english (mine is imperfect
> too, I'm not a native speaker neither), compared to read what
> Claude/GPT/Deepseek generated that was pasted as it is.
> I understand it's a good tool for helping on the language side, and
> that's ok to fix grammar and sentence structure.
> But asking "Please generate a summary from those email threads and
> explain what the current series is doing", and paste this is doomed to fail.
> 
> It also has a very detrimental side effect: it makes me start to wonder
> where the code is coming from also. Especially when seeing boilerplates
> with lengthy comments written in perfect english. My 2 cents is, use AI
> if you want/need, but make sure the result has this *human* touch.

Although these are not yet final/commited, please bear in mind the
proposed updated AI guidelines which broadly intend to forbid use
of AI for authoring commit messages & cover letters:

  https://lists.gnu.org/archive/html/qemu-devel/2026-09/msg00260.html


With regards,
Daniel
-- 
|: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
|: https://libvirt.org          ~~          https://entangle-photo.org :|
|: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|



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

* Re: [PATCH 4/8] target-info: replace QOM registration with a constructor list
  2026-10-13  9:26             ` Daniel P. Berrangé
@ 2026-10-13 15:53               ` Pierrick Bouvier
  0 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-13 15:53 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: luoyonggang, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/13/2026 2:26 AM, Daniel P. Berrangé wrote:
> On Wed, Oct 07, 2026 at 04:24:07PM -0700, Pierrick Bouvier wrote:
>> On 10/7/2026 3:54 PM, Yonggang Luo wrote:
>>> My work is here.
>>> https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
>>> I am afraid of posting 300 pathces into threads to flood it(and
>>> disturbing yours). So I'll wait for your work first. and resolving
>>> conflicts later, that's really time-consuming.
>>>
>>
>> It's indeed not possible to send 300 patches and expect this to work,
>> whether it's on this mailing list, or any software forge also.
>> It's also not possible to send a link, and expect anyone to take a look
>> at the 373 commits sitting it on top of master. My name is not Claude.
>> Instead, humans have to progress step by step, based on feedback. Yes it
>> takes time and it can be frustrating. And yes, I've been there (and
>> frustrated) also, I feel sorry for you.
>>
>> At the moment, if we want to make it move on, we need to focus on one
>> single thing:
>> "How to document/specify which targets a machine support".
>>
>>> I did many explanations before. seems my explanation is too bad and
>>> not to give a clean picture for you, let's delay these first.
>>>
>>
>> If I can suggest something politely here, IMHO, alternating between
>> genuinely human written messages, and AI content sent as it is on email
>> or commit messages is not helping on the receiver side.
>>
>> I would prefer anytime to deal with imperfect english (mine is imperfect
>> too, I'm not a native speaker neither), compared to read what
>> Claude/GPT/Deepseek generated that was pasted as it is.
>> I understand it's a good tool for helping on the language side, and
>> that's ok to fix grammar and sentence structure.
>> But asking "Please generate a summary from those email threads and
>> explain what the current series is doing", and paste this is doomed to fail.
>>
>> It also has a very detrimental side effect: it makes me start to wonder
>> where the code is coming from also. Especially when seeing boilerplates
>> with lengthy comments written in perfect english. My 2 cents is, use AI
>> if you want/need, but make sure the result has this *human* touch.
> 
> Although these are not yet final/commited, please bear in mind the
> proposed updated AI guidelines which broadly intend to forbid use
> of AI for authoring commit messages & cover letters:
> 
>   https://lists.gnu.org/archive/html/qemu-devel/2026-09/msg00260.html
>

While the AI discussion is on going, maybe it would be nice to forbid
that on the mailing list also.

> 
> With regards,
> Daniel



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

* Re: [PATCH 0/8] qom: pass TargetInfo to the is_available callback
  2026-10-13  4:03                           ` Yonggang Luo
@ 2026-10-13 15:56                             ` Pierrick Bouvier
  0 siblings, 0 replies; 62+ messages in thread
From: Pierrick Bouvier @ 2026-10-13 15:56 UTC (permalink / raw)
  To: luoyonggang
  Cc: Daniel P. Berrangé, qemu-devel, Cleber Rosa, Stefan Hajnoczi,
	Cédric Le Goater, Laurent Vivier, Zhao Liu, John Snow,
	Laurent Vivier, Richard Henderson, Joel Stanley, Fabiano Rosas,
	Kane Chen, Andrew Jeffery, Troy Lee, Jamin Lin, Stafford Horne,
	qemu-arm, Philippe Mathieu-Daude, Peter Maydell, Paolo Bonzini,
	Philippe Mathieu-Daudé, Marc-André Lureau, Steven Lee,
	Alexander Bulekov, Darren Kenny

On 10/12/2026 9:03 PM, Yonggang Luo wrote:
> On Tue, Oct 13, 2026 at 11:53 AM Pierrick Bouvier
> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>
>> On 10/12/26 7:43 PM, Yonggang Luo wrote:
>>> On Tue, Oct 13, 2026 at 9:26 AM Pierrick Bouvier
>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>
>>>> On 10/11/26 9:26 PM, Yonggang Luo wrote:
>>>>> On Mon, Oct 12, 2026 at 10:25 AM Pierrick Bouvier
>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>>
>>>>>> On 10/11/26 7:13 PM, Pierrick Bouvier wrote:
>>>>>>> On 10/11/26 1:22 PM, Yonggang Luo wrote:
>>>>>>>> On Fri, Oct 9, 2026 at 2:34 AM Pierrick Bouvier
>>>>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>>>>>
>>>>>>>>> On 10/8/2026 10:13 AM, Yonggang Luo wrote:
>>>>>>>>>> On Fri, Oct 9, 2026 at 12:06 AM Pierrick Bouvier
>>>>>>>>>> <pierrick.bouvier@oss.qualcomm.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>> On 10/8/2026 2:46 AM, Yonggang Luo wrote:
>>>>>>>>>>>> On Thu, Oct 8, 2026 at 5:42 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Wed, Oct 07, 2026 at 01:25:46PM -0700, Pierrick Bouvier wrote:
>>>>>>>>>>>>>> On 10/7/2026 4:47 AM, Yonggang Luo wrote:
>>>>>>>>>>>>>>> This allows a combined binary to register machine types from all its targets.
>>>>>>>>>>>>>>> Consequently, QMP `query-machines` can return machine entries from every
>>>>>>>>>>>>>>> target, even when `none` is selected. For example, a client can query the
>>>>>>>>>>>>>>> combined machine list with:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> ```json
>>>>>>>>>>>>>>> { "execute": "query-machines" }
>>>>>>>>>>>>>>> ```
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> The returned list includes the registered machine classes from all linked
>>>>>>>>>>>>>>> targets. This is separate from selecting a machine: with `-target none`,
>>>>>>>>>>>>>>> `-M virt` reports the targets that provide `virt` instead of choosing one
>>>>>>>>>>>>>>> arbitrarily:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> ```text
>>>>>>>>>>>>>>> qemu-system -target none -M virt
>>>>>>>>>>>>>>> unsupported machine type: "virt" for target "none"
>>>>>>>>>>>>>>> Available for targets:
>>>>>>>>>>>>>>>       aarch64
>>>>>>>>>>>>>>>       arm
>>>>>>>>>>>>>>> ```
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     From the long conversation on a previous thread, I thought we reached
>>>>>>>>>>>>>> the conclusion that if we didn't expose any ambiguous name, then -target
>>>>>>>>>>>>>> option is unnecessary, or maybe I got lost on track of this thread.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> https://lore.kernel.org/qemu-devel/ar_coT44h5-zJPVV@redhat.com/
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I'm not sure which semantic we want to have with -target none. If there
>>>>>>>>>>>>>> is no ambiguous name registered, we just don't need it at all. It's a
>>>>>>>>>>>>>> win-win IMHO.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Yes, if we expose unique names for every machine, then -target is then
>>>>>>>>>>>>> redundant.
>>>>>>>>>>>>
>>>>>>>>>>>> so how to diff riscv32-virt and risv64-virt? oh so for this machine we
>>>>>>>>>>>> needs two name?
>>>>>>>>>>>> "virt" needs register twice for it? or register only a single time,
>>>>>>>>>>>> but we prefix the target_name()
>>>>>>>>>>>> automatically? for example machine::name === "virt", but we can use
>>>>>>>>>>>> "riscv32-virt" "risv64-virt" to reach it?
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Yes, ideally we should have different variant of virt for 32/64 bit.
>>>>>>>>>>> Same goes for cpu max types.
>>>>>>>>>>>
>>>>>>>>>>> QOM type is always registered unambiguously ("$arch-virt"). Then, for
>>>>>>>>>>> the "alias" name, which is virt, in case multiple matches are found,
>>>>>>>>>>> command line can return an error with list of unambiguous names to call it.
>>>>>>>>>>>
>>>>>>>>>>> $ qemu-system -M virt
>>>>>>>>>>> Multiple virt machines are available. Please choose one of them:
>>>>>>>>>>> - aarch64-virt
>>>>>>>>>>> - riscv64-virt
>>>>>>>>>>>
>>>>>>>>>>> There is no "parsing" of the argument, it's just the real QOM type. Then
>>>>>>>>>>> we can find which target it implements from mc->targets.
>>>>>>>>>>> And then, we can automatically choose which cpus should be available
>>>>>>>>>>> based on that, thanks to cpu->targets.
>>>>>>>>>>>
>>>>>>>>>>> For existing binaries, nothing change.
>>>>>>>>>>
>>>>>>>>>> Good, I think we found a clean way now, is_available should be
>>>>>>>>>> removed, and TypeInfo::targets and TypeImpl::targets should be added.
>>>>>>>>>
>>>>>>>>> It goes into MachineClass only for now.
>>>>>>>>>
>>>>>>>>>> I think
>>>>>>>>>> for "virt" we can add a shared hw/machine-virt.c instead, and forwarding to
>>>>>>>>>> the $arch specific virt. so that we only have a single "virt" registered.
>>>>>>>>>> And it's
>>>>>>>>>> targets is
>>>>>>>>>> QEMU_ARCH_I386 |
>>>>>>>>>> QEMU_ARCH_ARM |
>>>>>>>>>> QEMU_ARCH_RISCV |
>>>>>>>>>> QEMU_ARCH_LOONGARCH |
>>>>>>>>>> QEMU_ARCH_M68K |
>>>>>>>>>> QEMU_ARCH_OR1K |
>>>>>>>>>> QEMU_ARCH_XTENSA |
>>>>>>>>>> QEMU_ARCH_HEXAGON
>>>>>>>>>>
>>>>>>>>>> So that we won't have a list of conflict QOM names for "virt" machines.
>>>>>>>>>> As now we indeed have only a single "virt" machine that redirects to
>>>>>>>>>> different targets.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The idea looks appealing, but I don't think it solves the problem to
>>>>>>>>> have multiple virt variants available at the same time.
>>>>>>>>>
>>>>>>>>> The "alias" idea you introduced before is good, we just need to add a
>>>>>>>>> check if an alias is really unique, else return an error, as explained
>>>>>>>>> previously.
>>>>>>>>>
>>>>>>>>> If "-M aarch64-virt" works for both the new and existing binary, and -M
>>>>>>>>> virt only for existing binaries (and ambiguous for new one), I think
>>>>>>>>> that's a safe approach.
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> For other types also conflict can be handled in the same way, such as
>>>>>>>>>> "-cpu host" "-cpu max"
>>>>>>>>>> maybe others, but I think they all have the same way to deal with.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> That's why  TypeInfo::targets and TypeImpl::targets better than sole
>>>>>>>>>> Machine::targets
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> One step at a time.
>>>>>>>>> Let's keep focused on declaring targets for a single machine first.
>>>>>>>>> Then we can iterate to solve the "virt" problem.
>>>>>>>>> Then convert all the existing machines and add a check in machine-target.c
>>>>>>>>> Then, and only then, we can see what happens with cpus.
>>>>>>>>
>>>>>>>> I tried this idea, but I faced a fatal error, because the
>>>>>>>> target_info() is not available until
>>>>>>>> the machine selected(the target arch will be select just along with
>>>>>>>> the machine selected), so basically
>>>>>>>> all calls to target_info() would raise an error(null pointer), how to
>>>>>>>> deal with it?
>>>>>>>>
>>>>>>>
>>>>>>> I see. Indeed, since we can't set a target before registering all types,
>>>>>>> it implies that all the types class_init can't use target_* functions.
>>>>>>>
>>>>>>>
>>>>>>> - register_accel_target_type
>>>>>>> - cpu_max_v8_register_type
>>>>>>>
>>>>>>
>>>>>> Sorry, mail sent to early.
>>>>>>
>>>>>> For the is_available callback usage, it should be easy to do the switch,
>>>>>> since it's basically the same information that what we are trying to do
>>>>>> - we can leave them for now.
>>>>>>
>>>>>> Some types (like accel and max mentioned above), explicitly change their
>>>>>> definition depending on the target. It's a behavior we can't rely on
>>>>>> anymore, and it means we need proper distinct types instead of a single
>>>>>> one with dynamic definition driven by target-info.
>>>>>>
>>>>>> I think that's the preliminary work needed, before being able to go
>>>>>> further: convert all existing usage in class_init with distinct types +
>>>>>> is_available, and then we can do the switch from is_available to the new
>>>>>> .targets approach.
>>>>>
>>>>> Hi Pierrick,
>>>>> I have already tried that introducing new QOM names just to make class_init
>>>>>    target-independent is too broad(means all usage of it should be handled)
>>>>> and could complicate compatibility(changed too much code).
>>>>> Can we avoid new names by some new means(ideas welcome)?
>>>>>
>>>>
>>>> As a first step, I don't think we need new names, is_available can be
>>>> used to selectively register one definition or another and avoid any
>>>> clash. What is missing at the moment though, is that some types (like
>>>> cpu max above) change their definition based on target definition.
>>>
>>>
>>>>
>>>> So for cpu max, we would have two distinct types, both named max, but
>>>> one with is_available(target_arm), and other one with
>>>> is_available(target_aarch64), so they are never registered at the same time.
>>>
>>>>
>>>> Same for virt machines. It's already what we have, duplication is
>>>> handled at the moment with distinct is_available callbacks.
>>>>
>>>> Then, see below.
>>>>
>>>>>
>>>>>>
>>>>>> It's probably worth having the conversion in its own series (only
>>>>>> cleanup usage of target_* in class_init), before trying to get rid of
>>>>>> is_available.
>>>>>
>>>>>>
>>>>>> For the implementation, you can use the multi-targets.c binary test to
>>>>>> drive the change. Remove the module init for target info (leaving no
>>>>>> target set), and add a hacky patch to skip call to is_available (and
>>>>>> return true instead) and allow double definition (which will rely on
>>>>>> is_available). Then, fix all the segfault. Once it compiles and runs,
>>>>>> only double definition will be left, which can be handled by inserting
>>>>>> the right is_available callbacks. Then in a subsequent series, the
>>>>>> switch to .targets can be made.
>>>>>
>>>>>
>>>>> Still have no clean clue about how to remove is_available , as we have many
>>>>> "virt" machines. Do you means all "virt" machines with "virt-machine" QOM names
>>>>> are inserted to the table? How to get it working because the "key" is string.
>>>>>
>>>>
>>>> Once we have type definition which only depends on is_available, we can
>>>> convert this to .targets, which would contain the same information.
>>>> For the rest, I have some ideas, but I would like first we do the first
>>>> part (convert to is_available), which is already a huge work in itself,
>>>> and a series of its own.
>>>
>>> Indeed I am confused .targets only exists on Machine, how is it
>>> related to -cpu host -cpu max?
>>>
>>
>> We can introduce cpu.targets after machine.targets.
>> First step is just to get something that works with is_available and
>> does not require any target info to be set.
> 
> Feels weird, what's wrong with this method:
>  target/arm/tcg/cpu-max-v8.c | 17 +++++++++++++----
>  1 file changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/target/arm/tcg/cpu-max-v8.c b/target/arm/tcg/cpu-max-v8.c
> index 65f851f2006..d7323ab431c 100644
> --- a/target/arm/tcg/cpu-max-v8.c
> +++ b/target/arm/tcg/cpu-max-v8.c
> @@ -119,12 +119,21 @@ void aarch32_max_v8_tcg_initfn(Object *obj)
>  #endif
>  }
> 
> +static void max_v8_tcg_initfn(Object *obj)
> +{
> +    if (target_aarch64()) {
> +        aarch64_max_v8_tcg_initfn(obj);
> +    } else {
> +        aarch32_max_v8_tcg_initfn(obj);
> +    }
> +}
> +
>  static void cpu_max_v8_register_type(void)
>  {
> -    static const ARMCPUInfo max_v8[2] = {
> -        { .name = "max-v8", .initfn = aarch32_max_v8_tcg_initfn },
> -        { .name = "max-v8", .initfn = aarch64_max_v8_tcg_initfn },
> +    static const ARMCPUInfo max_v8 = {
> +        .name = "max-v8",
> +        .initfn = max_v8_tcg_initfn,
>      };
> -    arm_cpu_register(&max_v8[target_aarch64()]);
> +    arm_cpu_register(&max_v8);
>  }
>  type_init(cpu_max_v8_register_type)
>

In this case, It seems simpler to me to register two max types, with
different is_available. Arm maintainers might have a different opinion,
so I encourage you to post this as a separate series with them in cc.

It's also the last inline patch I'll answer to (next ones will be
silently ignored).

> 
>>
>>>
>>> I already have a working copy that does not depend on target_info()
>>> and selects target_info() when the machine
>>> is selected, no QOM name introduced. only for machines, we will have
>>> $target_name-$machine_name as a name for selecting
>>> the exact machine.
>>>
>>> The cpu max cpu host is dealt by moving the choose code out of
>>> class_init, into object_init. I really did not get your idea by use
>>> is_avaiable. because when I try to get all QOMs to be registered. then
>>> I won't call is_available at all.
>>
>> As a first step, we rely on is_available, to work on distinguishing
>> proper types per target and break the dependency of multiple class_init
>> to target_info. Then, we can replace is_available with .targets.
>>
>>> because "is_available" depends on target_info(),(we won't have
>>> target_info() till the machine is selected).
>>>
>>
>> We can imagine registering types in different buckets per target, which
>> would allow for duplication.
> 
> 
> So your idea is multiple hash-tables for QOM types? key is the target_arch?
>

I don't want to dig more into this now, a lot of preliminary work has
been discussed already, let's focus on that.

Regards,
Pierrick


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

end of thread, other threads:[~2026-10-13 15:56 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-07 11:47 [PATCH 0/8] qom: pass TargetInfo to the is_available callback Yonggang Luo
2026-10-07 11:47 ` [PATCH 1/8] configs/targets: remove target info definitions Yonggang Luo
2026-10-07 20:26   ` Pierrick Bouvier
2026-10-08  9:46     ` Philippe Mathieu-Daudé
2026-10-07 11:47 ` [PATCH 2/8] target-info: rename target-info-stub.c in target-info-def.c Yonggang Luo
2026-10-07 11:48 ` [PATCH 3/8] target-info: rename target-info-impl.h to target-info-def.h Yonggang Luo
2026-10-07 20:27   ` Pierrick Bouvier
2026-10-07 11:48 ` [PATCH 4/8] target-info: replace QOM registration with a constructor list Yonggang Luo
2026-10-07 20:29   ` Pierrick Bouvier
2026-10-07 20:50     ` Yonggang Luo
2026-10-07 22:31       ` Pierrick Bouvier
2026-10-07 22:54         ` Yonggang Luo
2026-10-07 23:24           ` Pierrick Bouvier
2026-10-13  9:26             ` Daniel P. Berrangé
2026-10-13 15:53               ` Pierrick Bouvier
2026-10-07 23:02         ` Yonggang Luo
2026-10-07 23:28           ` Pierrick Bouvier
2026-10-12 21:27             ` Yonggang Luo
2026-10-13  3:57               ` Pierrick Bouvier
2026-10-13  8:58                 ` Yonggang Luo
2026-10-07 11:48 ` [PATCH 5/8] tests/unit: add target-info coverage for multi-target builds Yonggang Luo
2026-10-07 11:48 ` [PATCH 6/8] meson: load all target .mak files into target_mak_all Yonggang Luo
2026-10-07 20:30   ` Pierrick Bouvier
2026-10-07 11:48 ` [PATCH 7/8] target-info: Replace handwritten architecture checks with generated code Yonggang Luo
2026-10-07 20:36   ` Pierrick Bouvier
2026-10-07 11:48 ` [PATCH 8/8] qom: pass TargetInfo to is_available for later use Yonggang Luo
2026-10-07 20:44   ` Pierrick Bouvier
2026-10-07 21:42     ` Yonggang Luo
2026-10-08  0:00       ` Pierrick Bouvier
2026-10-08  0:03         ` Pierrick Bouvier
2026-10-08  2:08         ` Yonggang Luo
2026-10-08 15:58           ` Pierrick Bouvier
2026-10-08  9:36         ` Daniel P. Berrangé
2026-10-08  9:56           ` Yonggang Luo
2026-10-08 16:01             ` Pierrick Bouvier
2026-10-08 17:04               ` Yonggang Luo
2026-10-08 18:26                 ` Pierrick Bouvier
2026-10-08 18:33                   ` Yonggang Luo
2026-10-08 18:40                     ` Pierrick Bouvier
2026-10-07 20:25 ` [PATCH 0/8] qom: pass TargetInfo to the is_available callback Pierrick Bouvier
2026-10-08  9:42   ` Daniel P. Berrangé
2026-10-08  9:46     ` Yonggang Luo
2026-10-08 16:06       ` Pierrick Bouvier
2026-10-08 17:13         ` Yonggang Luo
2026-10-08 18:34           ` Pierrick Bouvier
2026-10-08 18:48             ` Yonggang Luo
2026-10-11 20:22             ` Yonggang Luo
2026-10-12  2:13               ` Pierrick Bouvier
2026-10-12  2:21                 ` Yonggang Luo
2026-10-12  2:25                 ` Pierrick Bouvier
2026-10-12  4:26                   ` Yonggang Luo
2026-10-12  7:11                     ` Pierrick Bouvier
2026-10-13  1:26                     ` Pierrick Bouvier
2026-10-13  2:43                       ` Yonggang Luo
2026-10-13  3:53                         ` Pierrick Bouvier
2026-10-13  4:03                           ` Yonggang Luo
2026-10-13 15:56                             ` Pierrick Bouvier
2026-10-11 20:32             ` Yonggang Luo
2026-10-07 20:46 ` Pierrick Bouvier
2026-10-09 21:58   ` Pierrick Bouvier
2026-10-09 22:08     ` Yonggang Luo
2026-10-09 22:21       ` Pierrick Bouvier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.