On Tue, Apr 29, 2025 at 09:43:24AM +0200, Markus Armbruster wrote:
> Pierrick Bouvier <pierrick.bouv...@linaro.org> writes:
> 
> > After looking at the introspection code, I don't see any major blocker.
> > We need to keep some of existing "if", as they are based on config-host, 
> > and should apply.
> > We can introduce a new "available_if" (or any other name), which 
> > generates a runtime check when building the schema, or when serializing 
> > a struct.
> >
> > This way, by modifying the .json with:
> > - if: 'TARGET_I386'
> > + available_if: 'target_i386()'
> >
> > This way, we keep the possibility to have ifdef, and we can expose at 
> > runtime based on available_if. So we can keep the exact same schema we 
> > have today per target.
> 
> The name is ugly.  Naming is hard.  No need to worry about it right now.
> 
> Semantics of having both 'if' and 'available_if'?  To work out an
> answer, let's consider how to convert conditionals:
> 
> * 'if': STRING
> 
>   If STRING is a target-specific macro, replace by 'available_if': PRED,
>   where PRED is the equivalent run-time predicate.
> 
>   Else, no change.
> 
> * 'if': { 'all': [COND, ...] }
> 
>   If COND contains only target-specific macros, replace by
>   'available_if': { 'all': [PRED, ...] }, where the PRED are the
>   equivalent run-time predicates.
> 
>   If COND contains no target-specific macros, no change.
> 
>   What if it contains both?
> 
>   - If each COND contains either only target-specific macros, or no
>     target-specific macros, we could split the target-specific ones off
>     into an additional 'available_if'.  This requires defining the
>     semantics of having both 'if' and 'available_if' as "both conditions
>     must be satisfied".
> 
>   - What if this isn't the case?
> 
> * 'if' { 'any': [COND, ...] }
> 
>   Similar, but to be able to split the COND we need "either condition
>   must be satisfied."
> 
> Even if we can make this work somehow, it would likely be a royal mess
> to explain in qapi-code-gen.rst.
> 
> We currently don't have "mixed" conditionals.  So we could sidestep the
> problem: you can have either 'if' or 'available_if', but not both.
> Feels like a cop out to me.
> 
> What if we move the "is dynamic" bit from the root of the conditional to
> its leaves?  So far, the leaves are macro names.  What if we
> additionally permit a function name?
> 
> Function name, not C expression, to not complicate generating code in
> languages other than C too much.
> 
> Ignore the question of syntax for now, i.e. how to decide whether a leaf
> is a macro or a function name.

I wonder if any of this is worth the pain in practice.....


Looking at the QAPI schema, we apply TARGET_xxxx conditions either to
commands, or to structs/enums that are used in args/return of commands.
We don't conditionalize individual fields, etc.

I tried to query our schema with 'jq' (incidentally rather tedious
because of our JSON-but-not-JSON language[1]). If I select only
commands we get:

query-cpu-definitions          => currently many arches
query-cpu-model-expansion      => currently many arches
query-cpu-model-baseline       => currently s390x only
query-cpu-model-comparison     => currently s390x only
query-s390x-cpu-polarization   => inherently s390x only
query-gic-capabilities         => inherently arm only
query-sev                      => inherently x86 only
query-sev-attestation-report   => inherently x86 only
query-sev-capabilities         => inherently x86 only
query-sev-launch-measure       => inherently x86 only
query-sgx                      => inherently x86 only
query-sgx-capabilities         => inherently x86 only
rtc-reset-reinjection          => inherently x86 only
set-cpu-topology               => inherently s390x only
sev-inject-launch-secret       => inherently x86 only
xen-event-inject               => currently x86 only
xen-event-list                 => currently x86 only

The two Xen commands are currently limited to x86, but if we ever extended
Xen to arm, possibly they would make sense. IOW, conceptually a target
conditional might be useful in future.

The CPU model commands are the ones where having the target conditions
visible in schema appears to add value, in that they'll allow a mgmt
app to detect when we extend any of them to cover new architectures.


Libvirt (and other mgmt apps) want to query the schema to see if commands
exist in the QEMU they're using, before trying to invoke them. To some
degree this is just a "nice to have" that improves error reporting/detection.


For the commands that are inherently arch specific, the mgmt app should
conceptually already know what architectures these commands apply to.
These target conditionals provide little (no) value when probing commands
in the schema.

IOW, if we (for example) have a single binary for x86 and s390, it should
be harmless if we report that 'query-sev' exists regardless of arch, as
the mgmt app should none the less already know to only use it with x86.

I don't know if libvirt correctly filters based on architecture in the
case of SEV/SGX/GIC/RTC when probing & using these features, but if it
does not, then I'd consider that a pre-existing bug that should be fixed.

Libvirt doesn't use the Xen commands.

For query-cpu-model-comparison/baseline, libvirt already filters its
usage of these based on s390 arch, so even if x86 reported them I
believe it won't break libvirt today. If these commands are extended
to other archs in future, libvirt might want a way to detect this.
On the flipside it might not be the end of the world if we just expose
them on all arches and simply have them return an error at runtime
where non-applicable. 


IOW, while the target conditions could theoretically provide value at
some point in future, it does not look like they do anything /today/
for libvirt.

Given that I wonder if we shouldn't just ignore the problem, and
blindly remove all TARGET_nnn conditions from QAPI schema today. Let
our future selves worry about it should this prove insufficient later.


With regards,
Daniel

[1] To use QAPI JSON with 'jq' you must convert ' to " and
    strip comments. eg
    
      cat *.json | sed -e "s/'/\"/g" -e 's/#.*//' | jq ...expression...
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Reply via email to