* [RFC] Target-aware machine inventory in combined qemu-system
@ 2026-10-02 13:18 Yonggang Luo
2026-10-02 15:32 ` Yonggang Luo
0 siblings, 1 reply; 4+ messages in thread
From: Yonggang Luo @ 2026-10-02 13:18 UTC (permalink / raw)
To: qemu-level, Pierrick Bouvier, Daniel P. Berrangé,
Philippe Mathieu-Daudé, Markus Armbruster, Peter Maydell
## Goal
The goal is to specify the minimum useful design for a combined `qemu-system`
binary and use it as a basis for iteration, not to define multi-target support
for every QEMU machine, CPU, and device.
The prototype combines two configured `SysEmuTarget`s that provide machines
with the same public name, `virt` (for example, AArch64 and RISC-V). Its first
runnable case is concrete: start AArch64 `virt` with CPU `max` using an
explicit target:
```text
qemu-system -target aarch64 -machine virt -cpu max
```
It also defines what happens before a target is chosen. With target `none`,
QMP can inspect the complete machine inventory, and each `MachineInfo` reports
its supported targets. The CLI must not guess which `virt` to run; it reports
the targets that provide that name. Inferring a target from `argv[0]` is
deferred because the current build does not provide target-named symlinks to
the combined `qemu-system` binary. Existing per-target binaries and their
familiar machine names remain unchanged.
Implementation branches:
- [single-binary-arm-riscv](https://gitlab.com/lygstate-qemu/qemu/-/tree/single-binary-arm-riscv?ref_type=heads)
combines `none-softmmu`, `aarch64-softmmu`, `arm-softmmu`, and
`microblaze-softmmu`.
[CI pipeline for
single-binary-arm-riscv](https://gitlab.com/lygstate-qemu/qemu/-/pipelines/2906623802).
- [combined-binary-multi-targets](https://gitlab.com/lygstate-qemu/qemu/-/tree/combined-binary-multi-targets?ref_type=heads)
extends the combined target set with `riscv32-softmmu`, `riscv64-softmmu`,
`i386-softmmu`, and `x86_64-softmmu`.
[CI pipeline for
combined-binary-multi-targets](https://gitlab.com/lygstate-qemu/qemu/-/pipelines/2906685964).
## Design
There are three possible policies for deciding which target a combined
emulator should run:
1. **Infer from `argv[0]`.** A target-named symlink to the combined
`qemu-system` binary could provide a target-specific invocation name and
allow target selection from `argv[0]`. Defer this policy: the current build
does not provide those symlinks, so there is no target-specific invocation
name to inspect.
2. **Require an explicit `-target` for execution.** This is the current
selection mechanism. Parse `-target` early, select its `TargetInfo` before
module and QOM initialization, then resolve `-machine` and `-cpu` within
that target. For example:
```text
qemu-system -target aarch64 -machine virt -cpu max -S -display none
```
This makes target choice explicit when starting a target-specific machine;
it does not prevent a target-neutral inspection mode.
1. **Expose no target-specific machine for execution while the target is
`none`.** Do not guess which same-named machine to start. This is not a
policy of hiding machines from management clients: `query-machines` still
reports the combined inventory and each machine's supported targets.
The implementation below combines the second and third policies. The first
can be considered later without changing the inventory contract. The design
has three stages: register the combined type set, use target availability
when resolving a requested machine, and expose the complete inventory through
QMP.
### 1. Combined Registration Before QOM Hooks
Before the optional QOM hooks described below, `type_register_internal()`
skipped availability filtering in the combined binary and retained
`TypeInfo`s from all configured targets. Single-target binaries continued to
filter each type against the selected target during registration. Retaining
the full type set lets the target-`none` inventory report machines and the
targets that provide them.
`type_init()` functions are collected before they run, so `TypeInfo`
registration is not guaranteed to be parent-first. A child may register
before its parent. When a `TypeInfo` is registered, `type_new()` copies its
`is_available` function pointer into the new `TypeImpl`. The registered type
retains the callback value supplied by that `TypeInfo` for later processing.
### 2. Resolve Machine Names Without Guessing
For a selected target, normal machine lookup sees only machine classes
available to that target. If lookup fails, the error path scans the complete
registered machine list and evaluates each matching name or alias against all
registered `TargetInfo` values.
For example, the existing qtest exercises the `none` case. The target is
selected as `none`, but machine registration has retained the target-specific
classes, allowing the error path to explain where `virt` is available:
```text
$ qemu-system -machine virt
unsupported machine type: "virt" for target "none"
Available for targets:
aarch64
arm
Use -machine help to list supported machines
```
The command fails rather than selecting an arbitrary `virt`. This also lets
users of a target-specific binary continue to use the familiar machine name;
the combined binary's explicit target path remains available when starting a
machine:
```text
qemu-system -target aarch64 -machine virt -cpu max -S -display none
```
Here `-target aarch64` selects the target before QOM and machine setup, and
`-S` leaves the guest paused. This is an example of the existing target
selection path, not a new CLI proposal in this RFC.
### 3. Report the Combined Inventory
`query-machines` iterates over the registered machine classes. For each class,
it returns the public machine `name`, the actual QOM `typename`, and every
configured target for which the class's availability callback returns true.
This allows clients to distinguish machines that share a public name and
look up the right QOM type without deriving it from `-M`.
An abbreviated response for a combined build containing ARM-family and
RISC-V targets can look like this; the exact records depend on the configured
targets and machines:
```json
{
"return": [
{
"name": "virt",
"typename": "arm-virt-machine",
"targets": [{ "arch": "aarch64" }, { "arch": "arm" }]
},
{
"name": "virt",
"typename": "riscv-virt-machine",
"targets": [{ "arch": "riscv32" }, { "arch": "riscv64" }]
}
]
}
```
A client can then use the returned QOM type directly:
```json
{
"execute": "qom-list-properties",
"arguments": { "typename": "arm-virt-machine" }
}
```
This RFC describes inventory and diagnostics; it does not change the target
selection CLI or propose globally filtering devices.
### Optional: QOM before/after hooks
The hooks are an optional implementation of post-registration processing:
they run around `MODULE_INIT_QOM` to validate parent chains after registration
batches. The after-hook walks the full registered-type set, validates parent
links, and inherits each missing `is_available` callback from its parent.
`TYPE_OBJECT` and `TYPE_INTERFACE` are distinct roots; each root's `TypeInfo`
explicitly sets the callback to `target_is_any`. A child may provide its own
callback or leave it NULL to inherit from its parent. The completed pass
therefore gives every registered type an effective callback before filtering.
Filtering is optional; when used, it runs after registration and parent
validation, reclaiming runtime QOM metadata but not compiled code.
#### ARM and AArch64 example
The unit test registers a shared ARM-family parent, narrower ARM and AArch64
parents, and callback-free children. It uses `TYPE_OBJECT` as the test root:
```c
#define TYPE_ARM_BASE_MACHINE_FAMILY "test-avail-arm-base-machine-family"
#define TYPE_VIRT_MACHINE_VERSION "test-avail-virt-machine-version"
#define TYPE_ARM_MACHINE_FAMILY "test-avail-arm-machine-family"
#define TYPE_ARM_MACHINE "test-avail-arm-machine"
#define TYPE_AARCH64_MACHINE_FAMILY "test-avail-aarch64-machine-family"
#define TYPE_AARCH64_MACHINE "test-avail-aarch64-machine"
static const TypeInfo arm_base_machine_info = {
.name = TYPE_ARM_BASE_MACHINE_FAMILY,
.parent = TYPE_OBJECT,
.abstract = true,
.is_available = target_is_base_arm,
};
static const TypeInfo virt_machine_version_info = {
.name = TYPE_VIRT_MACHINE_VERSION,
.parent = TYPE_ARM_BASE_MACHINE_FAMILY,
};
static const TypeInfo arm_machine_family_info = {
.name = TYPE_ARM_MACHINE_FAMILY,
.parent = TYPE_ARM_BASE_MACHINE_FAMILY,
.abstract = true,
.is_available = target_is_arm,
};
static const TypeInfo arm_machine_info = {
.name = TYPE_ARM_MACHINE,
.parent = TYPE_ARM_MACHINE_FAMILY,
};
static const TypeInfo aarch64_machine_family_info = {
.name = TYPE_AARCH64_MACHINE_FAMILY,
.parent = TYPE_ARM_BASE_MACHINE_FAMILY,
.abstract = true,
.is_available = target_is_aarch64,
};
static const TypeInfo aarch64_machine_info = {
.name = TYPE_AARCH64_MACHINE,
.parent = TYPE_AARCH64_MACHINE_FAMILY,
};
static void register_target_family_types(void)
{
type_register_static(&virt_machine_version_info);
type_register_static(&arm_machine_info);
type_register_static(&aarch64_machine_info);
type_register_static(&arm_base_machine_info);
type_register_static(&arm_machine_family_info);
type_register_static(&aarch64_machine_family_info);
}
```
The test selects an ARM-family target, verifies that its child inherits the
parent callback, and checks that the other family's child is filtered out.
Production ARM `virt` uses the same shape with `TYPE_ARM_BASE_MACHINE` parented
to target-neutral `TYPE_MACHINE`; each versioned `virt` TypeInfo inherits from
that family parent.
`DSO_BEFORE` registrations defer validation until normal QOM initialization,
so parent types from the static `type_init()` batch have a chance to register.
`DSO_AFTER` registrations are checked after each batch. This hook arrangement
provides incremental validation for late registrations; it is an
implementation choice, separate from the combined binary's requirement to
register types before applying target filtering.
## Reviewer Concerns and Design Responses
The responses below describe the current prototype. Broader policies that
remain open are listed under [Remaining Questions](#remaining-questions).
- **Pierrick Bouvier: RFC request and machine-selection ambiguity.** Pierrick
requested this focused RFC:
> @Yonggang: can you try to provide a RFC based on this, to see what it
> could look like? No need to cover all machines/cpus, just select one of
> machine+cpu, ideally with multiple SysEmuTarget (like virt and max cpu
> for aarch64), and let's iterate from this.
On target-qualified machine names and ambiguous lookup, he wrote:
> That's my point, the current abstraction will create something ambiguous
> by design. When people will specify -M virt, without $arch:, a random
> machine will be selected. At least, maybe this series should ensure there
> is only one virt alias, or make it forbidden and uses unambiguous names
> only.
>
> "$arch:" is just a workaround to not add -target option, except that it
> comes with additional problems, creating inconsistent command lines. I
> already expressed my skepticism about the "machine prefix" based approach,
> being more in favor to strongly filter types per target with an
> unambiguous -target option.
**Response:** the prototype uses the dedicated `-target` option, selecting
`TargetInfo` before QOM setup, while preserving `virt` as the `-M` name.
With target `none`, `-M virt` fails and reports the targets that provide the
name instead of choosing one. A spelling such as `-machine aarch64-virt` is
not a reliable general alternative: hyphens already occur in machine names
such as `virt-11.1` and `sbsa-ref`, so a parser cannot safely split a machine
name at the first hyphen. Resolving the name by searching registered
machine classes would require QOM initialization, but the target must be
selected before QOM setup. A literal alias could be added for one machine,
but that would be a per-machine convention, not general target selection.
The concrete run and failure cases are shown in [Design](#design).
- **Daniel P. Berrange: target metadata and device compatibility.** Daniel
wrote:
> It would require that we introduce a new field in MachineClass
> that returned that information about what target a machine is
> associated with.
>
> I note the SysEmuTarget covers both 32-bit and 64-bit variants.
>
> It might be better use QEMU_ARCH which correlates directly to
> the TCG targets, rather than the traditional binary target
> names?
>
> Likely the CPU class would also want to declare its list of
> supported targets.
>
> IMHO just leave devices to raise an error when passed to '-device'
> if not compatible with the requested machine.
**Response:** the prototype represents availability with
`TypeInfo.is_available(TargetInfo *)` on each type, rather than adding a
separate target list to each machine and CPU class. A NULL callback inherits
availability from the parent; the root types default to `target_is_any`.
`SysEmuTarget` is retained because it distinguishes system-emulation
variants such as 32-bit and 64-bit targets. `query-machines` evaluates the
availability callback for each configured target and returns the resulting
`MachineInfo.targets`; the `-target aarch64 -machine virt -cpu max` example
demonstrates selecting a compatible machine/CPU pair. The prototype does
not add exhaustive per-device target metadata: devices may fail setup when
their required machine bus is absent, with better diagnostics left as
follow-up work.
Target identity is kept distinct from the base architecture with
`TARGET_SYS_EMU`. Meson defaults it to `TARGET_NAME` for softmmu targets and
to `TARGET_ARCH` for other targets, unless a target config overrides it.
Thus system-emulation variants such as `arm` and `aarch64` remain distinct
even when they share a base `TARGET_ARCH`. `TargetInfo.target_arch` is built
from `TARGET_SYS_EMU`:
```diff
- .target_arch = glue(SYS_EMU_TARGET_, TARGET_ARCH),
+ .target_arch = glue(SYS_EMU_TARGET_, TARGET_SYS_EMU),
```
Full change: [GitLab commit
diff](https://gitlab.com/lygstate-qemu/qemu/-/commit/b765db23b4294a7ca829e15e8577af228f229f37).
- **Philippe Mathieu-Daude: target discovery and scope.** Philippe wrote:
> Why mix target information parsing at machine level when the
> machine already know it is target specific? People wanting to
> use the ARM virt machine don't want to know (and don't care)
> about the M68k virt machine.
>
> You still did not explained what you are trying to achieve
> with all your contributions, so my view is surely biased by
> what we envisioned 3 years ago when we started to pave our
> way for heterogenous emulation.
>
> My options so far for a single binary:
>
> - infer from argv[]
> - enforce with CLI -target
> - not expose any machine
**Response:** The goal here is the target `none` inspection case, not a
requirement that ARM users select or even list unrelated machines to run
ARM `virt`. All registered machines remain visible through `query-machines`,
with each `MachineInfo` carrying its supported `targets`; this lets
management clients discover the combined inventory. For CLI execution, a
target-specific machine is resolved only after explicit `-target` selection.
At target `none`, a request such as `-M virt` fails with the supported-target
hints instead of choosing a machine. Inferring from argv is deferred, and
the inventory/QOM-name work is kept separate from the broader
heterogeneous-emulation selection design.
- **Markus Armbruster: QOM identity in `query-machines`.** Markus's message
quoted the patch rationale and acked it:
> query-machines returned only the -M name, so management apps inferred
> the QOM type as that name plus "-machine". A prefixed type such as
> arm-virt-11.1-machine no longer matches -M virt-11.1. Return the QOM
> type in MachineInfo typename from object_class_get_name() in
> qmp_query_machines(). test_query_machines_typename checks that
> qom-list-properties accepts it.
>
> Acked-by: Markus Armbruster <armbru@redhat.com>
**Response:** `query-machines` returns the public machine `name`, the actual
QOM `typename`, and supported `targets`. The QOM type is obtained from
`object_class_get_name()`, so management clients can pass it to
`qom-list-properties` instead of deriving it from the `-M` name.
`test_query_machines_typename` covers this lookup.
## Existing Tests
- `test_combined_errors` verifies that `-M virt` at target `none` fails,
includes the available targets, and does not fall through to an unrelated
target-help hint.
- `test_combined_machine_list` verifies the combined machine inventory against
the configured target list.
- `test-qom-is-available` checks callback inheritance for ARM and AArch64
family parents, target filtering, late registration, class-data destruction,
missing parents, and parent cycles.
- The combined machine-option tests also exercise explicit target selection
and machine startup, including the AArch64 `virt` machine.
## Remaining Questions
- Is the current `-M virt` error with supported-target hints sufficient, or
should a later CLI provide a separate way to choose among candidates?
- Is `MachineInfo.targets` sufficient for management clients to interpret
the combined inventory?
- Should devices receive explicit target-availability annotations, or is
machine setup failure with useful diagnostics sufficient?
- After registration, should the combined emulator free QOM metadata for
types unavailable to the selected target to save runtime memory, or keep
all types registered and require every lookup and listing path to check
availability? Keeping all types simplifies the complete inventory but
retains metadata for targets that are not selected.
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] Target-aware machine inventory in combined qemu-system
2026-10-02 13:18 [RFC] Target-aware machine inventory in combined qemu-system Yonggang Luo
@ 2026-10-02 15:32 ` Yonggang Luo
2026-10-02 15:45 ` Pierrick Bouvier
0 siblings, 1 reply; 4+ messages in thread
From: Yonggang Luo @ 2026-10-02 15:32 UTC (permalink / raw)
To: qemu-level, Pierrick Bouvier, Daniel P. Berrangé,
Philippe Mathieu-Daudé, Markus Armbruster, Peter Maydell
Now I place this RFC at https://gitlab.com/qemu-project/qemu/-/work_items/4635
Maybe there would be a better dicuss place if possible.
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] Target-aware machine inventory in combined qemu-system
2026-10-02 15:32 ` Yonggang Luo
@ 2026-10-02 15:45 ` Pierrick Bouvier
2026-10-02 15:56 ` Daniel P. Berrangé
0 siblings, 1 reply; 4+ messages in thread
From: Pierrick Bouvier @ 2026-10-02 15:45 UTC (permalink / raw)
To: luoyonggang, qemu-level, Daniel P. Berrangé,
Philippe Mathieu-Daudé, Markus Armbruster, Peter Maydell
On 10/2/2026 8:32 AM, Yonggang Luo wrote:
> Now I place this RFC at https://gitlab.com/qemu-project/qemu/-/work_items/4635
> Maybe there would be a better dicuss place if possible.
>
Let's keep this on the mailing list, thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] Target-aware machine inventory in combined qemu-system
2026-10-02 15:45 ` Pierrick Bouvier
@ 2026-10-02 15:56 ` Daniel P. Berrangé
0 siblings, 0 replies; 4+ messages in thread
From: Daniel P. Berrangé @ 2026-10-02 15:56 UTC (permalink / raw)
To: Pierrick Bouvier
Cc: luoyonggang, qemu-level, Philippe Mathieu-Daudé,
Markus Armbruster, Peter Maydell
On Fri, Oct 02, 2026 at 08:45:00AM -0700, Pierrick Bouvier wrote:
> On 10/2/2026 8:32 AM, Yonggang Luo wrote:
> > Now I place this RFC at https://gitlab.com/qemu-project/qemu/-/work_items/4635
> > Maybe there would be a better dicuss place if possible.
> >
>
> Let's keep this on the mailing list, thanks.
Agreed, we don't really use the bug tracker for feature requests
or design discussions.
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] 4+ messages in thread
end of thread, other threads:[~2026-10-02 15:57 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-02 13:18 [RFC] Target-aware machine inventory in combined qemu-system Yonggang Luo
2026-10-02 15:32 ` Yonggang Luo
2026-10-02 15:45 ` Pierrick Bouvier
2026-10-02 15:56 ` Daniel P. Berrangé
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.