From: "Daniel P. Berrangé" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Yonggang Luo" <luoyonggang@gmail.com>,
"Philippe Mathieu-Daudé" <philmd@oss.qualcomm.com>,
"Pierrick Bouvier" <pierrick.bouvier@oss.qualcomm.com>,
"Daniel P. Berrangé" <berrange@redhat.com>
Subject: [PATCH 1/4] hw/core: record permitted targets against MachineClass
Date: Thu, 5 Nov 2026 10:24:29 +0000 [thread overview]
Message-ID: <20261105102432.1131493-2-berrange@redhat.com> (raw)
In-Reply-To: <20261105102432.1131493-1-berrange@redhat.com>
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
next prev parent reply other threads:[~2026-11-05 10:25 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
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é [this message]
2026-11-05 10:24 ` [PATCH 2/4] hw: replace 'is_available' with 'targets' in machines Daniel P. Berrangé
2026-11-05 10:24 ` [PATCH 3/4] target/riscv: remove 'is_available' from riscv CPUs Daniel P. Berrangé
2026-11-05 10:24 ` [PATCH 4/4] qom: drop the 'is_available' callback from TypeInfo Daniel P. Berrangé
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
2026-11-05 19:18 ` Yonggang Luo
2026-11-05 19:24 ` Pierrick Bouvier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261105102432.1131493-2-berrange@redhat.com \
--to=berrange@redhat.com \
--cc=luoyonggang@gmail.com \
--cc=philmd@oss.qualcomm.com \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.