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.