On 10/7/2026 5:00 PM, Pierrick Bouvier wrote:
> On 10/7/2026 2:42 PM, Yonggang Luo wrote:
>> On Thu, Oct 8, 2026 at 4:44 AM Pierrick Bouvier
>> <[email protected]> wrote:
>>>
>>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
>>>> Change TypeInfo.is_available to the new TypeIsAvailable type, which
>>>> takes a const TargetInfo *. Registration passes target_info(), so
>>>> behavior is unchanged. object.h only forward-declares TargetInfo.
>>>>
>>>> Switch the existing users (raspi, raspi4b, ast27x0 evb and fc) and the
>>>> generated machine parents to the matching target_is_<arch> helpers.
>>>>
>>>> Signed-off-by: Yonggang Luo <[email protected]>
>>>> ---
>>>>  hw/arm/aspeed_ast27x0-fc.c  |  2 +-
>>>>  hw/arm/aspeed_ast27x0_evb.c |  4 ++--
>>>>  hw/arm/raspi.c              |  4 ++--
>>>>  hw/arm/raspi4b.c            |  2 +-
>>>>  hw/arm/virt.c               |  4 ++--
>>>>  hw/m68k/virt.c              |  4 ++--
>>>>  hw/or1k/virt.c              |  2 +-
>>>>  include/qom/object.h        | 12 +++++++++++-
>>>>  qom/object.c                |  3 ++-
>>>>  9 files changed, 24 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
>>>> index 73362b60d2a..8a7c6a116ac 100644
>>>> --- a/hw/arm/aspeed_ast27x0-fc.c
>>>> +++ b/hw/arm/aspeed_ast27x0-fc.c
>>>> @@ -234,7 +234,7 @@ static const TypeInfo ast2700fc_types[] = {
>>>>          .parent         = TYPE_MACHINE,
>>>>          .class_init     = ast2700fc_class_init,
>>>>          .instance_size  = sizeof(Ast2700FCState),
>>>> -        .is_available   = target_aarch64,
>>>> +        .is_available   = target_is_aarch64,
>>>>      },
>>>>  };
>>>>
>>>> diff --git a/hw/arm/aspeed_ast27x0_evb.c b/hw/arm/aspeed_ast27x0_evb.c
>>>> index 460c9ff0d2e..02a8cff1d9d 100644
>>>> --- a/hw/arm/aspeed_ast27x0_evb.c
>>>> +++ b/hw/arm/aspeed_ast27x0_evb.c
>>>> @@ -75,13 +75,13 @@ static const TypeInfo aspeed_ast27x0_evb_types[] = {
>>>>          .name          = MACHINE_TYPE_NAME("ast2700a1-evb"),
>>>>          .parent        = TYPE_ASPEED_MACHINE,
>>>>          .class_init    = aspeed_machine_ast2700a1_evb_class_init,
>>>> -        .is_available  = target_aarch64,
>>>> +        .is_available  = target_is_aarch64,
>>>>      },
>>>>      {
>>>>          .name          = MACHINE_TYPE_NAME("ast2700a2-evb"),
>>>>          .parent        = TYPE_ASPEED_MACHINE,
>>>>          .class_init    = aspeed_machine_ast2700a2_evb_class_init,
>>>> -        .is_available  = target_aarch64,
>>>> +        .is_available  = target_is_aarch64,
>>>>      }
>>>>  };
>>>>
>>>> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
>>>> index fadbacb2534..22b06c6ca22 100644
>>>> --- a/hw/arm/raspi.c
>>>> +++ b/hw/arm/raspi.c
>>>> @@ -403,12 +403,12 @@ static const TypeInfo raspi_machine_types[] = {
>>>>          .name           = MACHINE_TYPE_NAME("raspi3ap"),
>>>>          .parent         = TYPE_RASPI_MACHINE,
>>>>          .class_init     = raspi3ap_machine_class_init,
>>>> -        .is_available   = target_aarch64,
>>>> +        .is_available   = target_is_aarch64,
>>>>      }, {
>>>>          .name           = MACHINE_TYPE_NAME("raspi3b"),
>>>>          .parent         = TYPE_RASPI_MACHINE,
>>>>          .class_init     = raspi3b_machine_class_init,
>>>> -        .is_available   = target_aarch64,
>>>> +        .is_available   = target_is_aarch64,
>>>>      }, {
>>>>          .name           = TYPE_RASPI_MACHINE,
>>>>          .parent         = TYPE_RASPI_BASE_MACHINE,
>>>> diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
>>>> index 566d64572db..a1dc477f25e 100644
>>>> --- a/hw/arm/raspi4b.c
>>>> +++ b/hw/arm/raspi4b.c
>>>> @@ -121,7 +121,7 @@ static const TypeInfo raspi4b_machine_type = {
>>>>      .parent         = TYPE_RASPI_BASE_MACHINE,
>>>>      .instance_size  = sizeof(Raspi4bMachineState),
>>>>      .class_init     = raspi4b_machine_class_init,
>>>> -    .is_available   = target_aarch64,
>>>> +    .is_available   = target_is_aarch64,
>>>>  };
>>>>
>>>>  static void raspi4b_machine_register_type(void)
>>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>>>> index 9d192515d85..18160f7fad3 100644
>>>> --- a/hw/arm/virt.c
>>>> +++ b/hw/arm/virt.c
>>>> @@ -132,7 +132,7 @@ static void arm_virt_compat_default_set(MachineClass 
>>>> *mc)
>>>>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
>>>>          .parent = TYPE_VIRT_MACHINE, \
>>>>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
>>>> -        .is_available = target_base_arm, \
>>>> +        .is_available = target_is_base_arm, \
>>>>      }; \
>>>>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
>>>>      { \
>>>> @@ -4430,7 +4430,7 @@ static const TypeInfo virt_machine_info = {
>>>>           { TYPE_HOTPLUG_HANDLER },
>>>>           { }
>>>>      },
>>>> -    .is_available = target_base_arm,
>>>> +    .is_available = target_is_base_arm,
>>>>  };
>>>>
>>>>  static void machvirt_machine_init(void)
>>>> diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
>>>> index e52546e4fab..ad2a43ef3fb 100644
>>>> --- a/hw/m68k/virt.c
>>>> +++ b/hw/m68k/virt.c
>>>> @@ -327,7 +327,7 @@ static const TypeInfo virt_machine_info = {
>>>>      .parent       = TYPE_MACHINE,
>>>>      .abstract     = true,
>>>>      .class_init   = virt_machine_class_init,
>>>> -    .is_available = target_m68k,
>>>> +    .is_available = target_is_m68k,
>>>>  };
>>>>
>>>>  static void virt_machine_register_types(void)
>>>> @@ -355,7 +355,7 @@ type_init(virt_machine_register_types)
>>>>          .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
>>>>          .parent = MACHINE_TYPE_NAME("virt"), \
>>>>          .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
>>>> -        .is_available = target_m68k, \
>>>> +        .is_available = target_is_m68k, \
>>>>      }; \
>>>>      static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
>>>>      { \
>>>> diff --git a/hw/or1k/virt.c b/hw/or1k/virt.c
>>>> index a3ff903839b..89fb786641f 100644
>>>> --- a/hw/or1k/virt.c
>>>> +++ b/hw/or1k/virt.c
>>>> @@ -559,7 +559,7 @@ static const TypeInfo or1ksim_machine_typeinfo = {
>>>>      .parent     = TYPE_MACHINE,
>>>>      .class_init = openrisc_virt_machine_init,
>>>>      .instance_size = sizeof(OR1KVirtState),
>>>> -    .is_available = target_or1k,
>>>> +    .is_available = target_is_or1k,
>>>>  };
>>>>
>>>>  static void or1ksim_machine_init_register_types(void)
>>>> diff --git a/include/qom/object.h b/include/qom/object.h
>>>> index 4c0645817a5..7d52a15f6b8 100644
>>>> --- a/include/qom/object.h
>>>> +++ b/include/qom/object.h
>>>> @@ -17,6 +17,7 @@
>>>>  #include "qapi/qapi-builtin-types.h"
>>>>  #include "qemu/module.h"
>>>>
>>>> +typedef struct TargetInfo TargetInfo;
>>>>  struct TypeImpl;
>>>>  typedef struct TypeImpl *Type;
>>>>
>>>> @@ -117,6 +118,15 @@ typedef void (ObjectUnparent)(Object *obj);
>>>>   */
>>>>  typedef void (ObjectFree)(void *obj);
>>>>
>>>> +/**
>>>> + * typedef TypeIsAvailable:
>>>> + * @ti: TargetInfo to test.
>>>> + *
>>>> + * Returns whether a type is available for @ti. Typical implementations
>>>> + * are target_is_*().
>>>> + */
>>>> +typedef bool (TypeIsAvailable)(const TargetInfo *ti);
>>>> +
>>>>  #define OBJECT_CLASS_CAST_CACHE 4
>>>>
>>>>  /**
>>>> @@ -498,7 +508,7 @@ struct TypeInfo
>>>>      void (*class_base_init)(ObjectClass *klass, const void *data);
>>>>      const void *class_data;
>>>>
>>>> -    bool (*is_available)(void);
>>>> +    TypeIsAvailable *is_available;
>>>>      const InterfaceInfo *interfaces;
>>>>  };
>>>>
>>>> diff --git a/qom/object.c b/qom/object.c
>>>> index 96498f3d001..253b9562b41 100644
>>>> --- a/qom/object.c
>>>> +++ b/qom/object.c
>>>> @@ -15,6 +15,7 @@
>>>>  #include "qom/compat-properties.h"
>>>>  #include "qom/object.h"
>>>>  #include "qom/object_interfaces.h"
>>>> +#include "qemu/target-info.h"
>>>>  #include "qemu/cutils.h"
>>>>  #include "qemu/memalign.h"
>>>>  #include "qapi/visitor.h"
>>>> @@ -167,7 +168,7 @@ static TypeImpl *type_register_internal(const TypeInfo 
>>>> *info)
>>>>          abort();
>>>>      }
>>>>
>>>> -    if (info->is_available && !info->is_available()) {
>>>> +    if (info->is_available && !info->is_available(target_info())) {
>>>>          return NULL;
>>>>      }
>>>>
>>>
>>> ```
>>> info->is_available(target_info())
>>> ```
>>>
>>> or
>>>
>>> ```
>>> is_available() {
>>>   TargetInfo ti * = target_info();
>>>   ...
>>> }
>>> ```
>>>
>>> Are doing the exact same thing today.
>>>
>>> So what is the future goal requiring to introduce this?
>>
>> From Daniel P. Berrangé's
>> requesthttps://lore.kernel.org/qemu-devel/[email protected]/
>>         I forgot to mention that this is also pretty important for making
>>         introspection work, as we need to be able to say
>>
>>           'qemu-system --machine none -qmp ...'
>>
>>         and connect to QMP to introspect the binary. Having to add a
>>         '--target <name>' into that mix is undesirable, as it creates
>>         a chicken & egg problem. You don't know what targets are built
>>         into qemu-system without introspecting it and you can't
>>         introspect it without selecting a target to introspect.
>>
>> From Pierrick's review
>> https://lore.kernel.org/qemu-devel/[email protected]/So,
>> for existing binary: -M virt works as before.
>>
>>         For new multi binary:
>>         $ qemu-system -M virt:
>>         Multiple machines were found, select one among:
>>         - aarch64-virt
>>         - riscv64-virt
>>
>>         Does it matches what you would expect?
>>
>> From Daniel's review
>> https://lore.kernel.org/qemu-devel/[email protected]/
>>         We already have  'QemuTargetInfo' struct which is used
>>         with 'query-target', that should also be used with the
>>         new 'query-targets' command.
>>
>>         We need to add the 'endianness' field to QemuTargetInfo.
>>
>>         I don't think that we need to report machines though.
>>         We already have 'query-machines' which gives much broader
>>         information on the machines. "MachineInfo" needs to
>>         gain
>>
>>         "targets": ["SysEmuTarget"]
>>
>>         to list which target(s) a machine can be used with.
>>
>>
>> To achieve these, we needs add TypeInfo parameter to it so that we can do
>>
>> static void report_unsupported_machine_type(const char *name, Error **errp)
>> {
>>     g_autoptr(GSList) machines = machine_class_get_list(true);
>>     g_autoptr(GString) targets = g_string_new(NULL);
>>     TargetInfoNode *node;
>>     GSList *el;
>>
>>     error_setg(errp, "unsupported machine type: \"%s\" for target \"%s\"",
>>                name, target_name());
>>     QLIST_FOREACH(node, target_info_list(), next) {
>>         for (el = machines; el; el = el->next) {
>>             MachineClass *mc = el->data;
>>
>>             if ((!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) &&
>>                 object_class_get_is_available(OBJECT_CLASS(mc))(node->info)) 
>> {
>>                 g_string_append_printf(targets, "  %s\n",
>>                                        node->info->target_name);
>>                 break;
>>             }
>>         }
>>     }
>>     if (targets->len) {
>>         error_append_hint(errp, "Available for targets:\n%s", targets->str);
>>     }
>> }
>>
>> That is we can iterate on all target-list, and check if it's can be fitlered.
>>
> 
> Ok, I finally see where this is going.
> 
> So, based on all the previous conversations, we agreed to have a
> qemu-system binary with all the QOM types available (for all targets).
> 
> I personally think that if we go this way, we should not have any
> -target option, and even less a -target none option.
> 
> The current is_available() approach was made with filtering per target
> in mind, which predates where things are now. So, it's a good time to
> reevaluate how to do it.
> 
> This leaves us with (at least) two options:
> - keep the callback and add TargetInfo parameter (what is done here)
> - remove is_available, and adopt a more declarative approach
> 
> How about we (re)-explore the second one?
> 
> It's what we did in the past
> (https://gitlab.com/qemu-project/qemu/-/commit/5de9216064d32eaac125dac4de1878486c16d73e),
> and that I removed recently, in favor of is_available.
> My rationale was that it was incomplete, since we needed to filter types
> per config also, and not only target.
> Now that direction is to not filter anything, filter per config is
> unneeded, and switching back to declarative instead of callback makes
> total sense. Using interfaces like we did has its own issues, and I
> would not like to see this coming back.
> 
> I'll do one very concrete proposal:
> 
> ```
> How about letting machines (and machines only first), have a new field
> 'targets', being a uint32_t mask with an array of EMU_TARGET?
> machine->targets = EMU_TARGET_X | EMU_TARGET_Y;
> ```
>

Machine class more exactly: mc->targets
See mc->desc for a concrete example of where it should be set.

> @Daniel, IIUC, this is exactly the approach you proposed a few weeks
> ago, just before I got frustrated and lost my patience against you. I
> think it's more clear for me where you wanted to go. Sorry it took such
> a large detour.
> 
> Yonggang, does that sounds good for you?
> Daniel, does that sounds good for you also?
> 
> Regards,
> Pierrick


Reply via email to