On 8/12/2026 7:26 AM, Daniel P. Berrangé wrote:
> On Wed, Aug 12, 2026 at 07:09:29AM -0700, Pierrick Bouvier wrote:
>> 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.
>
> That's a different interpration of "clear".
>
> What I'm proposing exposes the rules as data, and that ensures
> the rules are clear to machines.
>
> What you're proposing exposes the rules as code and that is only
> clear to human reviewers.
>
Agree, I will always prefer what is clear for human to read/understand.
That said, your requirement is fair also, and I see the value in
describing rules instead of a function pointer.
We both agree to add a field in TypeInfo, that's a good start.
I'll do my best to add something that satisfies both in next version.
>> >> 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?
>
> Introspection has always been a critical problem in QEMU and rectifying
> it after the fact is very costly. IMHO we need to do this as data from
> day one rather than knowingly taking a path that makes introspection
> harder.
>
>
> With regards,
> Daniel
Thanks for the feedback, and glad we found a solution that works for
both of us.
Regards,
Pierrick