On Tue, Oct 13, 2026 at 11:57 AM Pierrick Bouvier
<[email protected]> wrote:
>
> On 10/12/26 2:27 PM, Yonggang Luo wrote:
> > On Thu, Oct 8, 2026 at 7:28 AM Pierrick Bouvier
> > <[email protected]> wrote:
> >>
> >> On 10/7/2026 4:02 PM, Yonggang Luo wrote:
> >>> On Thu, Oct 8, 2026 at 6:31 AM Pierrick Bouvier
> >>> <[email protected]> wrote:
> >>>>
> >>>> On 10/7/2026 1:50 PM, Yonggang Luo wrote:
> >>>>> On Thu, Oct 8, 2026 at 4:29 AM Pierrick Bouvier
> >>>>> <[email protected]> wrote:
> >>>>>>
> >>>>>> On 10/7/2026 4:48 AM, Yonggang Luo wrote:
> >>>>>>> Register target definitions through constructors instead of
> >>>>>>> MODULE_INIT_TARGET_INFO, making target_info_list() and target_info()
> >>>>>>> available on entry to main(), without explicit initialization or a
> >>>>>>> call to module_call_init(MODULE_INIT_QOM).
> >>>>>>>
> >>>>>>> Keep the target list sorted by target_arch and default to its first
> >>>>>>> entry. Provide an unknown TargetInfo fallback for target-independent
> >>>>>>> tools such as qemu-img and unit tests that link no target-info-def.c
> >>>>>>> objects.
> >>>>>>>
> >>>>>>> Remove the obsolete QOM target-info registration infrastructure and
> >>>>>>> update the multi-target test to inspect target information before
> >>>>>>> initializing QOM.
> >>>>>>>
> >>>>>>> Signed-off-by: Yonggang Luo <[email protected]>
> >>>>>>> ---
> >>>>>>>   include/qemu/module.h           |  1 -
> >>>>>>>   include/qemu/target-info-def.h  | 56 +++++++++++++++++++++++++++---
> >>>>>>>   include/qemu/target-info-init.h | 53 ----------------------------
> >>>>>>>   include/qemu/target-info-qom.h  | 31 -----------------
> >>>>>>>   include/qemu/target-info.h      |  9 +++++
> >>>>>>>   meson.build                     |  6 ++--
> >>>>>>>   system/vl.c                     |  4 ---
> >>>>>>>   target-info-def.c               |  1 -
> >>>>>>>   target-info-qom.c               | 60 
> >>>>>>> --------------------------------
> >>>>>>>   target-info.c                   | 61 
> >>>>>>> ++++++++++++++++++++++++++++++++-
> >>>>>>>   tests/qtest/fuzz/fuzz.c         |  3 --
> >>>>>>>   tests/unit/test-multi-target.c  | 12 +++----
> >>>>>>>   12 files changed, 129 insertions(+), 168 deletions(-)
> >>>>>>>   delete mode 100644 include/qemu/target-info-init.h
> >>>>>>>   delete mode 100644 include/qemu/target-info-qom.h
> >>>>>>>   delete mode 100644 target-info-qom.c
> >>>>>>>
> >>>>>>
> >>>>>> This approach (custom list based) was considered before implementing
> >>>>>> things with QOM Types. The rationale I followed was that if everything
> >>>>>> is in QOM, we might better follow that for consistency sake.
> >>>>>> Yes, the compromise if that we need an extra init step, but it was not 
> >>>>>> a
> >>>>>> problem to add it.
> >>>>> I have issue to add the init step for unit-tests, and hard to write the 
> >>>>> -target
> >>>>> parse procedure and get it right. Not means this won't work. but for
> >>>>> me, too much
> >>>>> coupled.
> >>>>>
> >>>>
> >>>> We already have such a test upstream:
> >>>> https://gitlab.com/qemu-project/qemu/-/blob/master/tests/unit/test-multi-target.c#L35
> >>>>
> >>>> The init sequence is quite straightforward:
> >>>>
> >>>> ```
> >>>> /* initialize target types, and only them */
> >>>> module_call_init(MODULE_INIT_TARGET_INFO);
> >>>>
> >>>> /* we can get the list if we want, for -target or any other purpose */
> >>>> g_autoptr(GSList) targets = object_class_get_list(TYPE_TARGET_INFO, 
> >>>> false);
> >>>>
> >>>> /* set the global target info from any element in this list */
> >>>> TargetInfo* ti = ...;
> >>>> target_info_qom_set_target_info(ti);
> >>>>
> >>>> /* register rest of QOM types */
> >>>> module_call_init(MODULE_INIT_QOM);
> >>>> ```
> >>>>
> >>>> It works fine to implement -target (if we would like to do it), since I
> >>>> implemented it myself. That was also my initial motivation by the way.
> >>>>
> >>>> Also, I appreciate that target-info is NULL by default, it crashes
> >>>> loudly when it has not been set, and make it easy to find who depends on 
> >>>> it.
> >>>>
> >>>>> If we treat target_info as a QOM, but QOM needs target_info to set
> >>>>> up(is_avaible). That makes
> >>>>> the init sequence too much of a burden.
> >>>>>
> >>>>
> >>>> See sequence above, the solution is to initialize TARGET_INFO first,
> >>>> before the rest of QOM. You end up with the same result than with a
> >>>> statically initialized list.
> >>>>
> >>>>>
> >>>>> is_available is depends on target_arch
> >>>>> And before this patch, target_arch depends on QOM, pulls user/softmmu 
> >>>>> because
> >>>>> target_info_init. By moving target-info to be a custom list based, we
> >>>>> can decouple
> >>>>> target-info from qom/softmmu/user. and target-info will always
> >>>>> available once "main(argv, argc)" is entered. We also have the
> >>>>> advantage of doing all sorts
> >>>>> of tests against it.
> >>>>>
> >>>>
> >>>> Which kind of tests are you trying to add?
> >>>>
> >>>> For now, the exact list of places where we need to do this initialize
> >>>> target dance are:
> >>>> - system/vl.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> >>>> - tests/qtest/fuzz/fuzz.c:    module_call_init(MODULE_INIT_TARGET_INFO);
> >>>> - tests/unit/test-multi-target.c:
> >>>
> >>> # Multi targets test
> >>> if multi_target_objects != []
> >>>    test('test-multi-target',
> >>>         executable('test-multi-target',
> >>>                    sources: [multi_target_crates, 
> >>> files('test-multi-target.c')],
> >>>                    dependencies: multi_target_deps,
> >>>                    objects: multi_target_objects,
> >>>                    link_depends: [block_syms, qemu_syms],
> >>>                    link_args: multi_target_link_args),
> >>>         suite: ['unit'])
> >>> endif
> >>>
> >>> I see this test, I am trying to add tests that do not pull so many
> >>> multi_target_objects, as it would be huge.
> >>
> >> Agree, we should not add more binary.
> >> If you need truly multi targets test, this existing binary is a good
> >> place to start: just add a second test in it.
> >>
> >>> Just pull qom only.  And I am trying to call target_info() in
> >>> object.c, as inspect machines with
> >>> qemu-system is rejected, so maybe that's not an issue anymore
> >>>
> >>
> >> Seems like a good candidate for the multi-target.c test.
> >>
> >>>
> >>> I means Subject: [PATCH v3 00/10] machine: uniquify virt QOM names
> >>> https://lore.kernel.org/qemu-devel/[email protected]/#r
> >>>
> >>> So the current design always rejects types that do not belong to the
> >>> current target. Listing them
> >>> all is not an option at all. With this restriction, then these are
> >>> indeed not needed.
> >>> So I'll wait for your work first, otherwise it's always conflicting.
> >>>
> >>>
> >>>> module_call_init(MODULE_INIT_TARGET_INFO);
> >>>>
> >>>> If we want more tests, I'm totally ok to move this init code to
> >>>> target-info.c, and replace call sites if needed.
> >>>>
> >>>>>
> >>>>> Tools such as qemu-img and unit tests may link target-info.c without any
> >>>>> target-info-def.c objects. Their target list remains empty, so use this
> >>>>> fallback.
> >>>>>
> >>>>
> >>>> Why should this tool get access to target list? qemu-img deals with disk
> >>>> images, and is unrelated to targets.
> >>>>
> >>>>>
> >>>>> static TypeImpl *type_register_internal(const TypeInfo *info)
> >>>>> {
> >>>>>      TypeImpl *ti;
> >>>>>
> >>>>>      if (!type_name_is_valid(info->name)) {
> >>>>>          fprintf(stderr, "Registering '%s' with illegal type name\n",
> >>>>> info->name);
> >>>>>          abort();
> >>>>>      }
> >>>>>
> >>>>>      if (info->is_available && !info->is_available()) {
> >>>>>          return NULL;
> >>>>>      }
> >>>>>
> >>>>>      ti = type_new(info);
> >>>>>
> >>>>>      type_table_add(ti);
> >>>>>      return ti;
> >>>>> }
> >>>>>
> >>>>>>
> >>>>>> Is there another good value this list approach brings compared to what
> >>>>>> exists?
> >>>>>>
> >>>>>> Regards,
> >>>>>> Pierrick
> >>>>>
> >>>>>
> >>>>>
> >>>>
> >>>
> >>>
> >>
> >
> >
> > Hi, the cycle dependencies issue happened again, deal with it's a bit
> > nasty, there is workaround, but I think
> > the constructor list is the best, here is the rationale:
> >
> >
> > # Target discovery during QOM registration
> >
> > ## Problem
> >
> > Machine registration needs the list of targets compiled into the binary.
> > Currently, it obtains that list through:
> >
> > ```c
> > object_class_get_list(TYPE_TARGET_INFO, false);
> > ```
> >
> > Despite the filter, QOM initializes every registered type before checking
> > whether it implements the requested type.
> >
> > During `MODULE_INIT_QOM`, registration is only partially complete. A device
> > may already be registered while its parent's registration callback has not
> > run, causing failures such as:
> >
> > ```text
> > Type 'sys-bus-device' is missing its parent 'device'
> > ```
> >
> > The parent is linked into the binary. The problem is premature
> > initialization, not a missing library.
> >
> > ## Option 1: cache target-info QOM classes
> >
> > Enumerate target-info classes once, before device registration starts.
> > Machine registration then reads the cache instead of enumerating QOM.
> >
> > ### Demo
> >
> > Declare shared helpers:
> >
> > ```c
> > void target_info_qom_init(void);
> > const GSList *target_info_qom_get_targets(void);
> > ```
> >
> > Implement the cache:
> >
> > ```c
> > static GSList *target_info_classes;
> > static bool target_info_initialized;
> >
> > void target_info_qom_init(void)
> > {
> >      if (target_info_initialized) {
> >          return;
> >      }
> >
> >      module_call_init(MODULE_INIT_TARGET_INFO);
> >      target_info_classes = object_class_get_list(TYPE_TARGET_INFO, false);
> >      target_info_initialized = true;
> > }
> >
> > const GSList *target_info_qom_get_targets(void)
> > {
> >      assert(target_info_initialized);
> >      return target_info_classes;
> > }
> > ```
> >
> > Initialize it before other QOM registration:
> >
> > ```c
> > target_info_qom_init();
> > module_call_init(MODULE_INIT_QOM);
> > ```
> >
> > Machine registration uses the borrowed cache:
> >
> > ```c
> > for (const GSList *l = target_info_qom_get_targets(); l; l = l->next) {
> >      const TargetInfo *ti = TARGET_INFO_CLASS(l->data)->target_info;
> >
> >      machine_register_virt_type_for_target(info, name_suffix, arch_mask,
> >                                           latest, ti);
> > }
> > ```
> >
> > `target_info_qom_set_target()` should also use the cached list instead of
> > enumerating QOM again.
> >
> > ### Advantages
> >
> > - Preserves the existing QOM-based representation.
> > - Avoids enumeration during incomplete device registration.
> > - Requires relatively small changes.
> >
> > ### Disadvantages
> >
> > - Every relevant executable and test must initialize the cache before
> >    starting QOM registration.
> > - `object_class_get_list()` allocates list nodes.
> > - Callers borrow the list, so it cannot be freed while they are using it.
> > - Cleanup is possible after all consumers finish, but requires an explicit
> >    lifecycle policy. Keeping the cache until process exit is a lifetime
> >    allocation, not inherently an unreachable memory leak.
> > - Target-info types registered after cache creation are not included.
> > - Target discovery remains coupled to QOM class initialization.
> >
> > ## Option 2: constructor-populated TargetInfo registry
> >
> > Each target registers its immutable `TargetInfo` pointer directly.
> > Machine registration later iterates the registry without querying QOM.
> >
> > Use a statically allocated node per target so registration requires no
> > heap allocation.
> >
> > ### Demo
> >
> > Define a registration node and accessors:
> >
> > ```c
> > typedef struct TargetInfoRegistration {
> >      const TargetInfo *info;
> >      struct TargetInfoRegistration *next;
> > } TargetInfoRegistration;
> >
> > void target_info_register(TargetInfoRegistration *entry);
> > const TargetInfoRegistration *target_info_get_targets(void);
> > ```
> >
> > Implement the registry in shared code:
> >
> > ```c
> > static TargetInfoRegistration *target_info_targets;
> >
> > void target_info_register(TargetInfoRegistration *entry)
> > {
> >      entry->next = target_info_targets;
> >      target_info_targets = entry;
> > }
> >
> > const TargetInfoRegistration *target_info_get_targets(void)
> > {
> >      return target_info_targets;
> > }
> > ```
> >
> > Each target's translation unit provides its own static node and
> > constructor. For example:
> >
> > ```c
> > static TargetInfoRegistration target_info_registration = {
> >      .info = &target_info_stub,
> > };
> >
> > static void __attribute__((constructor)) register_target_info(void)
> > {
> >      target_info_register(&target_info_registration);
> > }
> > ```
> >
> > The constructor must run exactly once per node. The existing target-info
> > initialization macro can generate this registration code alongside the
> > QOM registration code; user-mode target-info behavior should remain
> > unchanged.
> >
> > Machine registration consumes the completed registry:
> >
> > ```c
> > for (const TargetInfoRegistration *entry = target_info_get_targets();
> >       entry;
> >       entry = entry->next) {
> >      machine_register_virt_type_for_target(info, name_suffix, arch_mask,
> >                                           latest, entry->info);
> > }
> > ```
> >
> > The sequence is:
> >
> > ```text
> > Target constructors register static metadata pointers
> >      ↓
> > Startup constructors finish
> >      ↓
> > Machine registration iterates the completed registry
> > ```
> >
> > QOM target-info classes can remain available for introspection.
> >
> > ### Advantages
> >
> > - Makes target discovery independent of QOM initialization.
> > - Removes the explicit cache-initialization step from executables and tests.
> > - Avoids premature initialization of unrelated device types.
> > - Uses static storage: no allocated list nodes and no registry cleanup.
> > - Does not require ordering between target constructors.
> >
> > ### Constraints
> >
> > - Constructors must only register metadata, not enumerate or initialize
> >    QOM classes.
> > - Consumers must run after startup constructors have completed.
> > - Each registration node must be inserted exactly once.
> > - Registry order must not be treated as a meaningful target ordering.
> > - This simple design assumes compiled-in targets; runtime loading or
> >    unloading would require additional lifecycle handling.
> >
> > ## Comparison
> >
> > | Aspect | QOM class cache | Static constructor registry |
> > |---|---|---|
> > | Discovery mechanism | QOM enumeration | Direct metadata registration |
> > | Explicit startup initialization | Required | Not required |
> > | Heap allocation for list nodes | Yes | No |
> > | Cleanup policy | Required if releasing the cache | No registry cleanup |
> > | Dependency on QOM initialization | Yes | No |
> > | Registration-order sensitivity | Avoided through explicit sequencing
> > | Avoided by consuming after constructors |
> > | Late target registration | Cache needs updating | Requires a defined
> > runtime registration policy |
> >
> > ## Recommendation
> >
> > Prefer the constructor-populated registry with statically allocated nodes.
> >
> > `TargetInfo` describes the binary's compiled-in capabilities. Accessing
> > that metadata should not require initializing the device model or
> > maintaining an allocated cache of QOM classes.
> >
> > The QOM cache fixes the immediate failure, but introduces an additional
> > startup contract and ownership policy. A static constructor registry
> > removes the underlying dependency and avoids heap allocation for the
> > registry itself.
> >
>
> I will politely say one last time (and ignore this in the future):

apologize, I am doing this mainly because my poor English, I am post a
small patches instead.


> please do not copy paste AI summary to motivate any kind of design.
> Also, please do not post inline patches. In case you would like to
> develop an idea, send a minimal series (with one or two patches)
> presenting the concept and implementation, it's more efficient for
> collaboration.
>
> Regards,
> Pierrick



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

Reply via email to