On 8/12/2026 6:03 AM, Daniel P. Berrangé wrote:
> On Wed, Aug 12, 2026 at 05:54:49AM -0700, Pierrick Bouvier wrote:
>> On 8/12/2026 3:52 AM, Daniel P. Berrangé wrote:
>>> On Mon, Aug 10, 2026 at 03:26:26PM -0700, Pierrick Bouvier wrote:
>>>> I have been experimenting today with static filtering of types, as you
>>>> suggested, and came up with two possibilities. Before implementing this
>>>> for all types, I would like to get some feedback on which way is the
>>>> best for you.
>>>>
>>>> 1. Add a new callback is_available to TypeInfo, similar to existing
>>>> interface.
>>>> Pros: local information is present in type definition, making obvious
>>>>       why a type is available or not. Very easy to implement
>>>>       since only type_register_static has to be modified to check it.
>>>> Cons: Add a new field to each existing type. Not the end of the world
>>>>       in terms of memory consumption, but worth mentioning.
>>>> 2. Add conditional around each type_register_static, or add an
>>>> alternative type_register_static_cond function.
>>>> Pros: I don't see any
>>>> Cons: Decouples type information from type definition, makes it harder
>>>>       to follow why a type is available or not. Much more verbose since
>>>>       we need to modify all type_register_static buried in macros.
>>>>
>>>> Based on this, I'm much more in favor or 1. The fact availability
>>>> information is in the same location than type definition is the biggest
>>>> advantage for me.
>>>>
>>>> On example given above, this would give something like this:
>>>> static const TypeInfo emulated_card_info = {
>>>>      .name          = TYPE_EMULATED_CCID,
>>>>      .parent        = TYPE_CCID_CARD,
>>>>      .instance_size = sizeof(EmulatedState),
>>>>      .class_init    = emulated_class_initfn,
>>>>      .is_available  = target_config_X,
>>>> };
>>>>
>>>> Would that work for you?
>>>> Do you have a 3rd way to offer to solve the problem we have?
>>>
>>> In the case of user creatable objects, we represented a classes'
>>> conditional availablity in QAPI schema. For example:
>>>
>>>   { 'struct': 'InputLinuxProperties',
>>>     'data': { 'evdev': 'str',
>>>               '*grab_all': 'bool',
>>>               '*repeat': 'bool',
>>>               '*grab-toggle': 'GrabToggleKeys' },
>>>     'if': 'CONFIG_LINUX' }
>>>
>>> Now this isn't quite a match for what we want, as QAPI schema is
>>> common to all targets and used to control the code generator to
>>> turn off output. Thus the permitted CONFIG_xxx are only those in
>>> config-host.mak, not any from $TARGET-softmmu-config-devices.mak
>>>
>>> The other scenario in QAPI is the concept of features:
>>>
>>> { 'struct': 'SevCommonProperties',
>>>   'data': { '*sev-device': 'str',
>>>             '*cbitpos': 'uint32',
>>>             'reduced-phys-bits': 'uint32',
>>>             '*kernel-hashes': 'bool' },
>>>   'features': ['confidential-guest-reset']}
>>>
>>> where again we just have a list of named strings. Features are fully
>>> dynamic, and crucially they are introspectable so applications can
>>> query at runtime what is available.
>>>
>>> The introspection concept is something that is highly likely to be
>>> relevant to our use cases here. If we have a single binary with all
>>> types, it would be very valuable to be able to query it once to
>>> discover everything in one go, instead of havnig to query it over
>>> and over again for each target. That implies the application doing
>>> the query needs to be told about per-target usage restrictions on
>>> types it is querying.
>>>
>>> We don't have QAPI schema for QDev devices currently, but it is likely
>>> we will do so in the future. We can't wait for that though as there is
>>> no clear ETA.
>>>
>>> What this all says to me though, is that instead of an 'is_available'
>>> method, we should instead just list the conditions as data in the
>>> TypeInfo struct directly. IOW a list of const strings like this:
>>>
>>>  static const TypeInfo emulated_card_info = {
>>>       .name          = TYPE_EMULATED_CCID,
>>>       .parent        = TYPE_CCID_CARD,
>>>       .instance_size = sizeof(EmulatedState),
>>>       .class_init    = emulated_class_initfn,
>>>       .available     = (const char *[]){ TARGET_AARCH64, CONFIG_something 
>>> .... },
>>>  };
>>>
>>> This will make it easy to add in introspection at a later date.
>>>
>>> The limitation is that this can only express an "AND" condition.
>>> You can not do complex AND+OR+grouping conditions that you could
>>> express in code, but IMHO that is not likely to be a problem.
>>> In the worst case you can define a higher level "CONFIG_BLAH"
>>> that encapsulates the complex condition.
>>>
>>
>> Those strings names reuse existing target config identifiers, which
>> can't be done because of config poisoning.
>> The string compare will definitively be visible at boot time, so we
>> should rely on enum instead if we go in this direction.
>>
>> I'm a bit worried about verbosity of the result:
>> .available     = (const char *[]){ ENUM_NAME_TARGET_AARCH64, {} }
>> versus:
>> is_available = target_aarch64
> 
> The verbosity could be hidden behind a macro that takes a tar
> 
> #define QOM_AVAIL_TGT(name) \
>    .available = (const char *[]) ENUM_TARGET # name, NULL }
> 
> So usage becomes
> 
>   static const TypeInfo emulated_card_info = {
>      .name          = TYPE_EMULATED_CCID,
>      .parent        = TYPE_CCID_CARD,
>      .instance_size = sizeof(EmulatedState),
>      .class_init    = emulated_class_initfn,
>      QOM_AVAIL_TGT(AARCH64),
>   }
> 
> A separate macro could be defined for the more complex case
> wanting multiple config options.
>

Then we'll have different macros for:
one target, a collection of target, a mix of target and config, config
only. Plus, we hide what was clear in the first place with:
.is_available = target_aarch64.

I'm not super fond of the result to be honest.
 >> 99% of the types will be filtered by target only, for which we have
>> functions in target-info API. Only a few of them will need custom
>> functions. It would be worth having a nice/short way to write this
>> without having to declare all combination in a file.
>> One of your point was to not include more macros, and seems like we'll
>> end up this way.
> 
> In this case the macros expand to data that is machine consumable
> at runtime, so I thjnk that's a good tradeoff.
> 
>> The introspection argument is good, but will we really need that? The
>> whole point of conversation was to register only types available,
>> ignoring the rest. If you want introspection, it means registering all
>> types and selectively filter them.
> 
> Yes, introspection is critical to mgmt apps and places where we
> forget/miss it cause endless pain.
>

We can easily make a mechanical replace on all '^\s*\.is_available'
lines when it will be needed. Feels like we are anticipating a bit too
much, and there would be no cost to change that later.

I would kindly ask again to consider if you would be ok to delay this to
when it's effectively introduced on QAPI side.

Would you be open to it?

> With regards,
> Daniel

Regards,
Pierrick

Reply via email to