Patrick Leis <vent...@google.com> writes:

> Corey and Peter,
>
> My team builds lots of configurations for Qemu boards, and one pain point
> has been that the qom path for a device depends on the device insertion
> order, child[0], child[1] and the like.

Yes.

Discussed in my "Dynamic & heterogeneous machines, initial
configuration: problems" memo, under "Problem 4: The
/machine/unattached/ orphanage".

Copy of the "Problem 4" part appended for your your convenience.  Full
memo archived at
https://lore.kernel.org/qemu-devel/87o7d1i7ky....@pond.sub.org/

>                                          I noticed that the qdev paths for
> devices also exist by their device id property.  By default, this ends up
> being the device type name.

Which kind of devices?

There are onboard devices and user-created devices.

A user-created device's QOM path is "/machine/peripheral/ID" when it was
created with a qdev ID, and "/machine/peripheral-anon/device[N]" (where
N counts up from zero) when it was created without a qdev ID.  N depends
on creation order, which is under the user's control.  Users can and
should avoid relying on their order by supplying an ID.

An onboard device's QOM path is chosen by board code.  For instance, q35
puts the mch device at "/machine/q35/mch".  However, if the board code
neglects to put the device anywhere, the system puts it at
"/machine/unattached/device[N]" (where N counts up from zero).  N
depends on creation order.

N can change at the drop of a hat.  Whether "device[N]" is a stable
interface is unclear.  It would clearly be a bad one.

If (part of) your problem is "/machine/peripheral-anon/device[N]",
supply IDs to bypass it.

If (part of) your problem is "/machine/unattached/device[N]", all I can
offer is the proper solution: fix the board code to put the device in
its proper place instead of abandoning it to the "/machine/unattached/"
orphanage.

>                              I was wondering if it made sense to override
> this with the device type plus the smbus address?  I did something similar
> with the i2c mux device, to resolve part of this issue.

I doubt it.

Questions?



= Problem 4: The /machine/unattached/ orphanage =

Is it okay for a QOM object to have no parent?

An object without a parent is not part of the composition tree; it has
no canonical path, and object_get_canonical_path() returns null.

Such objects can behave in wonky ways.  For instance,
object_property_set_link() treats a target object without a parent as
null.  If a linked object somehow loses its parent,
object_property_get_link() will return null even though the underlying C
pointer still points to the poor orphan.

This strongly suggests QOM was designed with the assumption that objects
always have a parent, except during initialization (before they are
connected to anything) and finalization (when no longer connected to
anything).  object_property_try_add_child()'s contract seems to confirm
this:

 * Child properties form the composition tree.  All objects need to be a child
 * of another object.  Objects can only be a child of one object.

Some functions to create objects take the new object's parent as a
parameter.  Example: object_new_with_props(), object_new_with_propv(),
clock_new(), ...

Others set a fixed parent.  For instance, we always add character
backends to "/chardevs/", objects created with object-add in
"/objects/", devices created with device_add in "/machine/peripheral/"
(with ID) or "/machine/peripheral-anon/" (without ID), ...

There are also functions that don't set a parent: object_new(),
object_new_with_class(), qdev_new(), qdev_try_new(), ...  Setting a
parent is the callers job then.  Invites misuse.  I'm aware of one
instance: @current_migration remains without a parent forever.

Not all callers care to set a parent themselves.  Instead, they rely on
the "/machine/unattached/" orphanage:

* qdev_connect_gpio_out_named() needs the input pin to have a parent.
  If it lacks one, it gets added to "/machine/unattached/" with a
  made-up name.

* device_set_realized() ensures realized devices have a parent by adding
  devices lacking one to "/machine/unattached/" with a made-up name.

* portio_list_add() adds a memory region.  If the caller doesn't specify
  the parent, "/machine/unattached/" is assumed.

* memory_region_init() adds a memory region, and may set the parent.  If
  the caller requests setting a parent without specifying one,
  "/machine/unattached/" is assumed.

* qemu_create_machine() adds the main system bus to
  "/machine/unattached/".

Except for the last one, the child names depend on execution order.  For
instance, device_set_realized() uses "device[N]", where N counts up from
zero.

These brittle, made-up names are visible in QMP QOM introspection.
Whether that's a stable interface is unclear.  Better not.

We don't rely on these names in C.  We follow pointers instead.

When we replace C code by configuration, we switch from pointers to
names.  Brittle names become a problem.


Reply via email to