* [PATCH v3 000/114] single-binary: link multi-targets into qemu-system
@ 2026-09-23 13:14 Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 001/114] meson: stale qemu-version.h only when .git exists Yonggang Luo
` (41 more replies)
0 siblings, 42 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
This series produces one qemu-system binary that can run ARM (32 and
64), RISC-V (32 and 64), and MicroBlaze.
Upstream filters machines with TypeInfo.is_available. This series
passes a TargetInfo into that callback, uniquifies QOM names that
collide in one process, and compiles those targets once so they can
share qemu-system.
A combined link cannot keep C symbols or QOM type names that were
unique only because each qemu-system-$arch was a separate binary.
These patches remove those collisions:
- TYPE_ACCEL_CPU is the fixed abstract type accel-cpu, registered
once next to TYPE_ACCEL. Leaf names still encode the CPU type so
accel_init_cpu_interfaces() can look up "<accel>-" plus
target_cpu_type() (tcg-accel-arm-cpu).
- virt QOM names are prefixed: arm-virt, riscv-virt, and the same
for or1k, hexagon, loongarch, m68k, and xtensa. Boards keep
-machine virt via machine_class_set_name(). query-machines returns
the QOM type in MachineInfo typename.
- virt ACPI helpers and RISC-V TCG crc32/crc32c/wfi helpers get an
arch prefix so the combined link does not need meson -D name
mangling. LoongArch virt_acpi_setup is renamed in the same pass.
Target selection has to work with more than one TargetInfo:
- The combined binary takes arch:name on -M/-machine and in a
[machine] type (aarch64:virt). arch: binds the target. microblaze:
runs that target's default machine. arm, aarch64, riscv32, and
riscv64 have no default. No -M leaves target none and the empty
none machine. qemu-system-$arch keeps the historic -M name.
-M help lists every target; arch:help lists one. query-targets
lists each linked target, including none.
- TargetInfo is a constructor list. target_info_select() picks the
entry, including SYS_EMU_TARGET_NONE. is_available takes const
TargetInfo *. While the target is still none, QOM skips the
unavailable filter so grouped -M help can list every machine.
- query-cpu-definitions, dump notes, and Angel semihosting sit on
TargetCpuOps indexed by target_arch(). Registration uses a
QEMU_ARCH_* bitmask so one object can fill ARM and AARCH64. The
table is target-ops.h / target-ops.c.
qemu-system-$TARGET is still built, including the Windows *w twin.
qemu-system is extra. It links each target whose arch sources are
only target-info-def.c: arm, aarch64, riscv32, riscv64, and
microblaze. Do not add qemu-systemw for that binary. A GUI
twin would keep QEMU exporting data from the .exe into DLLs, and
those data exports cannot be delay-loaded (qdev_prop_array and
other qdev_prop_*). That would block enabling modules globally on
Windows.
Examples:
qemu-system -M aarch64:virt ...
qemu-system -M microblaze:petalogix-s3adsp1800 ...
qemu-system-riscv64 -M virt ...
A bare machine name on qemu-system needs an arch: prefix. An unknown
target fails with "target '...' is not available".
Prerequisites:
[PATCH v2 0/9] machine: uniquify virt QOM names
https://patchew.org/QEMU/20260922215533.641-1-luoyonggang@gmail.com/
[PATCH 00/21] accel/tcg: share raise_excp across TCG targets
https://patchew.org/QEMU/20260918004225.827-1-luoyonggang@gmail.com/
[PATCH v5 00/11] single-binary: Compile hw/riscv once
https://patchew.org/QEMU/20260918-hw-riscv-cpu-int-v5-0-f98c5a244636@rev.ng/
v1: https://patchew.org/QEMU/20260823150731.896-1-luoyonggang@gmail.com/
v2: https://patchew.org/QEMU/20260826184229.1145-1-luoyonggang@gmail.com/
branch: https://gitlab.com/lygstate-qemu/qemu/-/tree/single-binary-arm-riscv?ref_type=heads
x86_64 and i386: https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
Changes v2 -> v3:
- Drop -target. v2 parsed a target_name token and required it on
bare qemu-system, with -target ? to list names. v3 selects the
target with arch:name on -M. No -M leaves target none. -M help
and arch:help list machines.
- Rebased onto current master. Upstream is_available(void) replaces
TYPE_TARGET_SPECIFIC. v3 passes const TargetInfo * into
is_available. The v2 patches that registered TYPE_TARGET_SPECIFIC
on ARM and RISC-V virt are dropped.
- TargetInfo is a constructor list, not chosen from argv[0].
target_info_select() sets the current entry. Add SysEmuTarget
none. A single-target binary does not switch TargetInfo; arch:
must match that binary or the machine is rejected.
- Drop -Dsingle_binary. qemu-system is built from
single_binary_supported_targets once arch_srcs are only
target-info-def.c. microblaze joins ARM and RISC-V. Per-target
binaries stay. Still no qemu-systemw for the combined binary.
- Unique virt QOM names extend past ARM and RISC-V to or1k,
hexagon, loongarch, m68k, and xtensa. query-machines returns
MachineInfo typename.
- TargetCpuOps is an array indexed by target_arch(), registered
with a QEMU_ARCH_* bitmask. The header moves from
target-info-qom.h to target-ops.h.
- Those targets are compiled once: ARM, RISC-V, and MicroBlaze fold
into common source sets, TARGET_* ifdefs become runtime checks, and
KVM moves to system_ss.
Pierrick Bouvier (2):
configs/targets: remove target info definitions
target-info: rename target-info-stub.c in target-info-def.c
Yonggang Luo (112):
meson: stale qemu-version.h only when .git exists
target-info: rename target-info-impl.h to target-info-def.h
target-info: set cpu_type from TARGET_BASE_ARCH
target: remove CPU_RESOLVING_TYPE
vl: parse early options before target-info init
target-info: replace QOM registration with a constructor list
tests/unit: add test-target-info
tests/qtest: prepare machine-list-test for combined qemu-system
kconfig: rename REGISTER to HW_REGISTER
target-info: add TargetKconfig
target-info: add target_is_* helpers for each architecture
target-info: add i386 and x86_64 helpers
qom: pass TargetInfo to is_available
module: use static ModuleEntry and per-type DSO lists
module: add before/after hooks and module_call_init_fn
qom: register late types through module_call_init_fn
qom: inherit is_available and filter after MODULE_INIT_QOM
tests/unit: add module-init and qom is-available tests
hw/arm/virt: prefix ACPI helpers with arm_virt_
hw/riscv/virt: prefix ACPI helpers with riscv_virt_
hw/loongarch/virt: prefix ACPI helper with loongarch_virt_
target/riscv: uniquify TCG crc32, crc32c, and wfi helper names
hw/riscv: gate boards with target_is_base_riscv
hw/intc: use target_long_bits in IMSIC geilen
hw/misc/riscv_cmgcr: replace target_ulong with uint64_t
hw/intc: use kvm_enabled() in APLIC AIA helpers
hw/intc: send IMSIC MSI via kvm_irqchip_send_msi()
target/riscv: add kvm stubs source set
tcg: fix off-by-one in helper extend-free assert
gdbstub: drop per-target cpu-param.h from helpers.h
hw/riscv: expand boston-aia and microblaze-v-generic to TypeInfo
target/riscv: Include migration/vmstate.h instead of migration/cpu.h
in machine.c
target/riscv: gate CPU types with TargetInfo
target/riscv: select ELF dump class from target_riscv64
target/riscv: replace TARGET_* macros in CSR helpers
target/riscv: use target_long_bits in pmpaddr granule checks
target/riscv: preserve signed XLEN semantics without target_long
target/riscv: replace leftover TARGET_LONG_BITS
target/riscv: select monitor width at runtime
target/riscv: replace target-width format macros
target/riscv: replace TARGET_LONG_BITS in translate
target-info: add tl_is_64() and target_is_tl32/64 helpers
target-info: dispatch CPU QMP, dump, and Angel semihosting
tcg: give TCGv its own type and runtime tl ops
exec: allow target_long.h, abi_ptr.h and cpu-ldst.h from common code
migration: add TargetInfo-gated vmstate fields
target/i386: always compile XMM, YMMH, and Hi16 VMSD
target/i386: replace VMSTATE_UINTTL with 32/64 TI fields
target/ppc: replace VMSTATE_UINTTL with 32/64 TI fields
target/sparc: replace VMSTATE_UINTTL with 32/64 TI fields
target/mips: replace VMSTATE_UINTTL with 32/64 TI fields
hw/hexagon: drop unused migration/cpu.h include
migration: remove unused cpu.h
target/riscv: gate KVM CPU VMSDs with target_has_kconfig_kvm
target/riscv: use tcg_imm_tl in translate
target/riscv: select FP and amocas width at runtime
target/riscv: drop TARGET_RISCV XL shortcuts in translate
target/riscv: select KVM host CPU width at runtime
accel: use a shared TYPE_ACCEL_CPU parent
kvm: always compile guest debug
hw/i386: move APIC_DEFAULT_ADDRESS to apic.h
kvm: stop including cpu.h from kvm.h
kvm: default kvm_arch_reset_parked_vcpu in stubs
kvm: drop COMPILING_PER_TARGET wrap around kvm_arch APIs
kvm: add split irqchip and send_msi stubs
kvm: replace TARGET_S390X and TARGET_PPC hints
kvm: move kvm_ss to system_ss
system: add qemu_host_arch() and reject unavailable -accel
kvm: add AccelClass is_available for host/guest pairing
hvf: add AccelClass is_available for host/guest pairing
xen: add AccelClass is_available for host/guest pairing
nitro: add AccelClass is_available for host/guest pairing
mshv: add AccelClass is_available for host/guest pairing
whpx: add AccelClass is_available for host/guest pairing
target/i386/nvmm: add AccelClass is_available for host/guest pairing
accel: replace ACCEL_CPU_NAME with accel_cpu_register_type
whpx: move whpx_ss to system_ss
hw/riscv: move boards and irqchip onto hw_common_arch
target/riscv: include target_long.h in TCG helpers
target/riscv: compile CPU and TCG once
target/arm: replace target_long in A64 translate
target/arm: use 64-bit TCG addresses in A64 translate
target/arm: move kvm_arm_set_cpreg_mig_tolerances to kvm.c
target/arm: allow -cpu host with Nitro
target/arm: gate -cpu host with TypeIsAvailable
target/arm: fix family-common KVM compile
tests/qtest: raise aspeed_smc-test timeout to 12 minutes
hw/intc: move ARM GIC kvm/hvf/whpx onto arm_common_ss
target/arm: fold arm_ss into common source sets
meson: link shared objects into qemu-system
target/microblaze: fold system sources into common source sets
meson: add microblaze-softmmu to the combined qemu-system list
boards: remove unused DEFINE_MACHINE_WITH_INTERFACES
hw/arm: set virt TypeInfo.is_available
hw/arm: set remaining 32-bit machine TypeInfo.is_available
hw/arm: set aarch64-only machine TypeInfo.is_available
hw/microblaze: set petalogix-s3adsp1800 TypeInfo.is_available
hw/arm: expand leftover 32-bit DEFINE_MACHINE to TypeInfo
hw/arm: expand imx8mm-evk DEFINE_MACHINE to TypeInfo
hw/microblaze: expand petalogix-ml605 and xlnx-zynqmp-pmu to TypeInfo
hw/i386: set TYPE_X86_MACHINE TypeInfo.is_available
hw/block/dataplane: move xen-block onto system_ss
hw/remote: move multiprocess memory onto remote_ss
hw/remote: set x-remote TypeInfo.is_available
target-info: add SysEmuTarget none
accel/tcg: tolerate NULL target_cpu_type for -M none
qom: skip unavailable filter when target_none()
module: load every arch-tagged module when target is none
target-info: select combined qemu-system target by name
vl: parse arch: machine types on combined qemu-system
qapi: add query-targets
tests/qtest: cover combined qemu-system machines and accel-cpu
MAINTAINERS | 1 -
accel/accel-common.c | 62 +-
accel/hvf/hvf-all.c | 15 +
accel/kvm/kvm-accel-ops.c | 4 -
accel/kvm/kvm-all.c | 45 +-
accel/kvm/meson.build | 2 +-
accel/mshv/mshv-all.c | 8 +
accel/nitro/nitro-accel.c | 8 +
accel/stubs/kvm-stub.c | 11 +
accel/tcg/tcg-all.c | 9 +-
accel/whpx/meson.build | 2 +-
accel/whpx/whpx-common.c | 32 +-
accel/xen/xen-all.c | 18 +
configs/targets/aarch64-softmmu.c | 25 -
configs/targets/aarch64-softmmu.mak | 1 -
configs/targets/arm-softmmu.c | 25 -
configs/targets/i386-softmmu.mak | 2 -
configs/targets/loongarch64-softmmu.mak | 1 -
configs/targets/meson.build | 6 -
configs/targets/ppc-softmmu.mak | 1 -
configs/targets/ppc64-softmmu.mak | 1 -
configs/targets/riscv32-softmmu.c | 24 -
configs/targets/riscv64-softmmu.c | 24 -
configs/targets/riscv64-softmmu.mak | 1 -
configs/targets/s390x-softmmu.mak | 1 -
configs/targets/x86_64-softmmu.mak | 2 -
hw/Kconfig | 2 +-
hw/arm/aspeed_ast1040_evb.c | 1 +
hw/arm/aspeed_ast10x0_evb.c | 2 +
hw/arm/aspeed_ast2400_palmetto.c | 1 +
hw/arm/aspeed_ast2400_quanta-q71l.c | 1 +
hw/arm/aspeed_ast2400_supermicrox11.c | 1 +
hw/arm/aspeed_ast2500_evb.c | 1 +
hw/arm/aspeed_ast2500_g220a.c | 1 +
hw/arm/aspeed_ast2500_romulus.c | 1 +
hw/arm/aspeed_ast2500_supermicro-x11spi.c | 1 +
hw/arm/aspeed_ast2500_tiogapass.c | 1 +
hw/arm/aspeed_ast2500_witherspoon.c | 1 +
hw/arm/aspeed_ast2500_yosemitev2.c | 1 +
hw/arm/aspeed_ast2600_anacapa.c | 1 +
hw/arm/aspeed_ast2600_bletchley.c | 1 +
hw/arm/aspeed_ast2600_catalina.c | 1 +
hw/arm/aspeed_ast2600_evb.c | 1 +
hw/arm/aspeed_ast2600_fby35.c | 1 +
hw/arm/aspeed_ast2600_fuji.c | 1 +
hw/arm/aspeed_ast2600_gb200nvl.c | 1 +
hw/arm/aspeed_ast2600_rainier.c | 1 +
hw/arm/aspeed_ast2600_sanmiguel.c | 1 +
hw/arm/aspeed_ast27x0-fc.c | 2 +-
hw/arm/aspeed_ast27x0_evb.c | 4 +-
hw/arm/ax3000-evk.c | 1 +
hw/arm/b-l475e-iot01a.c | 1 +
hw/arm/bananapi_m2u.c | 22 +-
hw/arm/collie.c | 1 +
hw/arm/cubieboard.c | 23 +-
hw/arm/digic_boards.c | 19 +-
hw/arm/exynos4_boards.c | 2 +
hw/arm/imx25_pdk.c | 19 +-
hw/arm/imx8mm-evk.c | 23 +-
hw/arm/imx8mp-evk.c | 1 +
hw/arm/integratorcp.c | 23 +-
hw/arm/kzm.c | 19 +-
hw/arm/max78000fthr.c | 19 +-
hw/arm/mcimx6ul-evk.c | 19 +-
hw/arm/mcimx7d-sabre.c | 23 +-
hw/arm/microbit.c | 1 +
hw/arm/mps2-tz.c | 5 +
hw/arm/mps2.c | 4 +
hw/arm/mps3r.c | 1 +
hw/arm/msf2-som.c | 19 +-
hw/arm/musca.c | 2 +
hw/arm/netduino2.c | 19 +-
hw/arm/netduinoplus2.c | 19 +-
hw/arm/npcm7xx_boards.c | 5 +
hw/arm/npcm8xx_boards.c | 1 +
hw/arm/olimex-stm32-h405.c | 19 +-
hw/arm/omap_sx1.c | 2 +
hw/arm/orangepi.c | 23 +-
hw/arm/raspi.c | 7 +-
hw/arm/raspi4b.c | 2 +-
hw/arm/realview.c | 4 +
hw/arm/sabrelite.c | 1 +
hw/arm/sbsa-ref.c | 1 +
hw/arm/stellaris.c | 2 +
hw/arm/stm32vldiscovery.c | 19 +-
hw/arm/versatilepb.c | 2 +
hw/arm/vexpress.c | 2 +
hw/arm/virt-acpi-build.c | 4 +-
hw/arm/virt.c | 13 +-
hw/arm/xen-pvh.c | 1 +
hw/arm/xilinx_zynq.c | 1 +
hw/arm/xlnx-versal-virt.c | 2 +
hw/arm/xlnx-zcu102.c | 1 +
hw/block/dataplane/meson.build | 2 +-
hw/core/Kconfig | 2 +-
hw/core/cpu-system.c | 23 +
hw/core/machine-qmp-cmds.c | 57 +
hw/core/meson.build | 2 +-
hw/dma/Kconfig | 4 +-
hw/hexagon/hexagon_dsp.c | 1 -
hw/i2c/Kconfig | 2 +-
hw/i386/acpi-common.c | 1 +
hw/i386/sgx.c | 1 +
hw/i386/vmport.c | 1 +
hw/i386/x86.c | 2 +
hw/intc/arm_gic_kvm.c | 1 +
hw/intc/arm_gicv3_its_kvm.c | 1 +
hw/intc/arm_gicv3_kvm.c | 1 +
hw/intc/meson.build | 16 +-
hw/intc/riscv_aplic.c | 14 +-
hw/intc/riscv_imsic.c | 18 +-
hw/intc/s390_flic.c | 1 +
hw/intc/s390_flic_kvm.c | 1 +
hw/loongarch/virt-acpi-build.c | 6 +-
hw/loongarch/virt.c | 2 +-
hw/microblaze/petalogix_ml605_mmu.c | 19 +-
hw/microblaze/petalogix_s3adsp1800_mmu.c | 1 +
hw/microblaze/xlnx-zynqmp-pmu.c | 19 +-
hw/misc/meson.build | 4 +-
hw/misc/riscv_cmgcr.c | 2 +-
hw/remote/machine.c | 3 +
hw/remote/meson.build | 4 +-
hw/riscv/boston-aia.c | 4 +-
hw/riscv/k230.c | 5 +-
hw/riscv/microblaze-v-generic.c | 19 +-
hw/riscv/microchip_pfsoc.c | 5 +-
hw/riscv/opentitan.c | 5 +-
hw/riscv/shakti_c.c | 5 +-
hw/riscv/sifive_e.c | 1 +
hw/riscv/sifive_u.c | 1 +
hw/riscv/spike.c | 1 +
hw/riscv/tt_atlantis.c | 5 +-
hw/riscv/virt-acpi-build.c | 2 +-
hw/riscv/virt.c | 7 +-
hw/riscv/xiangshan_kmh.c | 5 +-
hw/s390x/css.c | 1 +
hw/s390x/s390-pci-bus.c | 1 +
hw/s390x/s390-pci-inst.c | 1 +
hw/s390x/virtio-ccw.c | 1 +
hw/timer/meson.build | 2 +-
hw/usb/Kconfig | 2 +-
include/accel/accel-cpu-target.h | 31 -
include/accel/accel-cpu.h | 13 +
include/accel/tcg/cpu-ldst.h | 4 +-
include/exec/abi_ptr.h | 7 +-
include/exec/helper-head.h.inc | 21 +-
include/exec/poison.h | 2 +
include/exec/target_long.h | 13 +
include/gdbstub/helpers.h | 3 -
include/hw/arm/virt.h | 4 +-
include/hw/core/boards.h | 10 +-
include/hw/i386/apic.h | 3 +
include/hw/loongarch/virt.h | 2 +-
include/hw/riscv/virt.h | 4 +-
include/migration/cpu.h | 30 -
include/migration/vmstate.h | 125 ++
include/qemu/base-arch-defs.h | 9 +
include/qemu/config-file.h | 2 +
include/qemu/module.h | 41 +-
include/qemu/queue.h | 10 +
include/qemu/target-info-def.h | 90 ++
include/qemu/target-info-impl.h | 42 -
include/qemu/target-info-init.h | 53 -
include/qemu/target-info-qom.h | 30 -
include/qemu/target-info-select.h | 24 +
include/qemu/target-info.h | 214 +++-
include/qemu/target-kconfig-has.h | 7 +
include/qemu/target-kconfig.h | 34 +
include/qemu/target-ops.h | 58 +
include/qom/object.h | 27 +-
include/semihosting/common-semi.h | 63 +-
include/system/kvm.h | 23 +-
include/system/kvm_int.h | 2 -
include/tcg/tcg-op-common.h | 2 +
include/tcg/tcg-op-gvec-common.h | 12 +
include/tcg/tcg-op-gvec.h | 12 -
include/tcg/tcg-op-mem.h | 96 +-
include/tcg/tcg-op-tl.h | 1133 +++++++++++++++++
include/tcg/tcg-op.h | 293 +----
include/tcg/tcg.h | 42 +-
meson.build | 221 +++-
migration/savevm.c | 4 +
migration/trace-events | 1 +
migration/vmstate-types.c | 86 ++
migration/vmstate.c | 135 +-
page-vary-common.c | 2 +-
page-vary-system.c | 2 +-
qapi/machine.json | 48 +-
qemu-options.hx | 11 +-
qom/object.c | 145 ++-
rust/util/src/module.rs | 16 +-
scripts/gen-target-kconfig.py | 162 +++
stubs/dump.c | 27 -
stubs/kvm.c | 4 +
stubs/meson.build | 3 +-
stubs/qmp-cpu.c | 21 -
stubs/target-info-select.c | 14 +
system/arch_init.c | 19 +
system/target-info-select.c | 26 +
system/vl.c | 319 ++++-
target-info-stub.c => target-info-def.c | 20 +-
target-info-qom.c | 55 -
target-info.c | 213 +++-
target-kconfig.c | 20 +
target-ops.c | 50 +
target/alpha/cpu.h | 2 -
target/arm/arch_dump.c | 8 +-
target/arm/arm-qmp-cmds.c | 15 +-
target/arm/common-semi-target.c | 26 +-
target/arm/cpu.c | 6 +-
target/arm/cpu.h | 3 +-
target/arm/cpu64.c | 80 +-
target/arm/hvf/hvf-stub.c | 14 +
target/arm/hvf/meson.build | 1 +
target/arm/kvm-stub.c | 5 +
target/arm/kvm.c | 40 +-
target/arm/kvm_arm.h | 9 +
target/arm/meson.build | 11 +-
target/arm/tcg/translate-a64.c | 6 +-
target/arm/tcg/translate-a64.h | 3 +
target/arm/tcg/translate-sme.c | 5 +-
target/arm/tcg/translate-sve.c | 18 +-
target/arm/whpx/whpx-all.c | 1 -
target/arm/whpx/whpx-stub.c | 5 +
target/avr/cpu.h | 2 -
target/hexagon/common-semi-target.c | 26 +-
target/hexagon/cpu.h | 1 -
target/hppa/cpu.h | 2 -
target/i386/arch_dump.c | 8 +-
target/i386/cpu-qom.h | 1 +
target/i386/cpu-system.c | 12 +-
target/i386/cpu.c | 6 +-
target/i386/cpu.h | 12 +-
target/i386/hvf/hvf-cpu.c | 13 +-
target/i386/kvm/kvm-cpu.c | 12 +-
target/i386/kvm/kvm_i386.h | 2 +
target/i386/kvm/xen-emu.c | 1 +
target/i386/machine.c | 94 +-
target/i386/mshv/mshv-cpu.c | 12 +-
target/i386/nvmm/nvmm-all.c | 28 +-
target/i386/tcg/tcg-cpu.c | 12 +-
target/i386/whpx/whpx-all.c | 1 -
target/loongarch/arch_dump.c | 8 +-
target/loongarch/cpu.h | 2 -
target/loongarch/kvm/kvm.c | 1 +
target/loongarch/kvm/kvm_loongarch.h | 2 +
target/loongarch/loongarch-qmp-cmds.c | 15 +-
target/m68k/cpu.h | 2 -
target/microblaze/cpu.h | 2 -
target/microblaze/meson.build | 2 +-
target/mips/cpu.h | 2 -
target/mips/system/machine.c | 124 +-
target/mips/system/mips-qmp-cmds.c | 15 +-
target/none/cpu-param.h | 6 +
target/none/cpu-qom.h | 6 +
target/or1k/cpu-qom.h | 1 +
target/or1k/cpu.h | 2 -
target/ppc/arch_dump.c | 8 +-
target/ppc/cpu-qom.h | 1 +
target/ppc/cpu.h | 2 -
target/ppc/cpu_init.c | 1 +
target/ppc/kvm.c | 24 +-
target/ppc/machine.c | 78 +-
target/ppc/ppc-qmp-cmds.c | 15 +-
target/riscv/arch_dump.c | 18 +-
target/riscv/common-semi-target.c | 28 +-
target/riscv/cpu.c | 133 +-
target/riscv/cpu.h | 9 +-
target/riscv/helper.h | 6 +-
target/riscv/internals.h | 12 +-
target/riscv/kvm/kvm-cpu.c | 115 +-
target/riscv/kvm/kvm-stub.c | 33 +-
target/riscv/kvm/meson.build | 2 +-
target/riscv/machine.c | 16 +-
target/riscv/meson.build | 18 +-
target/riscv/monitor.c | 41 +-
target/riscv/riscv-qmp-cmds.c | 15 +-
target/riscv/tcg/bitmanip_helper.c | 14 +-
target/riscv/tcg/cpu_helper.c | 53 +-
target/riscv/tcg/crypto_helper.c | 1 +
target/riscv/tcg/csr.c | 20 +-
.../tcg/insn_trans/trans_privileged.c.inc | 2 +-
target/riscv/tcg/insn_trans/trans_rvb.c.inc | 18 +-
target/riscv/tcg/insn_trans/trans_rvd.c.inc | 18 +-
target/riscv/tcg/insn_trans/trans_rvf.c.inc | 11 +-
target/riscv/tcg/insn_trans/trans_rvi.c.inc | 12 +-
target/riscv/tcg/insn_trans/trans_rvm.c.inc | 6 +-
.../riscv/tcg/insn_trans/trans_rvzacas.c.inc | 32 +-
target/riscv/tcg/insn_trans/trans_rvzfh.c.inc | 8 +-
target/riscv/tcg/insn_trans/trans_xlrbr.c.inc | 4 +-
.../riscv/tcg/insn_trans/trans_xthead.c.inc | 2 +-
target/riscv/tcg/m128_helper.c | 3 +-
target/riscv/tcg/meson.build | 8 +-
target/riscv/tcg/op_helper.c | 2 +-
target/riscv/tcg/pmp.c | 5 +-
target/riscv/tcg/tcg-cpu.c | 13 +-
target/riscv/tcg/translate.c | 123 +-
target/riscv/tcg/vector_helper.c | 21 +-
target/riscv/tcg/vector_internals.c | 2 +-
target/riscv/tcg/vector_internals.h | 9 +-
target/rx/cpu.h | 2 -
target/s390x/arch_dump.c | 8 +-
target/s390x/cpu-qom.h | 1 +
target/s390x/cpu.h | 3 -
target/s390x/cpu_models_system.c | 15 +-
target/sh4/cpu-qom.h | 1 +
target/sh4/cpu.h | 2 -
target/sparc/cpu.h | 2 -
target/sparc/machine.c | 24 +-
target/tricore/cpu.h | 2 -
target/xtensa/cpu.h | 2 -
tcg/tcg.c | 42 +-
tests/qtest/accel-cpu-qom-test.c | 82 ++
tests/qtest/fuzz/fuzz.c | 3 -
tests/qtest/machine-list-combined-test.c | 111 ++
tests/qtest/machine-list-test.c | 94 ++
tests/qtest/machine-list-test.inc.h | 876 +++++++++++++
tests/qtest/machine-option-test.c | 714 +++++++++++
tests/qtest/meson.build | 31 +-
tests/unit/check-qom-interface.c | 12 +-
tests/unit/check-qom-proplist.c | 13 +-
tests/unit/meson.build | 13 +
tests/unit/test-io-channel-websock.c | 7 +-
tests/unit/test-io-task.c | 7 +-
tests/unit/test-module-init.c | 186 +++
tests/unit/test-qdev-global-props.c | 14 +-
tests/unit/test-qdev.c | 8 +-
tests/unit/test-qom-is-available.c | 250 ++++
tests/unit/test-ram-discard-manager.c | 7 +-
tests/unit/test-target-info.c | 38 +
tests/unit/test-target-kconfig-has.c | 22 +
tests/unit/test-vmstate.c | 377 +++++-
ui/console-vc.c | 13 +-
ui/dbus.c | 8 +-
ui/gtk.c | 10 +-
ui/spice-app.c | 7 +-
util/module.c | 171 ++-
util/qemu-config.c | 10 +-
338 files changed, 8224 insertions(+), 1876 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
delete mode 100644 include/accel/accel-cpu-target.h
delete mode 100644 include/migration/cpu.h
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 include/qemu/target-info-select.h
create mode 100644 include/qemu/target-kconfig-has.h
create mode 100644 include/qemu/target-kconfig.h
create mode 100644 include/qemu/target-ops.h
create mode 100644 include/tcg/tcg-op-tl.h
create mode 100644 scripts/gen-target-kconfig.py
delete mode 100644 stubs/dump.c
delete mode 100644 stubs/qmp-cpu.c
create mode 100644 stubs/target-info-select.c
create mode 100644 system/target-info-select.c
rename target-info-stub.c => target-info-def.c (71%)
delete mode 100644 target-info-qom.c
create mode 100644 target-kconfig.c
create mode 100644 target-ops.c
create mode 100644 target/arm/hvf/hvf-stub.c
create mode 100644 target/none/cpu-param.h
create mode 100644 target/none/cpu-qom.h
create mode 100644 tests/qtest/accel-cpu-qom-test.c
create mode 100644 tests/qtest/machine-list-combined-test.c
create mode 100644 tests/qtest/machine-list-test.c
create mode 100644 tests/qtest/machine-list-test.inc.h
create mode 100644 tests/qtest/machine-option-test.c
create mode 100644 tests/unit/test-module-init.c
create mode 100644 tests/unit/test-qom-is-available.c
create mode 100644 tests/unit/test-target-info.c
create mode 100644 tests/unit/test-target-kconfig-has.c
--
2.52.0.windows.1
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH v3 001/114] meson: stale qemu-version.h only when .git exists
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 002/114] configs/targets: remove target info definitions Yonggang Luo
` (40 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
build_always_stale for qemu-version.h is fs.exists on the source
.git. Matches qemu-version.sh, so a tree without git does not
regenerate the header on every ninja.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meson.build b/meson.build
index cfac634cf13..f17665c667d 100644
--- a/meson.build
+++ b/meson.build
@@ -3546,7 +3546,7 @@ qemu_version = custom_target('qemu-version.h',
command: qemu_version_cmd,
capture: true,
build_by_default: true,
- build_always_stale: true)
+ build_always_stale: fs.exists(meson.current_source_dir() / '.git'))
genh += qemu_version
hxdep = []
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 002/114] configs/targets: remove target info definitions
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 001/114] meson: stale qemu-version.h only when .git exists Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 003/114] target-info: rename target-info-stub.c in target-info-def.c Yonggang Luo
` (39 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
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>
---
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 +------
6 files changed, 1 insertion(+), 110 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/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 f17665c667d..f412d917d94 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')
@@ -4331,11 +4330,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.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 003/114] target-info: rename target-info-stub.c in target-info-def.c
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 001/114] meson: stale qemu-version.h only when .git exists Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 002/114] configs/targets: remove target info definitions Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 004/114] target-info: rename target-info-impl.h to target-info-def.h Yonggang Luo
` (38 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
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>
---
meson.build | 2 +-
target-info-stub.c => target-info-def.c | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename target-info-stub.c => target-info-def.c (100%)
diff --git a/meson.build b/meson.build
index f412d917d94..8bd2d725ca0 100644
--- a/meson.build
+++ b/meson.build
@@ -4330,7 +4330,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.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 004/114] target-info: rename target-info-impl.h to target-info-def.h
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (2 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 003/114] target-info: rename target-info-stub.c in target-info-def.c Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 005/114] target-info: set cpu_type from TARGET_BASE_ARCH Yonggang Luo
` (37 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
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 91be415ed33..0f6772e65c3 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 6965e4d1169..2b38673a3f8 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 bba4503151a..9abe72b1f55 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.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 005/114] target-info: set cpu_type from TARGET_BASE_ARCH
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (3 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 004/114] target-info: rename target-info-impl.h to target-info-def.h Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 006/114] target: remove CPU_RESOLVING_TYPE Yonggang Luo
` (36 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
target-info-def.c no longer includes cpu.h, so CPU_RESOLVING_TYPE
is unavailable. Emit TARGET_BASE_ARCH as an uppercase identifier in
config-target.h and set cpu_type to TYPE_${TARGET_BASE_ARCH}_CPU.
Alias the base-arch tokens whose QOM name differs: TYPE_I386_CPU,
TYPE_OR1K_CPU, TYPE_PPC_CPU, TYPE_S390X_CPU, and TYPE_SH4_CPU.
Drop the ArchCPU parent_obj and env offsetof checks with the cpu.h
include. Page-size checks stay, via cpu-param.h.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
include/qemu/target-info-def.h | 2 +-
meson.build | 1 +
target-info-def.c | 11 +++--------
target/i386/cpu-qom.h | 1 +
target/or1k/cpu-qom.h | 1 +
target/ppc/cpu-qom.h | 1 +
target/s390x/cpu-qom.h | 1 +
target/sh4/cpu-qom.h | 1 +
8 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/include/qemu/target-info-def.h b/include/qemu/target-info-def.h
index 8019d2c7196..ebd88463aea 100644
--- a/include/qemu/target-info-def.h
+++ b/include/qemu/target-info-def.h
@@ -19,7 +19,7 @@ typedef struct TargetInfo {
SysEmuTarget target_arch;
/* runtime equivalent of TARGET_LONG_BITS definition */
unsigned long_bits;
- /* runtime equivalent of CPU_RESOLVING_TYPE definition */
+ /* runtime equivalent of TYPE_${TARGET_BASE_ARCH}_CPU definition */
const char *cpu_type;
/* related to TARGET_BIG_ENDIAN definition */
EndianMode endianness;
diff --git a/meson.build b/meson.build
index 8bd2d725ca0..20345860c9f 100644
--- a/meson.build
+++ b/meson.build
@@ -3378,6 +3378,7 @@ foreach target : target_dirs
# Note that TARGET_BASE_ARCH ends up in config-target.h but it is
# not used to select files from sourcesets.
config_target_data.set('TARGET_' + v.to_upper(), 1)
+ config_target_data.set(k, v.to_upper())
elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
config_target_data.set_quoted(k, v)
elif v == 'y'
diff --git a/target-info-def.c b/target-info-def.c
index fa19cabc55f..f167f5f2ac1 100644
--- a/target-info-def.c
+++ b/target-info-def.c
@@ -10,15 +10,10 @@
#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"
+#include "cpu-qom.h"
+#include "cpu-param.h"
#include "exec/page-vary.h"
-/* Validate correct placement of CPUArchState. */
-QEMU_BUILD_BUG_ON(offsetof(ArchCPU, parent_obj) != 0);
-QEMU_BUILD_BUG_ON(offsetof(ArchCPU, env) != sizeof(CPUState));
-
/* Validate target page size, if invariant. */
#ifndef TARGET_PAGE_BITS_VARY
QEMU_BUILD_BUG_ON(TARGET_PAGE_BITS < TARGET_PAGE_BITS_MIN);
@@ -28,7 +23,7 @@ static const TargetInfo target_info_stub = {
.target_name = TARGET_NAME,
.target_arch = glue(SYS_EMU_TARGET_, TARGET_ARCH),
.long_bits = TARGET_LONG_BITS,
- .cpu_type = CPU_RESOLVING_TYPE,
+ .cpu_type = glue(TYPE_, glue(TARGET_BASE_ARCH, _CPU)),
.endianness = TARGET_BIG_ENDIAN ? ENDIAN_MODE_BIG : ENDIAN_MODE_LITTLE,
#ifdef TARGET_PAGE_BITS_VARY
.page_bits_vary = true,
diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
index d4e216d000c..7619c4a4826 100644
--- a/target/i386/cpu-qom.h
+++ b/target/i386/cpu-qom.h
@@ -27,6 +27,7 @@
#else
#define TYPE_X86_CPU "i386-cpu"
#endif
+#define TYPE_I386_CPU TYPE_X86_CPU
OBJECT_DECLARE_CPU_TYPE(X86CPU, X86CPUClass, X86_CPU)
diff --git a/target/or1k/cpu-qom.h b/target/or1k/cpu-qom.h
index 14bac33312e..c0d5e9e81ba 100644
--- a/target/or1k/cpu-qom.h
+++ b/target/or1k/cpu-qom.h
@@ -12,6 +12,7 @@
#include "hw/core/cpu.h"
#define TYPE_OPENRISC_CPU "or1k-cpu"
+#define TYPE_OR1K_CPU TYPE_OPENRISC_CPU
OBJECT_DECLARE_CPU_TYPE(OpenRISCCPU, OpenRISCCPUClass, OPENRISC_CPU)
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 8247fa23367..428cdc85488 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -28,6 +28,7 @@
#else
#define TYPE_POWERPC_CPU "powerpc-cpu"
#endif
+#define TYPE_PPC_CPU TYPE_POWERPC_CPU
OBJECT_DECLARE_CPU_TYPE(PowerPCCPU, PowerPCCPUClass, POWERPC_CPU)
diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h
index c59bb1eab15..07a8c881fe5 100644
--- a/target/s390x/cpu-qom.h
+++ b/target/s390x/cpu-qom.h
@@ -23,6 +23,7 @@
#include "hw/core/cpu.h"
#define TYPE_S390_CPU "s390x-cpu"
+#define TYPE_S390X_CPU TYPE_S390_CPU
OBJECT_DECLARE_CPU_TYPE(S390CPU, S390CPUClass, S390_CPU)
diff --git a/target/sh4/cpu-qom.h b/target/sh4/cpu-qom.h
index 6cf5fbb0745..08fa92106e9 100644
--- a/target/sh4/cpu-qom.h
+++ b/target/sh4/cpu-qom.h
@@ -23,6 +23,7 @@
#include "hw/core/cpu.h"
#define TYPE_SUPERH_CPU "superh-cpu"
+#define TYPE_SH4_CPU TYPE_SUPERH_CPU
#define TYPE_SH7750R_CPU SUPERH_CPU_TYPE_NAME("sh7750r")
#define TYPE_SH7751R_CPU SUPERH_CPU_TYPE_NAME("sh7751r")
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 006/114] target: remove CPU_RESOLVING_TYPE
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (4 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 005/114] target-info: set cpu_type from TARGET_BASE_ARCH Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 007/114] vl: parse early options before target-info init Yonggang Luo
` (35 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
cpu_type is TYPE_${TARGET_BASE_ARCH}_CPU, so the per-target
CPU_RESOLVING_TYPE macros are unused. Drop them from every
target cpu.h.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/alpha/cpu.h | 2 --
target/arm/cpu.h | 2 --
target/avr/cpu.h | 2 --
target/hexagon/cpu.h | 1 -
target/hppa/cpu.h | 2 --
target/i386/cpu.h | 2 --
target/loongarch/cpu.h | 2 --
target/m68k/cpu.h | 2 --
target/microblaze/cpu.h | 2 --
target/mips/cpu.h | 2 --
target/or1k/cpu.h | 2 --
target/ppc/cpu.h | 2 --
target/riscv/cpu.h | 2 --
target/rx/cpu.h | 2 --
target/s390x/cpu.h | 3 ---
target/sh4/cpu.h | 2 --
target/sparc/cpu.h | 2 --
target/tricore/cpu.h | 2 --
target/xtensa/cpu.h | 2 --
19 files changed, 38 deletions(-)
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 378bd96d941..a6ffe7eec29 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -433,8 +433,6 @@ void alpha_translate_init(void);
void alpha_translate_code(CPUState *cs, TranslationBlock *tb,
int *max_insns, vaddr pc, void *host_pc);
-#define CPU_RESOLVING_TYPE TYPE_ALPHA_CPU
-
G_NORETURN void dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
G_NORETURN void arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index e3f931dba26..359d86e2c37 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2395,8 +2395,6 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
#define ARM_CPUID_TI915T 0x54029152
#define ARM_CPUID_TI925T 0x54029252
-#define CPU_RESOLVING_TYPE TYPE_ARM_CPU
-
#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
/* Indexes used when registering address spaces with cpu_address_space_init */
diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index 1e4e839bd83..747655543d4 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -30,8 +30,6 @@
#error "AVR 8-bit does not support user mode"
#endif
-#define CPU_RESOLVING_TYPE TYPE_AVR_CPU
-
/*
* AVR has two memory spaces, data & code.
* e.g. both have 0 address
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index e79d8000304..54b0d69a827 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -52,7 +52,6 @@ typedef struct HexagonGlobalRegState HexagonGlobalRegState;
#define MAX_TLB_ENTRIES 1024
#define THREADS_MAX 16
-#define CPU_RESOLVING_TYPE TYPE_HEXAGON_CPU
#ifndef CONFIG_USER_ONLY
#define CPU_INTERRUPT_SWI CPU_INTERRUPT_TGT_INT_0
#define CPU_INTERRUPT_K0_UNLOCK CPU_INTERRUPT_TGT_INT_1
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index f453444d7f9..35b6b8af82a 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -339,8 +339,6 @@ void hppa_translate_init(void);
void hppa_translate_code(CPUState *cs, TranslationBlock *tb,
int *max_insns, vaddr pc, void *host_pc);
-#define CPU_RESOLVING_TYPE TYPE_HPPA_CPU
-
static inline vaddr hppa_form_gva_mask(uint64_t gva_offset_mask,
uint64_t spc, target_ulong off)
{
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 786957fadd0..eba184035d4 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2813,8 +2813,6 @@ void cpu_x86_update_dr7(CPUX86State *env, uint32_t new_dr7);
/* hw/pc.c */
uint64_t cpu_get_tsc(CPUX86State *env);
-#define CPU_RESOLVING_TYPE TYPE_X86_CPU
-
#ifdef TARGET_X86_64
#define TARGET_DEFAULT_CPU_TYPE X86_CPU_TYPE_NAME("qemu64")
#else
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index c592f698853..5d79ea836bf 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -553,6 +553,4 @@ static inline void set_pc(CPULoongArchState *env, uint64_t value)
#define HW_FLAGS_VA32 0x20
#define HW_FLAGS_EUEN_ASXE 0x40
-#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
-
#endif /* LOONGARCH_CPU_H */
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 7cf3791108c..b3962910ad1 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -579,8 +579,6 @@ enum {
ACCESS_DATA = 0x20, /* Data load/store access */
};
-#define CPU_RESOLVING_TYPE TYPE_M68K_CPU
-
/* MMU modes definitions */
#define MMU_KERNEL_IDX 0
#define MMU_USER_IDX 1
diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index b9602f72b94..00ceaf1acf7 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -401,8 +401,6 @@ void mb_tcg_init(void);
void mb_translate_code(CPUState *cs, TranslationBlock *tb,
int *max_insns, vaddr pc, void *host_pc);
-#define CPU_RESOLVING_TYPE TYPE_MICROBLAZE_CPU
-
/* MMU modes definitions */
#define MMU_NOMMU_IDX 0
#define MMU_KERNEL_IDX 1
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 32549791a18..0d2846eaf58 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1359,8 +1359,6 @@ enum {
*/
#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0
-#define CPU_RESOLVING_TYPE TYPE_MIPS_CPU
-
bool cpu_type_supports_cps_smp(const char *cpu_type);
bool cpu_supports_isa(const CPUMIPSState *env, uint64_t isa_mask);
bool cpu_type_supports_isa(const char *cpu_type, uint64_t isa);
diff --git a/target/or1k/cpu.h b/target/or1k/cpu.h
index fc4387ce7ae..34586755baf 100644
--- a/target/or1k/cpu.h
+++ b/target/or1k/cpu.h
@@ -320,8 +320,6 @@ void cpu_openrisc_count_start(OpenRISCCPU *cpu);
void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
#endif
-#define CPU_RESOLVING_TYPE TYPE_OPENRISC_CPU
-
#define TB_FLAGS_SM SR_SM
#define TB_FLAGS_DME SR_DME
#define TB_FLAGS_IME SR_IME
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 217b4f334e5..c11d64677df 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -29,8 +29,6 @@
#include "qom/object.h"
#include "hw/core/registerfields.h"
-#define CPU_RESOLVING_TYPE TYPE_POWERPC_CPU
-
#define TARGET_PAGE_BITS_64K 16
#define TARGET_PAGE_BITS_16M 24
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a97f30793b9..034d7e96c49 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -36,8 +36,6 @@
typedef struct CPUArchState CPURISCVState;
-#define CPU_RESOLVING_TYPE TYPE_RISCV_CPU
-
/*
* b0: Whether a instruction always raise a store AMO or not.
*/
diff --git a/target/rx/cpu.h b/target/rx/cpu.h
index 233615c32dc..49188c36c57 100644
--- a/target/rx/cpu.h
+++ b/target/rx/cpu.h
@@ -144,8 +144,6 @@ struct RXCPUClass {
ResettablePhases parent_phases;
};
-#define CPU_RESOLVING_TYPE TYPE_RX_CPU
-
const char *rx_crname(uint8_t cr);
void rx_cpu_do_interrupt(CPUState *cpu);
bool rx_cpu_exec_interrupt(CPUState *cpu, int int_req);
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 998bbb0d7ff..c77b297a26a 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -860,9 +860,6 @@ static inline uint8_t s390_cpu_get_state(const S390CPU *cpu)
}
-/* helper.c */
-#define CPU_RESOLVING_TYPE TYPE_S390_CPU
-
/* interrupt.c */
#define RA_IGNORED 0
void s390_program_interrupt(CPUS390XState *env, uint32_t code, uintptr_t ra);
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index d440aa6dbe7..eaf67fe8e6a 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -304,8 +304,6 @@ int cpu_sh4_is_cached(CPUSH4State *env, uint32_t addr);
void cpu_load_tlb(CPUSH4State * env);
-#define CPU_RESOLVING_TYPE TYPE_SUPERH_CPU
-
/* MMU modes definitions */
#define MMU_USER_IDX 1
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 31a16c2af03..fd409e74948 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -663,8 +663,6 @@ hwaddr cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
#endif
#endif
-#define CPU_RESOLVING_TYPE TYPE_SPARC_CPU
-
/* MMU modes definitions */
#if defined (TARGET_SPARC64)
#define MMU_USER_IDX 0
diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
index 12e497d2a7a..346b0e1f3f3 100644
--- a/target/tricore/cpu.h
+++ b/target/tricore/cpu.h
@@ -257,8 +257,6 @@ void tricore_tcg_init(void);
void tricore_translate_code(CPUState *cs, TranslationBlock *tb,
int *max_insns, vaddr pc, void *host_pc);
-#define CPU_RESOLVING_TYPE TYPE_TRICORE_CPU
-
/* helpers.c */
bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 0b2cb5a250d..ee8d9c10b16 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -603,8 +603,6 @@ G_NORETURN void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
uintptr_t retaddr);
G_NORETURN void xtensa_exception(CPUXtensaState *env, uint32_t excp);
-#define CPU_RESOLVING_TYPE TYPE_XTENSA_CPU
-
#if TARGET_BIG_ENDIAN
#define XTENSA_DEFAULT_CPU_MODEL "fsf"
#define XTENSA_DEFAULT_CPU_NOMMU_MODEL "fsf"
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 007/114] vl: parse early options before target-info init
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (5 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 006/114] target: remove CPU_RESOLVING_TYPE Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 008/114] target-info: replace QOM registration with a constructor list Yonggang Luo
` (34 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Move the first argv pass ahead of MODULE_INIT_TARGET_INFO so later
target-info selection can use command-line options before QOM init.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
system/vl.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/system/vl.c b/system/vl.c
index 0d52c5d0a46..dc883de8274 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -2910,16 +2910,6 @@ void qemu_init(int argc, char **argv)
error_init(argv[0]);
qemu_init_exec_dir(argv[0]);
- 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());
-
- qemu_init_subsystems();
-
/* first pass of option parsing */
optind = 1;
while (optind < argc) {
@@ -2938,6 +2928,16 @@ 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());
+
+ qemu_init_subsystems();
+
machine_opts_dict = qdict_new();
if (userconfig) {
qemu_read_default_config_file(&error_fatal);
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 008/114] target-info: replace QOM registration with a constructor list
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (6 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 007/114] vl: parse early options before target-info init Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 009/114] tests/unit: add test-target-info Yonggang Luo
` (33 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Replace MODULE_INIT_TARGET_INFO and target_info_qom_set_target with a
constructor list. target_info_init builds a TargetInfoNode;
target_info_list_add inserts it, sorted by target_arch, before main().
target_info() starts as an "unknown" TargetInfo and target_info_select
sets the current entry. target-info.c moves into libqom.
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 | 30 ------------------
include/qemu/target-info.h | 11 +++++++
meson.build | 6 ++--
system/vl.c | 4 ---
target-info-def.c | 1 -
target-info-qom.c | 55 --------------------------------
target-info.c | 56 ++++++++++++++++++++++++++++++++-
tests/qtest/fuzz/fuzz.c | 3 --
11 files changed, 120 insertions(+), 156 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 ebd88463aea..25dc7c508d3 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 0f6772e65c3..00000000000
--- a/include/qemu/target-info-qom.h
+++ /dev/null
@@ -1,30 +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);
-
-#endif /* QEMU_TARGET_INFO_QOM_H */
diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
index c09e5d2a3ec..c48973f20be 100644
--- a/include/qemu/target-info.h
+++ b/include/qemu/target-info.h
@@ -9,6 +9,17 @@
#ifndef QEMU_TARGET_INFO_H
#define QEMU_TARGET_INFO_H
+#include <stdbool.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 20345860c9f..9a6a80fd0c8 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()],
@@ -3871,9 +3874,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 dc883de8274..37cb4838188 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"
@@ -2930,9 +2929,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 f167f5f2ac1..954298b56d0 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 "cpu-qom.h"
#include "cpu-param.h"
#include "exec/page-vary.h"
diff --git a/target-info-qom.c b/target-info-qom.c
deleted file mode 100644
index 2b38673a3f8..00000000000
--- a/target-info-qom.c
+++ /dev/null
@@ -1,55 +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;
-}
diff --git a/target-info.c b/target-info.c
index 9abe72b1f55..6e66f48e1ff 100644
--- a/target-info.c
+++ b/target-info.c
@@ -10,7 +10,61 @@
#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"
+
+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);
+ }
+ }
+
+ /* Single-target default: the first list entry. */
+ 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);
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 009/114] tests/unit: add test-target-info
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (7 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 008/114] target-info: replace QOM registration with a constructor list Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 010/114] tests/qtest: prepare machine-list-test for combined qemu-system Yonggang Luo
` (32 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Collect each target-info-def.c object in target_info_def_objects,
keyed by target dir. Link every value so constructors fill the
list. Assert target_info() is not NULL and target_info_list() has
one entry per linked object.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
meson.build | 6 +++++-
tests/unit/meson.build | 4 ++++
tests/unit/test-target-info.c | 38 +++++++++++++++++++++++++++++++++++
3 files changed, 47 insertions(+), 1 deletion(-)
create mode 100644 tests/unit/test-target-info.c
diff --git a/meson.build b/meson.build
index 9a6a80fd0c8..776d38c5afd 100644
--- a/meson.build
+++ b/meson.build
@@ -4260,6 +4260,8 @@ endif
traceable = []
emulators = {}
+target_info_def = files('target-info-def.c')
+target_info_def_objects = {}
foreach target : target_dirs
config_target = config_target_mak[target]
target_name = config_target['TARGET_NAME']
@@ -4331,7 +4333,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)
@@ -4409,6 +4411,8 @@ foreach target : target_dirs
c_args: c_args,
build_by_default: false)
+ target_info_def_objects += {target: lib.extract_objects(target_info_def)}
+
if target.endswith('-softmmu')
execs = [{
'name': 'qemu-system-' + target_name,
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index e47bc7225ab..dc980a35955 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: target_info_def_objects.values(),
+ compile_args: ['-DTARGET_INFO_DEF_COUNT=@0@'.format(
+ target_info_def_objects.values().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.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 010/114] tests/qtest: prepare machine-list-test for combined qemu-system
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (8 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 009/114] tests/unit: add test-target-info Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 011/114] kconfig: rename REGISTER to HW_REGISTER Yonggang Luo
` (31 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Each built qemu-system target checks its query-target arch and
query-machines names, including the none machine and omitting the
abstract pegasos parent. xen, vmapple, nitro, and x-remote appear
only when that host build has them. The lists in
machine-list-test.inc.h are shared for a later combined
qemu-system test.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
tests/qtest/machine-list-test.c | 94 +++
tests/qtest/machine-list-test.inc.h | 876 ++++++++++++++++++++++++++++
tests/qtest/meson.build | 1 +
3 files changed, 971 insertions(+)
create mode 100644 tests/qtest/machine-list-test.c
create mode 100644 tests/qtest/machine-list-test.inc.h
diff --git a/tests/qtest/machine-list-test.c b/tests/qtest/machine-list-test.c
new file mode 100644
index 00000000000..35fb365197d
--- /dev/null
+++ b/tests/qtest/machine-list-test.c
@@ -0,0 +1,94 @@
+/*
+ * Per-target machine list tests.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+
+#include "libqtest.h"
+#include "qobject/qdict.h"
+#include "qobject/qlist.h"
+#include "qobject/qstring.h"
+
+/* query-target "arch" is SysEmuTarget, not always TARGET_NAME. */
+static const char *query_arch_for_target(const char *target_info)
+{
+ static const struct {
+ const char *target_name;
+ const char *arch;
+ } map[] = {
+ { "armeb", "arm" },
+ { "microblazeel", "microblaze" },
+ { "mips64el", "mips64" },
+ { "mipsel", "mips" },
+ { "ppc64le", "ppc64" },
+ { "sh4eb", "sh4" },
+ { "xtensaeb", "xtensa" },
+ };
+ size_t i;
+
+ for (i = 0; i < G_N_ELEMENTS(map); i++) {
+ if (!strcmp(target_info, map[i].target_name)) {
+ return map[i].arch;
+ }
+ }
+ return target_info;
+}
+
+#include "machine-list-test.inc.h"
+
+static QList *query_machine_names(QTestState *qts)
+{
+ QDict *resp;
+ QList *machines;
+ QList *names;
+ const QListEntry *e;
+
+ resp = qtest_qmp(qts, "{'execute': 'query-machines'}");
+ g_assert(qdict_haskey(resp, "return"));
+ machines = qdict_get_qlist(resp, "return");
+ g_assert_nonnull(machines);
+ names = qlist_new();
+ for (e = qlist_first(machines); e; e = qlist_next(e)) {
+ QDict *m = qobject_to(QDict, qlist_entry_obj(e));
+ const char *name;
+
+ g_assert_nonnull(m);
+ name = qdict_get_str(m, "name");
+ qlist_append_str(names, name);
+ }
+ qobject_unref(resp);
+ return names;
+}
+
+static void test_historic_machine_list(void)
+{
+ const char *target = qtest_get_arch();
+ const struct ShippedTarget *t = lookup_shipped_target(target);
+ QTestState *qts;
+ QDict *resp;
+ QDict *ret;
+ g_autoptr(QList) names = NULL;
+
+ qts = qtest_init("-nodefaults -M none");
+ read_accel_flags(qts);
+ resp = qtest_qmp(qts, "{'execute': 'query-target'}");
+ g_assert(qdict_haskey(resp, "return"));
+ ret = qdict_get_qdict(resp, "return");
+ g_assert_cmpstr(qdict_get_str(ret, "arch"), ==,
+ query_arch_for_target(target));
+ qobject_unref(resp);
+ names = query_machine_names(qts);
+ if (t) {
+ assert_name_list(names, t->name, t->machines, t->n_machines);
+ }
+ qtest_quit(qts);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("machine-list", test_historic_machine_list);
+ return g_test_run();
+}
diff --git a/tests/qtest/machine-list-test.inc.h b/tests/qtest/machine-list-test.inc.h
new file mode 100644
index 00000000000..e6e6f3ea7cd
--- /dev/null
+++ b/tests/qtest/machine-list-test.inc.h
@@ -0,0 +1,876 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* Normal machine lists for every softmmu target. */
+/* Xen, vmapple, nitro, and x-remote stay in special_machine_map. */
+
+static const char * const aarch64_machines[] = {
+ "amd-versal-virt",
+ "amd-versal2-virt",
+ "anacapa-bmc",
+ "ast1030-evb",
+ "ast1040-evb",
+ "ast1060-evb",
+ "ast2500-evb",
+ "ast2600-evb",
+ "ast2700a1-evb",
+ "ast2700a2-evb",
+ "ast2700fc",
+ "axiado-scm3003",
+ "b-l475e-iot01a",
+ "bletchley-bmc",
+ "bpim2u",
+ "canon-a1100",
+ "catalina-bmc",
+ "collie",
+ "cubieboard",
+ "emcraft-sf2",
+ "fby35-bmc",
+ "fuji-bmc",
+ "g220a-bmc",
+ "gb200nvl-bmc",
+ "imx25-pdk",
+ "imx8mm-evk",
+ "imx8mp-evk",
+ "integratorcp",
+ "kudo-bmc",
+ "kzm",
+ "lm3s6965evb",
+ "lm3s811evb",
+ "max78000fthr",
+ "mcimx6ul-evk",
+ "mcimx7d-sabre",
+ "microbit",
+ "mori-bmc",
+ "mps2-an385",
+ "mps2-an386",
+ "mps2-an500",
+ "mps2-an505",
+ "mps2-an511",
+ "mps2-an521",
+ "mps3-an524",
+ "mps3-an536",
+ "mps3-an547",
+ "mps3-an555",
+ "musca-a",
+ "musca-b1",
+ "netduino2",
+ "netduinoplus2",
+ "none",
+ "npcm750-evb",
+ "npcm845-evb",
+ "nuri",
+ "olimex-stm32-h405",
+ "orangepi-pc",
+ "palmetto-bmc",
+ "quanta-gbs-bmc",
+ "quanta-gsj",
+ "quanta-q71l-bmc",
+ "rainier-bmc",
+ "raspi0",
+ "raspi1ap",
+ "raspi2b",
+ "raspi3ap",
+ "raspi3b",
+ "raspi4b",
+ "realview-eb",
+ "realview-eb-mpcore",
+ "realview-pb-a8",
+ "realview-pbx-a9",
+ "romulus-bmc",
+ "sabrelite",
+ "sanmiguel-bmc",
+ "sbsa-ref",
+ "smdkc210",
+ "stm32vldiscovery",
+ "supermicro-x11spi-bmc",
+ "supermicrox11-bmc",
+ "sx1",
+ "sx1-v1",
+ "tiogapass-bmc",
+ "versatileab",
+ "versatilepb",
+ "vexpress-a15",
+ "vexpress-a9",
+ "virt-10.0",
+ "virt-10.1",
+ "virt-10.2",
+ "virt-11.0",
+ "virt-11.1",
+ "virt-11.2",
+ "virt-6.0",
+ "virt-6.1",
+ "virt-6.2",
+ "virt-7.0",
+ "virt-7.1",
+ "virt-7.2",
+ "virt-8.0",
+ "virt-8.1",
+ "virt-8.2",
+ "virt-9.0",
+ "virt-9.1",
+ "virt-9.2",
+ "witherspoon-bmc",
+ "xilinx-zynq-a9",
+ "xlnx-zcu102",
+ "yosemitev2-bmc",
+};
+
+static const char * const alpha_machines[] = {
+ "clipper",
+ "none",
+};
+
+static const char * const arm_machines[] = {
+ "anacapa-bmc",
+ "ast1030-evb",
+ "ast1040-evb",
+ "ast1060-evb",
+ "ast2500-evb",
+ "ast2600-evb",
+ "b-l475e-iot01a",
+ "bletchley-bmc",
+ "bpim2u",
+ "canon-a1100",
+ "catalina-bmc",
+ "collie",
+ "cubieboard",
+ "emcraft-sf2",
+ "fby35-bmc",
+ "fuji-bmc",
+ "g220a-bmc",
+ "gb200nvl-bmc",
+ "imx25-pdk",
+ "integratorcp",
+ "kudo-bmc",
+ "kzm",
+ "lm3s6965evb",
+ "lm3s811evb",
+ "max78000fthr",
+ "mcimx6ul-evk",
+ "mcimx7d-sabre",
+ "microbit",
+ "mori-bmc",
+ "mps2-an385",
+ "mps2-an386",
+ "mps2-an500",
+ "mps2-an505",
+ "mps2-an511",
+ "mps2-an521",
+ "mps3-an524",
+ "mps3-an536",
+ "mps3-an547",
+ "mps3-an555",
+ "musca-a",
+ "musca-b1",
+ "netduino2",
+ "netduinoplus2",
+ "none",
+ "npcm750-evb",
+ "nuri",
+ "olimex-stm32-h405",
+ "orangepi-pc",
+ "palmetto-bmc",
+ "quanta-gbs-bmc",
+ "quanta-gsj",
+ "quanta-q71l-bmc",
+ "rainier-bmc",
+ "raspi0",
+ "raspi1ap",
+ "raspi2b",
+ "realview-eb",
+ "realview-eb-mpcore",
+ "realview-pb-a8",
+ "realview-pbx-a9",
+ "romulus-bmc",
+ "sabrelite",
+ "sanmiguel-bmc",
+ "smdkc210",
+ "stm32vldiscovery",
+ "supermicro-x11spi-bmc",
+ "supermicrox11-bmc",
+ "sx1",
+ "sx1-v1",
+ "tiogapass-bmc",
+ "versatileab",
+ "versatilepb",
+ "vexpress-a15",
+ "vexpress-a9",
+ "virt-10.0",
+ "virt-10.1",
+ "virt-10.2",
+ "virt-11.0",
+ "virt-11.1",
+ "virt-11.2",
+ "virt-6.0",
+ "virt-6.1",
+ "virt-6.2",
+ "virt-7.0",
+ "virt-7.1",
+ "virt-7.2",
+ "virt-8.0",
+ "virt-8.1",
+ "virt-8.2",
+ "virt-9.0",
+ "virt-9.1",
+ "virt-9.2",
+ "witherspoon-bmc",
+ "xilinx-zynq-a9",
+ "yosemitev2-bmc",
+};
+
+static const char * const avr_machines[] = {
+ "arduino-duemilanove",
+ "arduino-mega",
+ "arduino-mega-2560-v3",
+ "arduino-uno",
+ "none",
+};
+
+static const char * const hexagon_machines[] = {
+ "V66G_1024",
+ "V68N_1024",
+ "V81DGB_1",
+ "V81QA_1",
+ "none",
+ "virt",
+};
+
+static const char * const hppa_machines[] = {
+ "715",
+ "A400",
+ "B160L",
+ "C3700",
+ "none",
+};
+
+static const char * const i386_machines[] = {
+ "isapc",
+ "microvm",
+ "none",
+ "pc-i440fx-10.0",
+ "pc-i440fx-10.1",
+ "pc-i440fx-10.2",
+ "pc-i440fx-11.0",
+ "pc-i440fx-11.1",
+ "pc-i440fx-11.2",
+ "pc-i440fx-6.0",
+ "pc-i440fx-6.1",
+ "pc-i440fx-6.2",
+ "pc-i440fx-7.0",
+ "pc-i440fx-7.1",
+ "pc-i440fx-7.2",
+ "pc-i440fx-8.0",
+ "pc-i440fx-8.1",
+ "pc-i440fx-8.2",
+ "pc-i440fx-9.0",
+ "pc-i440fx-9.1",
+ "pc-i440fx-9.2",
+ "pc-q35-10.0",
+ "pc-q35-10.1",
+ "pc-q35-10.2",
+ "pc-q35-11.0",
+ "pc-q35-11.1",
+ "pc-q35-11.2",
+ "pc-q35-6.0",
+ "pc-q35-6.1",
+ "pc-q35-6.2",
+ "pc-q35-7.0",
+ "pc-q35-7.1",
+ "pc-q35-7.2",
+ "pc-q35-8.0",
+ "pc-q35-8.1",
+ "pc-q35-8.2",
+ "pc-q35-9.0",
+ "pc-q35-9.1",
+ "pc-q35-9.2",
+};
+
+static const char * const loongarch64_machines[] = {
+ "none",
+ "virt-11.1",
+ "virt-11.2",
+};
+
+static const char * const m68k_machines[] = {
+ "an5206",
+ "mcf5208evb",
+ "next-cube",
+ "none",
+ "q800",
+ "virt-10.0",
+ "virt-10.1",
+ "virt-10.2",
+ "virt-11.0",
+ "virt-11.1",
+ "virt-11.2",
+ "virt-6.0",
+ "virt-6.1",
+ "virt-6.2",
+ "virt-7.0",
+ "virt-7.1",
+ "virt-7.2",
+ "virt-8.0",
+ "virt-8.1",
+ "virt-8.2",
+ "virt-9.0",
+ "virt-9.1",
+ "virt-9.2",
+};
+
+static const char * const microblaze_machines[] = {
+ "none",
+ "petalogix-ml605",
+ "petalogix-s3adsp1800",
+ "xlnx-zynqmp-pmu",
+};
+
+static const char * const mips_machines[] = {
+ "malta",
+ "none",
+};
+
+static const char * const mips64_machines[] = {
+ "magnum",
+ "malta",
+ "none",
+ "pica61",
+};
+
+static const char * const mips64el_machines[] = {
+ "boston",
+ "fuloong2e",
+ "loongson3-virt",
+ "magnum",
+ "malta",
+ "none",
+ "pica61",
+};
+
+static const char * const mipsel_machines[] = {
+ "malta",
+ "none",
+};
+
+static const char * const or1k_machines[] = {
+ "none",
+ "or1k-sim",
+ "virt",
+};
+
+static const char * const ppc_machines[] = {
+ "40p",
+ "amigaone",
+ "bamboo",
+ "g3beige",
+ "mac99",
+ "mpc8544ds",
+ "none",
+ "pegasos1",
+ "pegasos2",
+ "ppce500",
+ "ppe42_machine",
+ "sam460ex",
+ "virtex-ml507",
+};
+
+static const char * const ppc64_machines[] = {
+ "40p",
+ "amigaone",
+ "bamboo",
+ "g3beige",
+ "mac99",
+ "mpc8544ds",
+ "none",
+ "pegasos1",
+ "pegasos2",
+ "powernv10",
+ "powernv10-rainier",
+ "powernv11",
+ "powernv8",
+ "powernv9",
+ "ppce500",
+ "ppe42_machine",
+ "pseries-10.0",
+ "pseries-10.1",
+ "pseries-10.2",
+ "pseries-11.0",
+ "pseries-11.1",
+ "pseries-11.2",
+ "pseries-6.0",
+ "pseries-6.1",
+ "pseries-6.2",
+ "pseries-7.0",
+ "pseries-7.1",
+ "pseries-7.2",
+ "pseries-8.0",
+ "pseries-8.1",
+ "pseries-8.2",
+ "pseries-9.0",
+ "pseries-9.1",
+ "pseries-9.2",
+ "sam460ex",
+ "virtex-ml507",
+};
+
+static const char * const riscv32_machines[] = {
+ "amd-microblaze-v-generic",
+ "none",
+ "opentitan",
+ "sifive_e",
+ "sifive_u",
+ "spike",
+ "virt",
+};
+
+static const char * const riscv64_machines[] = {
+ "amd-microblaze-v-generic",
+ "boston-aia",
+ "k230",
+ "microchip-icicle-kit",
+ "none",
+ "shakti_c",
+ "sifive_e",
+ "sifive_u",
+ "spike",
+ "tt-atlantis",
+ "virt",
+ "xiangshan-kunminghu",
+};
+
+static const char * const rx_machines[] = {
+ "gdbsim-r5f562n7",
+ "gdbsim-r5f562n8",
+ "none",
+};
+
+static const char * const s390x_machines[] = {
+ "none",
+ "s390-ccw-virtio-10.0",
+ "s390-ccw-virtio-10.1",
+ "s390-ccw-virtio-10.2",
+ "s390-ccw-virtio-11.0",
+ "s390-ccw-virtio-11.1",
+ "s390-ccw-virtio-11.2",
+ "s390-ccw-virtio-6.0",
+ "s390-ccw-virtio-6.1",
+ "s390-ccw-virtio-6.2",
+ "s390-ccw-virtio-7.0",
+ "s390-ccw-virtio-7.1",
+ "s390-ccw-virtio-7.2",
+ "s390-ccw-virtio-8.0",
+ "s390-ccw-virtio-8.1",
+ "s390-ccw-virtio-8.2",
+ "s390-ccw-virtio-9.0",
+ "s390-ccw-virtio-9.1",
+ "s390-ccw-virtio-9.2",
+};
+
+static const char * const sh4_machines[] = {
+ "none",
+ "r2d",
+};
+
+static const char * const sh4eb_machines[] = {
+ "none",
+ "r2d",
+};
+
+static const char * const sparc_machines[] = {
+ "LX",
+ "SPARCClassic",
+ "SPARCbook",
+ "SS-10",
+ "SS-20",
+ "SS-4",
+ "SS-5",
+ "SS-600MP",
+ "Voyager",
+ "leon3_generic",
+ "none",
+};
+
+static const char * const sparc64_machines[] = {
+ "niagara",
+ "none",
+ "sun4u",
+ "sun4v",
+};
+
+static const char * const tricore_machines[] = {
+ "KIT_AURIX_TC277_TRB",
+ "none",
+ "tricore_testboard",
+};
+
+static const char * const x86_64_machines[] = {
+ "isapc",
+ "microvm",
+ "none",
+ "pc-i440fx-10.0",
+ "pc-i440fx-10.1",
+ "pc-i440fx-10.2",
+ "pc-i440fx-11.0",
+ "pc-i440fx-11.1",
+ "pc-i440fx-11.2",
+ "pc-i440fx-6.0",
+ "pc-i440fx-6.1",
+ "pc-i440fx-6.2",
+ "pc-i440fx-7.0",
+ "pc-i440fx-7.1",
+ "pc-i440fx-7.2",
+ "pc-i440fx-8.0",
+ "pc-i440fx-8.1",
+ "pc-i440fx-8.2",
+ "pc-i440fx-9.0",
+ "pc-i440fx-9.1",
+ "pc-i440fx-9.2",
+ "pc-q35-10.0",
+ "pc-q35-10.1",
+ "pc-q35-10.2",
+ "pc-q35-11.0",
+ "pc-q35-11.1",
+ "pc-q35-11.2",
+ "pc-q35-6.0",
+ "pc-q35-6.1",
+ "pc-q35-6.2",
+ "pc-q35-7.0",
+ "pc-q35-7.1",
+ "pc-q35-7.2",
+ "pc-q35-8.0",
+ "pc-q35-8.1",
+ "pc-q35-8.2",
+ "pc-q35-9.0",
+ "pc-q35-9.1",
+ "pc-q35-9.2",
+};
+
+static const char * const xtensa_machines[] = {
+ "kc705",
+ "kc705-nommu",
+ "lx200",
+ "lx200-nommu",
+ "lx60",
+ "lx60-nommu",
+ "ml605",
+ "ml605-nommu",
+ "none",
+ "sim",
+ "virt",
+};
+
+static const char * const xtensaeb_machines[] = {
+ "kc705",
+ "kc705-nommu",
+ "lx200",
+ "lx200-nommu",
+ "lx60",
+ "lx60-nommu",
+ "ml605",
+ "ml605-nommu",
+ "none",
+ "sim",
+ "virt",
+};
+
+static const struct ShippedTarget {
+ const char *name;
+ const char *arch;
+ const char *endianness;
+ const char * const *machines;
+ size_t n_machines;
+} shipped_targets[] = {
+ { "aarch64", "aarch64", "little",
+ aarch64_machines, G_N_ELEMENTS(aarch64_machines) },
+ { "alpha", "alpha", "little",
+ alpha_machines, G_N_ELEMENTS(alpha_machines) },
+ { "arm", "arm", "little",
+ arm_machines, G_N_ELEMENTS(arm_machines) },
+ { "avr", "avr", "little",
+ avr_machines, G_N_ELEMENTS(avr_machines) },
+ { "hexagon", "hexagon", "little",
+ hexagon_machines, G_N_ELEMENTS(hexagon_machines) },
+ { "hppa", "hppa", "big",
+ hppa_machines, G_N_ELEMENTS(hppa_machines) },
+ { "i386", "i386", "little",
+ i386_machines, G_N_ELEMENTS(i386_machines) },
+ { "loongarch64", "loongarch64", "little",
+ loongarch64_machines, G_N_ELEMENTS(loongarch64_machines) },
+ { "m68k", "m68k", "big",
+ m68k_machines, G_N_ELEMENTS(m68k_machines) },
+ { "microblaze", "microblaze", "big",
+ microblaze_machines, G_N_ELEMENTS(microblaze_machines) },
+ { "mips", "mips", "big",
+ mips_machines, G_N_ELEMENTS(mips_machines) },
+ { "mips64", "mips64", "big",
+ mips64_machines, G_N_ELEMENTS(mips64_machines) },
+ { "mips64el", "mips64", "little",
+ mips64el_machines, G_N_ELEMENTS(mips64el_machines) },
+ { "mipsel", "mips", "little",
+ mipsel_machines, G_N_ELEMENTS(mipsel_machines) },
+ { "or1k", "or1k", "big",
+ or1k_machines, G_N_ELEMENTS(or1k_machines) },
+ { "ppc", "ppc", "big",
+ ppc_machines, G_N_ELEMENTS(ppc_machines) },
+ { "ppc64", "ppc64", "big",
+ ppc64_machines, G_N_ELEMENTS(ppc64_machines) },
+ { "riscv32", "riscv32", "little",
+ riscv32_machines, G_N_ELEMENTS(riscv32_machines) },
+ { "riscv64", "riscv64", "little",
+ riscv64_machines, G_N_ELEMENTS(riscv64_machines) },
+ { "rx", "rx", "little",
+ rx_machines, G_N_ELEMENTS(rx_machines) },
+ { "s390x", "s390x", "big",
+ s390x_machines, G_N_ELEMENTS(s390x_machines) },
+ { "sh4", "sh4", "little",
+ sh4_machines, G_N_ELEMENTS(sh4_machines) },
+ { "sh4eb", "sh4", "big",
+ sh4eb_machines, G_N_ELEMENTS(sh4eb_machines) },
+ { "sparc", "sparc", "big",
+ sparc_machines, G_N_ELEMENTS(sparc_machines) },
+ { "sparc64", "sparc64", "big",
+ sparc64_machines, G_N_ELEMENTS(sparc64_machines) },
+ { "tricore", "tricore", "little",
+ tricore_machines, G_N_ELEMENTS(tricore_machines) },
+ { "x86_64", "x86_64", "little",
+ x86_64_machines, G_N_ELEMENTS(x86_64_machines) },
+ { "xtensa", "xtensa", "little",
+ xtensa_machines, G_N_ELEMENTS(xtensa_machines) },
+ { "xtensaeb", "xtensa", "big",
+ xtensaeb_machines, G_N_ELEMENTS(xtensaeb_machines) },
+};
+
+/*
+ * Machines omitted from the normal lists. Merged in when @accel is
+ * present (NULL means no accel check) and the host matches (NULL
+ * host_os or host_cpu means any). xenfv is an alias of xenfv-4.2.
+ * aarch64 HVF (vmapple) is built only on an aarch64 Darwin host.
+ * nitro is Linux-only, on x86_64-softmmu for an x86_64 host and
+ * aarch64-softmmu for an aarch64 host. x-remote follows KVM on Linux
+ * when host_cpu is the host that builds KVM for that target.
+ */
+static const char * const xen_pc_machines[] = {
+ "xenpv",
+ "xenpvh",
+ "xenfv-4.2",
+};
+
+static const char * const xen_aarch64_machines[] = {
+ "xenpvh",
+};
+
+static const char * const hvf_aarch64_machines[] = {
+ "vmapple",
+};
+
+static const char * const nitro_machines[] = {
+ "nitro",
+};
+
+static const char * const x_remote_machines[] = {
+ "x-remote",
+};
+
+static const struct SpecialMachineMap {
+ const char *target;
+ const char *accel;
+ const char *host_os;
+ const char *host_cpu;
+ const char * const *machines;
+ size_t n_machines;
+} special_machine_map[] = {
+ { "i386", "xen", NULL, "x86_64",
+ xen_pc_machines, G_N_ELEMENTS(xen_pc_machines) },
+ { "i386", "xen", NULL, "aarch64",
+ xen_pc_machines, G_N_ELEMENTS(xen_pc_machines) },
+ { "x86_64", "xen", NULL, "x86_64",
+ xen_pc_machines, G_N_ELEMENTS(xen_pc_machines) },
+ { "x86_64", "xen", NULL, "aarch64",
+ xen_pc_machines, G_N_ELEMENTS(xen_pc_machines) },
+ { "aarch64", "xen", NULL, "aarch64",
+ xen_aarch64_machines, G_N_ELEMENTS(xen_aarch64_machines) },
+ { "aarch64", "hvf", "darwin", "aarch64",
+ hvf_aarch64_machines, G_N_ELEMENTS(hvf_aarch64_machines) },
+ { "x86_64", NULL, "linux", "x86_64",
+ nitro_machines, G_N_ELEMENTS(nitro_machines) },
+ { "aarch64", NULL, "linux", "aarch64",
+ nitro_machines, G_N_ELEMENTS(nitro_machines) },
+ { "i386", "kvm", "linux", "x86_64",
+ x_remote_machines, G_N_ELEMENTS(x_remote_machines) },
+ { "x86_64", "kvm", "linux", "x86_64",
+ x_remote_machines, G_N_ELEMENTS(x_remote_machines) },
+ { "aarch64", "kvm", "linux", "aarch64",
+ x_remote_machines, G_N_ELEMENTS(x_remote_machines) },
+ { "ppc", "kvm", "linux", "ppc64",
+ x_remote_machines, G_N_ELEMENTS(x_remote_machines) },
+ { "ppc64", "kvm", "linux", "ppc64",
+ x_remote_machines, G_N_ELEMENTS(x_remote_machines) },
+ { "s390x", "kvm", "linux", "s390x",
+ x_remote_machines, G_N_ELEMENTS(x_remote_machines) },
+ { "riscv64", "kvm", "linux", "riscv64",
+ x_remote_machines, G_N_ELEMENTS(x_remote_machines) },
+ { "loongarch64", "kvm", "linux", "loongarch64",
+ x_remote_machines, G_N_ELEMENTS(x_remote_machines) },
+};
+
+static const struct ShippedTarget *lookup_shipped_target(const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < G_N_ELEMENTS(shipped_targets); i++) {
+ if (!strcmp(shipped_targets[i].name, name)) {
+ return &shipped_targets[i];
+ }
+ }
+ return NULL;
+}
+
+static bool have_xen;
+static bool have_hvf;
+static bool have_kvm;
+
+static const char *host_cpu(void)
+{
+#if defined(__aarch64__) || defined(_M_ARM64)
+ return "aarch64";
+#elif defined(__x86_64__) || defined(_M_X64)
+ return "x86_64";
+#elif defined(__powerpc64__)
+ return "ppc64";
+#elif defined(__s390x__)
+ return "s390x";
+#elif defined(__riscv) && __riscv_xlen == 64
+ return "riscv64";
+#elif defined(__loongarch64)
+ return "loongarch64";
+#else
+ return "other";
+#endif
+}
+
+static bool host_os_matches(const char *host_os)
+{
+ if (!host_os) {
+ return true;
+ }
+#if defined(CONFIG_LINUX)
+ return !strcmp(host_os, "linux");
+#elif defined(CONFIG_DARWIN)
+ return !strcmp(host_os, "darwin");
+#else
+ return false;
+#endif
+}
+
+static bool accel_present(const char *accel)
+{
+ if (!accel) {
+ return true;
+ }
+ if (!strcmp(accel, "xen")) {
+ return have_xen;
+ }
+ if (!strcmp(accel, "hvf")) {
+ return have_hvf;
+ }
+ if (!strcmp(accel, "kvm")) {
+ return have_kvm;
+ }
+ return false;
+}
+
+static bool host_cpu_matches(const char *want)
+{
+ if (!want) {
+ return true;
+ }
+ return !strcmp(want, host_cpu());
+}
+
+static bool special_applies(const struct SpecialMachineMap *s,
+ const char *target)
+{
+ return !strcmp(s->target, target) &&
+ accel_present(s->accel) &&
+ host_os_matches(s->host_os) &&
+ host_cpu_matches(s->host_cpu);
+}
+
+static void assert_name_list(QList *names, const char *target,
+ const char * const *expect, size_t n_expect)
+{
+ GHashTable *got = g_hash_table_new(g_str_hash, g_str_equal);
+ GHashTable *want = g_hash_table_new(g_str_hash, g_str_equal);
+ const QListEntry *e;
+ GHashTableIter iter;
+ gpointer key;
+ size_t i;
+
+ g_assert_nonnull(names);
+ for (e = qlist_first(names); e; e = qlist_next(e)) {
+ QString *qs = qobject_to(QString, qlist_entry_obj(e));
+
+ g_assert_nonnull(qs);
+ g_hash_table_add(got, (gpointer)qstring_get_str(qs));
+ }
+ for (i = 0; i < n_expect; i++) {
+ g_hash_table_add(want, (gpointer)expect[i]);
+ }
+ for (i = 0; i < G_N_ELEMENTS(special_machine_map); i++) {
+ const struct SpecialMachineMap *s = &special_machine_map[i];
+ size_t j;
+
+ if (!special_applies(s, target)) {
+ continue;
+ }
+ for (j = 0; j < s->n_machines; j++) {
+ g_hash_table_add(want, (gpointer)s->machines[j]);
+ }
+ }
+ g_hash_table_iter_init(&iter, got);
+ while (g_hash_table_iter_next(&iter, &key, NULL)) {
+ if (!g_hash_table_contains(want, key)) {
+ g_printerr("unexpected machine: %s\n", (const char *)key);
+ }
+ }
+ g_hash_table_iter_init(&iter, want);
+ while (g_hash_table_iter_next(&iter, &key, NULL)) {
+ if (!g_hash_table_contains(got, key)) {
+ g_printerr("missing machine: %s\n", (const char *)key);
+ }
+ }
+ g_assert_cmpuint(g_hash_table_size(got), ==, g_hash_table_size(want));
+ g_hash_table_unref(got);
+ g_hash_table_unref(want);
+}
+
+static void read_accel_flags(QTestState *qts)
+{
+ QDict *resp;
+ QDict *ret;
+ QList *present;
+ const QListEntry *e;
+
+ have_xen = false;
+ have_hvf = false;
+ have_kvm = false;
+ resp = qtest_qmp(qts, "{'execute': 'query-accelerators'}");
+ g_assert(qdict_haskey(resp, "return"));
+ ret = qdict_get_qdict(resp, "return");
+ present = qdict_get_qlist(ret, "present");
+ g_assert_nonnull(present);
+ for (e = qlist_first(present); e; e = qlist_next(e)) {
+ QString *qs = qobject_to(QString, qlist_entry_obj(e));
+ const char *name;
+
+ g_assert_nonnull(qs);
+ name = qstring_get_str(qs);
+ if (!strcmp(name, "xen")) {
+ have_xen = true;
+ } else if (!strcmp(name, "hvf")) {
+ have_hvf = true;
+ } else if (!strcmp(name, "kvm")) {
+ have_kvm = true;
+ }
+ }
+ qobject_unref(resp);
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 33f58b0e95c..8c53bb2e30e 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -23,6 +23,7 @@ qtests_generic = [
'cdrom-test',
'device-introspect-test',
'machine-none-test',
+ 'machine-list-test',
'qmp-test',
'qmp-cmd-test',
'qom-test',
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 011/114] kconfig: rename REGISTER to HW_REGISTER
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (9 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 010/114] tests/qtest: prepare machine-list-test for combined qemu-system Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 012/114] target-info: add TargetKconfig Yonggang Luo
` (30 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Rename config REGISTER to HW_REGISTER. register is a C keyword, and a
later TargetKconfig commit will use it as a struct member.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
hw/Kconfig | 2 +-
hw/core/Kconfig | 2 +-
hw/core/meson.build | 2 +-
hw/dma/Kconfig | 4 ++--
hw/i2c/Kconfig | 2 +-
hw/usb/Kconfig | 2 +-
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/hw/Kconfig b/hw/Kconfig
index c92ca2b13a3..94f963f2944 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -85,7 +85,7 @@ config XILINX_AXI
config XLNX_ZYNQMP
bool
- select REGISTER
+ select HW_REGISTER
select CAN_BUS
select PTIMER
select XLNX_BBRAM
diff --git a/hw/core/Kconfig b/hw/core/Kconfig
index d1bdf765ee8..839e249b9d0 100644
--- a/hw/core/Kconfig
+++ b/hw/core/Kconfig
@@ -29,7 +29,7 @@ config PLATFORM_BUS
bool
depends on DEVICE_TREE
-config REGISTER
+config HW_REGISTER
bool
config SPLIT_IRQ
diff --git a/hw/core/meson.build b/hw/core/meson.build
index 8fe776d2c86..1c645d7041d 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -21,7 +21,7 @@ system_ss.add(when: 'CONFIG_GUEST_LOADER', if_true: files('guest-loader.c'))
system_ss.add(when: 'CONFIG_OR_IRQ', if_true: files('or-irq.c'))
system_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('platform-bus.c'))
system_ss.add(when: 'CONFIG_PTIMER', if_true: files('ptimer.c'))
-system_ss.add(when: 'CONFIG_REGISTER', if_true: files('register.c'))
+system_ss.add(when: 'CONFIG_HW_REGISTER', if_true: files('register.c'))
system_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
system_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
system_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('sysbus-fdt.c'))
diff --git a/hw/dma/Kconfig b/hw/dma/Kconfig
index 0a23e7d7b87..8f221b20634 100644
--- a/hw/dma/Kconfig
+++ b/hw/dma/Kconfig
@@ -16,7 +16,7 @@ config I8257
config ZYNQ_DEVCFG
bool
- select REGISTER
+ select HW_REGISTER
config XLNX_ZDMA
bool
@@ -29,7 +29,7 @@ config SIFIVE_PDMA
config XLNX_CSU_DMA
bool
- select REGISTER
+ select HW_REGISTER
config K230_GSDMA
bool
\ No newline at end of file
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
index 0766130b596..3482f475cf9 100644
--- a/hw/i2c/Kconfig
+++ b/hw/i2c/Kconfig
@@ -20,7 +20,7 @@ config ARM_SBCON_I2C
config DESIGNWARE_I2C
bool
- select REGISTER
+ select HW_REGISTER
select I2C
config ACPI_SMBUS
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index e8c00f813a6..43771291a06 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -137,7 +137,7 @@ config IMX_USBPHY
config USB_DWC3
bool
select USB_XHCI_SYSBUS
- select REGISTER
+ select HW_REGISTER
config XLNX_USB_SUBSYS
bool
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 012/114] target-info: add TargetKconfig
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (10 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 011/114] kconfig: rename REGISTER to HW_REGISTER Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 013/114] target-info: add target_is_* helpers for each architecture Yonggang Luo
` (29 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Add a packed TargetKconfig of device and accel CONFIG_* bits,
generated from the Kconfig tree, and attach it to TargetInfo.
target_kconfig() returns the current bits, and
target_has_kconfig_<name>() tests them. Initialize
target_info_stub.kconfig from CONFIG_DEVICES.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
include/qemu/target-info-def.h | 2 +
include/qemu/target-kconfig-has.h | 7 ++
include/qemu/target-kconfig.h | 34 ++++++
meson.build | 14 +++
scripts/gen-target-kconfig.py | 162 +++++++++++++++++++++++++++
target-info-def.c | 6 +
target-kconfig.c | 20 ++++
tests/unit/meson.build | 1 +
tests/unit/test-target-kconfig-has.c | 22 ++++
9 files changed, 268 insertions(+)
create mode 100644 include/qemu/target-kconfig-has.h
create mode 100644 include/qemu/target-kconfig.h
create mode 100644 scripts/gen-target-kconfig.py
create mode 100644 target-kconfig.c
create mode 100644 tests/unit/test-target-kconfig-has.c
diff --git a/include/qemu/target-info-def.h b/include/qemu/target-info-def.h
index 25dc7c508d3..615596ed468 100644
--- a/include/qemu/target-info-def.h
+++ b/include/qemu/target-info-def.h
@@ -13,6 +13,7 @@
#include "qapi/qapi-types-machine.h"
#include "qemu/queue.h"
#include "qemu/target-info.h"
+#include "qemu/target-kconfig.h"
struct TargetInfo {
/* runtime equivalent of TARGET_NAME definition */
@@ -32,6 +33,7 @@ struct TargetInfo {
unsigned page_bits_init;
/* runtime equivalent of TARGET_PAGE_BITS_VARY definition */
bool page_bits_vary;
+ TargetKconfig kconfig;
};
typedef struct TargetInfoNode TargetInfoNode;
diff --git a/include/qemu/target-kconfig-has.h b/include/qemu/target-kconfig-has.h
new file mode 100644
index 00000000000..6616f75845a
--- /dev/null
+++ b/include/qemu/target-kconfig-has.h
@@ -0,0 +1,7 @@
+/*
+ * QEMU target_has_kconfig_* helpers
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "target-kconfig-has-gen.h"
diff --git a/include/qemu/target-kconfig.h b/include/qemu/target-kconfig.h
new file mode 100644
index 00000000000..21b2ba576ec
--- /dev/null
+++ b/include/qemu/target-kconfig.h
@@ -0,0 +1,34 @@
+/*
+ * QEMU target kconfig API
+ *
+ * Copyright (c) Yonggang Luo
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_TARGET_KCONFIG_H
+#define QEMU_TARGET_KCONFIG_H
+
+#include "qemu/compiler.h"
+
+/**
+ * struct TargetKconfig:
+ *
+ * Compile-time device and accel CONFIG_* bits. Not Kconfig.host
+ * or target/Kconfig. Target identity is TargetInfo, not these
+ * bits. Not kvm_enabled() etc. Fields and
+ * target_has_kconfig_<name>() are generated by
+ * scripts/gen-target-kconfig.py.
+ */
+typedef struct TargetKconfig {
+#include "target-kconfig-fields.h"
+} QEMU_PACKED TargetKconfig;
+
+/**
+ * target_kconfig:
+ *
+ * Returns: The current TargetKconfig (target_info()->kconfig).
+ */
+const TargetKconfig *target_kconfig(void);
+
+#endif
diff --git a/meson.build b/meson.build
index 776d38c5afd..8a017faaa74 100644
--- a/meson.build
+++ b/meson.build
@@ -3445,6 +3445,19 @@ genh += custom_target('config-poison.h',
capture: true,
command: [find_program('scripts/make-config-poison.sh'),
target_configs_h])
+genh += custom_target('target-kconfig',
+ output: ['target-kconfig-fields.h',
+ 'target-kconfig-init.h',
+ 'target-kconfig-has-gen.h',
+ 'target-kconfig-has.c.inc'],
+ depfile: 'target-kconfig.d',
+ command: [python, files('scripts/gen-target-kconfig.py'),
+ '--kconfig', meson.current_source_dir() / 'Kconfig',
+ '--depfile', '@DEPFILE@',
+ '--fields', '@OUTPUT0@',
+ '--init', '@OUTPUT1@',
+ '--has', '@OUTPUT2@',
+ '--has-c', '@OUTPUT3@'])
if fdt_required.length() > 0
error('fdt disabled but required by targets ' + ', '.join(fdt_required))
@@ -3779,6 +3792,7 @@ endif
qom_ss.add(files(
'target-info.c',
+ 'target-kconfig.c',
))
qom_ss = qom_ss.apply({})
libqom = static_library('qom', qom_ss.sources() + genh,
diff --git a/scripts/gen-target-kconfig.py b/scripts/gen-target-kconfig.py
new file mode 100644
index 00000000000..afeffc75ca0
--- /dev/null
+++ b/scripts/gen-target-kconfig.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+"""Generate TargetKconfig CONFIG_* field, initializer, and has headers.
+
+The field list is every `config FOO` from the QEMU Kconfig tree,
+parsed with scripts/minikconf.py (including accel/Kconfig: KVM,
+XEN, HVF, TCG, ...). Host proxies in Kconfig.host and the
+target/Kconfig tree (arch tokens and TARGET_BIG_ENDIAN) are
+omitted. Target identity is TargetInfo, not TargetKconfig.
+
+Each field also gets target_has_kconfig_<name>(const TargetInfo *).
+"""
+
+import argparse
+import os
+import sys
+
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+from minikconf import KconfigData, KconfigParser
+
+
+def field_name(config: str) -> str:
+ return config[len("CONFIG_"):].lower()
+
+
+def collect_from_kconfig(root: str) -> tuple[set[str], list[str]]:
+ data = KconfigData()
+ with open(root, "rt", encoding="utf-8") as fp:
+ KconfigParser.parse(fp, data)
+ names = {"CONFIG_" + name for name in data.defined_vars}
+ return names, list(data.previously_included)
+
+
+def collect_kconfig_names(path: str) -> set[str]:
+ data = KconfigData()
+ with open(path, "rt", encoding="utf-8") as fp:
+ KconfigParser.parse(fp, data)
+ return {"CONFIG_" + name for name in data.defined_vars}
+
+
+def collect_host_kconfig_names(kconfig_root: str) -> set[str]:
+ host = os.path.join(os.path.dirname(os.path.abspath(kconfig_root)),
+ "Kconfig.host")
+ return collect_kconfig_names(host)
+
+
+def collect_target_kconfig_names(kconfig_root: str) -> set[str]:
+ target = os.path.join(os.path.dirname(os.path.abspath(kconfig_root)),
+ "target", "Kconfig")
+ return collect_kconfig_names(target)
+
+
+def write_fields(path: str, configs: list[str]) -> None:
+ lines = [
+ "/* Generated by scripts/gen-target-kconfig.py. Do not edit. */",
+ "",
+ ]
+ for name in configs:
+ lines.append(f" uint32_t {field_name(name)} : 1;")
+ lines.append("")
+ with open(path, "w", encoding="utf-8", newline="\n") as fh:
+ fh.write("\n".join(lines))
+
+
+def write_init(path: str, configs: list[str]) -> None:
+ lines = [
+ "/* Generated by scripts/gen-target-kconfig.py. Do not edit. */",
+ "",
+ ]
+ for name in configs:
+ field = field_name(name)
+ lines.append(f"#if defined({name})")
+ lines.append(f" .{field} = true,")
+ lines.append("#endif")
+ lines.append("")
+ with open(path, "w", encoding="utf-8", newline="\n") as fh:
+ fh.write("\n".join(lines))
+
+
+def has_fn(config: str) -> str:
+ return "target_has_kconfig_" + field_name(config)
+
+
+def write_has_h(path: str, configs: list[str]) -> None:
+ lines = [
+ "/* Generated by scripts/gen-target-kconfig.py. Do not edit. */",
+ "",
+ "#ifndef TARGET_KCONFIG_HAS_GEN_H",
+ "#define TARGET_KCONFIG_HAS_GEN_H",
+ "",
+ "#include <stdbool.h>",
+ "",
+ "typedef struct TargetInfo TargetInfo;",
+ "",
+ ]
+ for name in configs:
+ lines.append(f"bool {has_fn(name)}(const TargetInfo *ti);")
+ lines.append("")
+ lines.append("#endif")
+ lines.append("")
+ with open(path, "w", encoding="utf-8", newline="\n") as fh:
+ fh.write("\n".join(lines))
+
+
+def write_has_c(path: str, configs: list[str]) -> None:
+ lines = [
+ "/* Generated by scripts/gen-target-kconfig.py. Do not edit. */",
+ "",
+ ]
+ for name in configs:
+ fn = has_fn(name)
+ field = field_name(name)
+ lines.append(f"bool {fn}(const TargetInfo *ti)")
+ lines.append("{")
+ lines.append(f" return ti->kconfig.{field};")
+ lines.append("}")
+ lines.append("")
+ with open(path, "w", encoding="utf-8", newline="\n") as fh:
+ fh.write("\n".join(lines))
+
+
+def write_depfile(path: str, outputs: list[str], deps: list[str]) -> None:
+ lines = [" ".join(outputs) + ":" ]
+ for dep in deps:
+ lines.append(f" {dep} \\")
+ if len(lines) > 1:
+ lines[-1] = lines[-1][:-2]
+ lines.append("")
+ with open(path, "w", encoding="utf-8", newline="\n") as fh:
+ fh.write("\n".join(lines))
+
+
+def main(argv: list[str]) -> int:
+ parser = argparse.ArgumentParser(
+ description="Generate TargetKconfig CONFIG_* include headers"
+ )
+ parser.add_argument("--fields", required=True, help="output fields header")
+ parser.add_argument("--init", required=True, help="output initializer header")
+ parser.add_argument("--has", required=True, help="output has-function header")
+ parser.add_argument("--has-c", required=True, help="output has-function bodies")
+ parser.add_argument("--kconfig", required=True, help="root Kconfig")
+ parser.add_argument("--depfile", help="ninja depfile of walked Kconfig files")
+ args = parser.parse_args(argv)
+
+ names, kconfig_files = collect_from_kconfig(args.kconfig)
+ names -= collect_host_kconfig_names(args.kconfig)
+ names -= collect_target_kconfig_names(args.kconfig)
+ configs = sorted(names)
+
+ write_fields(args.fields, configs)
+ write_init(args.init, configs)
+ write_has_h(args.has, configs)
+ write_has_c(args.has_c, configs)
+ if args.depfile:
+ write_depfile(args.depfile,
+ [args.fields, args.init, args.has, args.has_c],
+ kconfig_files)
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
diff --git a/target-info-def.c b/target-info-def.c
index 954298b56d0..44d153cefbc 100644
--- a/target-info-def.c
+++ b/target-info-def.c
@@ -7,6 +7,9 @@
*/
#include "qemu/osdep.h"
+#ifdef CONFIG_DEVICES
+#include CONFIG_DEVICES
+#endif
#include "qemu/target-info.h"
#include "qemu/target-info-def.h"
#include "cpu-qom.h"
@@ -33,6 +36,9 @@ static const TargetInfo target_info_stub = {
.page_bits_vary = false,
.page_bits_init = TARGET_PAGE_BITS,
#endif
+ .kconfig = {
+#include "target-kconfig-init.h"
+ },
};
target_info_init(target_info_stub)
diff --git a/target-kconfig.c b/target-kconfig.c
new file mode 100644
index 00000000000..078c0d8e7f3
--- /dev/null
+++ b/target-kconfig.c
@@ -0,0 +1,20 @@
+/*
+ * QEMU target kconfig helpers
+ *
+ * Copyright (c) Yonggang Luo
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/target-info.h"
+#include "qemu/target-info-def.h"
+#include "qemu/target-kconfig.h"
+#include "qemu/target-kconfig-has.h"
+
+const TargetKconfig *target_kconfig(void)
+{
+ return &target_info()->kconfig;
+}
+
+#include "target-kconfig-has.c.inc"
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index dc980a35955..c806dbc4ffa 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -47,6 +47,7 @@ tests = {
objects: target_info_def_objects.values(),
compile_args: ['-DTARGET_INFO_DEF_COUNT=@0@'.format(
target_info_def_objects.values().length())])],
+ 'test-target-kconfig-has': [qom],
'test-qemu-opts': [],
'test-keyval': [testqapi],
'test-logging': [],
diff --git a/tests/unit/test-target-kconfig-has.c b/tests/unit/test-target-kconfig-has.c
new file mode 100644
index 00000000000..289ed89b854
--- /dev/null
+++ b/tests/unit/test-target-kconfig-has.c
@@ -0,0 +1,22 @@
+/*
+ * target-kconfig-has.h include path test
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/target-kconfig-has.h"
+
+static void test_include(void)
+{
+ bool (*fn)(const TargetInfo *ti) = target_has_kconfig_tcg;
+
+ g_assert_nonnull(fn);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/target-kconfig-has/include", test_include);
+ return g_test_run();
+}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 013/114] target-info: add target_is_* helpers for each architecture
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (11 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 012/114] target-info: add TargetKconfig Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 014/114] target-info: add i386 and x86_64 helpers Yonggang Luo
` (28 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
This is added for latter use with is_available.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
include/qemu/target-info.h | 91 +++++++++++++++++++++++++++++++++++++-
target-info.c | 83 +++++++++++++++++++++++++++++-----
2 files changed, 161 insertions(+), 13 deletions(-)
diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
index c48973f20be..89656da1ca4 100644
--- a/include/qemu/target-info.h
+++ b/include/qemu/target-info.h
@@ -53,6 +53,14 @@ const char *target_cpu_type(void);
*/
bool target_big_endian(void);
+/**
+ * target_is_base_arm:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is ARM or Aarch64.
+ */
+bool target_is_base_arm(const TargetInfo *ti);
+
/**
* target_base_arm:
*
@@ -60,6 +68,14 @@ bool target_big_endian(void);
*/
bool target_base_arm(void);
+/**
+ * target_is_arm:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is ARM (32-bit, not Aarch64).
+ */
+bool target_is_arm(const TargetInfo *ti);
+
/**
* target_arm:
*
@@ -67,6 +83,14 @@ bool target_base_arm(void);
*/
bool target_arm(void);
+/**
+ * target_is_aarch64:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is Aarch64.
+ */
+bool target_is_aarch64(const TargetInfo *ti);
+
/**
* target_aarch64:
*
@@ -74,6 +98,14 @@ bool target_arm(void);
*/
bool target_aarch64(void);
+/**
+ * target_is_base_ppc:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is PowerPC 32-bit or 64-bit.
+ */
+bool target_is_base_ppc(const TargetInfo *ti);
+
/**
* target_base_ppc:
*
@@ -81,6 +113,14 @@ bool target_aarch64(void);
*/
bool target_base_ppc(void);
+/**
+ * target_is_ppc:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is PowerPC 32-bit.
+ */
+bool target_is_ppc(const TargetInfo *ti);
+
/**
* target_ppc:
*
@@ -88,6 +128,14 @@ bool target_base_ppc(void);
*/
bool target_ppc(void);
+/**
+ * target_is_ppc64:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is PowerPC 64-bit.
+ */
+bool target_is_ppc64(const TargetInfo *ti);
+
/**
* target_ppc64:
*
@@ -95,6 +143,14 @@ bool target_ppc(void);
*/
bool target_ppc64(void);
+/**
+ * target_is_s390x:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is S390x.
+ */
+bool target_is_s390x(const TargetInfo *ti);
+
/**
* target_s390x:
*
@@ -102,17 +158,48 @@ bool target_ppc64(void);
*/
bool target_s390x(void);
+/**
+ * target_is_base_riscv:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is RISC-V 32-bit or 64-bit.
+ */
+bool target_is_base_riscv(const TargetInfo *ti);
+
+/**
+ * target_base_riscv:
+ *
+ * Returns whether the target architecture is RISC-V 32-bit or 64-bit.
+ */
+bool target_base_riscv(void);
+
+/**
+ * target_is_riscv32:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is RISC-V 32-bit.
+ */
+bool target_is_riscv32(const TargetInfo *ti);
+
/**
* target_riscv32:
*
- * Returns whether the target architecture is riscv32
+ * Returns whether the target architecture is RISC-V 32-bit.
*/
bool target_riscv32(void);
+/**
+ * target_is_riscv64:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is RISC-V 64-bit.
+ */
+bool target_is_riscv64(const TargetInfo *ti);
+
/**
* target_riscv64:
*
- * Returns whether the target architecture is riscv64
+ * Returns whether the target architecture is RISC-V 64-bit.
*/
bool target_riscv64(void);
diff --git a/target-info.c b/target-info.c
index 6e66f48e1ff..6d57cad5d33 100644
--- a/target-info.c
+++ b/target-info.c
@@ -96,9 +96,9 @@ bool target_big_endian(void)
return target_endian_mode() == ENDIAN_MODE_BIG;
}
-bool target_base_arm(void)
+bool target_is_base_arm(const TargetInfo *ti)
{
- switch (target_arch()) {
+ switch (ti->target_arch) {
case SYS_EMU_TARGET_ARM:
case SYS_EMU_TARGET_AARCH64:
return true;
@@ -107,19 +107,34 @@ bool target_base_arm(void)
}
}
+bool target_base_arm(void)
+{
+ return target_is_base_arm(target_info());
+}
+
+bool target_is_arm(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_ARM;
+}
+
bool target_arm(void)
{
- return target_arch() == SYS_EMU_TARGET_ARM;
+ return target_is_arm(target_info());
+}
+
+bool target_is_aarch64(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_AARCH64;
}
bool target_aarch64(void)
{
- return target_arch() == SYS_EMU_TARGET_AARCH64;
+ return target_is_aarch64(target_info());
}
-bool target_base_ppc(void)
+bool target_is_base_ppc(const TargetInfo *ti)
{
- switch (target_arch()) {
+ switch (ti->target_arch) {
case SYS_EMU_TARGET_PPC:
case SYS_EMU_TARGET_PPC64:
return true;
@@ -128,27 +143,73 @@ bool target_base_ppc(void)
}
}
+bool target_base_ppc(void)
+{
+ return target_is_base_ppc(target_info());
+}
+
+bool target_is_ppc(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_PPC;
+}
+
bool target_ppc(void)
{
- return target_arch() == SYS_EMU_TARGET_PPC;
+ return target_is_ppc(target_info());
+}
+
+bool target_is_ppc64(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_PPC64;
}
bool target_ppc64(void)
{
- return target_arch() == SYS_EMU_TARGET_PPC64;
+ return target_is_ppc64(target_info());
+}
+
+bool target_is_s390x(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_S390X;
}
bool target_s390x(void)
{
- return target_arch() == SYS_EMU_TARGET_S390X;
+ return target_is_s390x(target_info());
+}
+
+bool target_is_base_riscv(const TargetInfo *ti)
+{
+ switch (ti->target_arch) {
+ case SYS_EMU_TARGET_RISCV32:
+ case SYS_EMU_TARGET_RISCV64:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool target_base_riscv(void)
+{
+ return target_is_base_riscv(target_info());
+}
+
+bool target_is_riscv32(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_RISCV32;
}
bool target_riscv32(void)
{
- return target_arch() == SYS_EMU_TARGET_RISCV32;
+ return target_is_riscv32(target_info());
+}
+
+bool target_is_riscv64(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_RISCV64;
}
bool target_riscv64(void)
{
- return target_arch() == SYS_EMU_TARGET_RISCV64;
+ return target_is_riscv64(target_info());
}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 014/114] target-info: add i386 and x86_64 helpers
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (12 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 013/114] target-info: add target_is_* helpers for each architecture Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 015/114] qom: pass TargetInfo to is_available Yonggang Luo
` (27 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
This is added for latter use with is_available.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
include/qemu/target-info.h | 45 ++++++++++++++++++++++++++++++++++++++
target-info.c | 36 ++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+)
diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
index 89656da1ca4..440da63e6cf 100644
--- a/include/qemu/target-info.h
+++ b/include/qemu/target-info.h
@@ -98,6 +98,51 @@ bool target_is_aarch64(const TargetInfo *ti);
*/
bool target_aarch64(void);
+/**
+ * target_is_base_i386:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is i386 or x86_64.
+ */
+bool target_is_base_i386(const TargetInfo *ti);
+
+/**
+ * target_base_i386:
+ *
+ * Returns whether the target architecture is i386 or x86_64.
+ */
+bool target_base_i386(void);
+
+/**
+ * target_is_i386:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is i386 (32-bit, not x86_64).
+ */
+bool target_is_i386(const TargetInfo *ti);
+
+/**
+ * target_i386:
+ *
+ * Returns whether the target architecture is i386 (32-bit, not x86_64).
+ */
+bool target_i386(void);
+
+/**
+ * target_is_x86_64:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns whether @ti is x86_64.
+ */
+bool target_is_x86_64(const TargetInfo *ti);
+
+/**
+ * target_x86_64:
+ *
+ * Returns whether the target architecture is x86_64.
+ */
+bool target_x86_64(void);
+
/**
* target_is_base_ppc:
* @ti: TargetInfo to inspect
diff --git a/target-info.c b/target-info.c
index 6d57cad5d33..36f75ece36f 100644
--- a/target-info.c
+++ b/target-info.c
@@ -132,6 +132,42 @@ bool target_aarch64(void)
return target_is_aarch64(target_info());
}
+bool target_is_base_i386(const TargetInfo *ti)
+{
+ switch (ti->target_arch) {
+ case SYS_EMU_TARGET_I386:
+ case SYS_EMU_TARGET_X86_64:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool target_base_i386(void)
+{
+ return target_is_base_i386(target_info());
+}
+
+bool target_is_i386(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_I386;
+}
+
+bool target_i386(void)
+{
+ return target_is_i386(target_info());
+}
+
+bool target_is_x86_64(const TargetInfo *ti)
+{
+ return ti->target_arch == SYS_EMU_TARGET_X86_64;
+}
+
+bool target_x86_64(void)
+{
+ return target_is_x86_64(target_info());
+}
+
bool target_is_base_ppc(const TargetInfo *ti)
{
switch (ti->target_arch) {
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 015/114] qom: pass TargetInfo to is_available
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (13 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 014/114] target-info: add i386 and x86_64 helpers Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 016/114] module: use static ModuleEntry and per-type DSO lists Yonggang Luo
` (26 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Change TypeInfo.is_available to TypeIsAvailable taking const
TargetInfo *. Store the callback on TypeImpl and add
object_class_get_is_available. ARM and RISC-V machines use
target_is_aarch64(), target_is_riscv32(), and target_is_riscv64().
object.h includes target-info.h.
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/riscv/boston-aia.c | 4 ++--
hw/riscv/k230.c | 4 ++--
hw/riscv/microchip_pfsoc.c | 4 ++--
hw/riscv/opentitan.c | 4 ++--
hw/riscv/shakti_c.c | 4 ++--
hw/riscv/tt_atlantis.c | 4 ++--
hw/riscv/xiangshan_kmh.c | 4 ++--
include/qom/object.h | 27 ++++++++++++++++++++++++---
qom/object.c | 11 ++++++++++-
13 files changed, 54 insertions(+), 24 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/riscv/boston-aia.c b/hw/riscv/boston-aia.c
index ba16b7dbc69..2618b424efe 100644
--- a/hw/riscv/boston-aia.c
+++ b/hw/riscv/boston-aia.c
@@ -468,14 +468,14 @@ static const TypeInfo boston_types[] = {
.name = TYPE_MIPS_BOSTON_AIA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(BostonState),
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
},
{
.name = MACHINE_TYPE_NAME("boston-aia"),
.parent = TYPE_MACHINE,
.class_init = boston_mach_class_init,
.instance_size = sizeof(MachineState),
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
},
};
diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c
index 43b6ae6d2f2..79715265da6 100644
--- a/hw/riscv/k230.c
+++ b/hw/riscv/k230.c
@@ -421,7 +421,7 @@ static const TypeInfo k230_soc_type_info = {
.instance_size = sizeof(K230SoCState),
.instance_init = k230_soc_init,
.class_init = k230_soc_class_init,
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
};
static void k230_soc_register_types(void)
@@ -560,7 +560,7 @@ static const TypeInfo k230_machine_typeinfo = {
.class_init = k230_machine_class_init,
.instance_init = k230_machine_instance_init,
.instance_size = sizeof(K230MachineState),
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
};
static void k230_machine_init_register_types(void)
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index b2991e5a710..cc4b6bc3529 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -505,7 +505,7 @@ static const TypeInfo microchip_pfsoc_soc_type_info = {
.instance_size = sizeof(MicrochipPFSoCState),
.instance_init = microchip_pfsoc_soc_instance_init,
.class_init = microchip_pfsoc_soc_class_init,
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
};
static void microchip_pfsoc_soc_register_types(void)
@@ -759,7 +759,7 @@ static const TypeInfo microchip_icicle_kit_machine_typeinfo = {
.class_init = microchip_icicle_kit_machine_class_init,
.instance_init = microchip_icicle_kit_machine_instance_init,
.instance_size = sizeof(MicrochipIcicleKitState),
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
};
static void microchip_icicle_kit_machine_init_register_types(void)
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index c3a563db926..9e3db34eed9 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -333,13 +333,13 @@ static const TypeInfo open_titan_types[] = {
.instance_size = sizeof(LowRISCIbexSoCState),
.instance_init = lowrisc_ibex_soc_init,
.class_init = lowrisc_ibex_soc_class_init,
- .is_available = target_riscv32,
+ .is_available = target_is_riscv32,
}, {
.name = TYPE_OPENTITAN_MACHINE,
.parent = TYPE_MACHINE,
.instance_size = sizeof(OpenTitanState),
.class_init = opentitan_machine_class_init,
- .is_available = target_riscv32,
+ .is_available = target_is_riscv32,
}
};
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
index 76cfe30918a..0f96258b764 100644
--- a/hw/riscv/shakti_c.c
+++ b/hw/riscv/shakti_c.c
@@ -98,7 +98,7 @@ static const TypeInfo shakti_c_machine_type_info = {
.class_init = shakti_c_machine_class_init,
.instance_init = shakti_c_machine_instance_init,
.instance_size = sizeof(ShaktiCMachineState),
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
};
static void shakti_c_machine_type_info_register(void)
@@ -188,7 +188,7 @@ static const TypeInfo shakti_c_type_info = {
.class_init = shakti_c_soc_class_init,
.instance_init = shakti_c_soc_instance_init,
.instance_size = sizeof(ShaktiCSoCState),
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
};
static void shakti_c_type_info_register(void)
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index f54eb942f37..086e95bd2d1 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -695,13 +695,13 @@ static const TypeInfo tt_atlantis_types[] = {
.instance_size = sizeof(TTAtlantisSoCState),
.instance_init = tt_atlantis_soc_init,
.class_init = tt_atlantis_soc_class_init,
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
}, {
.name = MACHINE_TYPE_NAME("tt-atlantis"),
.parent = TYPE_MACHINE,
.class_init = tt_atlantis_machine_class_init,
.instance_size = sizeof(TTAtlantisState),
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
},
};
diff --git a/hw/riscv/xiangshan_kmh.c b/hw/riscv/xiangshan_kmh.c
index f2383c53993..6bc669421fe 100644
--- a/hw/riscv/xiangshan_kmh.c
+++ b/hw/riscv/xiangshan_kmh.c
@@ -158,7 +158,7 @@ static const TypeInfo xiangshan_kmh_soc_info = {
.instance_size = sizeof(XiangshanKmhSoCState),
.instance_init = xiangshan_kmh_soc_instance_init,
.class_init = xiangshan_kmh_soc_class_init,
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
};
static void xiangshan_kmh_soc_register_types(void)
@@ -222,7 +222,7 @@ static const TypeInfo xiangshan_kmh_machine_info = {
.parent = TYPE_MACHINE,
.instance_size = sizeof(XiangshanKmhState),
.class_init = xiangshan_kmh_machine_class_init,
- .is_available = target_riscv64,
+ .is_available = target_is_riscv64,
};
static void xiangshan_kmh_machine_register_types(void)
diff --git a/include/qom/object.h b/include/qom/object.h
index 4c0645817a5..f2dc22f0eb0 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -16,6 +16,7 @@
#include "qapi/qapi-builtin-types.h"
#include "qemu/module.h"
+#include "qemu/target-info.h"
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
/**
@@ -473,8 +483,10 @@ struct Object
* @class_data: Data to pass to the @class_init,
* @class_base_init. This can be useful when building dynamic
* classes.
- * @is_available: callback invoked at registration time, to dynamically check if
- * this type should be available or not.
+ * @is_available: Optional callback. Unset inherits the parent type's
+ * callback in the MODULE_INIT_QOM after pass (parents are not all
+ * registered at type_register time). After inherit the callback is
+ * never NULL. Callers may also invoke it with a chosen TargetInfo.
* @interfaces: The list of interfaces associated with this type. This
* should point to a static array that's terminated with a zero filled
* element.
@@ -498,7 +510,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;
};
@@ -1087,6 +1099,15 @@ bool object_class_is_abstract(ObjectClass *klass);
*/
bool object_class_is_secure(ObjectClass *klass);
+/**
+ * object_class_get_is_available:
+ * @klass: The class to obtain TypeInfo.is_available for.
+ *
+ * Returns: The availability callback (own or inherited from a parent).
+ * Never %NULL after MODULE_INIT_QOM inherit.
+ */
+TypeIsAvailable *object_class_get_is_available(ObjectClass *klass);
+
/**
* object_class_by_name:
* @typename: The QOM typename to obtain the class for.
diff --git a/qom/object.c b/qom/object.c
index 96498f3d001..a3e75927e82 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-qapi.h"
#include "qemu/cutils.h"
#include "qemu/memalign.h"
#include "qapi/visitor.h"
@@ -71,6 +72,8 @@ struct TypeImpl
bool abstract;
bool secure;
+ TypeIsAvailable *is_available;
+
const char *parent;
TypeImpl *parent_type;
@@ -126,6 +129,7 @@ static TypeImpl *type_new(const TypeInfo *info)
ti->abstract = info->abstract;
ti->secure = info->secure;
+ ti->is_available = info->is_available;
for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
@@ -167,7 +171,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;
}
@@ -1153,6 +1157,11 @@ bool object_class_is_secure(ObjectClass *klass)
return klass->type->secure;
}
+TypeIsAvailable *object_class_get_is_available(ObjectClass *klass)
+{
+ return klass->type->is_available;
+}
+
const char *object_class_get_name(ObjectClass *klass)
{
return klass->type->name;
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 016/114] module: use static ModuleEntry and per-type DSO lists
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (14 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 015/114] qom: pass TargetInfo to is_available Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 017/114] module: add before/after hooks and module_call_init_fn Yonggang Luo
` (25 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
register_module_init malloc'd a ModuleEntry and a late DSO ran
from one shared list. Store each module_init in a static
ModuleEntry and keep a dso_list per init type. Concatenate a late
DSO onto the builtin list when that type is not done yet,
otherwise run it immediately.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
include/qemu/module.h | 22 ++++++--
include/qemu/queue.h | 10 ++++
rust/util/src/module.rs | 16 ++++--
util/module.c | 109 ++++++++++++++++++++++------------------
4 files changed, 98 insertions(+), 59 deletions(-)
diff --git a/include/qemu/module.h b/include/qemu/module.h
index 9885ac9afb3..34e05c75348 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -14,6 +14,7 @@
#ifndef QEMU_MODULE_H
#define QEMU_MODULE_H
+#include "qemu/queue.h"
#define DSO_STAMP_FUN glue(qemu_stamp, CONFIG_STAMP)
#define DSO_STAMP_FUN_STR stringify(DSO_STAMP_FUN)
@@ -26,16 +27,22 @@ void DSO_STAMP_FUN(void);
void qemu_module_dummy(void);
#define module_init(function, type) \
+static ModuleEntry glue(qemu_module_entry_, function) = { \
+ .init = function, \
+}; \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
{ \
- register_dso_module_init(function, type); \
+ register_dso_module_init(&glue(qemu_module_entry_, function), type); \
}
#else
/* This should not be used directly. Use block_init etc. instead. */
#define module_init(function, type) \
+static ModuleEntry glue(qemu_module_entry_, function) = { \
+ .init = function, \
+}; \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
{ \
- register_module_init(function, type); \
+ register_module_init(&glue(qemu_module_entry_, function), type); \
}
#endif
@@ -51,6 +58,13 @@ typedef enum {
MODULE_INIT_MAX
} module_init_type;
+typedef void (ModuleInitFn)(void);
+
+typedef struct ModuleEntry {
+ ModuleInitFn *init;
+ QTAILQ_ENTRY(ModuleEntry) node;
+} ModuleEntry;
+
#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
#define opts_init(function) module_init(function, MODULE_INIT_OPTS)
#define type_init(function) module_init(function, MODULE_INIT_QOM)
@@ -64,8 +78,8 @@ typedef enum {
#define block_module_load(lib, errp) module_load("block-", lib, errp)
#define ui_module_load(lib, errp) module_load("ui-", lib, errp)
-void register_module_init(void (*fn)(void), module_init_type type);
-void register_dso_module_init(void (*fn)(void), module_init_type type);
+void register_module_init(ModuleEntry *e, module_init_type type);
+void register_dso_module_init(ModuleEntry *e, module_init_type type);
void module_call_init(module_init_type type);
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index e029e7bf669..06ebe8b1dfc 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -470,6 +470,16 @@ union { \
(left)->field.tqe_circ.tql_prev->tql_next = (right)->field.tqe_next; \
} while (/*CONSTCOND*/0)
+#define QTAILQ_CONCAT(head1, head2, field) do { \
+ if (!QTAILQ_EMPTY(head2)) { \
+ (head1)->tqh_circ.tql_prev->tql_next = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_circ.tql_prev = \
+ (head1)->tqh_circ.tql_prev; \
+ (head1)->tqh_circ.tql_prev = (head2)->tqh_circ.tql_prev; \
+ QTAILQ_INIT(head2); \
+ } \
+} while (/*CONSTCOND*/0)
+
#define QTAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->tqh_first); \
(var); \
diff --git a/rust/util/src/module.rs b/rust/util/src/module.rs
index 06c45fc142b..45d8b67d6dc 100644
--- a/rust/util/src/module.rs
+++ b/rust/util/src/module.rs
@@ -8,6 +8,16 @@
macro_rules! module_init {
($type:ident => $body:block) => {
const _: () = {
+ extern "C" fn init_fn() {
+ $body
+ }
+
+ static mut ENTRY: $crate::bindings::ModuleEntry =
+ $crate::bindings::ModuleEntry {
+ init: Some(init_fn),
+ ..unsafe { ::core::mem::zeroed() }
+ };
+
#[used]
#[cfg_attr(
not(any(target_vendor = "apple", target_os = "windows")),
@@ -16,14 +26,10 @@ macro_rules! module_init {
#[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")]
#[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
pub static LOAD_MODULE: extern "C" fn() = {
- extern "C" fn init_fn() {
- $body
- }
-
extern "C" fn ctor_fn() {
unsafe {
$crate::bindings::register_module_init(
- Some(init_fn),
+ ::core::ptr::addr_of_mut!(ENTRY),
$crate::bindings::module_init_type::$type,
);
}
diff --git a/util/module.c b/util/module.c
index 8f8e6994f11..6c5980542f6 100644
--- a/util/module.c
+++ b/util/module.c
@@ -27,19 +27,26 @@
#endif
#include "trace.h"
-typedef struct ModuleEntry
+typedef QTAILQ_HEAD(, ModuleEntry) ModuleEntryList;
+
+typedef struct ModuleInit
{
- void (*init)(void);
- QTAILQ_ENTRY(ModuleEntry) node;
module_init_type type;
-} ModuleEntry;
+ ModuleEntryList list;
+ ModuleEntryList dso_list;
+ bool done;
+} ModuleInit;
-typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
+static ModuleInit module_inits[MODULE_INIT_MAX];
-static ModuleTypeList init_type_list[MODULE_INIT_MAX];
-static bool modules_init_done[MODULE_INIT_MAX];
+static void empty_dso_lists(void)
+{
+ int i;
-static ModuleTypeList dso_init_list;
+ for (i = 0; i < MODULE_INIT_MAX; i++) {
+ QTAILQ_INIT(&module_inits[i].dso_list);
+ }
+}
static void init_lists(void)
{
@@ -51,65 +58,56 @@ static void init_lists(void)
}
for (i = 0; i < MODULE_INIT_MAX; i++) {
- QTAILQ_INIT(&init_type_list[i]);
+ module_inits[i].type = i;
+ QTAILQ_INIT(&module_inits[i].list);
}
-
- QTAILQ_INIT(&dso_init_list);
+ empty_dso_lists();
inited = 1;
}
-
-static ModuleTypeList *find_type(module_init_type type)
+static ModuleInit *find_type(module_init_type type)
{
init_lists();
- return &init_type_list[type];
+ return &module_inits[type];
}
-void register_module_init(void (*fn)(void), module_init_type type)
+static void module_init_add(ModuleEntryList *list, ModuleEntry *e)
{
- ModuleEntry *e;
- ModuleTypeList *l;
-
- e = g_malloc0(sizeof(*e));
- e->init = fn;
- e->type = type;
+ QTAILQ_INSERT_TAIL(list, e, node);
+}
- l = find_type(type);
+void register_module_init(ModuleEntry *e, module_init_type type)
+{
+ module_init_add(&find_type(type)->list, e);
+}
- QTAILQ_INSERT_TAIL(l, e, node);
+void register_dso_module_init(ModuleEntry *e, module_init_type type)
+{
+ module_init_add(&find_type(type)->dso_list, e);
}
-void register_dso_module_init(void (*fn)(void), module_init_type type)
+static void module_init_run(ModuleInit *m, ModuleEntryList *list)
{
ModuleEntry *e;
- init_lists();
-
- e = g_malloc0(sizeof(*e));
- e->init = fn;
- e->type = type;
-
- QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
+ (void)m;
+ QTAILQ_FOREACH(e, list, node) {
+ e->init();
+ }
}
void module_call_init(module_init_type type)
{
- ModuleTypeList *l;
- ModuleEntry *e;
+ ModuleInit *m = find_type(type);
- if (modules_init_done[type]) {
+ if (m->done) {
return;
}
- l = find_type(type);
-
- QTAILQ_FOREACH(e, l, node) {
- e->init();
- }
-
- modules_init_done[type] = true;
+ module_init_run(m, &m->list);
+ m->done = true;
}
#ifdef CONFIG_MODULES
@@ -159,10 +157,13 @@ static bool module_load_dso(const char *fname, bool export_symbols,
{
GModule *g_module;
void (*sym)(void);
- ModuleEntry *e, *next;
+ int i;
int flags;
- assert(QTAILQ_EMPTY(&dso_init_list));
+ init_lists();
+ for (i = 0; i < MODULE_INIT_MAX; i++) {
+ assert(QTAILQ_EMPTY(&module_inits[i].dso_list));
+ }
flags = 0;
if (!export_symbols) {
@@ -183,19 +184,27 @@ static bool module_load_dso(const char *fname, bool export_symbols,
error_append_hint(errp,
"Only modules from the same build can be loaded.\n");
}
+ empty_dso_lists();
g_module_close(g_module);
return false;
}
- QTAILQ_FOREACH(e, &dso_init_list, node) {
- e->init();
- register_module_init(e->init, e->type);
+ for (i = 0; i < MODULE_INIT_MAX; i++) {
+ ModuleInit *m = &module_inits[i];
+
+ if (QTAILQ_EMPTY(&m->dso_list)) {
+ continue;
+ }
+
+ if (!m->done) {
+ QTAILQ_CONCAT(&m->list, &m->dso_list, node);
+ continue;
+ }
+
+ module_init_run(m, &m->dso_list);
}
trace_module_load_module(fname);
- QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
- QTAILQ_REMOVE(&dso_init_list, e, node);
- g_free(e);
- }
+ empty_dso_lists();
return true;
}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 017/114] module: add before/after hooks and module_call_init_fn
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (15 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 016/114] module: use static ModuleEntry and per-type DSO lists Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 018/114] qom: register late types through module_call_init_fn Yonggang Luo
` (24 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
module_call_init just walks the list. Add register_module_hooks
so one init type can wrap that walk with before and after
ModuleInitHook callbacks, and add module_call_init_fn so a single
function takes the same path.
module_call_init passes MODULE_INIT_PHASE_ON. A DSO or
module_call_init_fn passes DSO_BEFORE until module_call_init
finishes, then DSO_AFTER.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
include/qemu/module.h | 18 +++++++++++
util/module.c | 70 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/include/qemu/module.h b/include/qemu/module.h
index 34e05c75348..c10e32731fa 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -60,6 +60,20 @@ typedef enum {
typedef void (ModuleInitFn)(void);
+/*
+ * Where one module_init_run sits relative to module_call_init().
+ * DSO_BEFORE: a DSO or module_call_init_fn before module_call_init().
+ * ON: module_call_init() itself.
+ * DSO_AFTER: a DSO or module_call_init_fn after module_call_init().
+ */
+typedef enum ModuleInitPhase {
+ MODULE_INIT_PHASE_DSO_BEFORE,
+ MODULE_INIT_PHASE_ON,
+ MODULE_INIT_PHASE_DSO_AFTER,
+} ModuleInitPhase;
+
+typedef bool (ModuleInitHook)(ModuleInitPhase phase, Error **errp);
+
typedef struct ModuleEntry {
ModuleInitFn *init;
QTAILQ_ENTRY(ModuleEntry) node;
@@ -82,6 +96,10 @@ void register_module_init(ModuleEntry *e, module_init_type type);
void register_dso_module_init(ModuleEntry *e, module_init_type type);
void module_call_init(module_init_type type);
+void module_call_init_fn(module_init_type type, ModuleInitFn *init, Error **errp);
+
+void register_module_hooks(module_init_type type,
+ ModuleInitHook *before, ModuleInitHook *after);
/*
* module_load: attempt to load a module from a set of directories
diff --git a/util/module.c b/util/module.c
index 6c5980542f6..a007ecb53a6 100644
--- a/util/module.c
+++ b/util/module.c
@@ -32,6 +32,8 @@ typedef QTAILQ_HEAD(, ModuleEntry) ModuleEntryList;
typedef struct ModuleInit
{
module_init_type type;
+ ModuleInitHook *before;
+ ModuleInitHook *after;
ModuleEntryList list;
ModuleEntryList dso_list;
bool done;
@@ -88,14 +90,54 @@ void register_dso_module_init(ModuleEntry *e, module_init_type type)
module_init_add(&find_type(type)->dso_list, e);
}
-static void module_init_run(ModuleInit *m, ModuleEntryList *list)
+/**
+ * register_module_hooks:
+ * @type: init list
+ * @before: runs before every registered init for @type
+ * @after: runs after every registered init for @type
+ *
+ * One ModuleInit holds both callbacks so before and after stay 1:1.
+ * module_call_init(@type) passes MODULE_INIT_PHASE_ON. A DSO or
+ * module_call_init_fn passes DSO_BEFORE if module_call_init() has not
+ * finished, otherwise DSO_AFTER.
+ */
+void register_module_hooks(module_init_type type,
+ ModuleInitHook *before, ModuleInitHook *after)
+{
+ ModuleInit *m = find_type(type);
+
+ g_assert(before);
+ g_assert(after);
+ g_assert(!m->before && !m->after);
+
+ m->before = before;
+ m->after = after;
+}
+
+static bool module_init_run(ModuleInit *m, ModuleEntryList *list, bool is_dso,
+ Error **errp)
{
ModuleEntry *e;
+ ModuleInitPhase phase;
+
+ if (!is_dso) {
+ phase = MODULE_INIT_PHASE_ON;
+ } else if (m->done) {
+ phase = MODULE_INIT_PHASE_DSO_AFTER;
+ } else {
+ phase = MODULE_INIT_PHASE_DSO_BEFORE;
+ }
- (void)m;
+ if (m->before && !m->before(phase, errp)) {
+ return false;
+ }
QTAILQ_FOREACH(e, list, node) {
e->init();
}
+ if (m->after && !m->after(phase, errp)) {
+ return false;
+ }
+ return true;
}
void module_call_init(module_init_type type)
@@ -106,10 +148,27 @@ void module_call_init(module_init_type type)
return;
}
- module_init_run(m, &m->list);
+ module_init_run(m, &m->list, false, &error_abort);
m->done = true;
}
+/*
+ * Run a single init through @type's before/after hooks with is_dso=true.
+ * May run before or after module_call_init.
+ */
+void module_call_init_fn(module_init_type type, ModuleInitFn *init, Error **errp)
+{
+ ModuleInit *m = find_type(type);
+ ModuleEntry e = {
+ .init = init,
+ };
+ ModuleEntryList list;
+
+ QTAILQ_INIT(&list);
+ QTAILQ_INSERT_TAIL(&list, &e, node);
+ module_init_run(m, &list, true, errp);
+}
+
#ifdef CONFIG_MODULES
static const QemuModinfo module_info_stub[] = { {
@@ -201,7 +260,10 @@ static bool module_load_dso(const char *fname, bool export_symbols,
continue;
}
- module_init_run(m, &m->dso_list);
+ if (!module_init_run(m, &m->dso_list, true, errp)) {
+ empty_dso_lists();
+ return false;
+ }
}
trace_module_load_module(fname);
empty_dso_lists();
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 018/114] qom: register late types through module_call_init_fn
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (16 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 017/114] module: add before/after hooks and module_call_init_fn Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 019/114] qom: inherit is_available and filter after MODULE_INIT_QOM Yonggang Luo
` (23 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Display early_init, the console-vc fallback, the PPC KVM host CPU,
and unit-test types register after MODULE_INIT_QOM. Route them
through module_call_init_fn so they take the same before/init/after
path as a late DSO.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/ppc/kvm.c | 12 +++++++++++-
tests/unit/check-qom-interface.c | 12 +++++++++---
tests/unit/check-qom-proplist.c | 13 +++++++++----
tests/unit/test-io-channel-websock.c | 7 ++++++-
tests/unit/test-io-task.c | 7 ++++++-
tests/unit/test-qdev-global-props.c | 14 ++++++++++----
tests/unit/test-qdev.c | 8 +++++++-
tests/unit/test-ram-discard-manager.c | 7 ++++++-
ui/console-vc.c | 13 ++++++++++---
ui/dbus.c | 8 +++++++-
ui/gtk.c | 10 +++++++++-
ui/spice-app.c | 7 ++++++-
12 files changed, 96 insertions(+), 22 deletions(-)
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 8e89a6c665c..a3c16850a18 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -22,6 +22,7 @@
#include <linux/kvm.h>
#include "qapi/error.h"
+#include "qemu/module.h"
#include "qemu/error-report.h"
#include "cpu.h"
#include "cpu-models.h"
@@ -2706,6 +2707,13 @@ static void pseries_machine_class_fixup(ObjectClass *oc, void *opaque)
mc->default_cpu_type = TYPE_HOST_POWERPC_CPU;
}
+static TypeInfo host_cpu_type_info;
+
+static void kvm_ppc_register_host_cpu_type_qom(void)
+{
+ type_register_static(&host_cpu_type_info);
+}
+
static int kvm_ppc_register_host_cpu_type(void)
{
TypeInfo type_info = {
@@ -2722,7 +2730,9 @@ static int kvm_ppc_register_host_cpu_type(void)
return -1;
}
type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc));
- type_register_static(&type_info);
+ host_cpu_type_info = type_info;
+ module_call_init_fn(MODULE_INIT_QOM, kvm_ppc_register_host_cpu_type_qom,
+ &error_abort);
/* override TCG default cpu type with 'host' cpu model */
object_class_foreach(pseries_machine_class_fixup, TYPE_SPAPR_MACHINE,
false, NULL);
diff --git a/tests/unit/check-qom-interface.c b/tests/unit/check-qom-interface.c
index 86ae5f6c3b1..1da051ed98b 100644
--- a/tests/unit/check-qom-interface.c
+++ b/tests/unit/check-qom-interface.c
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qom/object.h"
+#include "qapi/error.h"
#include "qemu/module.h"
@@ -86,14 +87,19 @@ static void interface_intermediate_test(void)
test_interface_impl(TYPE_INTERMEDIATE_IMPL);
}
+static void register_types(void)
+{
+ type_register_static(&test_if_info);
+ type_register_static(&direct_impl_info);
+ type_register_static(&intermediate_impl_info);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
- type_register_static(&test_if_info);
- type_register_static(&direct_impl_info);
- type_register_static(&intermediate_impl_info);
+ module_call_init_fn(MODULE_INIT_QOM, register_types, &error_abort);
g_test_add_func("/qom/interface/direct_impl", interface_direct_test);
g_test_add_func("/qom/interface/intermediate_impl",
diff --git a/tests/unit/check-qom-proplist.c b/tests/unit/check-qom-proplist.c
index 89de92b7d91..074a69a7fd3 100644
--- a/tests/unit/check-qom-proplist.c
+++ b/tests/unit/check-qom-proplist.c
@@ -703,15 +703,20 @@ static void test_qom_partial_path(void)
object_unparent(cont1);
}
-int main(int argc, char **argv)
+static void register_types(void)
{
- g_test_init(&argc, &argv, NULL);
-
- module_call_init(MODULE_INIT_QOM);
type_register_static(&dummy_info);
type_register_static(&dummy_dev_info);
type_register_static(&dummy_bus_info);
type_register_static(&dummy_backend_info);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+ module_call_init_fn(MODULE_INIT_QOM, register_types, &error_abort);
g_test_add_func("/qom/proplist/createlist/tree",
test_dummy_createlist_tree);
diff --git a/tests/unit/test-io-channel-websock.c b/tests/unit/test-io-channel-websock.c
index 88da24f993d..d4a92572866 100644
--- a/tests/unit/test-io-channel-websock.c
+++ b/tests/unit/test-io-channel-websock.c
@@ -219,10 +219,15 @@ static void test_websock_stalled_write(const void *opaque)
g_assert_true(g_str_has_prefix(reply, "HTTP/1.1 400 Bad Request\r\n"));
}
+static void register_types(void)
+{
+ type_register_static(&qio_channel_stall_info);
+}
+
int main(int argc, char **argv)
{
module_call_init(MODULE_INIT_QOM);
- type_register_static(&qio_channel_stall_info);
+ module_call_init_fn(MODULE_INIT_QOM, register_types, &error_abort);
g_test_init(&argc, &argv, NULL);
#define TEST_BAD_REQUEST(name, request) \
diff --git a/tests/unit/test-io-task.c b/tests/unit/test-io-task.c
index b1c8ecb7abb..55c4a64f041 100644
--- a/tests/unit/test-io-task.c
+++ b/tests/unit/test-io-task.c
@@ -279,11 +279,16 @@ static void test_task_thread_failure(void)
}
+static void register_types(void)
+{
+ type_register_static(&dummy_info);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
- type_register_static(&dummy_info);
+ module_call_init_fn(MODULE_INIT_QOM, register_types, &error_abort);
g_test_add_func("/crypto/task/complete", test_task_complete);
g_test_add_func("/crypto/task/cancel", test_task_cancel);
g_test_add_func("/crypto/task/datafree", test_task_data_free);
diff --git a/tests/unit/test-qdev-global-props.c b/tests/unit/test-qdev-global-props.c
index 8ea362cbb90..e0aaee05d8b 100644
--- a/tests/unit/test-qdev-global-props.c
+++ b/tests/unit/test-qdev-global-props.c
@@ -27,6 +27,7 @@
#include "hw/core/qdev-properties.h"
#include "qom/object.h"
#include "qapi/error.h"
+#include "qemu/module.h"
#include "qapi/visitor.h"
@@ -302,17 +303,22 @@ static void test_subclass_global_props(void)
g_assert_cmpuint(mt->prop2, ==, 104);
}
-int main(int argc, char **argv)
+static void register_types(void)
{
- g_test_init(&argc, &argv, NULL);
-
- module_call_init(MODULE_INIT_QOM);
type_register_static(&static_prop_type);
type_register_static(&subclass_type);
type_register_static(&dynamic_prop_type);
type_register_static(&hotplug_type);
type_register_static(&nohotplug_type);
type_register_static(&nondevice_type);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+ module_call_init_fn(MODULE_INIT_QOM, register_types, &error_abort);
test_init_machine();
diff --git a/tests/unit/test-qdev.c b/tests/unit/test-qdev.c
index 77c3eee7171..5755fa57b58 100644
--- a/tests/unit/test-qdev.c
+++ b/tests/unit/test-qdev.c
@@ -2,6 +2,7 @@
#include "hw/core/qdev-properties.h"
#include "qom/object.h"
#include "qapi/error.h"
+#include "qemu/module.h"
#include "qapi/visitor.h"
@@ -89,12 +90,17 @@ static void test_qdev_double_realization(void)
}
+static void register_types(void)
+{
+ type_register_static(&my_dev_type_info);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
- type_register_static(&my_dev_type_info);
+ module_call_init_fn(MODULE_INIT_QOM, register_types, &error_abort);
test_init_machine();
g_test_add_func("/qdev/free-properties",
diff --git a/tests/unit/test-ram-discard-manager.c b/tests/unit/test-ram-discard-manager.c
index 3d39a1e94ba..5bdcf9b074c 100644
--- a/tests/unit/test-ram-discard-manager.c
+++ b/tests/unit/test-ram-discard-manager.c
@@ -1187,12 +1187,17 @@ static void test_replay_discarded(void)
test_teardown();
}
+static void register_types(void)
+{
+ type_register_static(&test_rds_info);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
- type_register_static(&test_rds_info);
+ module_call_init_fn(MODULE_INIT_QOM, register_types, &error_abort);
g_test_add_func("/ram-discard-manager/single-source/basic",
test_single_source_basic);
diff --git a/ui/console-vc.c b/ui/console-vc.c
index 53d9e9d39b3..c998a0dd807 100644
--- a/ui/console-vc.c
+++ b/ui/console-vc.c
@@ -6,6 +6,7 @@
#include "chardev/char.h"
#include "qapi/error.h"
+#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/queue.h"
#include "qom/compat-properties.h"
@@ -349,10 +350,16 @@ static const TypeInfo char_vc_type_info = {
.class_init = char_vc_class_init,
};
+static void register_default_char_vc(void)
+{
+ type_register_static(&char_vc_type_info);
+}
+
void qemu_console_early_init(void)
{
- /* set the default vc driver */
- if (!object_class_by_name(TYPE_CHARDEV_VC)) {
- type_register_static(&char_vc_type_info);
+ /* set the default vc driver if a display backend did not */
+ if (object_class_by_name(TYPE_CHARDEV_VC)) {
+ return;
}
+ module_call_init_fn(MODULE_INIT_QOM, register_default_char_vc, &error_abort);
}
diff --git a/ui/dbus.c b/ui/dbus.c
index 7be0f8e2611..34b33bb9ca1 100644
--- a/ui/dbus.c
+++ b/ui/dbus.c
@@ -38,6 +38,7 @@
#include "qemu/audio.h"
#include "audio/audio_int.h" /* FIXME: use QOM dynamic cast instead of drv->name */
#include "qapi/error.h"
+#include "qemu/module.h"
#include "trace.h"
#include "dbus.h"
@@ -623,6 +624,11 @@ static const TypeInfo dbus_vc_type_info = {
.class_init = dbus_vc_class_init,
};
+static void register_dbus_char_vc(void)
+{
+ type_register_static(&dbus_vc_type_info);
+}
+
static void
early_dbus_init(DisplayOptions *opts)
{
@@ -638,7 +644,7 @@ early_dbus_init(DisplayOptions *opts)
using_dbus_display = 1;
- type_register_static(&dbus_vc_type_info);
+ module_call_init_fn(MODULE_INIT_QOM, register_dbus_char_vc, &error_abort);
}
static void
diff --git a/ui/gtk.c b/ui/gtk.c
index ed7ffc06b15..2ddc1f8a901 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -38,6 +38,7 @@
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
+#include "qemu/module.h"
#include "qemu-main.h"
#include "ui/console.h"
@@ -2893,6 +2894,13 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
qemu_main = NULL;
}
+#if defined(CONFIG_VTE)
+static void register_gtk_char_vc(void)
+{
+ type_register_static(&char_gd_vc_type_info);
+}
+#endif
+
static void early_gtk_display_init(DisplayOptions *opts)
{
/* The QEMU code relies on the assumption that it's always run in
@@ -2946,7 +2954,7 @@ static void early_gtk_display_init(DisplayOptions *opts)
keycode_map = gd_get_keymap(&keycode_maplen, &keycode_xorgevdev);
#if defined(CONFIG_VTE)
- type_register_static(&char_gd_vc_type_info);
+ module_call_init_fn(MODULE_INIT_QOM, register_gtk_char_vc, &error_abort);
#endif
}
diff --git a/ui/spice-app.c b/ui/spice-app.c
index fe3df62bfa5..dae3415ec8d 100644
--- a/ui/spice-app.c
+++ b/ui/spice-app.c
@@ -132,6 +132,11 @@ static void spice_app_cleanup(void)
g_clear_pointer(&app_dir, g_free);
}
+static void register_spice_char_vc(void)
+{
+ type_register_static(&char_vc_type_info);
+}
+
static void spice_app_display_early_init(DisplayOptions *opts)
{
QemuOpts *qopts;
@@ -170,7 +175,7 @@ static void spice_app_display_early_init(DisplayOptions *opts)
exit(1);
}
- type_register_static(&char_vc_type_info);
+ module_call_init_fn(MODULE_INIT_QOM, register_spice_char_vc, &error_abort);
sock_path = g_strjoin("", app_dir, "/", "spice.sock", NULL);
qopts = qemu_opts_create(list, NULL, 0, &error_abort);
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 019/114] qom: inherit is_available and filter after MODULE_INIT_QOM
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (17 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 018/114] qom: register late types through module_call_init_fn Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 020/114] tests/unit: add module-init and qom is-available tests Yonggang Luo
` (22 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Parents are not all registered at type_register time, so a type
cannot inherit is_available then.
After MODULE_INIT_QOM, and after a late DSO, inherit the callback
from the parent, drop types that fail target_info(), and report a
missing parent. Skip that filter for MODULE_INIT_PHASE_DSO_BEFORE.
The inherit walk colors each type once, so it is O(N) in the number
of types. TYPE_INTERFACE and TYPE_OBJECT use target_is_any().
type_register_static aborts if it runs outside the QOM before/after
hooks.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
include/qemu/target-info.h | 9 +++
qom/object.c | 134 +++++++++++++++++++++++++++++++++++--
target-info.c | 6 ++
3 files changed, 145 insertions(+), 4 deletions(-)
diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
index 440da63e6cf..790fc74e9d3 100644
--- a/include/qemu/target-info.h
+++ b/include/qemu/target-info.h
@@ -53,6 +53,15 @@ const char *target_cpu_type(void);
*/
bool target_big_endian(void);
+/**
+ * target_is_any:
+ * @ti: TargetInfo to inspect
+ *
+ * Returns true for every TargetInfo. Usable as TypeInfo.is_available
+ * for types that are not target-scoped (TYPE_OBJECT).
+ */
+bool target_is_any(const TargetInfo *ti);
+
/**
* target_is_base_arm:
* @ti: TargetInfo to inspect
diff --git a/qom/object.c b/qom/object.c
index a3e75927e82..d0f9242ac99 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -14,6 +14,7 @@
#include "qapi/error.h"
#include "qom/compat-properties.h"
#include "qom/object.h"
+#include "qemu/module.h"
#include "qom/object_interfaces.h"
#include "qemu/target-info-qapi.h"
#include "qemu/cutils.h"
@@ -40,6 +41,7 @@
#include "qobject/qnum.h"
#include "qobject/qstring.h"
#include "qemu/error-report.h"
+#include "qemu/queue.h"
#define MAX_INTERFACES 32
@@ -81,11 +83,16 @@ struct TypeImpl
int num_interfaces;
InterfaceImpl interfaces[MAX_INTERFACES];
+
+ QTAILQ_ENTRY(TypeImpl) register_node;
};
static Type type_interface;
static GHashTable *type_table;
+static QTAILQ_HEAD(, TypeImpl) type_register_list =
+ QTAILQ_HEAD_INITIALIZER(type_register_list);
+static bool type_qom_registering;
static bool enumerating_types;
@@ -95,6 +102,21 @@ static void type_table_add(TypeImpl *ti)
g_hash_table_insert(type_table, (void *)ti->name, ti);
}
+static void type_table_remove(TypeImpl *ti)
+{
+ int i;
+
+ assert(!enumerating_types);
+ g_hash_table_remove(type_table, (void *)ti->name);
+ QTAILQ_REMOVE(&type_register_list, ti, register_node);
+ g_free((char *)ti->name);
+ g_free((char *)ti->parent);
+ for (i = 0; i < ti->num_interfaces; i++) {
+ g_free((char *)ti->interfaces[i].typename);
+ }
+ g_free(ti);
+}
+
static TypeImpl *type_table_lookup(const char *name)
{
return g_hash_table_lookup(type_table, name);
@@ -171,18 +193,20 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
abort();
}
- if (info->is_available && !info->is_available(target_info())) {
- return NULL;
- }
-
ti = type_new(info);
type_table_add(ti);
+ QTAILQ_INSERT_TAIL(&type_register_list, ti, register_node);
return ti;
}
TypeImpl *type_register_static(const TypeInfo *info)
{
+ if (!type_qom_registering) {
+ fprintf(stderr, "Registering '%s' outside QOM before/after\n",
+ info->name);
+ abort();
+ }
assert(info->parent);
return type_register_internal(info);
}
@@ -316,6 +340,8 @@ static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
iface_impl = type_new(&info);
iface_impl->parent_type = parent_type;
+ g_assert(interface_type->is_available);
+ iface_impl->is_available = interface_type->is_available;
type_initialize(iface_impl);
g_free((char *)info.name);
@@ -1159,6 +1185,7 @@ bool object_class_is_secure(ObjectClass *klass)
TypeIsAvailable *object_class_get_is_available(ObjectClass *klass)
{
+ g_assert(klass->type->is_available);
return klass->type->is_available;
}
@@ -3297,12 +3324,109 @@ static void object_class_init(ObjectClass *klass, const void *data)
NULL);
}
+static bool type_qom_before(ModuleInitPhase phase, Error **errp)
+{
+ (void)errp;
+ (void)phase;
+
+ type_qom_registering = true;
+ return true;
+}
+
+enum TypeVisitColor {
+ TYPE_VISIT_GRAY = 1,
+ TYPE_VISIT_BLACK,
+};
+
+static bool type_update_is_available(TypeImpl *type, GHashTable *visit,
+ Error **errp)
+{
+ TypeImpl *parent;
+ gpointer color;
+
+ color = g_hash_table_lookup(visit, type);
+ if (color == GINT_TO_POINTER(TYPE_VISIT_BLACK)) {
+ return true;
+ }
+ if (color == GINT_TO_POINTER(TYPE_VISIT_GRAY)) {
+ error_setg(errp, "Type '%s' has a cyclic parent chain",
+ type->name);
+ return false;
+ }
+
+ g_hash_table_insert(visit, type, GINT_TO_POINTER(TYPE_VISIT_GRAY));
+
+ parent = type_get_parent(type);
+ if (!parent) {
+ if (strcmp(type->name, TYPE_OBJECT) != 0 &&
+ strcmp(type->name, TYPE_INTERFACE) != 0) {
+ error_setg(errp,
+ "Type '%s' does not inherit from %s or %s",
+ type->name, TYPE_OBJECT, TYPE_INTERFACE);
+ return false;
+ }
+ } else {
+ if (!type_update_is_available(parent, visit, errp)) {
+ return false;
+ }
+ if (!type->is_available) {
+ type->is_available = parent->is_available;
+ }
+ }
+
+ g_hash_table_insert(visit, type, GINT_TO_POINTER(TYPE_VISIT_BLACK));
+ return true;
+}
+
+static bool type_qom_after(ModuleInitPhase phase, Error **errp)
+{
+ TypeImpl *type, *next;
+ GHashTable *visit;
+ Error *local_err = NULL;
+
+ type_qom_registering = false;
+ if (phase == MODULE_INIT_PHASE_DSO_BEFORE) {
+ return true;
+ }
+
+ visit = g_hash_table_new(NULL, NULL);
+ QTAILQ_FOREACH(type, &type_register_list, register_node) {
+ if (!type_update_is_available(type, visit, &local_err)) {
+ break;
+ }
+ }
+ g_hash_table_destroy(visit);
+
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return false;
+ }
+
+ QTAILQ_FOREACH_SAFE(type, &type_register_list, register_node, next) {
+ g_assert(type->is_available);
+ if (!type->is_available(target_info())) {
+ type_table_remove(type);
+ }
+ }
+
+ QTAILQ_FOREACH(type, &type_register_list, register_node) {
+ if (type->parent && !type_table_lookup(type->parent)) {
+ error_setg(errp, "Type '%s' is missing its parent '%s'",
+ type->name, type->parent);
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void __attribute__((constructor)) register_types(void)
{
static const TypeInfo interface_info = {
.name = TYPE_INTERFACE,
.class_size = sizeof(InterfaceClass),
.abstract = true,
+ .is_available = target_is_any,
};
static const TypeInfo object_info = {
@@ -3310,9 +3434,11 @@ static void __attribute__((constructor)) register_types(void)
.instance_size = sizeof(Object),
.class_init = object_class_init,
.abstract = true,
+ .is_available = target_is_any,
};
type_table = g_hash_table_new(g_str_hash, g_str_equal);
type_interface = type_register_internal(&interface_info);
type_register_internal(&object_info);
+ register_module_hooks(MODULE_INIT_QOM, type_qom_before, type_qom_after);
}
diff --git a/target-info.c b/target-info.c
index 36f75ece36f..a9ab4b465d3 100644
--- a/target-info.c
+++ b/target-info.c
@@ -96,6 +96,12 @@ bool target_big_endian(void)
return target_endian_mode() == ENDIAN_MODE_BIG;
}
+bool target_is_any(const TargetInfo *ti)
+{
+ (void)ti;
+ return true;
+}
+
bool target_is_base_arm(const TargetInfo *ti)
{
switch (ti->target_arch) {
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 020/114] tests/unit: add module-init and qom is-available tests
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (18 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 019/114] qom: inherit is_available and filter after MODULE_INIT_QOM Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 021/114] hw/arm/virt: prefix ACPI helpers with arm_virt_ Yonggang Luo
` (21 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
The hook phases and QOM inherit/filter path have no unit coverage.
Add test-module-init for before/after hooks and module_call_init_fn,
and test-qom-is-available for inherit, filter, and late register
when x86_64-softmmu is present.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
tests/unit/meson.build | 8 +
tests/unit/test-module-init.c | 186 +++++++++++++++++++++
tests/unit/test-qom-is-available.c | 250 +++++++++++++++++++++++++++++
3 files changed, 444 insertions(+)
create mode 100644 tests/unit/test-module-init.c
create mode 100644 tests/unit/test-qom-is-available.c
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index c806dbc4ffa..9387d2c34e6 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -2,6 +2,7 @@
testblock = declare_dependency(dependencies: [block], sources: 'iothread.c')
tests = {
+ 'test-module-init': [],
'check-block-qdict': [],
'check-qdict': [],
'check-qnum': [],
@@ -57,6 +58,13 @@ tests = {
'test-envlist': [],
}
+if 'x86_64-softmmu' in target_info_def_objects
+ tests += {
+ 'test-qom-is-available': [qom, declare_dependency(
+ objects: target_info_def_objects['x86_64-softmmu'])],
+ }
+endif
+
if have_system or have_tools
tests += {
'test-qmp-event': [testqapi],
diff --git a/tests/unit/test-module-init.c b/tests/unit/test-module-init.c
new file mode 100644
index 00000000000..85fa3ba3d54
--- /dev/null
+++ b/tests/unit/test-module-init.c
@@ -0,0 +1,186 @@
+/*
+ * Module before/after hooks, static ModuleEntry, and module_call_init_fn
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+
+#define SEQ_BEFORE 1
+#define SEQ_INIT_A 2
+#define SEQ_INIT_B 3
+#define SEQ_AFTER 4
+#define SEQ_FN 5
+
+static int seq[16];
+static int seq_n;
+static int first_seq[16];
+static int first_seq_n;
+static ModuleInitPhase last_phase;
+static ModuleInitPhase first_phase;
+static bool fail_before;
+static bool fail_after;
+static int fn_ran;
+static int dso_ran;
+
+static void seq_add(int id)
+{
+ g_assert_cmpint(seq_n, <, (int)ARRAY_SIZE(seq));
+ seq[seq_n++] = id;
+}
+
+static bool test_before(ModuleInitPhase phase, Error **errp)
+{
+ last_phase = phase;
+ seq_add(SEQ_BEFORE);
+ if (fail_before) {
+ error_setg(errp, "before failed");
+ return false;
+ }
+ return true;
+}
+
+static bool test_after(ModuleInitPhase phase, Error **errp)
+{
+ last_phase = phase;
+ seq_add(SEQ_AFTER);
+ if (fail_after) {
+ error_setg(errp, "after failed");
+ return false;
+ }
+ return true;
+}
+
+static void init_a(void)
+{
+ seq_add(SEQ_INIT_A);
+}
+
+static void init_b(void)
+{
+ seq_add(SEQ_INIT_B);
+}
+
+static void init_fn(void)
+{
+ fn_ran++;
+ seq_add(SEQ_FN);
+}
+
+static void init_dso(void)
+{
+ dso_ran++;
+}
+
+static ModuleEntry entry_a = {
+ .init = init_a,
+};
+
+static ModuleEntry entry_b = {
+ .init = init_b,
+};
+
+static ModuleEntry entry_dso = {
+ .init = init_dso,
+};
+
+static void reset_seq(void)
+{
+ seq_n = 0;
+ memset(seq, 0, sizeof(seq));
+}
+
+static void test_builtin_order(void)
+{
+ g_assert_cmpint(first_phase, ==, MODULE_INIT_PHASE_ON);
+ g_assert_cmpint(first_seq_n, ==, 4);
+ g_assert_cmpint(first_seq[0], ==, SEQ_BEFORE);
+ g_assert_cmpint(first_seq[1], ==, SEQ_INIT_A);
+ g_assert_cmpint(first_seq[2], ==, SEQ_INIT_B);
+ g_assert_cmpint(first_seq[3], ==, SEQ_AFTER);
+ g_assert_cmpint(dso_ran, ==, 0);
+}
+
+static void test_call_init_idempotent(void)
+{
+ reset_seq();
+ module_call_init(MODULE_INIT_FUZZ_TARGET);
+ g_assert_cmpint(seq_n, ==, 0);
+}
+
+static void test_call_init_fn(void)
+{
+ int old_fn = fn_ran;
+
+ reset_seq();
+ module_call_init_fn(MODULE_INIT_FUZZ_TARGET, init_fn, &error_abort);
+ g_assert_cmpint(last_phase, ==, MODULE_INIT_PHASE_DSO_AFTER);
+ g_assert_cmpint(fn_ran, ==, old_fn + 1);
+ g_assert_cmpint(seq_n, ==, 3);
+ g_assert_cmpint(seq[0], ==, SEQ_BEFORE);
+ g_assert_cmpint(seq[1], ==, SEQ_FN);
+ g_assert_cmpint(seq[2], ==, SEQ_AFTER);
+}
+
+static void test_before_fail(void)
+{
+ Error *err = NULL;
+ int old_fn = fn_ran;
+
+ reset_seq();
+ fail_before = true;
+ module_call_init_fn(MODULE_INIT_FUZZ_TARGET, init_fn, &err);
+ fail_before = false;
+ g_assert_nonnull(err);
+ g_assert_cmpstr(error_get_pretty(err), ==, "before failed");
+ g_assert_cmpint(fn_ran, ==, old_fn);
+ g_assert_cmpint(seq_n, ==, 1);
+ g_assert_cmpint(seq[0], ==, SEQ_BEFORE);
+ error_free(err);
+}
+
+static void test_after_fail(void)
+{
+ Error *err = NULL;
+ int old_fn = fn_ran;
+
+ reset_seq();
+ fail_after = true;
+ module_call_init_fn(MODULE_INIT_FUZZ_TARGET, init_fn, &err);
+ fail_after = false;
+ g_assert_nonnull(err);
+ g_assert_cmpstr(error_get_pretty(err), ==, "after failed");
+ g_assert_cmpint(fn_ran, ==, old_fn + 1);
+ g_assert_cmpint(seq_n, ==, 3);
+ g_assert_cmpint(seq[0], ==, SEQ_BEFORE);
+ g_assert_cmpint(seq[1], ==, SEQ_FN);
+ g_assert_cmpint(seq[2], ==, SEQ_AFTER);
+ error_free(err);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ register_module_hooks(MODULE_INIT_FUZZ_TARGET, test_before, test_after);
+ register_module_init(&entry_a, MODULE_INIT_FUZZ_TARGET);
+ register_module_init(&entry_b, MODULE_INIT_FUZZ_TARGET);
+ register_dso_module_init(&entry_dso, MODULE_INIT_FUZZ_TARGET);
+
+ reset_seq();
+ module_call_init(MODULE_INIT_FUZZ_TARGET);
+ first_seq_n = seq_n;
+ memcpy(first_seq, seq, sizeof(seq));
+ first_phase = last_phase;
+
+ g_test_add_func("/module/init/builtin-order", test_builtin_order);
+ g_test_add_func("/module/init/call-init-idempotent",
+ test_call_init_idempotent);
+ g_test_add_func("/module/init/call-init-fn", test_call_init_fn);
+ g_test_add_func("/module/init/before-fail", test_before_fail);
+ g_test_add_func("/module/init/after-fail", test_after_fail);
+
+ return g_test_run();
+}
diff --git a/tests/unit/test-qom-is-available.c b/tests/unit/test-qom-is-available.c
new file mode 100644
index 00000000000..641f0cf1bb4
--- /dev/null
+++ b/tests/unit/test-qom-is-available.c
@@ -0,0 +1,250 @@
+/*
+ * QOM is_available inherit and filter after MODULE_INIT_QOM
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "qemu/target-info-def.h"
+#include "qom/object.h"
+
+#define TYPE_I386_PARENT "test-avail-i386-parent"
+#define TYPE_I386_CHILD "test-avail-i386-child"
+#define TYPE_NEVER "test-avail-never"
+#define TYPE_NEVER_CHILD "test-avail-never-child"
+#define TYPE_DROP_CHILD "test-avail-drop-child"
+#define TYPE_TEST_IF "test-avail-if"
+#define TYPE_LATE_KEEP "test-avail-late-keep"
+#define TYPE_LATE_DROP "test-avail-late-drop"
+#define TYPE_ORPHAN_PARENT "test-avail-orphan-parent"
+#define TYPE_ORPHAN "test-avail-orphan"
+#define TYPE_CYCLE_A "test-avail-cycle-a"
+#define TYPE_CYCLE_B "test-avail-cycle-b"
+
+static bool test_never(const TargetInfo *ti)
+{
+ (void)ti;
+ return false;
+}
+
+static const TypeInfo i386_parent_info = {
+ .name = TYPE_I386_PARENT,
+ .parent = TYPE_OBJECT,
+ .is_available = target_is_base_i386,
+};
+
+static const TypeInfo i386_child_info = {
+ .name = TYPE_I386_CHILD,
+ .parent = TYPE_I386_PARENT,
+};
+
+static const TypeInfo never_info = {
+ .name = TYPE_NEVER,
+ .parent = TYPE_OBJECT,
+ .is_available = test_never,
+};
+
+static const TypeInfo never_child_info = {
+ .name = TYPE_NEVER_CHILD,
+ .parent = TYPE_NEVER,
+};
+
+static const TypeInfo drop_child_info = {
+ .name = TYPE_DROP_CHILD,
+ .parent = TYPE_OBJECT,
+ .is_available = test_never,
+};
+
+static const TypeInfo test_if_info = {
+ .name = TYPE_TEST_IF,
+ .parent = TYPE_INTERFACE,
+};
+
+static void register_kept_types(void)
+{
+ /* Child before parent: inherit is a list walk, not register order. */
+ type_register_static(&i386_child_info);
+ type_register_static(&i386_parent_info);
+ type_register_static(&never_child_info);
+ type_register_static(&never_info);
+ type_register_static(&drop_child_info);
+ type_register_static(&test_if_info);
+}
+
+static void test_roots(void)
+{
+ ObjectClass *obj = object_class_by_name(TYPE_OBJECT);
+ ObjectClass *iface = object_class_by_name(TYPE_INTERFACE);
+
+ g_assert_nonnull(obj);
+ g_assert_nonnull(iface);
+ g_assert(object_class_get_is_available(obj) == target_is_any);
+ g_assert(object_class_get_is_available(iface) == target_is_any);
+ g_assert_true(object_class_get_is_available(obj)(target_info()));
+}
+
+static void test_inherit_family(void)
+{
+ ObjectClass *parent = object_class_by_name(TYPE_I386_PARENT);
+ ObjectClass *child = object_class_by_name(TYPE_I386_CHILD);
+
+ if (target_is_base_i386(target_info())) {
+ g_assert_nonnull(parent);
+ g_assert_nonnull(child);
+ g_assert(object_class_get_is_available(parent) == target_is_base_i386);
+ g_assert(object_class_get_is_available(child) == target_is_base_i386);
+ } else {
+ g_assert_null(parent);
+ g_assert_null(child);
+ }
+}
+
+static void test_filter_never(void)
+{
+ g_assert_null(object_class_by_name(TYPE_NEVER));
+ g_assert_null(object_class_by_name(TYPE_NEVER_CHILD));
+ g_assert_null(object_class_by_name(TYPE_DROP_CHILD));
+}
+
+static void test_interface_inherit(void)
+{
+ ObjectClass *klass = object_class_by_name(TYPE_TEST_IF);
+
+ g_assert_nonnull(klass);
+ g_assert(object_class_get_is_available(klass) == target_is_any);
+}
+
+static void register_late_keep(void)
+{
+ static const TypeInfo late_keep_info = {
+ .name = TYPE_LATE_KEEP,
+ .parent = TYPE_OBJECT,
+ };
+
+ type_register_static(&late_keep_info);
+}
+
+static void register_late_drop(void)
+{
+ static const TypeInfo late_drop_info = {
+ .name = TYPE_LATE_DROP,
+ .parent = TYPE_OBJECT,
+ .is_available = test_never,
+ };
+
+ type_register_static(&late_drop_info);
+}
+
+static void test_late_keep(void)
+{
+ ObjectClass *klass;
+
+ module_call_init_fn(MODULE_INIT_QOM, register_late_keep, &error_abort);
+ klass = object_class_by_name(TYPE_LATE_KEEP);
+ g_assert_nonnull(klass);
+ g_assert(object_class_get_is_available(klass) == target_is_any);
+}
+
+static void test_late_drop(void)
+{
+ module_call_init_fn(MODULE_INIT_QOM, register_late_drop, &error_abort);
+ g_assert_null(object_class_by_name(TYPE_LATE_DROP));
+}
+
+static void register_orphan(void)
+{
+ static const TypeInfo parent_info = {
+ .name = TYPE_ORPHAN_PARENT,
+ .parent = TYPE_OBJECT,
+ .is_available = test_never,
+ };
+ static const TypeInfo child_info = {
+ .name = TYPE_ORPHAN,
+ .parent = TYPE_ORPHAN_PARENT,
+ .is_available = target_is_any,
+ };
+
+ type_register_static(&parent_info);
+ type_register_static(&child_info);
+}
+
+static void test_orphan_parent(void)
+{
+ Error *err = NULL;
+
+ module_call_init_fn(MODULE_INIT_QOM, register_orphan, &err);
+ g_assert_nonnull(err);
+ g_assert_cmpstr(error_get_pretty(err), ==,
+ "Type '" TYPE_ORPHAN "' is missing its parent '"
+ TYPE_ORPHAN_PARENT "'");
+ error_free(err);
+}
+
+static void register_cycle(void)
+{
+ static const TypeInfo a_info = {
+ .name = TYPE_CYCLE_A,
+ .parent = TYPE_CYCLE_B,
+ };
+ static const TypeInfo b_info = {
+ .name = TYPE_CYCLE_B,
+ .parent = TYPE_CYCLE_A,
+ };
+
+ type_register_static(&a_info);
+ type_register_static(&b_info);
+}
+
+static void test_cycle(void)
+{
+ Error *err = NULL;
+
+ module_call_init_fn(MODULE_INIT_QOM, register_cycle, &err);
+ g_assert_nonnull(err);
+ g_assert_true(strstr(error_get_pretty(err), "cyclic parent chain") != NULL);
+ error_free(err);
+}
+
+static void test_init_fn_before_call_init(void)
+{
+ if (g_test_subprocess()) {
+ test_roots();
+ test_inherit_family();
+ test_filter_never();
+ test_interface_inherit();
+ return;
+ }
+ g_test_trap_subprocess(NULL, 0, 0);
+ g_test_trap_assert_passed();
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert_nonnull(target_info());
+
+ if (g_test_subprocess()) {
+ module_call_init_fn(MODULE_INIT_QOM, register_kept_types, &error_abort);
+ module_call_init(MODULE_INIT_QOM);
+ } else {
+ module_call_init(MODULE_INIT_QOM);
+ module_call_init_fn(MODULE_INIT_QOM, register_kept_types, &error_abort);
+ }
+
+ g_test_add_func("/qom/is-available/roots", test_roots);
+ g_test_add_func("/qom/is-available/inherit-family", test_inherit_family);
+ g_test_add_func("/qom/is-available/filter-never", test_filter_never);
+ g_test_add_func("/qom/is-available/interface-inherit",
+ test_interface_inherit);
+ g_test_add_func("/qom/is-available/late-keep", test_late_keep);
+ g_test_add_func("/qom/is-available/late-drop", test_late_drop);
+ g_test_add_func("/qom/is-available/orphan-parent", test_orphan_parent);
+ g_test_add_func("/qom/is-available/cycle", test_cycle);
+ g_test_add_func("/qom/is-available/init-fn-before-call-init",
+ test_init_fn_before_call_init);
+
+ return g_test_run();
+}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 021/114] hw/arm/virt: prefix ACPI helpers with arm_virt_
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (19 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 020/114] tests/unit: add module-init and qom is-available tests Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 022/114] hw/riscv/virt: prefix ACPI helpers with riscv_virt_ Yonggang Luo
` (20 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- virt_acpi_setup and virt_is_acpi_enabled are generic names also used
by RISC-V and LoongArch virt. A combined binary cannot export two
functions with the same C symbol.
- Rename the ARM helpers to arm_virt_acpi_setup and
arm_virt_is_acpi_enabled. Leave the trace event virt_acpi_setup
unchanged; it is a separate identifier.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/arm/virt-acpi-build.c | 4 ++--
hw/arm/virt.c | 12 ++++++------
include/hw/arm/virt.h | 4 ++--
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index d368913e766..5737c3a8fa4 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -1559,7 +1559,7 @@ static const VMStateDescription vmstate_virt_acpi_build = {
},
};
-void virt_acpi_setup(VirtMachineState *vms)
+void arm_virt_acpi_setup(VirtMachineState *vms)
{
AcpiBuildTables tables;
AcpiBuildState *build_state;
@@ -1570,7 +1570,7 @@ void virt_acpi_setup(VirtMachineState *vms)
return;
}
- if (!virt_is_acpi_enabled(vms)) {
+ if (!arm_virt_is_acpi_enabled(vms)) {
trace_virt_acpi_setup();
return;
}
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c8ffa1ceaf4..331fae883c7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -769,7 +769,7 @@ static void fdt_add_cpu_nodes(VirtMachineState *vms)
&bottom_node,
CPU_TOPOLOGY_LEVEL_SOCKET);
if (cache_at_topo_level) {
- if (bottom_node == 1 && !virt_is_acpi_enabled(vms))
+ if (bottom_node == 1 && !arm_virt_is_acpi_enabled(vms))
error_setg(
&error_fatal,
"Cannot share L1 at socket_id %d."
@@ -809,7 +809,7 @@ static void fdt_add_cpu_nodes(VirtMachineState *vms)
top_cluster,
bottom_cluster, cpu,
&cluster_offset);
- if (bottom_cluster == 1 && !virt_is_acpi_enabled(vms)) {
+ if (bottom_cluster == 1 && !arm_virt_is_acpi_enabled(vms)) {
error_setg(&error_fatal,
"Cannot share L1 at socket_id %d, cluster_id %d. "
"DT limitation on sharing at cache level = 1.",
@@ -2036,7 +2036,7 @@ static void create_smmuv3_dev_dtb(VirtMachineState *vms, DeviceState *dev,
hwaddr base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
MachineState *ms = MACHINE(vms);
- if (!(vms->bootinfo.firmware_loaded && virt_is_acpi_enabled(vms))) {
+ if (!(vms->bootinfo.firmware_loaded && arm_virt_is_acpi_enabled(vms))) {
if (object_property_get_bool(OBJECT(dev), "accel", &error_abort)) {
error_setg(errp, "SMMUv3 with accel=on not supported for DT");
return;
@@ -2446,7 +2446,7 @@ void virt_machine_done(Notifier *notifier, void *data)
pci_bus_add_fw_cfg_extra_pci_roots(vms->fw_cfg, vms->bus,
&error_abort);
- virt_acpi_setup(vms);
+ arm_virt_acpi_setup(vms);
virt_build_smbios(vms);
}
@@ -3210,7 +3210,7 @@ static void machvirt_init(MachineState *machine)
create_pcie(vms);
create_cxl_host_reg_region(vms);
- if (aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
+ if (aarch64 && firmware_loaded && arm_virt_is_acpi_enabled(vms)) {
vms->acpi_dev = create_acpi_ged(vms);
vms->generic_error_notifier.notify = virt_generic_error_req;
notifier_list_add(&acpi_generic_error_notifiers,
@@ -3560,7 +3560,7 @@ static void virt_set_oem_table_id(Object *obj, const char *value,
}
-bool virt_is_acpi_enabled(const VirtMachineState *vms)
+bool arm_virt_is_acpi_enabled(const VirtMachineState *vms)
{
if (vms->acpi == ON_OFF_AUTO_OFF) {
return false;
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 383ee320948..2ee61cc5a06 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -218,8 +218,8 @@ struct VirtMachineState {
#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("arm-virt")
OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE)
-void virt_acpi_setup(VirtMachineState *vms);
-bool virt_is_acpi_enabled(const VirtMachineState *vms);
+void arm_virt_acpi_setup(VirtMachineState *vms);
+bool arm_virt_is_acpi_enabled(const VirtMachineState *vms);
#define CLIDR_CTYPE_NO_CACHE 0x00
#define CLIDR_CTYPE_I_CACHE 0x01
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 022/114] hw/riscv/virt: prefix ACPI helpers with riscv_virt_
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (20 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 021/114] hw/arm/virt: prefix ACPI helpers with arm_virt_ Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 023/114] hw/loongarch/virt: prefix ACPI helper with loongarch_virt_ Yonggang Luo
` (19 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- virt_acpi_setup and virt_is_acpi_enabled collide with ARM virt when
both architectures are linked into one qemu-system binary.
- Rename the RISC-V helpers to riscv_virt_acpi_setup and
riscv_virt_is_acpi_enabled. Leave file-local virt_acpi_build* names
unchanged.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/riscv/virt-acpi-build.c | 2 +-
hw/riscv/virt.c | 6 +++---
include/hw/riscv/virt.h | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
index 8e516ec1148..de47631852f 100644
--- a/hw/riscv/virt-acpi-build.c
+++ b/hw/riscv/virt-acpi-build.c
@@ -1021,7 +1021,7 @@ static const VMStateDescription vmstate_virt_acpi_build = {
},
};
-void virt_acpi_setup(RISCVVirtState *s)
+void riscv_virt_acpi_setup(RISCVVirtState *s)
{
AcpiBuildTables tables;
AcpiBuildState *build_state;
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 686222fa0da..0edf75fefc3 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -706,8 +706,8 @@ static void virt_machine_done(Notifier *notifier, void *data)
virt_build_smbios(s);
- if (virt_is_acpi_enabled(s)) {
- virt_acpi_setup(s);
+ if (riscv_virt_is_acpi_enabled(s)) {
+ riscv_virt_acpi_setup(s);
}
}
@@ -1067,7 +1067,7 @@ static void virt_set_iommu_sys(Object *obj, Visitor *v, const char *name,
visit_type_OnOffAuto(v, name, &s->iommu_sys, errp);
}
-bool virt_is_acpi_enabled(RISCVVirtState *s)
+bool riscv_virt_is_acpi_enabled(RISCVVirtState *s)
{
return s->acpi != ON_OFF_AUTO_OFF;
}
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 969aa5866ee..1cdc5840b7a 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -121,9 +121,9 @@ enum {
#define VIRT_PLIC_SIZE(__num_context) \
(VIRT_PLIC_CONTEXT_BASE + (__num_context) * VIRT_PLIC_CONTEXT_STRIDE)
-bool virt_is_acpi_enabled(RISCVVirtState *s);
+bool riscv_virt_is_acpi_enabled(RISCVVirtState *s);
bool virt_is_iommu_sys_enabled(RISCVVirtState *s);
-void virt_acpi_setup(RISCVVirtState *vms);
+void riscv_virt_acpi_setup(RISCVVirtState *vms);
/*
* The virt machine physical address space used by some of the devices
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 023/114] hw/loongarch/virt: prefix ACPI helper with loongarch_virt_
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (21 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 022/114] hw/riscv/virt: prefix ACPI helpers with riscv_virt_ Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 024/114] target/riscv: uniquify TCG crc32, crc32c, and wfi helper names Yonggang Luo
` (18 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- virt_acpi_setup is the same C symbol used by ARM and RISC-V virt.
Rename it now so a later combined binary does not need meson -D
prefixes for LoongArch.
- Rename the file-local virt_is_acpi_enabled to
loongarch_virt_is_acpi_enabled to match.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt-acpi-build.c | 6 +++---
hw/loongarch/virt.c | 2 +-
include/hw/loongarch/virt.h | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/hw/loongarch/virt-acpi-build.c b/hw/loongarch/virt-acpi-build.c
index 600ef60fc58..b9df9b3a127 100644
--- a/hw/loongarch/virt-acpi-build.c
+++ b/hw/loongarch/virt-acpi-build.c
@@ -674,7 +674,7 @@ static const VMStateDescription vmstate_acpi_build = {
},
};
-static bool virt_is_acpi_enabled(LoongArchVirtMachineState *lvms)
+static bool loongarch_virt_is_acpi_enabled(LoongArchVirtMachineState *lvms)
{
if (lvms->acpi == ON_OFF_AUTO_OFF) {
return false;
@@ -682,7 +682,7 @@ static bool virt_is_acpi_enabled(LoongArchVirtMachineState *lvms)
return true;
}
-void virt_acpi_setup(LoongArchVirtMachineState *lvms)
+void loongarch_virt_acpi_setup(LoongArchVirtMachineState *lvms)
{
AcpiBuildTables tables;
AcpiBuildState *build_state;
@@ -692,7 +692,7 @@ void virt_acpi_setup(LoongArchVirtMachineState *lvms)
return;
}
- if (!virt_is_acpi_enabled(lvms)) {
+ if (!loongarch_virt_is_acpi_enabled(lvms)) {
ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");
return;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 2b003443eb0..18923500fc2 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -242,7 +242,7 @@ static void virt_done(Notifier *notifier, void *data)
LoongArchVirtMachineState *lvms = container_of(notifier,
LoongArchVirtMachineState, machine_done);
virt_build_smbios(lvms);
- virt_acpi_setup(lvms);
+ loongarch_virt_acpi_setup(lvms);
virt_fdt_setup(lvms);
}
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 09529de48bd..4316a414f44 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -132,7 +132,7 @@ struct LoongArchVirtMachineState {
#define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("loongarch-virt")
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
-void virt_acpi_setup(LoongArchVirtMachineState *lvms);
+void loongarch_virt_acpi_setup(LoongArchVirtMachineState *lvms);
void virt_fdt_setup(LoongArchVirtMachineState *lvms);
static inline bool virt_has_dmsi(LoongArchVirtMachineState *lvms)
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 024/114] target/riscv: uniquify TCG crc32, crc32c, and wfi helper names
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (22 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 023/114] hw/loongarch/virt: prefix ACPI helper with loongarch_virt_ Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 025/114] hw/riscv: gate boards with target_is_base_riscv Yonggang Luo
` (17 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- ARM already exports helper_crc32, helper_crc32c, helper_wfi, and the
matching helper_info_* objects. RISC-V used the same DEF_HELPER names,
which collide in a combined qemu-system link.
- Rename the RISC-V helpers to riscv_crc32, riscv_crc32c, and riscv_wfi
so the generated C symbols are unique without meson -D prefixes.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/helper.h | 6 +++---
target/riscv/tcg/bitmanip_helper.c | 4 ++--
target/riscv/tcg/insn_trans/trans_privileged.c.inc | 2 +-
target/riscv/tcg/insn_trans/trans_xlrbr.c.inc | 4 ++--
target/riscv/tcg/op_helper.c | 2 +-
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 9458a5152be..ef629b3c650 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -83,8 +83,8 @@ DEF_HELPER_FLAGS_1(unzip, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(zip, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_2(xperm4, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(xperm8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
-DEF_HELPER_FLAGS_2(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl)
-DEF_HELPER_FLAGS_2(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(riscv_crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(riscv_crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl)
/* Floating Point - Half Precision */
DEF_HELPER_FLAGS_3(fadd_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
@@ -134,7 +134,7 @@ DEF_HELPER_1(sret, tl, env)
DEF_HELPER_1(mret, tl, env)
DEF_HELPER_1(mnret, tl, env)
DEF_HELPER_1(ctr_clear, void, env)
-DEF_HELPER_1(wfi, void, env)
+DEF_HELPER_1(riscv_wfi, void, env)
DEF_HELPER_1(wrs_nto, void, env)
DEF_HELPER_1(tlb_flush, void, env)
DEF_HELPER_1(tlb_flush_all, void, env)
diff --git a/target/riscv/tcg/bitmanip_helper.c b/target/riscv/tcg/bitmanip_helper.c
index d8d94bca7ba..5af3efe194d 100644
--- a/target/riscv/tcg/bitmanip_helper.c
+++ b/target/riscv/tcg/bitmanip_helper.c
@@ -117,7 +117,7 @@ target_ulong HELPER(xperm8)(target_ulong rs1, target_ulong rs2)
return do_xperm(rs1, rs2, 3);
}
-target_ulong HELPER(crc32)(target_ulong rs1, target_ulong sz)
+target_ulong HELPER(riscv_crc32)(target_ulong rs1, target_ulong sz)
{
for (target_ulong i = 0; i < sz; i++) {
rs1 = crc32_table[rs1 & 0xFF] ^ (rs1 >> 8);
@@ -126,7 +126,7 @@ target_ulong HELPER(crc32)(target_ulong rs1, target_ulong sz)
return rs1;
}
-target_ulong HELPER(crc32c)(target_ulong rs1, target_ulong sz)
+target_ulong HELPER(riscv_crc32c)(target_ulong rs1, target_ulong sz)
{
for (target_ulong i = 0; i < sz; i++) {
rs1 = crc32c_table[rs1 & 0xFF] ^ (rs1 >> 8);
diff --git a/target/riscv/tcg/insn_trans/trans_privileged.c.inc b/target/riscv/tcg/insn_trans/trans_privileged.c.inc
index a8eaccef67e..0df78e89745 100644
--- a/target/riscv/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_privileged.c.inc
@@ -144,7 +144,7 @@ static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
#ifndef CONFIG_USER_ONLY
decode_save_opc(ctx, 0);
gen_update_pc(ctx, ctx->cur_insn_len);
- gen_helper_wfi(tcg_env);
+ gen_helper_riscv_wfi(tcg_env);
return true;
#else
return false;
diff --git a/target/riscv/tcg/insn_trans/trans_xlrbr.c.inc b/target/riscv/tcg/insn_trans/trans_xlrbr.c.inc
index 01da2b6ce1d..795231f0839 100644
--- a/target/riscv/tcg/insn_trans/trans_xlrbr.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_xlrbr.c.inc
@@ -29,11 +29,11 @@ static bool gen_crc(DisasContext *ctx, arg_r2 *a,
#define TRANS_CRC32(NAME, SIZE) \
static bool trans_crc32_##NAME(DisasContext *ctx, arg_r2 *a) \
{ if (SIZE == 8) { REQUIRE_64BIT(ctx); }; \
- return gen_crc(ctx, a, gen_helper_crc32, tcg_constant_tl(SIZE)); }
+ return gen_crc(ctx, a, gen_helper_riscv_crc32, tcg_constant_tl(SIZE)); }
#define TRANS_CRC32C(NAME, SIZE) \
static bool trans_crc32c_##NAME(DisasContext *ctx, arg_r2 *a) \
{ if (SIZE == 8) { REQUIRE_64BIT(ctx); }; \
- return gen_crc(ctx, a, gen_helper_crc32c, tcg_constant_tl(SIZE)); }
+ return gen_crc(ctx, a, gen_helper_riscv_crc32c, tcg_constant_tl(SIZE)); }
TRANS_CRC32(b, 1);
TRANS_CRC32(h, 2);
diff --git a/target/riscv/tcg/op_helper.c b/target/riscv/tcg/op_helper.c
index a00370a7973..4f4932614f1 100644
--- a/target/riscv/tcg/op_helper.c
+++ b/target/riscv/tcg/op_helper.c
@@ -591,7 +591,7 @@ void helper_ctr_clear(CPURISCVState *env)
riscv_ctr_clear(env);
}
-void helper_wfi(CPURISCVState *env)
+void HELPER(riscv_wfi)(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
bool rvs = riscv_has_ext(env, RVS);
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 025/114] hw/riscv: gate boards with target_is_base_riscv
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (23 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 024/114] target/riscv: uniquify TCG crc32, crc32c, and wfi helper names Yonggang Luo
@ 2026-09-23 13:14 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 026/114] hw/intc: use target_long_bits in IMSIC geilen Yonggang Luo
` (16 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:14 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Set TypeInfo.is_available to target_is_base_riscv on RISC-V machines
so a combined qemu-system lists them only for riscv32/riscv64.
---
hw/riscv/k230.c | 1 +
hw/riscv/microchip_pfsoc.c | 1 +
hw/riscv/opentitan.c | 1 +
hw/riscv/shakti_c.c | 1 +
hw/riscv/sifive_e.c | 1 +
hw/riscv/sifive_u.c | 1 +
hw/riscv/spike.c | 1 +
hw/riscv/tt_atlantis.c | 1 +
hw/riscv/virt.c | 1 +
hw/riscv/xiangshan_kmh.c | 1 +
10 files changed, 10 insertions(+)
diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c
index 79715265da6..3890cb6357d 100644
--- a/hw/riscv/k230.c
+++ b/hw/riscv/k230.c
@@ -557,6 +557,7 @@ static void k230_machine_class_init(ObjectClass *oc, const void *data)
static const TypeInfo k230_machine_typeinfo = {
.name = TYPE_RISCV_K230_MACHINE,
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.class_init = k230_machine_class_init,
.instance_init = k230_machine_instance_init,
.instance_size = sizeof(K230MachineState),
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index cc4b6bc3529..103c0d7f7ca 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -756,6 +756,7 @@ static void microchip_icicle_kit_machine_class_init(ObjectClass *oc,
static const TypeInfo microchip_icicle_kit_machine_typeinfo = {
.name = MACHINE_TYPE_NAME("microchip-icicle-kit"),
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.class_init = microchip_icicle_kit_machine_class_init,
.instance_init = microchip_icicle_kit_machine_instance_init,
.instance_size = sizeof(MicrochipIcicleKitState),
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index 9e3db34eed9..db1fb3e3347 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -337,6 +337,7 @@ static const TypeInfo open_titan_types[] = {
}, {
.name = TYPE_OPENTITAN_MACHINE,
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.instance_size = sizeof(OpenTitanState),
.class_init = opentitan_machine_class_init,
.is_available = target_is_riscv32,
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
index 0f96258b764..e8ae770f7ca 100644
--- a/hw/riscv/shakti_c.c
+++ b/hw/riscv/shakti_c.c
@@ -95,6 +95,7 @@ static void shakti_c_machine_class_init(ObjectClass *klass, const void *data)
static const TypeInfo shakti_c_machine_type_info = {
.name = TYPE_RISCV_SHAKTI_MACHINE,
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.class_init = shakti_c_machine_class_init,
.instance_init = shakti_c_machine_instance_init,
.instance_size = sizeof(ShaktiCMachineState),
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 1b6f9ab4fee..087d0c48e1e 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -165,6 +165,7 @@ static void sifive_e_machine_class_init(ObjectClass *oc, const void *data)
static const TypeInfo sifive_e_machine_typeinfo = {
.name = MACHINE_TYPE_NAME("sifive_e"),
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.class_init = sifive_e_machine_class_init,
.instance_init = sifive_e_machine_instance_init,
.instance_size = sizeof(SiFiveEState),
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 344f3d915d7..d5cc9255da6 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -679,6 +679,7 @@ static void sifive_u_machine_class_init(ObjectClass *oc, const void *data)
static const TypeInfo sifive_u_machine_typeinfo = {
.name = MACHINE_TYPE_NAME("sifive_u"),
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.class_init = sifive_u_machine_class_init,
.instance_init = sifive_u_machine_instance_init,
.instance_size = sizeof(SiFiveUState),
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 63cf77e1de3..4bb58ec6203 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -292,6 +292,7 @@ static void spike_machine_class_init(ObjectClass *oc, const void *data)
static const TypeInfo spike_machine_typeinfo = {
.name = MACHINE_TYPE_NAME("spike"),
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.class_init = spike_machine_class_init,
.instance_init = spike_machine_instance_init,
.instance_size = sizeof(SpikeState),
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index 086e95bd2d1..6e7272d705c 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -699,6 +699,7 @@ static const TypeInfo tt_atlantis_types[] = {
}, {
.name = MACHINE_TYPE_NAME("tt-atlantis"),
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.class_init = tt_atlantis_machine_class_init,
.instance_size = sizeof(TTAtlantisState),
.is_available = target_is_riscv64,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 0edf75fefc3..2240a516d85 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1202,6 +1202,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
static const TypeInfo virt_machine_typeinfo = {
.name = TYPE_RISCV_VIRT_MACHINE,
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.class_init = virt_machine_class_init,
.instance_init = virt_machine_instance_init,
.instance_finalize = virt_machine_instance_finalize,
diff --git a/hw/riscv/xiangshan_kmh.c b/hw/riscv/xiangshan_kmh.c
index 6bc669421fe..9578a11aee6 100644
--- a/hw/riscv/xiangshan_kmh.c
+++ b/hw/riscv/xiangshan_kmh.c
@@ -220,6 +220,7 @@ static void xiangshan_kmh_machine_class_init(ObjectClass *klass, const void *dat
static const TypeInfo xiangshan_kmh_machine_info = {
.name = TYPE_XIANGSHAN_KMH_MACHINE,
.parent = TYPE_MACHINE,
+ .is_available = target_is_base_riscv,
.instance_size = sizeof(XiangshanKmhState),
.class_init = xiangshan_kmh_machine_class_init,
.is_available = target_is_riscv64,
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 026/114] hw/intc: use target_long_bits in IMSIC geilen
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (24 preceding siblings ...)
2026-09-23 13:14 ` [PATCH v3 025/114] hw/riscv: gate boards with target_is_base_riscv Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 027/114] hw/misc/riscv_cmgcr: replace target_ulong with uint64_t Yonggang Luo
` (15 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Compare geilen to target_long_bits() instead of TARGET_LONG_BITS so
the check works when TARGET_* is poisoned.
---
hw/intc/riscv_imsic.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index bf0434e96fd..30fb60cc312 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -52,7 +52,7 @@ static void riscv_cpu_set_geilen(CPURISCVState *env, uint8_t geilen)
return;
}
- if (geilen > (TARGET_LONG_BITS - 1)) {
+ if (geilen > (target_long_bits() - 1)) {
return;
}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 027/114] hw/misc/riscv_cmgcr: replace target_ulong with uint64_t
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (25 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 026/114] hw/intc: use target_long_bits in IMSIC geilen Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 028/114] hw/intc: use kvm_enabled() in APLIC AIA helpers Yonggang Luo
` (14 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Change get_exception_base() to return uint64_t so the GCR model
compiles in libsystem_riscv with -DCPU_DEFS_H.
- Match reset_base and cpu_set_exception_base(), which already use
uint64_t.
---
hw/misc/riscv_cmgcr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/misc/riscv_cmgcr.c b/hw/misc/riscv_cmgcr.c
index 0390996f78b..2086a33f08e 100644
--- a/hw/misc/riscv_cmgcr.c
+++ b/hw/misc/riscv_cmgcr.c
@@ -110,7 +110,7 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
return 0;
}
-static inline target_ulong get_exception_base(RISCVGCRVPState *vps)
+static inline uint64_t get_exception_base(RISCVGCRVPState *vps)
{
return vps->reset_base & GCR_CL_RESET_BASE_RESETBASE_MSK;
}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 028/114] hw/intc: use kvm_enabled() in APLIC AIA helpers
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (26 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 027/114] hw/misc/riscv_cmgcr: replace target_ulong with uint64_t Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-26 9:35 ` Philippe Mathieu-Daudé
2026-09-23 13:15 ` [PATCH v3 029/114] hw/intc: send IMSIC MSI via kvm_irqchip_send_msi() Yonggang Luo
` (13 subsequent siblings)
41 siblings, 1 reply; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Replace CONFIG_KVM ifdefs in riscv_use_emulated_aplic and
riscv_aplic_set_kvm_msicfgaddr with kvm_enabled().
---
hw/intc/riscv_aplic.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index d8e25bfda14..03a0852b8b8 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -167,7 +167,10 @@ bool riscv_is_kvm_aia_aplic_imsic(bool msimode)
bool riscv_use_emulated_aplic(bool msimode)
{
-#ifdef CONFIG_KVM
+ if (!kvm_enabled()) {
+ return true;
+ }
+
if (tcg_enabled()) {
return true;
}
@@ -177,21 +180,20 @@ bool riscv_use_emulated_aplic(bool msimode)
}
return kvm_kernel_irqchip_split();
-#else
- return true;
-#endif
}
void riscv_aplic_set_kvm_msicfgaddr(RISCVAPLICState *aplic, hwaddr addr)
{
-#ifdef CONFIG_KVM
+ if (!kvm_enabled()) {
+ return;
+ }
+
if (riscv_use_emulated_aplic(aplic->msimode)) {
addr >>= APLIC_xMSICFGADDR_PPN_SHIFT;
aplic->kvm_msicfgaddr = extract64(addr, 0, 32);
aplic->kvm_msicfgaddrH = extract64(addr, 32, 32) &
APLIC_MMSICFGADDRH_VALID_MASK;
}
-#endif
}
/*
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 029/114] hw/intc: send IMSIC MSI via kvm_irqchip_send_msi()
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (27 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 028/114] hw/intc: use kvm_enabled() in APLIC AIA helpers Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 030/114] target/riscv: add kvm stubs source set Yonggang Luo
` (12 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Drop the CONFIG_KVM ioctl path and call kvm_irqchip_send_msi() when
KVM and an in-kernel irqchip are enabled.
---
hw/intc/riscv_imsic.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index 30fb60cc312..033b7813060 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -311,19 +311,15 @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
goto err;
}
-#if defined(CONFIG_KVM)
- if (kvm_irqchip_in_kernel()) {
- struct kvm_msi msi;
-
- msi.address_lo = extract64(imsic->mmio.addr + addr, 0, 32);
- msi.address_hi = extract64(imsic->mmio.addr + addr, 32, 32);
- msi.data = le32_to_cpu(value);
-
- kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi);
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+ MSIMessage msg = {
+ .address = imsic->mmio.addr + addr,
+ .data = (uint32_t)value,
+ };
+ kvm_irqchip_send_msi(kvm_state, msg);
return;
}
-#endif
/* Writes only supported for MSI little-endian registers */
page = addr >> IMSIC_MMIO_PAGE_SHIFT;
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 030/114] target/riscv: add kvm stubs source set
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (28 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 029/114] hw/intc: send IMSIC MSI via kvm_irqchip_send_msi() Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 031/114] tcg: fix off-by-one in helper extend-free assert Yonggang Luo
` (11 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Add riscv_stubs_ss and kvm-stub.c, matching the ARM target_stubs_arch
pattern (has_mp_state returns false; other entry points are
g_assert_not_reached).
- Register target_stubs_arch += {'riscv': riscv_stubs_ss}.
- Leave target_arch / target_system_arch in place; next change can
move RISC-V onto target_common_system_arch.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/kvm/kvm-stub.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/target/riscv/kvm/kvm-stub.c b/target/riscv/kvm/kvm-stub.c
index 64e39c96d89..1c8c324cd44 100644
--- a/target/riscv/kvm/kvm-stub.c
+++ b/target/riscv/kvm/kvm-stub.c
@@ -9,6 +9,37 @@
#include "qemu/osdep.h"
#include "target/riscv/kvm/kvm_riscv.h"
+/*
+ * Safe to call without KVM. Return "not supported".
+ */
+bool kvm_riscv_has_mp_state(void)
+{
+ return false;
+}
+
+/*
+ * These functions should never actually be called without KVM support.
+ */
+void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
+{
+ g_assert_not_reached();
+}
+
+void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
+{
+ g_assert_not_reached();
+}
+
+void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
+{
+ g_assert_not_reached();
+}
+
+uint64_t kvm_riscv_get_timebase_frequency(RISCVCPU *cpu)
+{
+ g_assert_not_reached();
+}
+
void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
uint64_t aia_irq_num, uint64_t aia_msi_num,
uint64_t aplic_base, uint64_t imsic_base,
@@ -17,7 +48,7 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
g_assert_not_reached();
}
-uint64_t kvm_riscv_get_timebase_frequency(RISCVCPU *cpu)
+void riscv_kvm_aplic_request(void *opaque, int irq, int level)
{
g_assert_not_reached();
}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 031/114] tcg: fix off-by-one in helper extend-free assert
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (29 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 030/114] target/riscv: add kvm stubs source set Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 032/114] gdbstub: drop per-target cpu-param.h from helpers.h Yonggang Luo
` (10 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Allow n_extend == MAX_CALL_IARGS after filling extend_free.
- The old < check fired on a valid seven-argument extend.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
tcg/tcg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 489df0e7386..6d55cc284df 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2599,7 +2599,7 @@ static void tcg_gen_callN(void *func, TCGHelperInfo *info,
QTAILQ_INSERT_TAIL(&tcg_ctx->ops, op, link);
}
- tcg_debug_assert(n_extend < ARRAY_SIZE(extend_free));
+ tcg_debug_assert(n_extend <= ARRAY_SIZE(extend_free));
for (i = 0; i < n_extend; ++i) {
tcg_temp_free_i64(extend_free[i]);
}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 032/114] gdbstub: drop per-target cpu-param.h from helpers.h
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (30 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 031/114] tcg: fix off-by-one in helper extend-free assert Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 033/114] hw/riscv: expand boston-aia and microblaze-v-generic to TypeInfo Yonggang Luo
` (9 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Stop including cpu-param.h from gdbstub/helpers.h so once-compiled
gdbstub can use the helpers without TARGET_* macros.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
include/gdbstub/helpers.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/include/gdbstub/helpers.h b/include/gdbstub/helpers.h
index b2f41d6d280..7250e457c2c 100644
--- a/include/gdbstub/helpers.h
+++ b/include/gdbstub/helpers.h
@@ -15,9 +15,6 @@
#include "qemu/bswap.h"
#include "qemu/target-info.h"
-#ifdef COMPILING_PER_TARGET
-#include "cpu-param.h"
-#endif
/*
* The GDB remote protocol transfers values in target byte order. As
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 033/114] hw/riscv: expand boston-aia and microblaze-v-generic to TypeInfo
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (31 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 032/114] gdbstub: drop per-target cpu-param.h from helpers.h Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 034/114] target/riscv: Include migration/vmstate.h instead of migration/cpu.h in machine.c Yonggang Luo
` (8 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
Replace DEFINE_MACHINE with TypeInfo on boston-aia and
amd-microblaze-v-generic. Set is_available to target_is_base_riscv.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
hw/riscv/microblaze-v-generic.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/hw/riscv/microblaze-v-generic.c b/hw/riscv/microblaze-v-generic.c
index 3f07ab21328..9b60a955152 100644
--- a/hw/riscv/microblaze-v-generic.c
+++ b/hw/riscv/microblaze-v-generic.c
@@ -14,6 +14,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/target-info.h"
#include "qemu/units.h"
#include "qemu/target-info.h"
#include "qapi/error.h"
@@ -177,8 +178,10 @@ static void mb_v_generic_init(MachineState *machine)
create_unimplemented_device("qspi", QSPI_BASEADDR, 0x10000);
}
-static void mb_v_generic_machine_init(MachineClass *mc)
+static void mb_v_generic_machine_class_init(ObjectClass *oc, const void *data)
{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
mc->desc = "AMD Microblaze-V generic platform";
mc->init = mb_v_generic_init;
mc->min_cpus = 1;
@@ -188,4 +191,16 @@ static void mb_v_generic_machine_init(MachineClass *mc)
mc->default_cpus = 1;
}
-DEFINE_MACHINE("amd-microblaze-v-generic", mb_v_generic_machine_init)
+static const TypeInfo mb_v_generic_machine_class_init_typeinfo = {
+ .name = MACHINE_TYPE_NAME("amd-microblaze-v-generic"),
+ .parent = TYPE_MACHINE,
+ .class_init = mb_v_generic_machine_class_init,
+ .is_available = target_is_base_riscv,
+};
+
+static void mb_v_generic_machine_class_init_register_types(void)
+{
+ type_register_static(&mb_v_generic_machine_class_init_typeinfo);
+}
+
+type_init(mb_v_generic_machine_class_init_register_types)
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 034/114] target/riscv: Include migration/vmstate.h instead of migration/cpu.h in machine.c
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (32 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 033/114] hw/riscv: expand boston-aia and microblaze-v-generic to TypeInfo Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-27 12:16 ` Chao Liu
2026-09-23 13:15 ` [PATCH v3 035/114] target/riscv: gate CPU types with TargetInfo Yonggang Luo
` (7 subsequent siblings)
41 siblings, 1 reply; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
already uses fixed-width VMSTATE_* macros and does not need TARGET_LONG_BITS UINTTL helpers.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/machine.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index bf203bffcef..00805745fbf 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -21,7 +21,7 @@
#include "qemu/error-report.h"
#include "system/kvm.h"
#include "system/tcg.h"
-#include "migration/cpu.h"
+#include "migration/vmstate.h"
#include "exec/icount.h"
#include "target/riscv/tcg/debug.h"
#ifdef CONFIG_KVM
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 035/114] target/riscv: gate CPU types with TargetInfo
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (33 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 034/114] target/riscv: Include migration/vmstate.h instead of migration/cpu.h in machine.c Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 036/114] target/riscv: select ELF dump class from target_riscv64 Yonggang Luo
` (6 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Gate CPU types with TypeInfo.is_available instead of
TARGET_RISCV32/64: DEFINE_RISCV_CPU_AVAIL, DEFINE_RISCV64_CPU,
and DEFINE_RISCV_CPU_32_64SYS.
- Add RISCVCPUDef.target_init. max and bare keep RV64/SV57 in
the TypeInfo; on riscv32 the callbacks set RV32/SV32 after
merge. Do not inherit the parent pointer.
- Validate RV64/128 misa_mxl_max only when not target_riscv32().
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/cpu.c | 128 ++++++++++++++++++++++++++++++---------------
target/riscv/cpu.h | 7 +++
2 files changed, 93 insertions(+), 42 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c6f17390755..4343f431d62 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1586,18 +1586,37 @@ static const MISAExtInfo misa_ext_info_arr[] = {
MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
};
+static void riscv_max_target_init(RISCVCPUClass *mcc)
+{
+ if (!target_riscv32()) {
+ return;
+ }
+ mcc->def->misa_mxl_max = MXL_RV32;
+ mcc->def->cfg.max_satp_mode = VM_1_10_SV32;
+}
+
+static void riscv_bare_target_init(RISCVCPUClass *mcc)
+{
+ if (!target_riscv32()) {
+ return;
+ }
+ /* BARE has no misa_mxl_max, so the class_base_init satp clamp skips it. */
+ mcc->def->cfg.max_satp_mode = VM_1_10_SV32;
+}
+
static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
{
CPUClass *cc = CPU_CLASS(mcc);
/* Validate that MISA_MXL is set properly. */
switch (mcc->def->misa_mxl_max) {
-#ifdef TARGET_RISCV64
case MXL_RV64:
case MXL_RV128:
+ if (target_riscv32()) {
+ g_assert_not_reached();
+ }
cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
break;
-#endif
case MXL_RV32:
cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
break;
@@ -3092,6 +3111,8 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data)
if (pcc->def) {
mcc->def = g_memdup2(pcc->def, sizeof(*pcc->def));
+ /* TypeInfo supplies target_init; do not inherit the parent pointer. */
+ mcc->def->target_init = NULL;
} else {
mcc->def = g_new0(RISCVCPUDef, 1);
}
@@ -3152,6 +3173,9 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data)
mcc->def->custom_csrs = def->custom_csrs;
}
#endif
+ if (def->target_init) {
+ def->target_init(mcc);
+ }
}
if (!object_class_is_abstract(c)) {
@@ -3262,6 +3286,7 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename)
.name = (type_name), \
.parent = (parent_type_name), \
.abstract = true, \
+ .is_available = target_is_base_riscv, \
.class_data = &(const RISCVCPUDef) { \
.priv_spec = RISCV_PROFILE_ATTR_UNUSED, \
.vext_spec = RISCV_PROFILE_ATTR_UNUSED, \
@@ -3270,10 +3295,11 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename)
}, \
}
-#define DEFINE_RISCV_CPU(type_name, parent_type_name, ...) \
+#define DEFINE_RISCV_CPU_AVAIL(type_name, parent_type_name, avail, ...) \
{ \
.name = (type_name), \
.parent = (parent_type_name), \
+ .is_available = (avail), \
.class_data = &(const RISCVCPUDef) { \
.priv_spec = RISCV_PROFILE_ATTR_UNUSED, \
.vext_spec = RISCV_PROFILE_ATTR_UNUSED, \
@@ -3282,8 +3308,37 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename)
}, \
}
+#define DEFINE_RISCV_CPU(type_name, parent_type_name, ...) \
+ DEFINE_RISCV_CPU_AVAIL(type_name, parent_type_name, \
+ target_is_base_riscv, __VA_ARGS__)
+
+#define DEFINE_RISCV64_CPU(type_name, parent_type_name, ...) \
+ DEFINE_RISCV_CPU_AVAIL(type_name, parent_type_name, \
+ target_is_riscv64, __VA_ARGS__)
+
+/*
+ * Original:
+ * #if defined(TARGET_RISCV32) || \
+ * (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
+ *
+ * RV32 models on every riscv32 binary, and on system riscv64
+ * (-cpu rv32 / e31 / ibex). Not linux-user riscv64.
+ */
+static bool riscv32_64sys_available(const TargetInfo *ti)
+{
+#ifdef CONFIG_USER_ONLY
+ return target_is_riscv32(ti);
+#else
+ return target_is_base_riscv(ti);
+#endif
+}
+
+#define DEFINE_RISCV_CPU_32_64SYS(type_name, parent_type_name, ...) \
+ DEFINE_RISCV_CPU_AVAIL(type_name, parent_type_name, \
+ riscv32_64sys_available, __VA_ARGS__)
+
#define DEFINE_PROFILE_CPU(type_name, parent_type_name, profile_) \
- DEFINE_RISCV_CPU(type_name, parent_type_name, \
+ DEFINE_RISCV64_CPU(type_name, parent_type_name, \
.profile = &(profile_))
static void riscv_cpu_instance_finalize(Object *obj)
@@ -3311,6 +3366,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.class_size = sizeof(RISCVCPUClass),
.class_init = riscv_cpu_common_class_init,
.class_base_init = riscv_cpu_class_base_init,
+ .is_available = target_is_base_riscv,
},
DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_DYNAMIC_CPU, TYPE_RISCV_CPU,
@@ -3339,21 +3395,14 @@ static const TypeInfo riscv_cpu_type_infos[] = {
* only MBARE will be available if the user doesn't enable
* a mode manually (see riscv_cpu_satp_mode_finalize()).
*/
-#ifdef TARGET_RISCV32
- .cfg.max_satp_mode = VM_1_10_SV32,
-#else
.cfg.max_satp_mode = VM_1_10_SV57,
-#endif
+ .target_init = riscv_bare_target_init,
),
DEFINE_RISCV_CPU(TYPE_RISCV_CPU_MAX, TYPE_RISCV_DYNAMIC_CPU,
-#if defined(TARGET_RISCV32)
- .misa_mxl_max = MXL_RV32,
- .cfg.max_satp_mode = VM_1_10_SV32,
-#elif defined(TARGET_RISCV64)
.misa_mxl_max = MXL_RV64,
.cfg.max_satp_mode = VM_1_10_SV57,
-#endif
+ .target_init = riscv_max_target_init,
),
DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E, TYPE_RISCV_VENDOR_CPU,
@@ -3378,9 +3427,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.pmp_regions = 8
),
-#if defined(TARGET_RISCV32) || \
- (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE32, TYPE_RISCV_DYNAMIC_CPU,
+ DEFINE_RISCV_CPU_32_64SYS(TYPE_RISCV_CPU_BASE32, TYPE_RISCV_DYNAMIC_CPU,
.cfg.max_satp_mode = VM_1_10_SV32,
.misa_mxl_max = MXL_RV32,
@@ -3406,7 +3453,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.ext_svvptc = true,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_IBEX, TYPE_RISCV_VENDOR_CPU,
+ DEFINE_RISCV_CPU_32_64SYS(TYPE_RISCV_CPU_IBEX, TYPE_RISCV_VENDOR_CPU,
.misa_mxl_max = MXL_RV32,
.misa_ext = RVI | RVM | RVC | RVU,
.priv_spec = PRIV_VERSION_1_12_0,
@@ -3423,37 +3470,35 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.ext_xlrbr = true
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E31, TYPE_RISCV_CPU_SIFIVE_E,
+ DEFINE_RISCV_CPU_32_64SYS(TYPE_RISCV_CPU_SIFIVE_E31, TYPE_RISCV_CPU_SIFIVE_E,
.misa_mxl_max = MXL_RV32
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E34, TYPE_RISCV_CPU_SIFIVE_E,
+ DEFINE_RISCV_CPU_32_64SYS(TYPE_RISCV_CPU_SIFIVE_E34, TYPE_RISCV_CPU_SIFIVE_E,
.misa_mxl_max = MXL_RV32,
.misa_ext = RVF, /* IMAFCU */
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_U34, TYPE_RISCV_CPU_SIFIVE_U,
+ DEFINE_RISCV_CPU_32_64SYS(TYPE_RISCV_CPU_SIFIVE_U34, TYPE_RISCV_CPU_SIFIVE_U,
.misa_mxl_max = MXL_RV32,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV32I, TYPE_RISCV_BARE_CPU,
+ DEFINE_RISCV_CPU_32_64SYS(TYPE_RISCV_CPU_RV32I, TYPE_RISCV_BARE_CPU,
.misa_mxl_max = MXL_RV32,
.misa_ext = RVI
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV32E, TYPE_RISCV_BARE_CPU,
+ DEFINE_RISCV_CPU_32_64SYS(TYPE_RISCV_CPU_RV32E, TYPE_RISCV_BARE_CPU,
.misa_mxl_max = MXL_RV32,
.misa_ext = RVE
),
-#endif
-#if (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_MAX32, TYPE_RISCV_DYNAMIC_CPU,
+#ifndef CONFIG_USER_ONLY
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_MAX32, TYPE_RISCV_DYNAMIC_CPU,
.cfg.max_satp_mode = VM_1_10_SV32,
.misa_mxl_max = MXL_RV32,
),
#endif
-#if defined(TARGET_RISCV64)
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE64, TYPE_RISCV_DYNAMIC_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_BASE64, TYPE_RISCV_DYNAMIC_CPU,
.cfg.max_satp_mode = VM_1_10_SV57,
.misa_mxl_max = MXL_RV64,
@@ -3479,19 +3524,19 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.ext_svvptc = true,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E51, TYPE_RISCV_CPU_SIFIVE_E,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_SIFIVE_E51, TYPE_RISCV_CPU_SIFIVE_E,
.misa_mxl_max = MXL_RV64
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_U54, TYPE_RISCV_CPU_SIFIVE_U,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_SIFIVE_U54, TYPE_RISCV_CPU_SIFIVE_U,
.misa_mxl_max = MXL_RV64,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SHAKTI_C, TYPE_RISCV_CPU_SIFIVE_U,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_SHAKTI_C, TYPE_RISCV_CPU_SIFIVE_U,
.misa_mxl_max = MXL_RV64,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_THEAD_C906, TYPE_RISCV_VENDOR_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_THEAD_C906, TYPE_RISCV_VENDOR_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVG | RVC | RVS | RVU,
.priv_spec = PRIV_VERSION_1_11_0,
@@ -3519,7 +3564,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
#endif
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_THEAD_C908, TYPE_RISCV_VENDOR_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_THEAD_C908, TYPE_RISCV_VENDOR_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU,
.priv_spec = PRIV_VERSION_1_12_0,
@@ -3566,12 +3611,12 @@ static const TypeInfo riscv_cpu_type_infos[] = {
#endif
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_THEAD_C908V, TYPE_RISCV_CPU_THEAD_C908,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_THEAD_C908V, TYPE_RISCV_CPU_THEAD_C908,
.misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU | RVV,
.vext_spec = VEXT_VERSION_1_00_0,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_TT_ASCALON, TYPE_RISCV_VENDOR_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_TT_ASCALON, TYPE_RISCV_VENDOR_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVG | RVC | RVS | RVU | RVH | RVV,
.priv_spec = PRIV_VERSION_1_13_0,
@@ -3635,7 +3680,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.max_satp_mode = VM_1_10_SV57,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_VEYRON_V1, TYPE_RISCV_VENDOR_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_VEYRON_V1, TYPE_RISCV_VENDOR_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVG | RVC | RVS | RVU | RVH,
.priv_spec = PRIV_VERSION_1_12_0,
@@ -3671,7 +3716,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.max_satp_mode = VM_1_10_SV48,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_XIANGSHAN_NANHU, TYPE_RISCV_VENDOR_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_XIANGSHAN_NANHU, TYPE_RISCV_VENDOR_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVG | RVC | RVB | RVS | RVU,
.priv_spec = PRIV_VERSION_1_12_0,
@@ -3694,7 +3739,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.max_satp_mode = VM_1_10_SV39,
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_XIANGSHAN_KMH, TYPE_RISCV_VENDOR_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_XIANGSHAN_KMH, TYPE_RISCV_VENDOR_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVG | RVC | RVB | RVS | RVU | RVH | RVV,
.priv_spec = PRIV_VERSION_1_13_0,
@@ -3754,7 +3799,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
),
/* https://mips.com/products/hardware/p8700/ */
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_MIPS_P8700, TYPE_RISCV_VENDOR_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_MIPS_P8700, TYPE_RISCV_VENDOR_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU,
.priv_spec = PRIV_VERSION_1_12_0,
@@ -3777,16 +3822,16 @@ static const TypeInfo riscv_cpu_type_infos[] = {
),
#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE128, TYPE_RISCV_DYNAMIC_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_BASE128, TYPE_RISCV_DYNAMIC_CPU,
.cfg.max_satp_mode = VM_1_10_SV57,
.misa_mxl_max = MXL_RV128,
),
#endif /* CONFIG_TCG */
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV64I, TYPE_RISCV_BARE_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_RV64I, TYPE_RISCV_BARE_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVI
),
- DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV64E, TYPE_RISCV_BARE_CPU,
+ DEFINE_RISCV64_CPU(TYPE_RISCV_CPU_RV64E, TYPE_RISCV_BARE_CPU,
.misa_mxl_max = MXL_RV64,
.misa_ext = RVE
),
@@ -3795,7 +3840,6 @@ static const TypeInfo riscv_cpu_type_infos[] = {
DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22S64, TYPE_RISCV_CPU_RV64I, RVA22S64),
DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA23U64, TYPE_RISCV_CPU_RV64I, RVA23U64),
DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA23S64, TYPE_RISCV_CPU_RV64I, RVA23S64),
-#endif /* TARGET_RISCV64 */
};
DEFINE_TYPES(riscv_cpu_type_infos)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 034d7e96c49..265c6322067 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -597,6 +597,13 @@ typedef struct RISCVCPUDef {
#endif
/* This is just a setter for env->num_triggers. */
uint32_t num_triggers;
+
+ /*
+ * Optional per-CPU callback run from riscv_cpu_class_base_init
+ * after the static def is merged. Use it to adjust fields that
+ * depend on the build target (e.g. clamp misa_mxl_max for RV32).
+ */
+ void (*target_init)(struct RISCVCPUClass *mcc);
} RISCVCPUDef;
/**
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 036/114] target/riscv: select ELF dump class from target_riscv64
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (34 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 035/114] target/riscv: gate CPU types with TargetInfo Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 037/114] target/riscv: replace TARGET_* macros in CSR helpers Yonggang Luo
` (5 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Replace TARGET_RISCV64 with target_riscv64() so dump class still
follows the QEMU target, not guest MXL.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/arch_dump.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/target/riscv/arch_dump.c b/target/riscv/arch_dump.c
index 12b68799070..2704bd8d94e 100644
--- a/target/riscv/arch_dump.c
+++ b/target/riscv/arch_dump.c
@@ -175,11 +175,11 @@ int cpu_get_dump_info(ArchDumpInfo *info,
info->d_machine = EM_RISCV;
-#if defined(TARGET_RISCV64)
- info->d_class = ELFCLASS64;
-#else
- info->d_class = ELFCLASS32;
-#endif
+ if (target_riscv64()) {
+ info->d_class = ELFCLASS64;
+ } else {
+ info->d_class = ELFCLASS32;
+ }
info->d_endian = (env->mstatus & MSTATUS_UBE) != 0 ?
ELFDATA2MSB : ELFDATA2LSB;
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 037/114] target/riscv: replace TARGET_* macros in CSR helpers
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (35 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 036/114] target/riscv: select ELF dump class from target_riscv64 Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 038/114] target/riscv: use target_long_bits in pmpaddr granule checks Yonggang Luo
` (4 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Use target_long_bits() instead of TARGET_LONG_BITS for the CSR
write mask.
- Use target_riscv64() instead of TARGET_RISCV64 for MISA RV64 and
the PMP address mask.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/tcg/csr.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index 061bc9db77b..0b96fff6b96 100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/target-info.h"
#include "qemu/log.h"
#include "qemu/timer.h"
#include "cpu.h"
@@ -2143,17 +2144,18 @@ static RISCVException read_misa_i128(CPURISCVState *env, int csrno,
static RISCVException read_misa(CPURISCVState *env, int csrno,
target_ulong *val)
{
- target_ulong misa;
+ uint64_t misa;
switch (env->misa_mxl) {
case MXL_RV32:
- misa = (target_ulong)MXL_RV32 << 30;
+ misa = (uint64_t)MXL_RV32 << 30;
break;
-#ifdef TARGET_RISCV64
case MXL_RV64:
- misa = (target_ulong)MXL_RV64 << 62;
+ if (!target_riscv64()) {
+ g_assert_not_reached();
+ }
+ misa = (uint64_t)MXL_RV64 << 62;
break;
-#endif
default:
g_assert_not_reached();
}
@@ -5430,13 +5432,11 @@ static RISCVException read_pmpaddr(CPURISCVState *env, int csrno,
* here to avoid complaints about masking bits 0-53
* of a potential 32 bit target_ulong '*var'.
*/
-#ifdef TARGET_RISCV64
- if (env->misa_mxl == MXL_RV64
+ if (target_riscv64() && env->misa_mxl == MXL_RV64
&& csrno >= CSR_PMPADDR0 && csrno <= CSR_PMPADDR63) {
- target_ulong read_mask = MAKE_64BIT_MASK(0, 54);
+ uint64_t read_mask = MAKE_64BIT_MASK(0, 54);
*val &= read_mask;
}
-#endif
return RISCV_EXCP_NONE;
}
@@ -5755,7 +5755,7 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
RISCVException riscv_csr_write_i64(CPURISCVState *env, int csrno, uint64_t val)
{
return riscv_csrrw(env, csrno, NULL, val,
- MAKE_64BIT_MASK(0, TARGET_LONG_BITS), 0);
+ MAKE_64BIT_MASK(0, target_long_bits()), 0);
}
RISCVException riscv_csr_read_i64(CPURISCVState *env, int csrno, uint64_t *res)
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 038/114] target/riscv: use target_long_bits in pmpaddr granule checks
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (36 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 037/114] target/riscv: replace TARGET_* macros in CSR helpers Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 039/114] target/riscv: preserve signed XLEN semantics without target_long Yonggang Luo
` (3 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Replace TARGET_LONG_BITS with target_long_bits() for TOR/NAPOT
PMP address masking.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/tcg/pmp.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/target/riscv/tcg/pmp.c b/target/riscv/tcg/pmp.c
index 41b55519a8e..03ee7c74300 100644
--- a/target/riscv/tcg/pmp.c
+++ b/target/riscv/tcg/pmp.c
@@ -23,6 +23,7 @@
#include "qemu/log.h"
#include "qapi/error.h"
#include "cpu.h"
+#include "qemu/target-info.h"
#include "target/riscv/tcg/csr.h"
#include "trace.h"
#include "exec/cputlb.h"
@@ -643,14 +644,14 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index)
/* fallthrough */
case PMP_AMATCH_TOR:
/* Bit [g-1:0] read all zero */
- if (g >= 1 && g < TARGET_LONG_BITS) {
+ if (g >= 1 && g < target_long_bits()) {
uint64_t granule = 1ULL << g;
val = ROUND_DOWN(val, granule);
}
break;
case PMP_AMATCH_NAPOT:
/* Bit [g-2:0] read all one */
- if (g >= 2 && g < TARGET_LONG_BITS) {
+ if (g >= 2 && g < target_long_bits()) {
val = deposit64(val, 0, g - 1, -1ULL);
}
break;
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 039/114] target/riscv: preserve signed XLEN semantics without target_long
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (37 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 038/114] target/riscv: use target_long_bits in pmpaddr granule checks Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 040/114] target/riscv: replace leftover TARGET_LONG_BITS Yonggang Luo
` (2 subsequent siblings)
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Mask pointer-masked addresses with extract64/sextract64 at
runtime XLEN instead of a target_long arithmetic shift.
- Pass vector vx scalars as int64_t after sextract64 from the
helper tl slot so RV32 keeps bit 31 as the sign bit.
- Leave every target_ulong helper argument unchanged.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/internals.h | 12 ++++++++----
target/riscv/tcg/vector_helper.c | 21 +++++++++++----------
target/riscv/tcg/vector_internals.c | 2 +-
target/riscv/tcg/vector_internals.h | 9 +++++----
4 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 1ee7e99e988..0844867246d 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -214,6 +214,7 @@ static inline target_ulong adjust_addr_body(CPURISCVState *env,
{
RISCVPmPmm pmm = PMM_FIELD_DISABLED;
uint32_t pmlen = 0;
+ unsigned kept;
bool signext = false;
/* do nothing for rv32 mode */
@@ -235,13 +236,16 @@ static inline target_ulong adjust_addr_body(CPURISCVState *env,
signext = riscv_cpu_virt_mem_enabled(env, is_virt_addr);
pmlen = riscv_pm_get_pmlen(pmm);
- addr = addr << pmlen;
- /* sign/zero extend masked address by N-1 bit */
+ /*
+ * Drop the top pmlen bits of XLEN. Do not rely on target_ulong
+ * shift wrap; common-system target_ulong is always 64 bits.
+ */
+ kept = target_long_bits() - pmlen;
if (signext) {
- addr = (target_long)addr >> pmlen;
+ addr = sextract64(addr, 0, kept);
} else {
- addr = addr >> pmlen;
+ addr = extract64(addr, 0, kept);
}
return addr;
diff --git a/target/riscv/tcg/vector_helper.c b/target/riscv/tcg/vector_helper.c
index 0d1e4e09646..0b78a733ce4 100644
--- a/target/riscv/tcg/vector_helper.c
+++ b/target/riscv/tcg/vector_helper.c
@@ -1248,7 +1248,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
ETYPE carry = vext_elem_mask(v0, i); \
\
- *((ETYPE *)vd + H(i)) = DO_OP(s2, (ETYPE)(target_long)s1, carry);\
+ *((ETYPE *)vd + H(i)) = DO_OP(s2, (ETYPE)sextract64(s1, 0, target_long_bits()), carry);\
} \
env->vstart = 0; \
/* set tail elements to 1s */ \
@@ -1325,7 +1325,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
ETYPE carry = !vm && vext_elem_mask(v0, i); \
vext_set_elem_mask(vd, i, \
- DO_OP(s2, (ETYPE)(target_long)s1, carry)); \
+ DO_OP(s2, (ETYPE)sextract64(s1, 0, target_long_bits()), carry)); \
} \
env->vstart = 0; \
/*
@@ -1609,7 +1609,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
continue; \
} \
vext_set_elem_mask(vd, i, \
- DO_OP(s2, (ETYPE)(target_long)s1)); \
+ DO_OP(s2, (ETYPE)sextract64(s1, 0, target_long_bits()))); \
} \
env->vstart = 0; \
/*
@@ -2050,7 +2050,7 @@ GEN_VEXT_VV(vnmsub_vv_w, 4)
GEN_VEXT_VV(vnmsub_vv_d, 8)
#define OPIVX3(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
-static void do_##NAME(void *vd, target_long s1, void *vs2, int i) \
+static void do_##NAME(void *vd, int64_t s1, void *vs2, int i) \
{ \
TX2 s2 = *((T2 *)vs2 + HS2(i)); \
TD d = *((TD *)vd + HD(i)); \
@@ -2246,7 +2246,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
for (i = env->vstart; i < vl; i++) { \
ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
ETYPE d = (!vext_elem_mask(v0, i) ? s2 : \
- (ETYPE)(target_long)s1); \
+ (ETYPE)sextract64(s1, 0, target_long_bits())); \
*((ETYPE *)vd + H(i)) = d; \
} \
env->vstart = 0; \
@@ -2397,12 +2397,12 @@ GEN_VEXT_VV_RM(vsaddu_vv_h, 2)
GEN_VEXT_VV_RM(vsaddu_vv_w, 4)
GEN_VEXT_VV_RM(vsaddu_vv_d, 8)
-typedef void opivx2_rm_fn(void *vd, target_long s1, void *vs2, int i,
+typedef void opivx2_rm_fn(void *vd, int64_t s1, void *vs2, int i,
CPURISCVState *env, uint8_t vxrm);
#define OPIVX2_RM(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
static inline void \
-do_##NAME(void *vd, target_long s1, void *vs2, int i, \
+do_##NAME(void *vd, int64_t s1, void *vs2, int i, \
CPURISCVState *env, uint8_t vxrm) \
{ \
TX2 s2 = *((T2 *)vs2 + HS2(i)); \
@@ -2410,7 +2410,7 @@ do_##NAME(void *vd, target_long s1, void *vs2, int i, \
}
static inline void
-vext_vx_rm_1(void *vd, void *v0, target_long s1, void *vs2,
+vext_vx_rm_1(void *vd, void *v0, int64_t s1, void *vs2,
CPURISCVState *env,
uint32_t vl, uint32_t vm, uint8_t vxrm,
opivx2_rm_fn *fn, uint32_t vma, uint32_t esz)
@@ -2427,7 +2427,7 @@ vext_vx_rm_1(void *vd, void *v0, target_long s1, void *vs2,
}
static inline void
-vext_vx_rm_2(void *vd, void *v0, target_long s1, void *vs2,
+vext_vx_rm_2(void *vd, void *v0, int64_t s1, void *vs2,
CPURISCVState *env,
uint32_t desc,
opivx2_rm_fn *fn, uint32_t esz)
@@ -2468,7 +2468,8 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
void *vs2, CPURISCVState *env, \
uint32_t desc) \
{ \
- vext_vx_rm_2(vd, v0, s1, vs2, env, desc, \
+ vext_vx_rm_2(vd, v0, sextract64(s1, 0, target_long_bits()), \
+ vs2, env, desc, \
do_##NAME, ESZ); \
}
diff --git a/target/riscv/tcg/vector_internals.c b/target/riscv/tcg/vector_internals.c
index b490b1d3989..95327052666 100644
--- a/target/riscv/tcg/vector_internals.c
+++ b/target/riscv/tcg/vector_internals.c
@@ -81,7 +81,7 @@ void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2,
vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
}
-void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2,
+void do_vext_vx(void *vd, void *v0, int64_t s1, void *vs2,
CPURISCVState *env, uint32_t desc,
opivx2_fn fn, uint32_t esz)
{
diff --git a/target/riscv/tcg/vector_internals.h b/target/riscv/tcg/vector_internals.h
index 5681b818153..da093d561eb 100644
--- a/target/riscv/tcg/vector_internals.h
+++ b/target/riscv/tcg/vector_internals.h
@@ -201,20 +201,20 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \
do_##NAME, ESZ); \
}
-typedef void opivx2_fn(void *vd, target_long s1, void *vs2, int i);
+typedef void opivx2_fn(void *vd, int64_t s1, void *vs2, int i);
/*
* (T1)s1 gives the real operator type.
* (TX1)(T1)s1 expands the operator type of widen or narrow operations.
*/
#define OPIVX2(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
-static void do_##NAME(void *vd, target_long s1, void *vs2, int i) \
+static void do_##NAME(void *vd, int64_t s1, void *vs2, int i) \
{ \
TX2 s2 = *((T2 *)vs2 + HS2(i)); \
*((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1); \
}
-void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2,
+void do_vext_vx(void *vd, void *v0, int64_t s1, void *vs2,
CPURISCVState *env, uint32_t desc,
opivx2_fn fn, uint32_t esz);
@@ -224,7 +224,8 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
void *vs2, CPURISCVState *env, \
uint32_t desc) \
{ \
- do_vext_vx(vd, v0, s1, vs2, env, desc, \
+ do_vext_vx(vd, v0, sextract64(s1, 0, target_long_bits()), \
+ vs2, env, desc, \
do_##NAME, ESZ); \
}
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v3 040/114] target/riscv: replace leftover TARGET_LONG_BITS
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (38 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 039/114] target/riscv: preserve signed XLEN semantics without target_long Yonggang Luo
@ 2026-09-23 13:15 ` Yonggang Luo
2026-09-23 13:37 ` [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Jan Beulich
2026-09-23 14:44 ` Pierrick Bouvier
41 siblings, 0 replies; 45+ messages in thread
From: Yonggang Luo @ 2026-09-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
- Use target_long_bits() in bitmanip clmul/clmulr/xperm loops and in
the m128 signed-div overflow check.
- Compare xperm element positions to target_long_bits() instead of
sizeof(target_ulong), which is always 8 in common-system.
- Leave translate.c and insn_trans TARGET_LONG_BITS for riscv-tcg-tl.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
target/riscv/tcg/bitmanip_helper.c | 10 +++++-----
target/riscv/tcg/m128_helper.c | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/target/riscv/tcg/bitmanip_helper.c b/target/riscv/tcg/bitmanip_helper.c
index 5af3efe194d..db226146054 100644
--- a/target/riscv/tcg/bitmanip_helper.c
+++ b/target/riscv/tcg/bitmanip_helper.c
@@ -30,7 +30,7 @@ target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2)
{
target_ulong result = 0;
- for (int i = 0; i < TARGET_LONG_BITS; i++) {
+ for (int i = 0; i < target_long_bits(); i++) {
if ((rs2 >> i) & 1) {
result ^= (rs1 << i);
}
@@ -43,9 +43,9 @@ target_ulong HELPER(clmulr)(target_ulong rs1, target_ulong rs2)
{
target_ulong result = 0;
- for (int i = 0; i < TARGET_LONG_BITS; i++) {
+ for (int i = 0; i < target_long_bits(); i++) {
if ((rs2 >> i) & 1) {
- result ^= (rs1 >> (TARGET_LONG_BITS - i - 1));
+ result ^= (rs1 >> (target_long_bits() - i - 1));
}
}
@@ -98,9 +98,9 @@ static inline target_ulong do_xperm(target_ulong rs1, target_ulong rs2,
target_ulong mask = (1LL << sz) - 1;
target_ulong pos;
- for (int i = 0; i < TARGET_LONG_BITS; i += sz) {
+ for (int i = 0; i < target_long_bits(); i += sz) {
pos = ((rs2 >> i) & mask) << sz_log2;
- if (pos < sizeof(target_ulong) * 8) {
+ if (pos < target_long_bits()) {
r |= ((rs1 >> pos) & mask) << i;
}
}
diff --git a/target/riscv/tcg/m128_helper.c b/target/riscv/tcg/m128_helper.c
index 7d9b83b1b2c..e59a1ffd7a7 100644
--- a/target/riscv/tcg/m128_helper.c
+++ b/target/riscv/tcg/m128_helper.c
@@ -71,7 +71,7 @@ target_ulong HELPER(divs_i128)(CPURISCVState *env,
if (vl == 0 && vh == 0) { /* Div by zero check */
ql = ~0x0;
qh = ~0x0;
- } else if (uh == (1ULL << (TARGET_LONG_BITS - 1)) && ul == 0 &&
+ } else if (uh == (1ULL << (target_long_bits() - 1)) && ul == 0 &&
vh == ~0x0 && vl == ~0x0) {
/* Signed div overflow check (-2**127 / -1) */
ql = ul;
--
2.52.0.windows.1
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH v3 000/114] single-binary: link multi-targets into qemu-system
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (39 preceding siblings ...)
2026-09-23 13:15 ` [PATCH v3 040/114] target/riscv: replace leftover TARGET_LONG_BITS Yonggang Luo
@ 2026-09-23 13:37 ` Jan Beulich
2026-09-23 14:44 ` Pierrick Bouvier
41 siblings, 0 replies; 45+ messages in thread
From: Jan Beulich @ 2026-09-23 13:37 UTC (permalink / raw)
To: Yonggang Luo
Cc: xen-devel, qemu-ppc, qemu-riscv, kvm, qemu-arm, qemu-s390x,
qemu-devel
(reducing Cc list to mailing lists)
On 23.09.2026 15:14, Yonggang Luo wrote:
> This series produces one qemu-system binary that can run ARM (32 and
> 64), RISC-V (32 and 64), and MicroBlaze.
> Upstream filters machines with TypeInfo.is_available. This series
> passes a TargetInfo into that callback, uniquifies QOM names that
> collide in one process, and compiles those targets once so they can
> share qemu-system.
>
> A combined link cannot keep C symbols or QOM type names that were
> unique only because each qemu-system-$arch was a separate binary.
> These patches remove those collisions:
>
> - TYPE_ACCEL_CPU is the fixed abstract type accel-cpu, registered
> once next to TYPE_ACCEL. Leaf names still encode the CPU type so
> accel_init_cpu_interfaces() can look up "<accel>-" plus
> target_cpu_type() (tcg-accel-arm-cpu).
> - virt QOM names are prefixed: arm-virt, riscv-virt, and the same
> for or1k, hexagon, loongarch, m68k, and xtensa. Boards keep
> -machine virt via machine_class_set_name(). query-machines returns
> the QOM type in MachineInfo typename.
> - virt ACPI helpers and RISC-V TCG crc32/crc32c/wfi helpers get an
> arch prefix so the combined link does not need meson -D name
> mangling. LoongArch virt_acpi_setup is renamed in the same pass.
>
> Target selection has to work with more than one TargetInfo:
>
> - The combined binary takes arch:name on -M/-machine and in a
> [machine] type (aarch64:virt). arch: binds the target. microblaze:
> runs that target's default machine. arm, aarch64, riscv32, and
> riscv64 have no default. No -M leaves target none and the empty
> none machine. qemu-system-$arch keeps the historic -M name.
> -M help lists every target; arch:help lists one. query-targets
> lists each linked target, including none.
> - TargetInfo is a constructor list. target_info_select() picks the
> entry, including SYS_EMU_TARGET_NONE. is_available takes const
> TargetInfo *. While the target is still none, QOM skips the
> unavailable filter so grouped -M help can list every machine.
> - query-cpu-definitions, dump notes, and Angel semihosting sit on
> TargetCpuOps indexed by target_arch(). Registration uses a
> QEMU_ARCH_* bitmask so one object can fill ARM and AARCH64. The
> table is target-ops.h / target-ops.c.
>
> qemu-system-$TARGET is still built, including the Windows *w twin.
> qemu-system is extra. It links each target whose arch sources are
> only target-info-def.c: arm, aarch64, riscv32, riscv64, and
> microblaze. Do not add qemu-systemw for that binary. A GUI
> twin would keep QEMU exporting data from the .exe into DLLs, and
> those data exports cannot be delay-loaded (qdev_prop_array and
> other qdev_prop_*). That would block enabling modules globally on
> Windows.
>
> Examples:
>
> qemu-system -M aarch64:virt ...
> qemu-system -M microblaze:petalogix-s3adsp1800 ...
> qemu-system-riscv64 -M virt ...
>
> A bare machine name on qemu-system needs an arch: prefix. An unknown
> target fails with "target '...' is not available".
>
> Prerequisites:
> [PATCH v2 0/9] machine: uniquify virt QOM names
> https://patchew.org/QEMU/20260922215533.641-1-luoyonggang@gmail.com/
> [PATCH 00/21] accel/tcg: share raise_excp across TCG targets
> https://patchew.org/QEMU/20260918004225.827-1-luoyonggang@gmail.com/
> [PATCH v5 00/11] single-binary: Compile hw/riscv once
> https://patchew.org/QEMU/20260918-hw-riscv-cpu-int-v5-0-f98c5a244636@rev.ng/
>
> v1: https://patchew.org/QEMU/20260823150731.896-1-luoyonggang@gmail.com/
> v2: https://patchew.org/QEMU/20260826184229.1145-1-luoyonggang@gmail.com/
> branch: https://gitlab.com/lygstate-qemu/qemu/-/tree/single-binary-arm-riscv?ref_type=heads
> x86_64 and i386: https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
>
> Changes v2 -> v3:
> - Drop -target. v2 parsed a target_name token and required it on
> bare qemu-system, with -target ? to list names. v3 selects the
> target with arch:name on -M. No -M leaves target none. -M help
> and arch:help list machines.
> - Rebased onto current master. Upstream is_available(void) replaces
> TYPE_TARGET_SPECIFIC. v3 passes const TargetInfo * into
> is_available. The v2 patches that registered TYPE_TARGET_SPECIFIC
> on ARM and RISC-V virt are dropped.
> - TargetInfo is a constructor list, not chosen from argv[0].
> target_info_select() sets the current entry. Add SysEmuTarget
> none. A single-target binary does not switch TargetInfo; arch:
> must match that binary or the machine is rejected.
> - Drop -Dsingle_binary. qemu-system is built from
> single_binary_supported_targets once arch_srcs are only
> target-info-def.c. microblaze joins ARM and RISC-V. Per-target
> binaries stay. Still no qemu-systemw for the combined binary.
> - Unique virt QOM names extend past ARM and RISC-V to or1k,
> hexagon, loongarch, m68k, and xtensa. query-machines returns
> MachineInfo typename.
> - TargetCpuOps is an array indexed by target_arch(), registered
> with a QEMU_ARCH_* bitmask. The header moves from
> target-info-qom.h to target-ops.h.
> - Those targets are compiled once: ARM, RISC-V, and MicroBlaze fold
> into common source sets, TARGET_* ifdefs become runtime checks, and
> KVM moves to system_ss.
>
> Pierrick Bouvier (2):
> configs/targets: remove target info definitions
> target-info: rename target-info-stub.c in target-info-def.c
>
> Yonggang Luo (112):
> meson: stale qemu-version.h only when .git exists
> target-info: rename target-info-impl.h to target-info-def.h
> target-info: set cpu_type from TARGET_BASE_ARCH
> target: remove CPU_RESOLVING_TYPE
> vl: parse early options before target-info init
> target-info: replace QOM registration with a constructor list
> tests/unit: add test-target-info
> tests/qtest: prepare machine-list-test for combined qemu-system
> kconfig: rename REGISTER to HW_REGISTER
> target-info: add TargetKconfig
> target-info: add target_is_* helpers for each architecture
> target-info: add i386 and x86_64 helpers
> qom: pass TargetInfo to is_available
> module: use static ModuleEntry and per-type DSO lists
> module: add before/after hooks and module_call_init_fn
> qom: register late types through module_call_init_fn
> qom: inherit is_available and filter after MODULE_INIT_QOM
> tests/unit: add module-init and qom is-available tests
> hw/arm/virt: prefix ACPI helpers with arm_virt_
> hw/riscv/virt: prefix ACPI helpers with riscv_virt_
> hw/loongarch/virt: prefix ACPI helper with loongarch_virt_
> target/riscv: uniquify TCG crc32, crc32c, and wfi helper names
> hw/riscv: gate boards with target_is_base_riscv
> hw/intc: use target_long_bits in IMSIC geilen
> hw/misc/riscv_cmgcr: replace target_ulong with uint64_t
> hw/intc: use kvm_enabled() in APLIC AIA helpers
> hw/intc: send IMSIC MSI via kvm_irqchip_send_msi()
> target/riscv: add kvm stubs source set
> tcg: fix off-by-one in helper extend-free assert
> gdbstub: drop per-target cpu-param.h from helpers.h
> hw/riscv: expand boston-aia and microblaze-v-generic to TypeInfo
> target/riscv: Include migration/vmstate.h instead of migration/cpu.h
> in machine.c
> target/riscv: gate CPU types with TargetInfo
> target/riscv: select ELF dump class from target_riscv64
> target/riscv: replace TARGET_* macros in CSR helpers
> target/riscv: use target_long_bits in pmpaddr granule checks
> target/riscv: preserve signed XLEN semantics without target_long
> target/riscv: replace leftover TARGET_LONG_BITS
> target/riscv: select monitor width at runtime
> target/riscv: replace target-width format macros
> target/riscv: replace TARGET_LONG_BITS in translate
> target-info: add tl_is_64() and target_is_tl32/64 helpers
> target-info: dispatch CPU QMP, dump, and Angel semihosting
> tcg: give TCGv its own type and runtime tl ops
> exec: allow target_long.h, abi_ptr.h and cpu-ldst.h from common code
> migration: add TargetInfo-gated vmstate fields
> target/i386: always compile XMM, YMMH, and Hi16 VMSD
> target/i386: replace VMSTATE_UINTTL with 32/64 TI fields
> target/ppc: replace VMSTATE_UINTTL with 32/64 TI fields
> target/sparc: replace VMSTATE_UINTTL with 32/64 TI fields
> target/mips: replace VMSTATE_UINTTL with 32/64 TI fields
> hw/hexagon: drop unused migration/cpu.h include
> migration: remove unused cpu.h
> target/riscv: gate KVM CPU VMSDs with target_has_kconfig_kvm
> target/riscv: use tcg_imm_tl in translate
> target/riscv: select FP and amocas width at runtime
> target/riscv: drop TARGET_RISCV XL shortcuts in translate
> target/riscv: select KVM host CPU width at runtime
> accel: use a shared TYPE_ACCEL_CPU parent
> kvm: always compile guest debug
> hw/i386: move APIC_DEFAULT_ADDRESS to apic.h
> kvm: stop including cpu.h from kvm.h
> kvm: default kvm_arch_reset_parked_vcpu in stubs
> kvm: drop COMPILING_PER_TARGET wrap around kvm_arch APIs
> kvm: add split irqchip and send_msi stubs
> kvm: replace TARGET_S390X and TARGET_PPC hints
> kvm: move kvm_ss to system_ss
> system: add qemu_host_arch() and reject unavailable -accel
> kvm: add AccelClass is_available for host/guest pairing
> hvf: add AccelClass is_available for host/guest pairing
> xen: add AccelClass is_available for host/guest pairing
> nitro: add AccelClass is_available for host/guest pairing
> mshv: add AccelClass is_available for host/guest pairing
> whpx: add AccelClass is_available for host/guest pairing
> target/i386/nvmm: add AccelClass is_available for host/guest pairing
> accel: replace ACCEL_CPU_NAME with accel_cpu_register_type
> whpx: move whpx_ss to system_ss
> hw/riscv: move boards and irqchip onto hw_common_arch
> target/riscv: include target_long.h in TCG helpers
> target/riscv: compile CPU and TCG once
> target/arm: replace target_long in A64 translate
> target/arm: use 64-bit TCG addresses in A64 translate
> target/arm: move kvm_arm_set_cpreg_mig_tolerances to kvm.c
> target/arm: allow -cpu host with Nitro
> target/arm: gate -cpu host with TypeIsAvailable
> target/arm: fix family-common KVM compile
> tests/qtest: raise aspeed_smc-test timeout to 12 minutes
> hw/intc: move ARM GIC kvm/hvf/whpx onto arm_common_ss
> target/arm: fold arm_ss into common source sets
> meson: link shared objects into qemu-system
> target/microblaze: fold system sources into common source sets
> meson: add microblaze-softmmu to the combined qemu-system list
> boards: remove unused DEFINE_MACHINE_WITH_INTERFACES
> hw/arm: set virt TypeInfo.is_available
> hw/arm: set remaining 32-bit machine TypeInfo.is_available
> hw/arm: set aarch64-only machine TypeInfo.is_available
> hw/microblaze: set petalogix-s3adsp1800 TypeInfo.is_available
> hw/arm: expand leftover 32-bit DEFINE_MACHINE to TypeInfo
> hw/arm: expand imx8mm-evk DEFINE_MACHINE to TypeInfo
> hw/microblaze: expand petalogix-ml605 and xlnx-zynqmp-pmu to TypeInfo
> hw/i386: set TYPE_X86_MACHINE TypeInfo.is_available
> hw/block/dataplane: move xen-block onto system_ss
> hw/remote: move multiprocess memory onto remote_ss
> hw/remote: set x-remote TypeInfo.is_available
> target-info: add SysEmuTarget none
> accel/tcg: tolerate NULL target_cpu_type for -M none
> qom: skip unavailable filter when target_none()
> module: load every arch-tagged module when target is none
> target-info: select combined qemu-system target by name
> vl: parse arch: machine types on combined qemu-system
> qapi: add query-targets
> tests/qtest: cover combined qemu-system machines and accel-cpu
Now this is really excessive: You mail out a huge series (a fair part
of which apparently still needs to make it through), cross posting to
lists covering components which are touched only in very few places of
the series. I consider such rude already for much smaller series; here
you definitely should have made per-patch Cc lists. I wouldn't be
surprised if xen-devel@ isn't the only list which is being spammed for
no good reason.
Jan
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v3 000/114] single-binary: link multi-targets into qemu-system
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
` (40 preceding siblings ...)
2026-09-23 13:37 ` [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Jan Beulich
@ 2026-09-23 14:44 ` Pierrick Bouvier
41 siblings, 0 replies; 45+ messages in thread
From: Pierrick Bouvier @ 2026-09-23 14:44 UTC (permalink / raw)
To: Yonggang Luo, qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Peter Maydell, Sunil V L,
Stefan Hajnoczi, Palmer Dabbelt, Fabiano Rosas, Xianglai Li,
Jiaxun Yang, Max Filippov, qemu-ppc, Zhao Liu, Paolo Bonzini,
Bibo Mao, Michael S. Tsirkin, Laurent Vivier, David Hildenbrand,
Richard Henderson, Daniel P. Berrangé, Nicholas Piggin,
qemu-riscv, kvm, Edgar E. Iglesias, Alex Bennée,
Stafford Horne, Marc-André Lureau, Markus Armbruster,
Weiwei Li, Song Gao, qemu-arm, qemu-s390x, Brian Cain
Hi Yonggang,
On 9/23/2026 6:14 AM, Yonggang Luo wrote:
> This series produces one qemu-system binary that can run ARM (32 and
> 64), RISC-V (32 and 64), and MicroBlaze.
> Upstream filters machines with TypeInfo.is_available. This series
> passes a TargetInfo into that callback, uniquifies QOM names that
> collide in one process, and compiles those targets once so they can
> share qemu-system.
>
> A combined link cannot keep C symbols or QOM type names that were
> unique only because each qemu-system-$arch was a separate binary.
> These patches remove those collisions:
>
> - TYPE_ACCEL_CPU is the fixed abstract type accel-cpu, registered
> once next to TYPE_ACCEL. Leaf names still encode the CPU type so
> accel_init_cpu_interfaces() can look up "<accel>-" plus
> target_cpu_type() (tcg-accel-arm-cpu).
> - virt QOM names are prefixed: arm-virt, riscv-virt, and the same
> for or1k, hexagon, loongarch, m68k, and xtensa. Boards keep
> -machine virt via machine_class_set_name(). query-machines returns
> the QOM type in MachineInfo typename.
> - virt ACPI helpers and RISC-V TCG crc32/crc32c/wfi helpers get an
> arch prefix so the combined link does not need meson -D name
> mangling. LoongArch virt_acpi_setup is renamed in the same pass.
>
> Target selection has to work with more than one TargetInfo:
>
> - The combined binary takes arch:name on -M/-machine and in a
> [machine] type (aarch64:virt). arch: binds the target. microblaze:
> runs that target's default machine. arm, aarch64, riscv32, and
> riscv64 have no default. No -M leaves target none and the empty
> none machine. qemu-system-$arch keeps the historic -M name.
> -M help lists every target; arch:help lists one. query-targets
> lists each linked target, including none.
> - TargetInfo is a constructor list. target_info_select() picks the
> entry, including SYS_EMU_TARGET_NONE. is_available takes const
> TargetInfo *. While the target is still none, QOM skips the
> unavailable filter so grouped -M help can list every machine.
> - query-cpu-definitions, dump notes, and Angel semihosting sit on
> TargetCpuOps indexed by target_arch(). Registration uses a
> QEMU_ARCH_* bitmask so one object can fill ARM and AARCH64. The
> table is target-ops.h / target-ops.c.
>
> qemu-system-$TARGET is still built, including the Windows *w twin.
> qemu-system is extra. It links each target whose arch sources are
> only target-info-def.c: arm, aarch64, riscv32, riscv64, and
> microblaze. Do not add qemu-systemw for that binary. A GUI
> twin would keep QEMU exporting data from the .exe into DLLs, and
> those data exports cannot be delay-loaded (qdev_prop_array and
> other qdev_prop_*). That would block enabling modules globally on
> Windows.
>
> Examples:
>
> qemu-system -M aarch64:virt ...
> qemu-system -M microblaze:petalogix-s3adsp1800 ...
> qemu-system-riscv64 -M virt ...
>
> A bare machine name on qemu-system needs an arch: prefix. An unknown
> target fails with "target '...' is not available".
>
> Prerequisites:
> [PATCH v2 0/9] machine: uniquify virt QOM names
> https://patchew.org/QEMU/20260922215533.641-1-luoyonggang@gmail.com/
> [PATCH 00/21] accel/tcg: share raise_excp across TCG targets
> https://patchew.org/QEMU/20260918004225.827-1-luoyonggang@gmail.com/
> [PATCH v5 00/11] single-binary: Compile hw/riscv once
> https://patchew.org/QEMU/20260918-hw-riscv-cpu-int-v5-0-f98c5a244636@rev.ng/
>
> v1: https://patchew.org/QEMU/20260823150731.896-1-luoyonggang@gmail.com/
> v2: https://patchew.org/QEMU/20260826184229.1145-1-luoyonggang@gmail.com/
> branch: https://gitlab.com/lygstate-qemu/qemu/-/tree/single-binary-arm-riscv?ref_type=heads
> x86_64 and i386: https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads
>
thanks to pursue this effort.
It seems like your mail provider blocked the send after 40 patches. It
can either be:
- usually I have to reenter my password (after a timeout around 3 to 4
min) to keep on sending patches. A better way is to setup your password
in git config.
- Your reached your daily quota because there are two many cc on each
patch. Reduce cc list.
Also, I would recommend you start easy, with only two base arch as
targets (like aarch64 + riscv64). This makes the series much nicer to
review and iterate. Then you can do one series per extra target.
It takes time, but that's the only sane way to move forward.
Also, I would invite you to get the command line details reviewed first,
as it was the biggest point of discussion last time I tried this. Once
you reach a consensus, it will be trivial to add new targets in.
I'll follow any choice the community will make for this.
Regards,
Pierrick
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v3 028/114] hw/intc: use kvm_enabled() in APLIC AIA helpers
2026-09-23 13:15 ` [PATCH v3 028/114] hw/intc: use kvm_enabled() in APLIC AIA helpers Yonggang Luo
@ 2026-09-26 9:35 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 45+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-09-26 9:35 UTC (permalink / raw)
To: Yonggang Luo, qemu-devel
Cc: Cornelia Huck, xen-devel, Chao Liu, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Liu Zhiwei, Pierrick Bouvier, Peter Maydell, Sunil V L,
Stefan Hajnoczi, Palmer Dabbelt, Fabiano Rosas, Xianglai Li,
Jiaxun Yang, Max Filippov, qemu-ppc, Zhao Liu, Paolo Bonzini,
Bibo Mao, Michael S. Tsirkin, Laurent Vivier, David Hildenbrand,
Richard Henderson, Daniel P. Berrangé, Nicholas Piggin,
qemu-riscv, kvm, Edgar E. Iglesias, Alex Bennée,
Stafford Horne, Marc-André Lureau, Markus Armbruster,
Weiwei Li, Song Gao, qemu-arm, qemu-s390x, Brian Cain
On 23/9/26 15:15, Yonggang Luo wrote:
> - Replace CONFIG_KVM ifdefs in riscv_use_emulated_aplic and
> riscv_aplic_set_kvm_msicfgaddr with kvm_enabled().
Can you provide your S-o-b tag please?
> ---
> hw/intc/riscv_aplic.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index d8e25bfda14..03a0852b8b8 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -167,7 +167,10 @@ bool riscv_is_kvm_aia_aplic_imsic(bool msimode)
>
> bool riscv_use_emulated_aplic(bool msimode)
> {
> -#ifdef CONFIG_KVM
> + if (!kvm_enabled()) {
> + return true;
> + }
> +
> if (tcg_enabled()) {
> return true;
> }
> @@ -177,21 +180,20 @@ bool riscv_use_emulated_aplic(bool msimode)
> }
>
> return kvm_kernel_irqchip_split();
> -#else
> - return true;
> -#endif
> }
>
> void riscv_aplic_set_kvm_msicfgaddr(RISCVAPLICState *aplic, hwaddr addr)
> {
> -#ifdef CONFIG_KVM
> + if (!kvm_enabled()) {
> + return;
> + }
> +
> if (riscv_use_emulated_aplic(aplic->msimode)) {
> addr >>= APLIC_xMSICFGADDR_PPN_SHIFT;
> aplic->kvm_msicfgaddr = extract64(addr, 0, 32);
> aplic->kvm_msicfgaddrH = extract64(addr, 32, 32) &
> APLIC_MMSICFGADDRH_VALID_MASK;
> }
> -#endif
> }
>
> /*
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v3 034/114] target/riscv: Include migration/vmstate.h instead of migration/cpu.h in machine.c
2026-09-23 13:15 ` [PATCH v3 034/114] target/riscv: Include migration/vmstate.h instead of migration/cpu.h in machine.c Yonggang Luo
@ 2026-09-27 12:16 ` Chao Liu
0 siblings, 0 replies; 45+ messages in thread
From: Chao Liu @ 2026-09-27 12:16 UTC (permalink / raw)
To: Yonggang Luo
Cc: qemu-devel, Cornelia Huck, xen-devel, Igor Mammedov,
Alistair Francis, Daniel Henrique Barboza, Peter Xu, Eric Blake,
Philippe Mathieu-Daudé, Liu Zhiwei, Pierrick Bouvier,
Peter Maydell, Sunil V L, Stefan Hajnoczi, Palmer Dabbelt,
Fabiano Rosas, Xianglai Li, Jiaxun Yang, Max Filippov, qemu-ppc,
Zhao Liu, Paolo Bonzini, Bibo Mao, Michael S. Tsirkin,
Laurent Vivier, David Hildenbrand, Richard Henderson,
Daniel P. Berrangé, Nicholas Piggin, qemu-riscv, kvm,
Edgar E. Iglesias, Alex Bennée, Stafford Horne,
Marc-André Lureau, Markus Armbruster, Weiwei Li, Song Gao,
qemu-arm, qemu-s390x, Brian Cain
On Wed, Sep 23, 2026 at 09:15:08PM +0800, Yonggang Luo wrote:
> already uses fixed-width VMSTATE_* macros and does not need TARGET_LONG_BITS UINTTL helpers.
Please wrap the commit message at 76 columns.
>
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
> target/riscv/machine.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index bf203bffcef..00805745fbf 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -21,7 +21,7 @@
> #include "qemu/error-report.h"
> #include "system/kvm.h"
> #include "system/tcg.h"
> -#include "migration/cpu.h"
> +#include "migration/vmstate.h"
> #include "exec/icount.h"
> #include "target/riscv/tcg/debug.h"
> #ifdef CONFIG_KVM
> --
> 2.52.0.windows.1
>
^ permalink raw reply [flat|nested] 45+ messages in thread
end of thread, other threads:[~2026-09-27 12:16 UTC | newest]
Thread overview: 45+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-23 13:14 [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 001/114] meson: stale qemu-version.h only when .git exists Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 002/114] configs/targets: remove target info definitions Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 003/114] target-info: rename target-info-stub.c in target-info-def.c Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 004/114] target-info: rename target-info-impl.h to target-info-def.h Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 005/114] target-info: set cpu_type from TARGET_BASE_ARCH Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 006/114] target: remove CPU_RESOLVING_TYPE Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 007/114] vl: parse early options before target-info init Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 008/114] target-info: replace QOM registration with a constructor list Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 009/114] tests/unit: add test-target-info Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 010/114] tests/qtest: prepare machine-list-test for combined qemu-system Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 011/114] kconfig: rename REGISTER to HW_REGISTER Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 012/114] target-info: add TargetKconfig Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 013/114] target-info: add target_is_* helpers for each architecture Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 014/114] target-info: add i386 and x86_64 helpers Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 015/114] qom: pass TargetInfo to is_available Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 016/114] module: use static ModuleEntry and per-type DSO lists Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 017/114] module: add before/after hooks and module_call_init_fn Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 018/114] qom: register late types through module_call_init_fn Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 019/114] qom: inherit is_available and filter after MODULE_INIT_QOM Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 020/114] tests/unit: add module-init and qom is-available tests Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 021/114] hw/arm/virt: prefix ACPI helpers with arm_virt_ Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 022/114] hw/riscv/virt: prefix ACPI helpers with riscv_virt_ Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 023/114] hw/loongarch/virt: prefix ACPI helper with loongarch_virt_ Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 024/114] target/riscv: uniquify TCG crc32, crc32c, and wfi helper names Yonggang Luo
2026-09-23 13:14 ` [PATCH v3 025/114] hw/riscv: gate boards with target_is_base_riscv Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 026/114] hw/intc: use target_long_bits in IMSIC geilen Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 027/114] hw/misc/riscv_cmgcr: replace target_ulong with uint64_t Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 028/114] hw/intc: use kvm_enabled() in APLIC AIA helpers Yonggang Luo
2026-09-26 9:35 ` Philippe Mathieu-Daudé
2026-09-23 13:15 ` [PATCH v3 029/114] hw/intc: send IMSIC MSI via kvm_irqchip_send_msi() Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 030/114] target/riscv: add kvm stubs source set Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 031/114] tcg: fix off-by-one in helper extend-free assert Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 032/114] gdbstub: drop per-target cpu-param.h from helpers.h Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 033/114] hw/riscv: expand boston-aia and microblaze-v-generic to TypeInfo Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 034/114] target/riscv: Include migration/vmstate.h instead of migration/cpu.h in machine.c Yonggang Luo
2026-09-27 12:16 ` Chao Liu
2026-09-23 13:15 ` [PATCH v3 035/114] target/riscv: gate CPU types with TargetInfo Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 036/114] target/riscv: select ELF dump class from target_riscv64 Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 037/114] target/riscv: replace TARGET_* macros in CSR helpers Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 038/114] target/riscv: use target_long_bits in pmpaddr granule checks Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 039/114] target/riscv: preserve signed XLEN semantics without target_long Yonggang Luo
2026-09-23 13:15 ` [PATCH v3 040/114] target/riscv: replace leftover TARGET_LONG_BITS Yonggang Luo
2026-09-23 13:37 ` [PATCH v3 000/114] single-binary: link multi-targets into qemu-system Jan Beulich
2026-09-23 14:44 ` Pierrick Bouvier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox