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.


>
> It's something we asked multiple times, and until we don't have a short
> series doing this change + a single and minimal modification showing the
> reason, I will still be asking.
>
> If the goal is to implement some sort of classification for
> machines/cpus, I would suggest to just send a simple series doing this
> change (and only this - no additional cleanups/refactoring), and an
> example for a single machine + cpu, so we can talk about it.
>
> Regards,
> Pierrick



-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo

Reply via email to