* [PATCH 1/4] hw/core: record permitted targets against MachineClass
2026-11-05 10:24 [PATCH 0/4] hw: support machine filtering without is_available Daniel P. Berrangé
@ 2026-11-05 10:24 ` Daniel P. Berrangé
2026-11-05 10:24 ` [PATCH 2/4] hw: replace 'is_available' with 'targets' in machines Daniel P. Berrangé
` (4 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Daniel P. Berrangé @ 2026-11-05 10:24 UTC (permalink / raw)
To: qemu-devel
Cc: Yonggang Luo, Philippe Mathieu-Daudé, Pierrick Bouvier,
Daniel P. Berrangé
Record a bitmask of QEMU_ARCH_nnnn in the 'targets' field
of MachineClass.
When a request is made to create a machine, it will be
validated against machine_class_is_available(MachineClass),
which checks target_arch() against the 'targets' field.
This prevents realization of, for example, an aarch64-only
machine linked into the arm emulator binary.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
hw/core/machine-qmp-cmds.c | 18 ++++++++++++++++++
hw/core/machine.c | 13 +++++++++++++
include/hw/core/boards.h | 3 +++
qapi/machine.json | 12 +++++++++++-
system/vl.c | 9 +++++++++
5 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index 0558d6d703c..3a33a046622 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -33,6 +33,7 @@
#include "system/runstate.h"
#include "system/system.h"
#include "hw/s390x/storage-keys.h"
+#include "qemu/base-arch-defs.h"
/*
* QMP query for enabled and present accelerators
@@ -153,6 +154,7 @@ qmp_query_cpu_model_expansion(CpuModelExpansionType type,
}
MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
+ bool has_all_targets, bool all_targets,
Error **errp)
{
GSList *el, *machines;
@@ -164,6 +166,10 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
const char *default_cpu_type = machine_class_default_cpu_type(mc);
MachineInfo *info;
+ if (!all_targets && !machine_class_is_available(mc)) {
+ continue;
+ }
+
info = g_malloc0(sizeof(*info));
if (mc->is_default) {
info->has_is_default = true;
@@ -188,6 +194,18 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
}
info->secure = object_class_is_secure(OBJECT_CLASS(mc));
+ if (all_targets) {
+ SysEmuTargetList **targets;
+ size_t i;
+ info->has_targets = true;
+ targets = &info->targets;
+ for (i = 0; i < SYS_EMU_TARGET__MAX; i++) {
+ if (mc->targets & QEMU_ARCH_BIT(i)) {
+ QAPI_LIST_APPEND(targets, i);
+ }
+ }
+ }
+
if (compat_props && mc->compat_props) {
int i;
info->compat_props = NULL;
diff --git a/hw/core/machine.c b/hw/core/machine.c
index ed9bf8f5008..9743754fc7f 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -40,6 +40,8 @@
#include "hw/acpi/generic_event_device.h"
#include "qemu/audio.h"
#include "hw/arm/smmuv3.h"
+#include "qemu/base-arch-defs.h"
+#include "qemu/target-info-qapi.h"
GlobalProperty hw_compat_11_1[] = {
{ "sysbus-ehci-usb", "x-migrate-fetch-addr-64bit", "off" },
@@ -711,6 +713,17 @@ bool device_type_is_dynamic_sysbus(MachineClass *mc, const char *type)
return allowed;
}
+bool machine_class_is_available(MachineClass *mc)
+{
+ /*
+ * XXX: Once all machines have 'targets' set, we
+ * can remove the 'mc->targets == 0' check
+ */
+ return mc->targets == 0 ||
+ QEMU_ARCH_BIT(target_arch()) & mc->targets;
+}
+
+
static char *machine_get_audiodev(Object *obj, Error **errp)
{
MachineState *ms = MACHINE(obj);
diff --git a/include/hw/core/boards.h b/include/hw/core/boards.h
index d0e4ad98201..cb493397b13 100644
--- a/include/hw/core/boards.h
+++ b/include/hw/core/boards.h
@@ -37,6 +37,8 @@ const char *machine_default_cpu_type(const MachineState *ms);
*/
const char *machine_class_default_cpu_type(MachineClass *mc);
+bool machine_class_is_available(MachineClass *mc);
+
void machine_add_audiodev_property(MachineClass *mc);
void machine_run_board_init(MachineState *machine, const char *mem_path, Error **errp);
bool machine_usb(MachineState *machine);
@@ -282,6 +284,7 @@ struct MachineClass {
int default_ipa_size, int max_ipa_size);
bool (*get_kernel_irqchip_default) (const MachineState *machine);
+ int targets; /* QEMU_ARCH_xxx bitmask */
BlockInterfaceType block_default_type;
int units_per_default_bus;
int max_cpus;
diff --git a/qapi/machine.json b/qapi/machine.json
index 18d9dce849b..95b02043768 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -194,6 +194,10 @@
# not providing a security boundary, or its status is undefined.
# (since 11.2)
#
+# @targets: list of targets that the machine can be used with. Only
+# present when `query-machines` argument @all-targets is true.
+# (since 12.0)
+#
# Features:
#
# @unstable: Member @compat-props is experimental.
@@ -205,6 +209,7 @@
'*is-default': 'bool', 'cpu-max': 'int',
'hotpluggable-cpus': 'bool', 'numa-mem-supported': 'bool',
'deprecated': 'bool', '*default-cpu-type': 'str',
+ '*targets': ['SysEmuTarget'],
'*default-ram-id': 'str', 'acpi': 'bool',
'*compat-props': { 'type': ['CompatProperty'],
'features': ['unstable'] },
@@ -217,6 +222,10 @@
# @compat-props: if true, also return compatibility properties.
# (default: false) (since 9.1)
#
+# @all-targets: if true, return info about all machines present
+# instead of only those available with the current active
+# target (since 12.0)
+#
# Features:
#
# @unstable: Argument @compat-props is experimental.
@@ -248,7 +257,8 @@
##
{ 'command': 'query-machines',
'data': { '*compat-props': { 'type': 'bool',
- 'features': [ 'unstable' ] } },
+ 'features': [ 'unstable' ] },
+ '*all-targets': 'bool' },
'returns': ['MachineInfo'] }
##
diff --git a/system/vl.c b/system/vl.c
index e7b759d5442..ace64284ae4 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -1583,6 +1583,9 @@ static void machine_help_func(const QDict *qdict)
machines = g_slist_sort_with_data(machines, machine_class_cmp, NULL);
for (el = machines; el; el = el->next) {
MachineClass *mc = el->data;
+ if (!machine_class_is_available(mc)) {
+ continue;
+ }
if (mc->alias) {
printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->name);
}
@@ -2208,6 +2211,12 @@ static bool qemu_create_machine(QDict *qdict)
MachineClass *machine_class = select_machine(qdict, &error_fatal);
object_set_machine_compat_props(machine_class->compat_props);
+ if (!machine_class_is_available(machine_class)) {
+ error_report("Machine '%s' is not available with this target",
+ machine_class->name);
+ return false;
+ }
+
if (!object_class_check_security(OBJECT_CLASS(machine_class),
&local_err)) {
error_report_err(local_err);
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 2/4] hw: replace 'is_available' with 'targets' in machines
2026-11-05 10:24 [PATCH 0/4] hw: support machine filtering without is_available Daniel P. Berrangé
2026-11-05 10:24 ` [PATCH 1/4] hw/core: record permitted targets against MachineClass Daniel P. Berrangé
@ 2026-11-05 10:24 ` Daniel P. Berrangé
2026-11-05 10:24 ` [PATCH 3/4] target/riscv: remove 'is_available' from riscv CPUs Daniel P. Berrangé
` (3 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Daniel P. Berrangé @ 2026-11-05 10:24 UTC (permalink / raw)
To: qemu-devel
Cc: Yonggang Luo, Philippe Mathieu-Daudé, Pierrick Bouvier,
Daniel P. Berrangé
For every machine which currently has an 'is_available'
callback set on the TypeInfo, set the 'targets' field
on the MachineClass to the equivalent arch list, and
remove 'is_available'.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
hw/arm/aspeed_ast27x0-fc.c | 3 ++-
hw/arm/aspeed_ast27x0_evb.c | 5 +++--
hw/arm/raspi.c | 21 +++++++++++++--------
hw/arm/raspi4b.c | 3 ++-
hw/arm/virt.c | 5 +++--
hw/hexagon/virt.c | 3 ++-
hw/m68k/virt.c | 4 ++--
hw/or1k/virt.c | 3 ++-
hw/riscv/virt.c | 4 +++-
9 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
index 73362b60d2a..ea340c6f1cf 100644
--- a/hw/arm/aspeed_ast27x0-fc.c
+++ b/hw/arm/aspeed_ast27x0-fc.c
@@ -22,6 +22,7 @@
#include "hw/arm/boot.h"
#include "hw/block/flash.h"
#include "hw/arm/aspeed_coprocessor.h"
+#include "qemu/base-arch-defs.h"
#define TYPE_AST2700FC MACHINE_TYPE_NAME("ast2700fc")
OBJECT_DECLARE_SIMPLE_TYPE(Ast2700FCState, AST2700FC);
@@ -226,6 +227,7 @@ static void ast2700fc_class_init(ObjectClass *oc, const void *data)
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->min_cpus = mc->max_cpus = mc->default_cpus = 6;
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_AARCH64);
}
static const TypeInfo ast2700fc_types[] = {
@@ -234,7 +236,6 @@ static const TypeInfo ast2700fc_types[] = {
.parent = TYPE_MACHINE,
.class_init = ast2700fc_class_init,
.instance_size = sizeof(Ast2700FCState),
- .is_available = target_aarch64,
},
};
diff --git a/hw/arm/aspeed_ast27x0_evb.c b/hw/arm/aspeed_ast27x0_evb.c
index 460c9ff0d2e..b252edc5103 100644
--- a/hw/arm/aspeed_ast27x0_evb.c
+++ b/hw/arm/aspeed_ast27x0_evb.c
@@ -11,6 +11,7 @@
#include "hw/arm/aspeed.h"
#include "hw/arm/aspeed_soc.h"
#include "hw/sensor/tmp105.h"
+#include "qemu/base-arch-defs.h"
/* AST2700 evb hardware value */
/* SCU HW Strap1 */
@@ -45,6 +46,7 @@ static void aspeed_machine_ast2700a1_evb_class_init(ObjectClass *oc,
amc->i2c_init = ast2700_evb_i2c_init;
amc->vbootrom = true;
mc->default_ram_size = 1 * GiB;
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_AARCH64);
aspeed_machine_class_init_cpus_defaults(mc);
}
@@ -67,6 +69,7 @@ static void aspeed_machine_ast2700a2_evb_class_init(ObjectClass *oc,
amc->i2c_init = ast2700_evb_i2c_init;
amc->vbootrom = true;
mc->default_ram_size = 2 * GiB;
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_AARCH64);
aspeed_machine_class_init_cpus_defaults(mc);
}
@@ -75,13 +78,11 @@ 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,
},
{
.name = MACHINE_TYPE_NAME("ast2700a2-evb"),
.parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_machine_ast2700a2_evb_class_init,
- .is_available = target_aarch64,
}
};
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index fadbacb2534..b1d2eece2c0 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -25,6 +25,8 @@
#include "hw/core/boards.h"
#include "hw/core/loader.h"
#include "qom/object.h"
+#include "qemu/base-arch-defs.h"
+
#define TYPE_RASPI_MACHINE MACHINE_TYPE_NAME("raspi-common")
OBJECT_DECLARE_SIMPLE_TYPE(RaspiMachineState, RASPI_MACHINE)
@@ -330,10 +332,15 @@ void raspi_machine_class_common_init(MachineClass *mc,
};
static void raspi_machine_class_init(MachineClass *mc,
- uint32_t board_rev)
+ uint32_t board_rev,
+ bool arch64bitonly)
{
raspi_machine_class_common_init(mc, board_rev);
mc->init = raspi_machine_init;
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_AARCH64);
+ if (!arch64bitonly) {
+ mc->targets |= QEMU_ARCH_BIT(SYS_EMU_TARGET_ARM);
+ }
};
static void raspi0_machine_class_init(ObjectClass *oc, const void *data)
@@ -343,7 +350,7 @@ static void raspi0_machine_class_init(ObjectClass *oc, const void *data)
mc->auto_create_sdcard = true;
rmc->board_rev = 0x920092; /* Revision 1.2 */
- raspi_machine_class_init(mc, rmc->board_rev);
+ raspi_machine_class_init(mc, rmc->board_rev, false);
};
static void raspi1ap_machine_class_init(ObjectClass *oc, const void *data)
@@ -353,7 +360,7 @@ static void raspi1ap_machine_class_init(ObjectClass *oc, const void *data)
mc->auto_create_sdcard = true;
rmc->board_rev = 0x900021; /* Revision 1.1 */
- raspi_machine_class_init(mc, rmc->board_rev);
+ raspi_machine_class_init(mc, rmc->board_rev, false);
};
static void raspi2b_machine_class_init(ObjectClass *oc, const void *data)
@@ -363,7 +370,7 @@ static void raspi2b_machine_class_init(ObjectClass *oc, const void *data)
mc->auto_create_sdcard = true;
rmc->board_rev = 0xa21041;
- raspi_machine_class_init(mc, rmc->board_rev);
+ raspi_machine_class_init(mc, rmc->board_rev, false);
};
static void raspi3ap_machine_class_init(ObjectClass *oc, const void *data)
@@ -373,7 +380,7 @@ static void raspi3ap_machine_class_init(ObjectClass *oc, const void *data)
mc->auto_create_sdcard = true;
rmc->board_rev = 0x9020e0; /* Revision 1.0 */
- raspi_machine_class_init(mc, rmc->board_rev);
+ raspi_machine_class_init(mc, rmc->board_rev, true);
};
static void raspi3b_machine_class_init(ObjectClass *oc, const void *data)
@@ -383,7 +390,7 @@ static void raspi3b_machine_class_init(ObjectClass *oc, const void *data)
mc->auto_create_sdcard = true;
rmc->board_rev = 0xa02082;
- raspi_machine_class_init(mc, rmc->board_rev);
+ raspi_machine_class_init(mc, rmc->board_rev, true);
};
static const TypeInfo raspi_machine_types[] = {
@@ -403,12 +410,10 @@ 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,
}, {
.name = MACHINE_TYPE_NAME("raspi3b"),
.parent = TYPE_RASPI_MACHINE,
.class_init = raspi3b_machine_class_init,
- .is_available = target_aarch64,
}, {
.name = TYPE_RASPI_MACHINE,
.parent = TYPE_RASPI_BASE_MACHINE,
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 600dfe686f2..92c3f580f96 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -21,6 +21,7 @@
#include "hw/arm/boot.h"
#include "qom/object.h"
#include "hw/arm/bcm2838.h"
+#include "qemu/base-arch-defs.h"
#include <libfdt.h>
#define TYPE_RASPI4B_MACHINE MACHINE_TYPE_NAME("raspi4b")
@@ -93,6 +94,7 @@ static void raspi4b_machine_class_init(ObjectClass *oc, const void *data)
raspi_machine_class_common_init(mc, rmc->board_rev);
mc->auto_create_sdcard = true;
mc->init = raspi4b_machine_init;
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_AARCH64);
}
static const TypeInfo raspi4b_machine_type = {
@@ -100,7 +102,6 @@ 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,
};
static void raspi4b_machine_register_type(void)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 0b11f7e328c..bd38e3262a4 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -94,6 +94,7 @@
#include "hw/cxl/cxl_host.h"
#include "qemu/guest-random.h"
#include "hw/watchdog/sbsa_gwdt.h"
+#include "qemu/base-arch-defs.h"
static GlobalProperty arm_virt_compat_defaults[] = {
{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
@@ -131,7 +132,6 @@ static void arm_virt_compat_default_set(MachineClass *mc)
.name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
.parent = TYPE_VIRT_MACHINE, \
.class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
- .is_available = target_base_arm, \
.secure = true, \
}; \
static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
@@ -4204,6 +4204,8 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
hc->unplug = virt_machine_device_unplug_cb;
mc->nvdimm_supported = true;
mc->smp_props.clusters_supported = true;
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_AARCH64) |
+ QEMU_ARCH_BIT(SYS_EMU_TARGET_ARM);
/* Supported caches */
mc->smp_props.cache_supported[CACHE_LEVEL_AND_TYPE_L1D] = true;
@@ -4444,7 +4446,6 @@ static const TypeInfo virt_machine_info = {
{ TYPE_HOTPLUG_HANDLER },
{ }
},
- .is_available = target_base_arm,
};
static void machvirt_machine_init(void)
diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c
index d8e91770595..57ef8b5e736 100644
--- a/hw/hexagon/virt.c
+++ b/hw/hexagon/virt.c
@@ -17,6 +17,7 @@
#include "qemu/units.h"
#include "machine_cfg_v68n_1024.h.inc"
#include "system/device_tree.h"
+#include "qemu/base-arch-defs.h"
enum {
VIRT_UART0,
@@ -115,6 +116,7 @@ static void virt_class_init(ObjectClass *oc, const void *data)
mc->no_cdrom = 1;
mc->numa_mem_supported = false;
mc->default_nic = "virtio-mmio-bus";
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_HEXAGON);
}
@@ -123,7 +125,6 @@ static const TypeInfo virt_machine_types[] = { {
.parent = TYPE_HEXAGON_COMMON_MACHINE,
.instance_size = sizeof(HexagonVirtMachineState),
.class_init = virt_class_init,
- .is_available = target_hexagon,
} };
DEFINE_TYPES(virt_machine_types)
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index e52546e4fab..f35eac74147 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -36,6 +36,7 @@
#include "hw/intc/goldfish_pic.h"
#include "hw/virtio/virtio-mmio.h"
#include "hw/virtio/virtio-blk.h"
+#include "qemu/base-arch-defs.h"
/*
* 6 goldfish-pic for CPU IRQ #1 to IRQ #6
@@ -320,6 +321,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
mc->no_floppy = 1;
mc->no_parallel = 1;
mc->default_ram_id = "m68k_virt.ram";
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_M68K);
}
static const TypeInfo virt_machine_info = {
@@ -327,7 +329,6 @@ static const TypeInfo virt_machine_info = {
.parent = TYPE_MACHINE,
.abstract = true,
.class_init = virt_machine_class_init,
- .is_available = target_m68k,
};
static void virt_machine_register_types(void)
@@ -355,7 +356,6 @@ type_init(virt_machine_register_types)
.name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
.parent = MACHINE_TYPE_NAME("virt"), \
.class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
- .is_available = target_m68k, \
}; \
static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
{ \
diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
index a3ff903839b..f5580f3c3da 100644
--- a/hw/or1k/virt.c
+++ b/hw/or1k/virt.c
@@ -28,6 +28,7 @@
#include "system/system.h"
#include "system/qtest.h"
#include "system/reset.h"
+#include "qemu/base-arch-defs.h"
#include <libfdt.h>
@@ -552,6 +553,7 @@ static void openrisc_virt_machine_init(ObjectClass *oc, const void *data)
mc->max_cpus = VIRT_CPUS_MAX;
mc->is_default = false;
mc->default_cpu_type = OPENRISC_CPU_TYPE_NAME("or1200");
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_OR1K);
}
static const TypeInfo or1ksim_machine_typeinfo = {
@@ -559,7 +561,6 @@ static const TypeInfo or1ksim_machine_typeinfo = {
.parent = TYPE_MACHINE,
.class_init = openrisc_virt_machine_init,
.instance_size = sizeof(OR1KVirtState),
- .is_available = target_or1k,
};
static void or1ksim_machine_init_register_types(void)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 8bc5a7b0728..6b3d6a764f3 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -61,6 +61,7 @@
#include "qapi/qapi-type-infos-common.h"
#include "hw/virtio/virtio-iommu.h"
#include "hw/uefi/var-service-api.h"
+#include "qemu/base-arch-defs.h"
#include "aia.h"
@@ -1140,6 +1141,8 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
mc->default_ram_id = "riscv_virt_board.ram";
assert(!mc->get_hotplug_handler);
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
+ mc->targets = QEMU_ARCH_BIT(SYS_EMU_TARGET_RISCV64) |
+ QEMU_ARCH_BIT(SYS_EMU_TARGET_RISCV32);
hc->plug = virt_machine_device_plug_cb;
@@ -1195,7 +1198,6 @@ static const TypeInfo virt_machine_typeinfo = {
.instance_init = virt_machine_instance_init,
.instance_finalize = virt_machine_instance_finalize,
.instance_size = sizeof(RISCVVirtState),
- .is_available = target_base_riscv,
.interfaces = (const InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER },
{ }
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 3/4] target/riscv: remove 'is_available' from riscv CPUs
2026-11-05 10:24 [PATCH 0/4] hw: support machine filtering without is_available Daniel P. Berrangé
2026-11-05 10:24 ` [PATCH 1/4] hw/core: record permitted targets against MachineClass Daniel P. Berrangé
2026-11-05 10:24 ` [PATCH 2/4] hw: replace 'is_available' with 'targets' in machines Daniel P. Berrangé
@ 2026-11-05 10:24 ` Daniel P. Berrangé
2026-11-05 10:24 ` [PATCH 4/4] qom: drop the 'is_available' callback from TypeInfo Daniel P. Berrangé
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Daniel P. Berrangé @ 2026-11-05 10:24 UTC (permalink / raw)
To: qemu-devel
Cc: Yonggang Luo, Philippe Mathieu-Daudé, Pierrick Bouvier,
Daniel P. Berrangé
Allow CPU classes to always be registered, with any logic about
which CPUs are usable in which machines to be done in code, if
it is needed.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
target/riscv/kvm/kvm-cpu.c | 1 -
target/riscv/tcg/tcg-cpu.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 5beb6023380..bf9504635e0 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -2241,7 +2241,6 @@ static const TypeInfo kvm_cpu_accel_type_info = {
.parent = TYPE_ACCEL_CPU,
.class_init = kvm_cpu_accel_class_init,
- .is_available = target_base_riscv,
.abstract = true,
};
static void kvm_cpu_accel_register_types(void)
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 5834ec1524f..3d9c9973292 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -1755,7 +1755,6 @@ static const TypeInfo riscv_tcg_cpu_accel_type_info = {
.parent = TYPE_ACCEL_CPU,
.class_init = riscv_tcg_cpu_accel_class_init,
- .is_available = target_base_riscv,
.abstract = true,
};
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 4/4] qom: drop the 'is_available' callback from TypeInfo
2026-11-05 10:24 [PATCH 0/4] hw: support machine filtering without is_available Daniel P. Berrangé
` (2 preceding siblings ...)
2026-11-05 10:24 ` [PATCH 3/4] target/riscv: remove 'is_available' from riscv CPUs Daniel P. Berrangé
@ 2026-11-05 10:24 ` Daniel P. Berrangé
2026-11-05 17:25 ` [PATCH 0/4] hw: support machine filtering without is_available Pierrick Bouvier
2026-11-05 19:18 ` Yonggang Luo
5 siblings, 0 replies; 11+ messages in thread
From: Daniel P. Berrangé @ 2026-11-05 10:24 UTC (permalink / raw)
To: qemu-devel
Cc: Yonggang Luo, Philippe Mathieu-Daudé, Pierrick Bouvier,
Daniel P. Berrangé
For the purposes of introspection, a binary must always register
all compiled in types (classes). Any filtering of what is
permitted with a given selected target should happen at time of
use/query. As such the 'is_available' callback on TypeInfo is
an undesirable design pattern and with Machine classes converted
it can be removed.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
include/qom/object.h | 3 ---
qom/object.c | 4 ----
rust/qom/src/qom.rs | 1 -
3 files changed, 8 deletions(-)
diff --git a/include/qom/object.h b/include/qom/object.h
index 70d8ea3e299..06a55b410ba 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -475,8 +475,6 @@ 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.
* @interfaces: The list of interfaces associated with this type. This
* should point to a static array that's terminated with a zero filled
* element.
@@ -500,7 +498,6 @@ struct TypeInfo
void (*class_base_init)(ObjectClass *klass, const void *data);
const void *class_data;
- bool (*is_available)(void);
const InterfaceInfo *interfaces;
};
diff --git a/qom/object.c b/qom/object.c
index cd0590c3fd0..1d9ff06cacf 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -167,10 +167,6 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
abort();
}
- if (info->is_available && !info->is_available()) {
- return NULL;
- }
-
ti = type_new(info);
type_table_add(ti);
diff --git a/rust/qom/src/qom.rs b/rust/qom/src/qom.rs
index 81449eeefad..372be188622 100644
--- a/rust/qom/src/qom.rs
+++ b/rust/qom/src/qom.rs
@@ -695,7 +695,6 @@ pub trait ObjectImpl: ObjectType + IsA<Object> {
class_init: Some(rust_class_init::<Self>),
class_base_init: Self::CLASS_BASE_INIT,
class_data: core::ptr::null(),
- is_available: None,
interfaces: core::ptr::null(),
};
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 0/4] hw: support machine filtering without is_available
2026-11-05 10:24 [PATCH 0/4] hw: support machine filtering without is_available Daniel P. Berrangé
` (3 preceding siblings ...)
2026-11-05 10:24 ` [PATCH 4/4] qom: drop the 'is_available' callback from TypeInfo Daniel P. Berrangé
@ 2026-11-05 17:25 ` Pierrick Bouvier
2026-11-06 15:35 ` Daniel P. Berrangé
2026-11-05 19:18 ` Yonggang Luo
5 siblings, 1 reply; 11+ messages in thread
From: Pierrick Bouvier @ 2026-11-05 17:25 UTC (permalink / raw)
To: Daniel P. Berrangé, qemu-devel
Cc: Yonggang Luo, Philippe Mathieu-Daudé
On 11/5/2026 2:24 AM, Daniel P. Berrangé wrote:
> The 'is_available' callback on TypeInfo is based on a mistaken
> notion that we should filter out classes at registration time
> based on architecture.
>
> This creates new problems however, some already present and
> some which will impact a future multi-target binary
>
> * For introspection of the binaries' features, we have
> a dependancy on selecting a target before we can
> introspect features. It would require re-launching
> QEMU for each target, leading to lots of redundant
> introspection and a big time sink. It would also not
> be possible to introspect targets
>
> * It creates a circular dependancy on QOM initialization
> inside the QOM initialization code, since 'target_info()'
> itself uses QOM. This then requires further work to break
> by initializing QOM target info before the rest of QOM.
>
> * We have no means to introspect what targets a machine
> type can be used with, as this information is expressed
> as code (in target_XXXX() methods), instead of as data.
>
> * New fields in TypeInfo requires more changes to macros
> used for initializing machines.
>
> There is no inherant conceptual reason why we must filter out
> classes at type registration time. This is just a shortcut to
> workaround historical technical debt where certain classes
> have clashing names. This is an undesirable approach, as it
> is trading one set of problems for a new set of problems.
>
> This series proposes removal of the 'is_available' concept
> from QOM, and illustrates handling machines with full introspection
> support available from the MachineClass.
>
> This implies fixing the root cause, of clashing class names,
> but does not include patches since various series have already
> been posted for machine class name fixes.
>
> The machine changes are fairly simple
>
> * MachineClass gains a 'targets' field which is a bit mask
> of SysEmuTarget
> * machine_class_is_available() matches 'targets' against
> 'target_info()'
> * -machine CLI enforces machine_class_is_available()
> * query-machines filters on machine_class_is_available
> by default
> * query-machines gains 'all-targets': 'bool' to opt-in
> to returning the unfiltered list, with a 'targets'
> list present
>
> NB, this removes filtering from riscv CPUs with no
> alternative proposed. I'm unclear what this was trying
> to address to begin with, but utlimately it should be
> possible to address it with runtime filtering/matching
> of classes, instead of hiding TypeInfo registration.
> If someone gives me info on the CPUs problem I can a
> make a design suggestion.
>
> Daniel P. Berrangé (4):
> hw/core: record permitted targets against MachineClass
> hw: replace 'is_available' with 'targets' in machines
> target/riscv: remove 'is_available' from riscv CPUs
> qom: drop the 'is_available' callback from TypeInfo
>
> hw/arm/aspeed_ast27x0-fc.c | 3 ++-
> hw/arm/aspeed_ast27x0_evb.c | 5 +++--
> hw/arm/raspi.c | 21 +++++++++++++--------
> hw/arm/raspi4b.c | 3 ++-
> hw/arm/virt.c | 5 +++--
> hw/core/machine-qmp-cmds.c | 18 ++++++++++++++++++
> hw/core/machine.c | 13 +++++++++++++
> hw/hexagon/virt.c | 3 ++-
> hw/m68k/virt.c | 4 ++--
> hw/or1k/virt.c | 3 ++-
> hw/riscv/virt.c | 4 +++-
> include/hw/core/boards.h | 3 +++
> include/qom/object.h | 3 ---
> qapi/machine.json | 12 +++++++++++-
> qom/object.c | 4 ----
> rust/qom/src/qom.rs | 1 -
> system/vl.c | 9 +++++++++
> target/riscv/kvm/kvm-cpu.c | 1 -
> target/riscv/tcg/tcg-cpu.c | 1 -
> 19 files changed, 86 insertions(+), 30 deletions(-)
>
Thanks for posting the series.
Would that be possible to complete it so that beyond compilation, test
./build/tests/unit/test-multi-target passes also? At the moment it fails
with duplicated types being registered.
That's why this is_available was introduced in the first place. It was
just a way to move forward and provide the multi-target test to prevent
regression while work on single-binary is continued by Yonggang.
With a complete picture, I would be more than happy to remove
is_available, I have no personal attach to it.
Regards,
Pierrick
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH 0/4] hw: support machine filtering without is_available
2026-11-05 17:25 ` [PATCH 0/4] hw: support machine filtering without is_available Pierrick Bouvier
@ 2026-11-06 15:35 ` Daniel P. Berrangé
2026-11-06 16:28 ` Yonggang Luo
2026-11-06 17:13 ` Pierrick Bouvier
0 siblings, 2 replies; 11+ messages in thread
From: Daniel P. Berrangé @ 2026-11-06 15:35 UTC (permalink / raw)
To: Pierrick Bouvier; +Cc: qemu-devel, Yonggang Luo, Philippe Mathieu-Daudé
On Thu, Nov 05, 2026 at 09:25:28AM -0800, Pierrick Bouvier wrote:
> On 11/5/2026 2:24 AM, Daniel P. Berrangé wrote:
> > The 'is_available' callback on TypeInfo is based on a mistaken
> > notion that we should filter out classes at registration time
> > based on architecture.
> >
> > This creates new problems however, some already present and
> > some which will impact a future multi-target binary
> >
> > * For introspection of the binaries' features, we have
> > a dependancy on selecting a target before we can
> > introspect features. It would require re-launching
> > QEMU for each target, leading to lots of redundant
> > introspection and a big time sink. It would also not
> > be possible to introspect targets
> >
> > * It creates a circular dependancy on QOM initialization
> > inside the QOM initialization code, since 'target_info()'
> > itself uses QOM. This then requires further work to break
> > by initializing QOM target info before the rest of QOM.
> >
> > * We have no means to introspect what targets a machine
> > type can be used with, as this information is expressed
> > as code (in target_XXXX() methods), instead of as data.
> >
> > * New fields in TypeInfo requires more changes to macros
> > used for initializing machines.
> >
> > There is no inherant conceptual reason why we must filter out
> > classes at type registration time. This is just a shortcut to
> > workaround historical technical debt where certain classes
> > have clashing names. This is an undesirable approach, as it
> > is trading one set of problems for a new set of problems.
> >
> > This series proposes removal of the 'is_available' concept
> > from QOM, and illustrates handling machines with full introspection
> > support available from the MachineClass.
> >
> > This implies fixing the root cause, of clashing class names,
> > but does not include patches since various series have already
> > been posted for machine class name fixes.
> >
> > The machine changes are fairly simple
> >
> > * MachineClass gains a 'targets' field which is a bit mask
> > of SysEmuTarget
> > * machine_class_is_available() matches 'targets' against
> > 'target_info()'
> > * -machine CLI enforces machine_class_is_available()
> > * query-machines filters on machine_class_is_available
> > by default
> > * query-machines gains 'all-targets': 'bool' to opt-in
> > to returning the unfiltered list, with a 'targets'
> > list present
> >
> > NB, this removes filtering from riscv CPUs with no
> > alternative proposed. I'm unclear what this was trying
> > to address to begin with, but utlimately it should be
> > possible to address it with runtime filtering/matching
> > of classes, instead of hiding TypeInfo registration.
> > If someone gives me info on the CPUs problem I can a
> > make a design suggestion.
> >
> > Daniel P. Berrangé (4):
> > hw/core: record permitted targets against MachineClass
> > hw: replace 'is_available' with 'targets' in machines
> > target/riscv: remove 'is_available' from riscv CPUs
> > qom: drop the 'is_available' callback from TypeInfo
> >
> > hw/arm/aspeed_ast27x0-fc.c | 3 ++-
> > hw/arm/aspeed_ast27x0_evb.c | 5 +++--
> > hw/arm/raspi.c | 21 +++++++++++++--------
> > hw/arm/raspi4b.c | 3 ++-
> > hw/arm/virt.c | 5 +++--
> > hw/core/machine-qmp-cmds.c | 18 ++++++++++++++++++
> > hw/core/machine.c | 13 +++++++++++++
> > hw/hexagon/virt.c | 3 ++-
> > hw/m68k/virt.c | 4 ++--
> > hw/or1k/virt.c | 3 ++-
> > hw/riscv/virt.c | 4 +++-
> > include/hw/core/boards.h | 3 +++
> > include/qom/object.h | 3 ---
> > qapi/machine.json | 12 +++++++++++-
> > qom/object.c | 4 ----
> > rust/qom/src/qom.rs | 1 -
> > system/vl.c | 9 +++++++++
> > target/riscv/kvm/kvm-cpu.c | 1 -
> > target/riscv/tcg/tcg-cpu.c | 1 -
> > 19 files changed, 86 insertions(+), 30 deletions(-)
> >
>
> Thanks for posting the series.
>
> Would that be possible to complete it so that beyond compilation, test
> ./build/tests/unit/test-multi-target passes also? At the moment it fails
> with duplicated types being registered.
Oh I see, it didn't failure because I only enabled
the two arm/aarch64 targets, once i add in more
targets we get a clash on the virt-machine class.
FYI, it also fails without my patch series present
in some scenarios:
# child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) stderr: "Registering `vm-launch-update' which already exists\n"
**
ERROR:../tests/unit/test-multi-target.c:41:test_qom_types_are_unique: child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) failed unexpectedly
not ok /multi-targets/qom-types-are-unique/aarch64 - ERROR:../tests/unit/test-multi-target.c:41:test_qom_types_are_unique: child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) failed unexpectedly
Bail out!
Aborted (core dumped) tests/unit/test-multi-target
This is caused by presence of 'igvm-devel' at build time on
one of my machines (Fedora), which enables this device type,
if you have both arm and aarch64 targets enabled.
We need to add igvm to our Fedora dockerfile to catch this
in CI.
Moving it from specific_ss to system_ss make the test pass,
but I'm unclear if it is sufficient to rely on lack of
compiler and test complaints ? Or it needs manual code
inspection to make sure the device is safe in this
scenario ?
> That's why this is_available was introduced in the first place. It was
> just a way to move forward and provide the multi-target test to prevent
> regression while work on single-binary is continued by Yonggang.
Right, so with my series, we would first need the class
renames to fix the multi-target test.
I should have labelled this posting "POC" as it was not
tested thoroughly.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/4] hw: support machine filtering without is_available
2026-11-06 15:35 ` Daniel P. Berrangé
@ 2026-11-06 16:28 ` Yonggang Luo
2026-11-06 17:13 ` Pierrick Bouvier
1 sibling, 0 replies; 11+ messages in thread
From: Yonggang Luo @ 2026-11-06 16:28 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: Pierrick Bouvier, qemu-devel, Philippe Mathieu-Daudé
On Fri, Nov 6, 2026 at 11:35 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Thu, Nov 05, 2026 at 09:25:28AM -0800, Pierrick Bouvier wrote:
> > On 11/5/2026 2:24 AM, Daniel P. Berrangé wrote:
> > > The 'is_available' callback on TypeInfo is based on a mistaken
> > > notion that we should filter out classes at registration time
> > > based on architecture.
> > >
> > > This creates new problems however, some already present and
> > > some which will impact a future multi-target binary
> > >
> > > * For introspection of the binaries' features, we have
> > > a dependancy on selecting a target before we can
> > > introspect features. It would require re-launching
> > > QEMU for each target, leading to lots of redundant
> > > introspection and a big time sink. It would also not
> > > be possible to introspect targets
> > >
> > > * It creates a circular dependancy on QOM initialization
> > > inside the QOM initialization code, since 'target_info()'
> > > itself uses QOM. This then requires further work to break
> > > by initializing QOM target info before the rest of QOM.
> > >
> > > * We have no means to introspect what targets a machine
> > > type can be used with, as this information is expressed
> > > as code (in target_XXXX() methods), instead of as data.
> > >
> > > * New fields in TypeInfo requires more changes to macros
> > > used for initializing machines.
> > >
> > > There is no inherant conceptual reason why we must filter out
> > > classes at type registration time. This is just a shortcut to
> > > workaround historical technical debt where certain classes
> > > have clashing names. This is an undesirable approach, as it
> > > is trading one set of problems for a new set of problems.
> > >
> > > This series proposes removal of the 'is_available' concept
> > > from QOM, and illustrates handling machines with full introspection
> > > support available from the MachineClass.
> > >
> > > This implies fixing the root cause, of clashing class names,
> > > but does not include patches since various series have already
> > > been posted for machine class name fixes.
> > >
> > > The machine changes are fairly simple
> > >
> > > * MachineClass gains a 'targets' field which is a bit mask
> > > of SysEmuTarget
> > > * machine_class_is_available() matches 'targets' against
> > > 'target_info()'
> > > * -machine CLI enforces machine_class_is_available()
> > > * query-machines filters on machine_class_is_available
> > > by default
> > > * query-machines gains 'all-targets': 'bool' to opt-in
> > > to returning the unfiltered list, with a 'targets'
> > > list present
> > >
> > > NB, this removes filtering from riscv CPUs with no
> > > alternative proposed. I'm unclear what this was trying
> > > to address to begin with, but utlimately it should be
> > > possible to address it with runtime filtering/matching
> > > of classes, instead of hiding TypeInfo registration.
> > > If someone gives me info on the CPUs problem I can a
> > > make a design suggestion.
> > >
> > > Daniel P. Berrangé (4):
> > > hw/core: record permitted targets against MachineClass
> > > hw: replace 'is_available' with 'targets' in machines
> > > target/riscv: remove 'is_available' from riscv CPUs
> > > qom: drop the 'is_available' callback from TypeInfo
> > >
> > > hw/arm/aspeed_ast27x0-fc.c | 3 ++-
> > > hw/arm/aspeed_ast27x0_evb.c | 5 +++--
> > > hw/arm/raspi.c | 21 +++++++++++++--------
> > > hw/arm/raspi4b.c | 3 ++-
> > > hw/arm/virt.c | 5 +++--
> > > hw/core/machine-qmp-cmds.c | 18 ++++++++++++++++++
> > > hw/core/machine.c | 13 +++++++++++++
> > > hw/hexagon/virt.c | 3 ++-
> > > hw/m68k/virt.c | 4 ++--
> > > hw/or1k/virt.c | 3 ++-
> > > hw/riscv/virt.c | 4 +++-
> > > include/hw/core/boards.h | 3 +++
> > > include/qom/object.h | 3 ---
> > > qapi/machine.json | 12 +++++++++++-
> > > qom/object.c | 4 ----
> > > rust/qom/src/qom.rs | 1 -
> > > system/vl.c | 9 +++++++++
> > > target/riscv/kvm/kvm-cpu.c | 1 -
> > > target/riscv/tcg/tcg-cpu.c | 1 -
> > > 19 files changed, 86 insertions(+), 30 deletions(-)
> > >
> >
> > Thanks for posting the series.
> >
> > Would that be possible to complete it so that beyond compilation, test
> > ./build/tests/unit/test-multi-target passes also? At the moment it fails
> > with duplicated types being registered.
>
> Oh I see, it didn't failure because I only enabled
> the two arm/aarch64 targets, once i add in more
> targets we get a clash on the virt-machine class.
>
> FYI, it also fails without my patch series present
> in some scenarios:
>
> # child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) stderr: "Registering `vm-launch-update' which already exists\n"
> **
> ERROR:../tests/unit/test-multi-target.c:41:test_qom_types_are_unique: child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) failed unexpectedly
> not ok /multi-targets/qom-types-are-unique/aarch64 - ERROR:../tests/unit/test-multi-target.c:41:test_qom_types_are_unique: child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) failed unexpectedly
> Bail out!
> Aborted (core dumped) tests/unit/test-multi-target
>
> This is caused by presence of 'igvm-devel' at build time on
> one of my machines (Fedora), which enables this device type,
> if you have both arm and aarch64 targets enabled.
>
> We need to add igvm to our Fedora dockerfile to catch this
> in CI.
>
> Moving it from specific_ss to system_ss make the test pass,
> but I'm unclear if it is sufficient to rely on lack of
> compiler and test complaints ? Or it needs manual code
> inspection to make sure the device is safe in this
> scenario ?
>
> > That's why this is_available was introduced in the first place. It was
> > just a way to move forward and provide the multi-target test to prevent
> > regression while work on single-binary is continued by Yonggang.
>
> Right, so with my series, we would first need the class
> renames to fix the multi-target test.
>
> I should have labelled this posting "POC" as it was not
> tested thoroughly.
It's good to have these, make the progress more clear, and we have
more agreements.
I think a possible direction is comes with
qom: filter type lookup with TypeBucket
https://lore.kernel.org/qemu-devel/20261105190346.1539-1-luoyonggang@gmail.com/T/#mc0a763e16d33b7b7c79d87fb07936ae4f04d68a0
So we can get conflict machine names such as "virt-machine" to be
registered with this TypeBucket.
Then we can limit the subclasses of TYPE_MACHINE to use this means(TypeBucket).
That is we can add unit-test in tests/unit/test-multi-target.c
to ensure after object_class_get_list(NULL, true); only TYPE_MACHINE's
subclass's "targets" can differ from QEMU_ARCH_ALL.
Or one more abstract class TYPE_CPU(only when absolutely necessary).
For example deal with:
target/arm: register separate max-v8 CPU types for arm and aarch64
https://lore.kernel.org/qemu-devel/auyP09mbwuefulBL@redhat.com/
>
> With regards,
> Daniel
> --
> |: https://berrange.com ~~ https://hachyderm.io/@berrange :|
> |: https://libvirt.org ~~ https://entangle-photo.org :|
> |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
>
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH 0/4] hw: support machine filtering without is_available
2026-11-06 15:35 ` Daniel P. Berrangé
2026-11-06 16:28 ` Yonggang Luo
@ 2026-11-06 17:13 ` Pierrick Bouvier
1 sibling, 0 replies; 11+ messages in thread
From: Pierrick Bouvier @ 2026-11-06 17:13 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, Yonggang Luo, Philippe Mathieu-Daudé
On 11/6/2026 7:35 AM, Daniel P. Berrangé wrote:
>>
>> Thanks for posting the series.
>>
>> Would that be possible to complete it so that beyond compilation, test
>> ./build/tests/unit/test-multi-target passes also? At the moment it fails
>> with duplicated types being registered.
>
> Oh I see, it didn't failure because I only enabled
> the two arm/aarch64 targets, once i add in more
> targets we get a clash on the virt-machine class.
>
> FYI, it also fails without my patch series present
> in some scenarios:
>
> # child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) stderr: "Registering `vm-launch-update' which already exists\n"
> **
> ERROR:../tests/unit/test-multi-target.c:41:test_qom_types_are_unique: child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) failed unexpectedly
> not ok /multi-targets/qom-types-are-unique/aarch64 - ERROR:../tests/unit/test-multi-target.c:41:test_qom_types_are_unique: child process (/multi-targets/qom-types-are-unique/aarch64 [1950288]) failed unexpectedly
> Bail out!
> Aborted (core dumped) tests/unit/test-multi-target
>
> This is caused by presence of 'igvm-devel' at build time on
> one of my machines (Fedora), which enables this device type,
> if you have both arm and aarch64 targets enabled.
>
> We need to add igvm to our Fedora dockerfile to catch this
> in CI.
>
> Moving it from specific_ss to system_ss make the test pass,
> but I'm unclear if it is sufficient to rely on lack of
> compiler and test complaints ? Or it needs manual code
> inspection to make sure the device is safe in this
> scenario ?
>
We are guaranteed a "common" file works because config poisoning ensures
the whole compilation unit, including headers, does not use any target
specific code (#ifdef).
So if it compiles, it's a safe change.
>> That's why this is_available was introduced in the first place. It was
>> just a way to move forward and provide the multi-target test to prevent
>> regression while work on single-binary is continued by Yonggang.
>
> Right, so with my series, we would first need the class
> renames to fix the multi-target test.
>
Correct. That's why is_available was used to do selective registration
for virt and max cpu, because I don't see how a rename can work without
breaking existing binaries.
Introducing .targets does not solve the problem by itself, since name
conflict is still there. That's why I suggested to use buckets per
target, which is what Yonggang implemented.
I have no strong attachment to any approach and would be happy to follow
any end-to-end solution you recommend. I'll let you lead on this.
> I should have labelled this posting "POC" as it was not
> tested thoroughly.
>
No worries, it would have been caught in CI anyway, so we are safe here.
> With regards,
> Daniel
Regards,
Pierrick
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/4] hw: support machine filtering without is_available
2026-11-05 10:24 [PATCH 0/4] hw: support machine filtering without is_available Daniel P. Berrangé
` (4 preceding siblings ...)
2026-11-05 17:25 ` [PATCH 0/4] hw: support machine filtering without is_available Pierrick Bouvier
@ 2026-11-05 19:18 ` Yonggang Luo
2026-11-05 19:24 ` Pierrick Bouvier
5 siblings, 1 reply; 11+ messages in thread
From: Yonggang Luo @ 2026-11-05 19:18 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, Philippe Mathieu-Daudé, Pierrick Bouvier
On Thu, Nov 5, 2026 at 6:24 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> The 'is_available' callback on TypeInfo is based on a mistaken
Thanks, we realized the limitation of 'is_available', and discussed
with Pierrick a lot
about this, I implemented both ways to remove 'is_available' in my local branch.
One is this idea(these patches), add targets in MachineClass::targets,
but we have to rename "virt-machine" that
in conflict.
The other one also achieves the same effect, except no need to rename
"virt-machine" QOM type names, by introducing a private
TypeBucket in object.c I post a small series to answer you question,
in my local branch, "is_avaiable" is removed.
https://lore.kernel.org/qemu-devel/20261105190346.1539-1-luoyonggang@gmail.com/T/#t
In both local branches, there is no more QOM name conflict, and target
is selected till the machine selection. so that
have no target_info() access in class_init or type_init.
object_class_get_list(NULL, true); can be called without target
selection, the current question which direction is better.
Both ways works fine, and both ways have their advantages and disadvantages.
> notion that we should filter out classes at registration time
> based on architecture.
>
> This creates new problems however, some already present and
> some which will impact a future multi-target binary
>
> * For introspection of the binaries' features, we have
> a dependancy on selecting a target before we can
> introspect features. It would require re-launching
> QEMU for each target, leading to lots of redundant
> introspection and a big time sink. It would also not
> be possible to introspect targets
>
> * It creates a circular dependancy on QOM initialization
> inside the QOM initialization code, since 'target_info()'
> itself uses QOM. This then requires further work to break
> by initializing QOM target info before the rest of QOM.
>
> * We have no means to introspect what targets a machine
> type can be used with, as this information is expressed
> as code (in target_XXXX() methods), instead of as data.
>
> * New fields in TypeInfo requires more changes to macros
> used for initializing machines.
>
> There is no inherant conceptual reason why we must filter out
> classes at type registration time. This is just a shortcut to
> workaround historical technical debt where certain classes
> have clashing names. This is an undesirable approach, as it
> is trading one set of problems for a new set of problems.
>
> This series proposes removal of the 'is_available' concept
> from QOM, and illustrates handling machines with full introspection
> support available from the MachineClass.
>
> This implies fixing the root cause, of clashing class names,
> but does not include patches since various series have already
> been posted for machine class name fixes.
>
> The machine changes are fairly simple
>
> * MachineClass gains a 'targets' field which is a bit mask
> of SysEmuTarget
> * machine_class_is_available() matches 'targets' against
> 'target_info()'
> * -machine CLI enforces machine_class_is_available()
> * query-machines filters on machine_class_is_available
> by default
> * query-machines gains 'all-targets': 'bool' to opt-in
> to returning the unfiltered list, with a 'targets'
> list present
>
> NB, this removes filtering from riscv CPUs with no
> alternative proposed. I'm unclear what this was trying
> to address to begin with, but utlimately it should be
> possible to address it with runtime filtering/matching
> of classes, instead of hiding TypeInfo registration.
> If someone gives me info on the CPUs problem I can a
> make a design suggestion.
>
> Daniel P. Berrangé (4):
> hw/core: record permitted targets against MachineClass
> hw: replace 'is_available' with 'targets' in machines
> target/riscv: remove 'is_available' from riscv CPUs
> qom: drop the 'is_available' callback from TypeInfo
>
> hw/arm/aspeed_ast27x0-fc.c | 3 ++-
> hw/arm/aspeed_ast27x0_evb.c | 5 +++--
> hw/arm/raspi.c | 21 +++++++++++++--------
> hw/arm/raspi4b.c | 3 ++-
> hw/arm/virt.c | 5 +++--
> hw/core/machine-qmp-cmds.c | 18 ++++++++++++++++++
> hw/core/machine.c | 13 +++++++++++++
> hw/hexagon/virt.c | 3 ++-
> hw/m68k/virt.c | 4 ++--
> hw/or1k/virt.c | 3 ++-
> hw/riscv/virt.c | 4 +++-
> include/hw/core/boards.h | 3 +++
> include/qom/object.h | 3 ---
> qapi/machine.json | 12 +++++++++++-
> qom/object.c | 4 ----
> rust/qom/src/qom.rs | 1 -
> system/vl.c | 9 +++++++++
> target/riscv/kvm/kvm-cpu.c | 1 -
> target/riscv/tcg/tcg-cpu.c | 1 -
> 19 files changed, 86 insertions(+), 30 deletions(-)
>
> --
> 2.56.0
>
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH 0/4] hw: support machine filtering without is_available
2026-11-05 19:18 ` Yonggang Luo
@ 2026-11-05 19:24 ` Pierrick Bouvier
0 siblings, 0 replies; 11+ messages in thread
From: Pierrick Bouvier @ 2026-11-05 19:24 UTC (permalink / raw)
To: luoyonggang, Daniel P. Berrangé
Cc: qemu-devel, Philippe Mathieu-Daudé
On 11/5/2026 11:18 AM, Yonggang Luo wrote:
> On Thu, Nov 5, 2026 at 6:24 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>>
>> The 'is_available' callback on TypeInfo is based on a mistaken
>
> Thanks, we realized the limitation of 'is_available', and discussed
> with Pierrick a lot
> about this, I implemented both ways to remove 'is_available' in my local branch.
>
> One is this idea(these patches), add targets in MachineClass::targets,
> but we have to rename "virt-machine" that
> in conflict.
>
> The other one also achieves the same effect, except no need to rename
> "virt-machine" QOM type names, by introducing a private
> TypeBucket in object.c I post a small series to answer you question,
> in my local branch, "is_avaiable" is removed.
> https://lore.kernel.org/qemu-devel/20261105190346.1539-1-luoyonggang@gmail.com/T/#t
>
>
> In both local branches, there is no more QOM name conflict, and target
> is selected till the machine selection. so that
> have no target_info() access in class_init or type_init.
> object_class_get_list(NULL, true); can be called without target
> selection, the current question which direction is better.
> Both ways works fine, and both ways have their advantages and disadvantages.
>
I was waiting for Daniel to explicitly describe what is expected:
implement it is even better. Now that we have the two approaches clearly
described, I'll let Daniel pick and finalize the one he wants to see for
this new binary.
Only requirement is that it has to build and pass the multi target test,
so we know there is no regression.
Thanks for your work and persistence on this Yonggang.
>
>
>> notion that we should filter out classes at registration time
>> based on architecture.
>>
>> This creates new problems however, some already present and
>> some which will impact a future multi-target binary
>>
>> * For introspection of the binaries' features, we have
>> a dependancy on selecting a target before we can
>> introspect features. It would require re-launching
>> QEMU for each target, leading to lots of redundant
>> introspection and a big time sink. It would also not
>> be possible to introspect targets
>>
>> * It creates a circular dependancy on QOM initialization
>> inside the QOM initialization code, since 'target_info()'
>> itself uses QOM. This then requires further work to break
>> by initializing QOM target info before the rest of QOM.
>>
>> * We have no means to introspect what targets a machine
>> type can be used with, as this information is expressed
>> as code (in target_XXXX() methods), instead of as data.
>>
>> * New fields in TypeInfo requires more changes to macros
>> used for initializing machines.
>>
>> There is no inherant conceptual reason why we must filter out
>> classes at type registration time. This is just a shortcut to
>> workaround historical technical debt where certain classes
>> have clashing names. This is an undesirable approach, as it
>> is trading one set of problems for a new set of problems.
>>
>> This series proposes removal of the 'is_available' concept
>> from QOM, and illustrates handling machines with full introspection
>> support available from the MachineClass.
>>
>> This implies fixing the root cause, of clashing class names,
>> but does not include patches since various series have already
>> been posted for machine class name fixes.
>>
>> The machine changes are fairly simple
>>
>> * MachineClass gains a 'targets' field which is a bit mask
>> of SysEmuTarget
>> * machine_class_is_available() matches 'targets' against
>> 'target_info()'
>> * -machine CLI enforces machine_class_is_available()
>> * query-machines filters on machine_class_is_available
>> by default
>> * query-machines gains 'all-targets': 'bool' to opt-in
>> to returning the unfiltered list, with a 'targets'
>> list present
>>
>> NB, this removes filtering from riscv CPUs with no
>> alternative proposed. I'm unclear what this was trying
>> to address to begin with, but utlimately it should be
>> possible to address it with runtime filtering/matching
>> of classes, instead of hiding TypeInfo registration.
>> If someone gives me info on the CPUs problem I can a
>> make a design suggestion.
>
>
>
>>
>> Daniel P. Berrangé (4):
>> hw/core: record permitted targets against MachineClass
>> hw: replace 'is_available' with 'targets' in machines
>> target/riscv: remove 'is_available' from riscv CPUs
>> qom: drop the 'is_available' callback from TypeInfo
>>
>> hw/arm/aspeed_ast27x0-fc.c | 3 ++-
>> hw/arm/aspeed_ast27x0_evb.c | 5 +++--
>> hw/arm/raspi.c | 21 +++++++++++++--------
>> hw/arm/raspi4b.c | 3 ++-
>> hw/arm/virt.c | 5 +++--
>> hw/core/machine-qmp-cmds.c | 18 ++++++++++++++++++
>> hw/core/machine.c | 13 +++++++++++++
>> hw/hexagon/virt.c | 3 ++-
>> hw/m68k/virt.c | 4 ++--
>> hw/or1k/virt.c | 3 ++-
>> hw/riscv/virt.c | 4 +++-
>> include/hw/core/boards.h | 3 +++
>> include/qom/object.h | 3 ---
>> qapi/machine.json | 12 +++++++++++-
>> qom/object.c | 4 ----
>> rust/qom/src/qom.rs | 1 -
>> system/vl.c | 9 +++++++++
>> target/riscv/kvm/kvm-cpu.c | 1 -
>> target/riscv/tcg/tcg-cpu.c | 1 -
>> 19 files changed, 86 insertions(+), 30 deletions(-)
>>
>> --
>> 2.56.0
>>
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread