summaryrefslogtreecommitdiffstats
path: root/hw/core/bus.c
diff options
context:
space:
mode:
authorMarkus Armbruster2020-06-10 07:31:53 +0200
committerMarkus Armbruster2020-06-15 21:36:30 +0200
commit9940b2cfbc05cdffdf6b42227a80cb1e6d2a85c2 (patch)
treea3ac47ae7886a3d0a0f0768d4a48f84eae2b6f73 /hw/core/bus.c
parentRevert "hw/versatile: realize the PCI root bus as part of the versatile init" (diff)
downloadqemu-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.c14
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);