From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
To: Markus Armbruster <armbru@redhat.com>
Cc: qemu-devel@nongnu.org, richard.henderson@linaro.org,
stefanha@redhat.com, "Michael Roth" <michael.roth@amd.com>,
pbonzini@redhat.com, berrange@redhat.com,
peter.maydell@linaro.org, thuth@redhat.com, jsnow@redhat.com,
philmd@linaro.org, "Alex Bennée" <alex.bennee@linaro.org>,
devel@lists.libvirt.org
Subject: Re: [RFC PATCH 0/3] single-binary: make QAPI generated files common
Date: Fri, 25 Apr 2025 14:07:34 -0700 [thread overview]
Message-ID: <5b21965d-2428-454c-9dd7-266987495abd@linaro.org> (raw)
In-Reply-To: <87a584b69n.fsf@pond.sub.org>
On 4/25/25 08:38, Markus Armbruster wrote:
> Pierrick Bouvier <pierrick.bouvier@linaro.org> writes:
>
>> Note: This RFC was posted to trigger a discussion around this topic, and it's
>> not expected to merge it as it is.
>>
>> Context
>> =======
>>
>> Linaro is working towards heterogeneous emulation, mixing several architectures
>> in a single QEMU process. The first prerequisite is to be able to build such a
>> binary, which we commonly name "single-binary" in our various series.
>> An (incomplete) list of series is available here:
>> https://patchew.org/search?q=project%3AQEMU+single-binary
>>
>> We don't expect to change existing command line interface or any observable
>> behaviour, it should be identical to existing binaries. If anyone notices a
>> difference, it will be a bug.
>
> Define "notice a difference" :) More on that below.
>
Given a single-binary *named* exactly like an existing qemu-system-X
binary, any user or QEMU management layer should not be able to
distinguish it from the real qemu-system-X binary.
The new potential things will be:
- introduction of an (optional) -target option, which allows to
override/disambiguate default target detected.
- potentially more boards/cpus/devices visible, once we start developing
heterogeneous emulation. See it as a new CONFIG_{new_board} present.
Out of that, once the current target is identified, based on argv[0],
there should be absolutely no difference, whether in the behaviour, UI,
command line, or the monitor interfaces.
Maybe (i.e. probably) one day people will be interested to create a new
shiny command line for heteregenous scenarios, but for now, this is
*not* the goal we pursue. We just want to be able to manually define a
board mixing two different cpu architectures, without reinventing all
the wheels coming with that. Once everything is ready (and not before),
it will be a good time to revisit the command line interface to reflect
this. Definitely a small task compared to all we have left to do now.
Finally, even if we decide to do those changes, I think they should be
reflected on both existing binaries and the new single-binary. It would
be a mistake to create "yet another" way to use QEMU, just because we
have N architectures available instead of one.
>> The first objective we target is to combine qemu-system-arm and
>> qemu-system-aarch64 in a single binary, showing that we can build and link such
>> a thing. While being useless from a feature point of view, it allows us to make
>> good progress towards the goal, and unify two "distinct" architectures, and gain
>> experience on problems met.
>
> Makes sense to me.
>
>> Our current approach is to remove compilation units duplication to be able to
>> link all object files together. One of the concerned subsystem is QAPI.
>>
>> QAPI
>> ====
>>
>> QAPI generated files contain conditional clauses to define various structures,
>> enums, and commands only for specific targets. This forces files to be
>> compiled for every target.
>
> To be precise: conditionals that use macros restricted to
> target-specific code, i.e. the ones poisoned by exec/poison.h. Let's
> call them target-specific QAPI conditionals.
>
> The QAPI generator is blissfully unaware of all this.
>
Indeed, the only thing QAPI generaor is aware of is that it's a compile
time definition, since it implements those with #if, compared to a
runtime check.
> The build system treats QAPI modules qapi/*-target.json as
> target-specific. The .c files generated for them are compiled per
> target. See qapi/meson.build.
>
> Only such target-specific modules can can use target-specific QAPI
> conditionals. Use in target-independent modules will generate C that
> won't compile.
>
> Poisoned macros used in qapi/*-target.json:
>
> CONFIG_KVM
> TARGET_ARM
> TARGET_I386
> TARGET_LOONGARCH64
> TARGET_MIPS
> TARGET_PPC
> TARGET_RISCV
> TARGET_S390X
>
>> What we try to do here is to build them only once
>> instead.
>
> You're trying to eliminate target-specific QAPI conditionals. Correct?
>
Yes, but without impacting the list of commands exposed. Thus, it would
be needed to select at runtime to expose/register commands.
>> In the past, we identied that the best approach to solve this is to expose code
>> for all targets (thus removing all #if clauses), and stub missing
>> symbols for concerned targets.
>
> This affects QAPI/QMP introspection, i.e. the value of query-qmp-schema.
>
> Management applications can no longer use introspection to find out
> whether target-specific things are available.
>
As asked on my previous email answering Daniel, would that be possible
to build the schema dynamically, so we can decide what to expose or not
introspection wise?
> For instance, query-cpu-definitions is implemented for targets arm,
> i386, loongarch, mips, ppc, riscv, and s390x. It initially was for
> fewer targets, and more targets followed one by one. Still more may
> follow in the future. Right now, management applications can use
> introspection to find out whether it is available. That stops working
> when you make it available for all targets, stubbed out for the ones
> that don't (yet) implement it.
>
I will repeat, just to be clear, I don't think exposing all commands is
a good idea.
The current series *does not* do this, simply because I didn't want to
huge work for nothing.
> Management applications may have to be adjusted for this.
>
> This is not an attempt to shoot down your approach. I'm merely
> demonstrating limitations of your promise "if anyone notices a
> difference, it will be a bug."
>
I stick to this promise :).
> Now, we could get really fancy and try to keep introspection the same by
> applying conditionals dynamically somehow. I.e. have the single binary
> return different introspection values depending on the actual guest's
> target.
>
> This requires fixing the target before introspection. Unless this is
> somehow completely transparent (wrapper scripts, or awful hacks based on
> the binary's filename, perhaps), management applications may have to be
> adjusted to actually do that.
>
> Applies not just to introspection. Consider query-cpu-definitions
> again. It currently returns CPU definitions for *the* target. What
> would a single binary's query-cpu-definitions return? The CPU
> definitions for *all* its targets? Management applications then receive
> CPUs that won't work, which may upset them. To avoid noticable
> difference, we again have to fix the target before we look.
>
> Of course, "fixing the target" stops making sense once we move to
> heterogeneous machines with multiple targets.
>
At this point, I don't have think about what should be the semantic when
we'll have multiple targets running simultaneously (expose the union,
restrict to the main arch, choose a third way).
>> This series build QAPI generated code once, by removing all TARGET_{arch} and
>> CONFIG_KVM clauses. What it does *not* at the moment is:
>> - prevent target specific commands to be visible for all targets
>> (see TODO comment on patch 2 explaining how to address this)
>> - nothing was done to hide all this from generated documentation
>
> For better or worse, generated documentation always contains everything.
>
Fine for me, it makes sense, as the official documentation published,
which is what people will consume primarily, is for all targets.
> An argument could be made for stripping out documentation for the stuff
> that isn't included in this build.
>
>> From what I understood, the only thing that matters is to limit qmp commands
>> visible. Exposing enums, structure, or events is not a problem, since they
>> won't be used/triggered for non concerned targets. Please correct me if this is
>> wrong, and if there are unexpected consequences for libvirt or other consumers.
>
> I'm not sure what you mean by "to limit qmp commands visible".
>
> QAPI/QMP introspection has all commands and events, and all types
> reachable from them. query-qmp-schema returns an array, where each
> array element describes one command, event, or type. When a command,
> event, or type is conditional in the schema, the element is wrapped in
> the #if generated for the condition.
>
After reading and answering to your valuable email, I definitely think
the introspection schema we expose should be adapted, independently of
how we build QAPI code (i.e. using #ifdef TARGET or not).
Is it something technically hard to achieve?
>>
>> Impact on code size
>> ===================
>>
>> There is a strong focus on keeping QEMU fast and small. Concerning performance,
>> there is no impact, as the only thing that would change is to conditionally
>> check current target to register some commands.
>> Concerning code size, you can find the impact on various qemu-system binaries
>> with optimized and stripped build.
>>
>> upstream:
>> 12588 ./build/qemu-system-s390x
>> 83992 ./build/qemu-system-x86_64
>> 31884 ./build/qemu-system-aarch64
>> upstream + this series:
>> 12644 ./build/qemu-system-s390x (+56kB, +0.004%)
>> 84076 ./build/qemu-system-x86_64 (+84kB, +0.001%)
>> 31944 ./build/qemu-system-aarch64 (+60kB, +0.001%)
>>
>> Feedback
>> ========
>>
>> The goal of this series is to be spark a conversation around following topics:
>>
>> - Would you be open to such an approach? (expose all code, and restrict commands
>> registered at runtime only for specific targets)
>
> Yes, if we can find acceptable solutions for the problems that come with
> it.
>
>> - Are there unexpected consequences for libvirt or other consumers to expose
>> more definitions than what we have now?
>
> Maybe.
>
>> - Would you recommend another approach instead? I experimented with having per
>> target generated files, but we still need to expose quite a lot in headers, so
>> my opinion is that it's much more complicated for zero benefit. As well, the
>> code size impact is more than negligible, so the simpler, the better.
>>
>> Feel free to add anyone I could have missed in CC.
>
> I'm throwing in devel@lists.libvirt.org.
>
>> Regards,
>> Pierrick
>>
>> Pierrick Bouvier (3):
>> qapi: add weak stubs for target specific commands
>> qapi: always expose TARGET_* or CONFIG_KVM code
>> qapi: make all generated files common
>>
>> qapi/commands-weak-stubs.c | 38 ++++++++++++++++++++++++++++++++++++++
>> qapi/meson.build | 5 ++++-
>> scripts/qapi/commands.py | 4 ++++
>> scripts/qapi/common.py | 4 +++-
>> 4 files changed, 49 insertions(+), 2 deletions(-)
>> create mode 100644 qapi/commands-weak-stubs.c
>
Thanks,
Pierrick
next prev parent reply other threads:[~2025-04-25 21:08 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-24 18:33 [RFC PATCH 0/3] single-binary: make QAPI generated files common Pierrick Bouvier
2025-04-24 18:33 ` [RFC PATCH 1/3] qapi: add weak stubs for target specific commands Pierrick Bouvier
2025-04-24 18:52 ` Pierrick Bouvier
2025-04-24 18:33 ` [RFC PATCH 2/3] qapi: always expose TARGET_* or CONFIG_KVM code Pierrick Bouvier
2025-04-24 18:33 ` [RFC PATCH 3/3] qapi: make all generated files common Pierrick Bouvier
2025-04-24 20:31 ` Philippe Mathieu-Daudé
2025-04-24 21:08 ` Richard Henderson
2025-04-24 20:43 ` [RFC PATCH 0/3] single-binary: make QAPI " Philippe Mathieu-Daudé
2025-04-24 21:15 ` Richard Henderson
2025-04-24 22:22 ` Pierrick Bouvier
2025-04-24 20:44 ` Philippe Mathieu-Daudé
2025-04-25 7:35 ` Daniel P. Berrangé
2025-04-25 20:39 ` Pierrick Bouvier
2025-04-28 8:37 ` Daniel P. Berrangé
2025-04-28 15:54 ` Pierrick Bouvier
2025-04-25 22:16 ` Philippe Mathieu-Daudé
2025-04-26 4:53 ` Markus Armbruster
2025-04-25 15:38 ` Markus Armbruster
2025-04-25 21:07 ` Pierrick Bouvier [this message]
2025-04-25 21:13 ` Pierrick Bouvier
2025-04-26 6:21 ` Markus Armbruster
2025-04-28 16:05 ` Pierrick Bouvier
2025-04-29 7:43 ` Markus Armbruster
2025-04-29 8:37 ` Daniel P. Berrangé
2025-04-29 19:26 ` Pierrick Bouvier
2025-05-07 11:21 ` Markus Armbruster
2025-04-29 19:15 ` Pierrick Bouvier
2025-05-07 7:55 ` Markus Armbruster
2025-05-07 11:32 ` Daniel P. Berrangé
2025-05-07 19:00 ` Pierrick Bouvier
2025-05-07 18:54 ` Pierrick Bouvier
2025-04-28 10:25 ` Peter Krempa
2025-04-28 16:18 ` Pierrick Bouvier
2025-04-28 8:55 ` Peter Krempa
2025-04-28 11:07 ` Markus Armbruster
2025-04-28 12:48 ` Philippe Mathieu-Daudé
2025-04-28 16:35 ` Pierrick Bouvier
2025-04-29 8:23 ` Markus Armbruster
2025-04-29 9:20 ` Thomas Huth
2025-04-29 9:32 ` Daniel P. Berrangé
2025-04-29 9:39 ` Philippe Mathieu-Daudé
2025-04-29 19:48 ` Pierrick Bouvier
2025-04-30 5:40 ` Thomas Huth
2025-04-30 6:18 ` Pierrick Bouvier
2025-04-29 9:35 ` Philippe Mathieu-Daudé
2025-04-29 9:47 ` Daniel P. Berrangé
2025-04-29 19:57 ` Pierrick Bouvier
2025-04-29 20:11 ` Pierrick Bouvier
2025-04-29 12:04 ` BALATON Zoltan
2025-04-28 18:14 ` Stefan Hajnoczi
2025-04-28 19:25 ` Pierrick Bouvier
2025-04-28 19:54 ` Stefan Hajnoczi
2025-04-28 21:35 ` Pierrick Bouvier
2025-05-07 23:19 ` 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=5b21965d-2428-454c-9dd7-266987495abd@linaro.org \
--to=pierrick.bouvier@linaro.org \
--cc=alex.bennee@linaro.org \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=devel@lists.libvirt.org \
--cc=jsnow@redhat.com \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=stefanha@redhat.com \
--cc=thuth@redhat.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).