diff options
author | Markus Armbruster | 2020-06-10 07:31:53 +0200 |
---|---|---|
committer | Markus Armbruster | 2020-06-15 21:36:30 +0200 |
commit | 9940b2cfbc05cdffdf6b42227a80cb1e6d2a85c2 (patch) | |
tree | a3ac47ae7886a3d0a0f0768d4a48f84eae2b6f73 /hw/core/bus.c | |
parent | Revert "hw/versatile: realize the PCI root bus as part of the versatile init" (diff) | |
download | qemu-9940b2cfbc05cdffdf6b42227a80cb1e6d2a85c2.tar.gz qemu-9940b2cfbc05cdffdf6b42227a80cb1e6d2a85c2.tar.xz qemu-9940b2cfbc05cdffdf6b42227a80cb1e6d2a85c2.zip |
qdev: New qdev_new(), qdev_realize(), etc.
We commonly plug devices into their bus right when we create them,
like this:
dev = qdev_create(bus, type_name);
Note that @dev is a weak reference. The reference from @bus to @dev
is the only strong one.
We realize at some later time, either with
object_property_set_bool(OBJECT(dev), true, "realized", errp);
or its convenience wrapper
qdev_init_nofail(dev);
If @dev still has no QOM parent then, realizing makes the
/machine/unattached/ orphanage its QOM parent.
Note that the device returned by qdev_create() is plugged into a bus,
but doesn't have a QOM parent, yet. Until it acquires one,
unrealizing the bus will hang in bus_unparent():
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
DeviceState *dev = kid->child;
object_unparent(OBJECT(dev));
}
object_unparent() does nothing when its argument has no QOM parent,
and the loop spins forever.
Device state "no QOM parent, but plugged into bus" is dangerous.
Paolo suggested to delay plugging into the bus until realize. We need
to plug into the parent bus before we call the device's realize
method, in case it uses the parent bus. So the dangerous state still
exists, but only within realization, where we can manage it safely.
This commit creates infrastructure to do this:
dev = qdev_new(type_name);
...
qdev_realize_and_unref(dev, bus, errp)
Note that @dev becomes a strong reference here.
qdev_realize_and_unref() drops it. There is also plain
qdev_realize(), which doesn't drop it.
The remainder of this series will convert all users to this new
interface.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Cc: Alistair Francis <alistair@alistair23.me>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Cc: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-5-armbru@redhat.com>
Diffstat (limited to 'hw/core/bus.c')
-rw-r--r-- | hw/core/bus.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/hw/core/bus.c b/hw/core/bus.c index 33a4443217..6f6071f5fa 100644 --- a/hw/core/bus.c +++ b/hw/core/bus.c @@ -164,6 +164,20 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam return bus; } +bool qbus_realize(BusState *bus, Error **errp) +{ + Error *err = NULL; + + object_property_set_bool(OBJECT(bus), true, "realized", &err); + error_propagate(errp, err); + return !err; +} + +void qbus_unrealize(BusState *bus) +{ + object_property_set_bool(OBJECT(bus), false, "realized", &error_abort); +} + static bool bus_get_realized(Object *obj, Error **errp) { BusState *bus = BUS(obj); |