qdev: add "check if address free" callback for buses
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 6 Oct 2020 12:38:55 +0000 (15:38 +0300)
committerwanchao-xu <wanchao.xu@samsung.com>
Tue, 9 Jan 2024 11:49:16 +0000 (19:49 +0800)
Git-commit: bb755ba47f3747251c0eadf681ee68b9033309b8
References: bsc#1184574

Check if an address is free on the bus before plugging in the
device.  This makes it possible to do the check without any
side effects, and to detect the problem early without having
to do it in the realize callback.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20201006123904.610658-5-mlevitsk@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Lin Ma <lma@suse.com>
48 files changed:
hw/core/qdev.c
hw/core/sysbus.c
hw/display/virtio-gpu-pci.c
hw/display/virtio-vga.c
hw/i386/amd_iommu.c
hw/isa/piix4.c
hw/misc/auxbus.c
hw/misc/macio/macio.c
hw/net/virtio-net.c
hw/pci-host/designware.c
hw/pci-host/gpex.c
hw/pci-host/prep.c
hw/pci-host/q35.c
hw/pci-host/versatile.c
hw/pci-host/xilinx-pcie.c
hw/s390x/event-facility.c
hw/s390x/sclp.c
hw/s390x/vhost-vsock-ccw.c
hw/s390x/virtio-ccw-9p.c
hw/s390x/virtio-ccw-balloon.c
hw/s390x/virtio-ccw-blk.c
hw/s390x/virtio-ccw-crypto.c
hw/s390x/virtio-ccw-gpu.c
hw/s390x/virtio-ccw-input.c
hw/s390x/virtio-ccw-net.c
hw/s390x/virtio-ccw-rng.c
hw/s390x/virtio-ccw-scsi.c
hw/s390x/virtio-ccw-serial.c
hw/sd/core.c
hw/ssi/ssi.c
hw/virtio/vhost-scsi-pci.c
hw/virtio/vhost-user-blk-pci.c
hw/virtio/vhost-user-fs-pci.c
hw/virtio/vhost-user-scsi-pci.c
hw/virtio/vhost-vsock-pci.c
hw/virtio/virtio-9p-pci.c
hw/virtio/virtio-balloon-pci.c
hw/virtio/virtio-blk-pci.c
hw/virtio/virtio-crypto-pci.c
hw/virtio/virtio-input-pci.c
hw/virtio/virtio-net-pci.c
hw/virtio/virtio-pmem-pci.c
hw/virtio/virtio-rng-pci.c
hw/virtio/virtio-scsi-pci.c
hw/virtio/virtio-serial-pci.c
hw/xen/xen-legacy-backend.c
include/hw/qdev-core.h
qdev-monitor.c

index cf1ba28fe35346618cb71120576c0de8e1e9f6ea..342ea8a3feb955c3318616252ead009f7336a322 100644 (file)
@@ -93,10 +93,20 @@ static void bus_add_child(BusState *bus, DeviceState *child)
                              NULL);
 }
 
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
+static bool bus_check_address(BusState *bus, DeviceState *child, Error **errp)
+{
+    BusClass *bc = BUS_GET_CLASS(bus);
+    return !bc->check_address || bc->check_address(bus, child, errp);
+}
+
+bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp)
 {
     bool replugging = dev->parent_bus != NULL;
 
+    if (!bus_check_address(bus, dev, errp)) {
+        return false;
+    }
+
     if (replugging) {
         /* Keep a reference to the device while it's not plugged into
          * any bus, to avoid it potentially evaporating when it is
@@ -112,6 +122,7 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
     if (replugging) {
         object_unref(OBJECT(dev));
     }
+    return true;
 }
 
 /* Create a new device.  This only initializes the device state
@@ -157,7 +168,7 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
         bus = sysbus_get_default();
     }
 
-    qdev_set_parent_bus(dev, bus);
+    qdev_set_parent_bus(dev, bus, &error_abort);
     object_unref(OBJECT(dev));
     return dev;
 }
index 9e69c83aedfe8578e9988ba93e7916e6ff12219c..1d79960bbaaeba984d0fb7937002721f2683a934 100644 (file)
@@ -383,7 +383,7 @@ void sysbus_init_child_obj(Object *parent, const char *childname, void *child,
 {
     object_initialize_child(parent, childname, child, childsize, childtype,
                             &error_abort, NULL);
-    qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
+    qdev_set_parent_bus(DEVICE(child), sysbus_get_default(), &error_abort);
 }
 
 static void sysbus_register_types(void)
index 25e4038874ed091d5d74311cf1180a42473e252a..67021040bec57e41ce3e4f9e29868e9384bd8820 100644 (file)
@@ -33,7 +33,7 @@ static void virtio_gpu_pci_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
     int i;
     Error *local_error = NULL;
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     virtio_pci_force_virtio_1(vpci_dev);
     object_property_set_bool(OBJECT(vdev), true, "realized", &local_error);
 
index cc6e66ea1c2cfe1f76c05ceebbbf22e27b129274..adca75d7cd055d5442873ed610d689618744e040 100644 (file)
@@ -136,7 +136,7 @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
     vpci_dev->common.offset = offset;
 
     /* init virtio bits */
-    qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus), &error_abort);
     virtio_pci_force_virtio_1(vpci_dev);
     object_property_set_bool(OBJECT(g), true, "realized", &err);
     if (err) {
index ac5f2fddc5463e4c8776ac2f5036e7d1f7ccf2d0..ff1c870b41bcbb1865d00512504ddca61f8e4829 100644 (file)
@@ -1548,7 +1548,7 @@ static void amdvi_realize(DeviceState *dev, Error **err)
 
     /* This device should take care of IOMMU PCI properties */
     x86_iommu->type = TYPE_AMD;
-    qdev_set_parent_bus(DEVICE(&s->pci), &bus->qbus);
+    qdev_set_parent_bus(DEVICE(&s->pci), &bus->qbus, &error_abort);
     object_property_set_bool(OBJECT(&s->pci), true, "realized", err);
     ret = pci_add_capability(&s->pci.dev, AMDVI_CAPAB_ID_SEC, 0,
                                          AMDVI_CAPAB_SIZE, err);
index a7ed885dc8e49537c1241eaea7e1568f8de4f660..0c09c195fe17cc27ba4b7164ab7993ed33060e5f 100644 (file)
@@ -195,7 +195,7 @@ static void piix4_realize(PCIDevice *dev, Error **errp)
     i8257_dma_init(isa_bus, 0);
 
     /* RTC */
-    qdev_set_parent_bus(DEVICE(&s->rtc), BUS(isa_bus));
+    qdev_set_parent_bus(DEVICE(&s->rtc), BUS(isa_bus), &error_abort);
     qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000);
     object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
     if (err) {
index f8e7b979712571cdf66565cf4ba2cea372a35183..b35439e3640e4d4981a569ea58ea5c1fc74a80a2 100644 (file)
@@ -70,7 +70,7 @@ AUXBus *aux_init_bus(DeviceState *parent, const char *name)
     bus = AUX_BUS(qbus_create(TYPE_AUX_BUS, parent, name));
     auxtoi2c = object_new_with_props(TYPE_AUXTOI2C, OBJECT(bus), "i2c",
                                      &error_abort, NULL);
-    qdev_set_parent_bus(DEVICE(auxtoi2c), BUS(bus));
+    qdev_set_parent_bus(DEVICE(auxtoi2c), BUS(bus), &error_abort);
 
     bus->bridge = AUXTOI2C(auxtoi2c);
 
@@ -275,7 +275,7 @@ DeviceState *aux_create_slave(AUXBus *bus, const char *type)
 
     dev = DEVICE(object_new(type));
     assert(dev);
-    qdev_set_parent_bus(dev, &bus->qbus);
+    qdev_set_parent_bus(dev, &bus->qbus, &error_abort);
     return dev;
 }
 
index 50f20d82066143bedd6c30f4d3be13b1b1d97bfd..b22c8597ec238ef90c157993a54b5875c4525baf 100644 (file)
@@ -100,7 +100,7 @@ static void macio_init_child_obj(MacIOState *s, const char *childname,
 {
     object_initialize_child(OBJECT(s), childname, child, childsize, childtype,
                             &error_abort, NULL);
-    qdev_set_parent_bus(DEVICE(child), BUS(&s->macio_bus));
+    qdev_set_parent_bus(DEVICE(child), BUS(&s->macio_bus), &error_abort);
 }
 
 static void macio_common_realize(PCIDevice *d, Error **errp)
@@ -355,7 +355,7 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp)
         object_property_set_link(OBJECT(&s->pmu), OBJECT(sysbus_dev), "gpio",
                                  &error_abort);
         qdev_prop_set_bit(DEVICE(&s->pmu), "has-adb", ns->has_adb);
-        qdev_set_parent_bus(DEVICE(&s->pmu), BUS(&s->macio_bus));
+        qdev_set_parent_bus(DEVICE(&s->pmu), BUS(&s->macio_bus), &error_abort);
 
         object_property_set_bool(OBJECT(&s->pmu), true, "realized", &err);
         if (err) {
@@ -371,7 +371,7 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp)
         /* CUDA */
         object_initialize_child(OBJECT(s), "cuda", &s->cuda, sizeof(s->cuda),
                                 TYPE_CUDA, &error_abort, NULL);
-        qdev_set_parent_bus(DEVICE(&s->cuda), BUS(&s->macio_bus));
+        qdev_set_parent_bus(DEVICE(&s->cuda), BUS(&s->macio_bus), &error_abort);
         qdev_prop_set_uint64(DEVICE(&s->cuda), "timebase-frequency",
                              s->frequency);
 
index 7483d11ec2300f483899c24b53bff422829bf3de..4764b83d568dcd5efdd9a95d829e593e761ecfcd 100644 (file)
@@ -2815,7 +2815,7 @@ static bool failover_replug_primary(VirtIONet *n, Error **errp)
         error_setg(errp, "virtio_net: couldn't find primary bus");
         return false;
     }
-    qdev_set_parent_bus(n->primary_dev, n->primary_bus);
+    qdev_set_parent_bus(n->primary_dev, n->primary_bus, &error_abort);
     n->primary_should_be_hidden = false;
     qemu_opt_set_bool(n->primary_device_opts,
                       "partially_hotplugged", true, &err);
index f9c5d29d13c86509a3198d214dc6a87242eca9b8..6a5e677a0c59542937b5c7a73c2f3003e3bfaddb 100644 (file)
@@ -707,7 +707,7 @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
                        "pcie-bus-address-space");
     pci_setup_iommu(pci->bus, designware_pcie_host_set_iommu, s);
 
-    qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus));
+    qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus), &error_abort);
     qdev_init_nofail(DEVICE(&s->root));
 }
 
index 0ca604dc628ebccc3f622625bb18d091529ac4c2..a76587c7f3d0c573325d7fd83a2a338045040e9b 100644 (file)
@@ -98,7 +98,7 @@ static void gpex_host_realize(DeviceState *dev, Error **errp)
                                      pci_swizzle_map_irq_fn, s, &s->io_mmio,
                                      &s->io_ioport, 0, 4, TYPE_PCIE_BUS);
 
-    qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus));
+    qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus), &error_abort);
     pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq);
     qdev_init_nofail(DEVICE(&s->gpex_root));
 }
index 7f366d9313d8824c52e5cb531b634e6b2afb92ea..ceff1a8e0fe4d8c8aa8023c3bd0c0a42da4c1ae2 100644 (file)
@@ -317,7 +317,7 @@ static void raven_pcihost_initfn(Object *obj)
 
     object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE);
     pci_dev = DEVICE(&s->pci_dev);
-    qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus));
+    qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus), &error_abort);
     object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr",
                             NULL);
     qdev_prop_set_bit(pci_dev, "multifunction", false);
index 158d270b9f0c94490acb57932985f394712ec05e..b27a058e50a49d0e3e8f103501ab4084b949185d 100644 (file)
@@ -63,7 +63,7 @@ static void q35_host_realize(DeviceState *dev, Error **errp)
                                 s->mch.address_space_io,
                                 0, TYPE_PCIE_BUS);
     PC_MACHINE(qdev_get_machine())->bus = pci->bus;
-    qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus));
+    qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus), &error_abort);
     qdev_init_nofail(DEVICE(&s->mch));
 }
 
index b731d0544fa163100fe5f7d128a024fbba0c9070..e68a1e1b3c7c510882289ae04a1e40bd0076b6a2 100644 (file)
@@ -17,6 +17,7 @@
 #include "hw/qdev-properties.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qapi/error.h"
 
 /* Old and buggy versions of QEMU used the wrong mapping from
  * PCI IRQs to system interrupt lines. Unfortunately the Linux
@@ -408,7 +409,7 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp)
     h->bus = &s->pci_bus;
 
     object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_VERSATILE_PCI_HOST);
-    qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus));
+    qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus), &error_abort);
 
     for (i = 0; i < 4; i++) {
         sysbus_init_irq(sbd, &s->irq[i]);
index 17d502434956e9c6a609d95907b478b8e845bcf4..56aa94016459566e2fb522ab8d7e1f6e8113e724 100644 (file)
@@ -137,7 +137,7 @@ static void xilinx_pcie_host_realize(DeviceState *dev, Error **errp)
                                      pci_swizzle_map_irq_fn, s, &s->mmio,
                                      &s->io, 0, 4, TYPE_PCIE_BUS);
 
-    qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus));
+    qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus), &error_abort);
     qdev_init_nofail(DEVICE(&s->root));
 }
 
index 66205697ae7597a328e97b408e488309a1701fdf..17e77fb17390f3f3f1954d47055b4cbc91d31bbe 100644 (file)
@@ -464,12 +464,12 @@ static void init_event_facility(Object *obj)
     new = object_new(TYPE_SCLP_QUIESCE);
     object_property_add_child(obj, TYPE_SCLP_QUIESCE, new, NULL);
     object_unref(new);
-    qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus));
+    qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus), &error_abort);
 
     new = object_new(TYPE_SCLP_CPU_HOTPLUG);
     object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new, NULL);
     object_unref(new);
-    qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus));
+    qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus), &error_abort);
     /* the facility will automatically realize the devices via the bus */
 }
 
index 1c380a49cc7140687329e43e9745da1180e4d739..ade09fc9d35cf372d1abeb2a29f72b89339ccecc 100644 (file)
@@ -350,7 +350,7 @@ static void sclp_realize(DeviceState *dev, Error **errp)
      * as we can't find a fitting bus via the qom tree, we have to add the
      * event facility to the sysbus, so e.g. a sclp console can be created.
      */
-    qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default());
+    qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default(), &error_abort);
 
     ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
     if (ret == -E2BIG) {
index 1835812bd11a7c4c275206f3905ce4b34718f214..23c5491223fbb7fffa6effa43954867ec77aa693 100644 (file)
@@ -24,7 +24,7 @@ static void vhost_vsock_ccw_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     VHostVSockCCWState *dev = VHOST_VSOCK_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 5453a964d2dc3f5943f492c2c4e6bb1fe896cc39..f7db31e4f3d23653a1216dca0c30eec8d9e6b1c1 100644 (file)
@@ -21,7 +21,7 @@ static void virtio_ccw_9p_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     V9fsCCWState *dev = VIRTIO_9P_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 7088612f6bce233b18574ad6312103ec69337f45..92ebd7bcfbda7da5bc7e6af4a55ccb64e10af349 100644 (file)
@@ -21,7 +21,7 @@ static void virtio_ccw_balloon_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 1512af8974dff0b303cda91e9ad82f206a1022d9..9b12fa9e219b808e83e8318942521c2a63f5233d 100644 (file)
@@ -21,7 +21,7 @@ static void virtio_ccw_blk_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 086b397ad274e11a69465dc699292c03c58d534f..95fd93d5cb6d6f76a947f75a58babf4df24c72ba 100644 (file)
@@ -21,7 +21,7 @@ static void virtio_ccw_crypto_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     DeviceState *vdev = DEVICE(&dev->vdev);
     Error *err = NULL;
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
index be46ca7a968c2b9baa44569be6897dfbb2c6be76..afa30e330fb9b6bc3559baf82949bdef63f2fcfa 100644 (file)
@@ -20,7 +20,7 @@ static void virtio_ccw_gpu_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     VirtIOGPUCcw *dev = VIRTIO_GPU_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 370b776790c8bca383e78ea4df34a978d5541858..5adfdc3ee47cf364bd701d6ce5187d62c727c24f 100644 (file)
@@ -20,7 +20,7 @@ static void virtio_ccw_input_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     VirtIOInputCcw *dev = VIRTIO_INPUT_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 12c03d73c4dcc081514cac3bc1aff7985c14c8d5..756069b3dfc17963703573dd050c2658ea50b599 100644 (file)
@@ -24,7 +24,7 @@ static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 
     virtio_net_set_netclient_name(&dev->vdev, qdev->id,
                                   object_get_typename(OBJECT(qdev)));
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 854254dd50f5e9bc0e45f5d535715424c39b0f7e..6a5c2dd9b938966be7ee9249168a71da706437f3 100644 (file)
@@ -22,7 +22,7 @@ static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     DeviceState *vdev = DEVICE(&dev->vdev);
     Error *err = NULL;
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
index 4662288b5b009da0b2ecf74eaff94d773c6a64bd..9a01a027210f7d1c372d88a5196320fdd9d84e3d 100644 (file)
@@ -33,7 +33,7 @@ static void virtio_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
         g_free(bus_name);
     }
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
@@ -78,7 +78,7 @@ static void vhost_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
     VHostSCSICcw *dev = VHOST_SCSI_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index eafb7d5c1f4c799d33980a6db0211d731b603e85..c7f4d47aa426f9357e899cef8c88f915a1e9c01b 100644 (file)
@@ -15,6 +15,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/virtio-serial.h"
 #include "virtio-ccw.h"
+#include "qapi/error.h"
 
 static void virtio_ccw_serial_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 {
@@ -33,7 +34,7 @@ static void virtio_ccw_serial_realize(VirtioCcwDevice *ccw_dev, Error **errp)
         g_free(bus_name);
     }
 
-    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index abec48bccb80a92cf3c8e6dee3975a8558af284f..371122c120e04268e9ba6644625b7e7f31dfcb75 100644 (file)
@@ -23,6 +23,7 @@
 #include "hw/qdev-core.h"
 #include "hw/sd/sd.h"
 #include "qemu/module.h"
+#include "qapi/error.h"
 #include "trace.h"
 
 static inline const char *sdbus_name(SDBus *sdbus)
@@ -210,7 +211,7 @@ void sdbus_reparent_card(SDBus *from, SDBus *to)
     readonly = sc->get_readonly(card);
 
     sdbus_set_inserted(from, false);
-    qdev_set_parent_bus(DEVICE(card), &to->qbus);
+    qdev_set_parent_bus(DEVICE(card), &to->qbus, &error_abort);
     sdbus_set_inserted(to, true);
     sdbus_set_readonly(to, readonly);
 }
index c6415eb6e329ee78f822f67231921e08646f124d..49e79254ebf703a53ac22197f517dc577304a742 100644 (file)
@@ -16,6 +16,7 @@
 #include "hw/ssi/ssi.h"
 #include "migration/vmstate.h"
 #include "qemu/module.h"
+#include "qapi/error.h"
 
 struct SSIBus {
     BusState parent_obj;
@@ -159,7 +160,7 @@ static int ssi_auto_connect_slave(Object *child, void *opaque)
     }
 
     cs_line = qdev_get_gpio_in_named(DEVICE(dev), SSI_GPIO_CS, 0);
-    qdev_set_parent_bus(DEVICE(dev), BUS(arg->bus));
+    qdev_set_parent_bus(DEVICE(dev), BUS(arg->bus), &error_abort);
     **arg->cs_linep = cs_line;
     (*arg->cs_linep)++;
     return 0;
index e8dfbfc60f9a5f25b4d7214872d1e02baa7d71e1..9e454801e7a1b66b17eef996f30f23e74d689650 100644 (file)
@@ -53,7 +53,7 @@ static void vhost_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         vpci_dev->nvectors = vs->conf.num_queues + 3;
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 1dc834a3ff153719100cd0fca89193cd606d76c8..fb4f321acff7c44b941bbaf836f093be2ce5b8ae 100644 (file)
@@ -58,7 +58,7 @@ static void vhost_user_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         vpci_dev->nvectors = dev->vdev.num_queues + 1;
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 933a3f265b6a9657d3404a0aa3113a629baa8afd..65ce9fda95f9dd23de2ae2406973866f62d8e9d6 100644 (file)
@@ -15,6 +15,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/vhost-user-fs.h"
 #include "virtio-pci.h"
+#include "qapi/error.h"
 
 struct VHostUserFSPCI {
     VirtIOPCIProxy parent_obj;
@@ -43,7 +44,7 @@ static void vhost_user_fs_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         vpci_dev->nvectors = dev->vdev.conf.num_request_queues + 1;
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index ff13af70308f7ddadd7874cca185909747312395..011afba8582c8f61dbb5176d29449fc3e3dc4acf 100644 (file)
@@ -59,7 +59,7 @@ static void vhost_user_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         vpci_dev->nvectors = vs->conf.num_queues + 3;
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 4ca097ffff5a8569245332800ba8df9892ad56ea..beaee685524608208147ba51fdcea72b3e3ab9a9 100644 (file)
@@ -17,6 +17,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/vhost-vsock.h"
 #include "qemu/module.h"
+#include "qapi/error.h"
 
 typedef struct VHostVSockPCI VHostVSockPCI;
 
@@ -44,7 +45,7 @@ static void vhost_vsock_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
     VHostVSockPCI *dev = VHOST_VSOCK_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 22a183cca7e5292f2c90e7938e4d9326c6993105..9d2bc7cd857fd48e681998a2d55edbfd1d83877a 100644 (file)
@@ -19,6 +19,7 @@
 #include "hw/9pfs/virtio-9p.h"
 #include "hw/qdev-properties.h"
 #include "qemu/module.h"
+#include "qapi/error.h"
 
 /*
  * virtio-9p-pci: This extends VirtioPCIProxy.
@@ -38,7 +39,7 @@ static void virtio_9p_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
     V9fsPCIState *dev = VIRTIO_9P_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 69ca0579110f66bc70464caadbac67eab4844a3e..894513fbed1b8d0029d049fc07d64129ecb4d104 100644 (file)
@@ -48,7 +48,7 @@ static void virtio_balloon_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         vpci_dev->class_code = PCI_CLASS_OTHERS;
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index d9b69a5af351df5c52a6cba1bbc47cc99c56bb8d..6b9e03ef5bec673179c953e53e84e5ef61d8ac3f 100644 (file)
@@ -55,7 +55,7 @@ static void virtio_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         vpci_dev->nvectors = dev->vdev.conf.num_queues + 1;
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index d853dc460cc5144a8735b3d332b635b9c2b36135..46e96ccccf3b0121954869771bceeb22099992c5 100644 (file)
@@ -53,7 +53,7 @@ static void virtio_crypto_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         return;
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     virtio_pci_force_virtio_1(vpci_dev);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
     object_property_set_link(OBJECT(vcrypto),
index 80b1172c90b0d37cb8f23b650069fd39544e576f..b7fe75938f5cd0f9f58a1a227d7b023d6adeea29 100644 (file)
@@ -12,6 +12,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/virtio-input.h"
 #include "qemu/module.h"
+#include "qapi/error.h"
 
 typedef struct VirtIOInputPCI VirtIOInputPCI;
 typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;
@@ -49,7 +50,7 @@ static void virtio_input_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
     VirtIOInputPCI *vinput = VIRTIO_INPUT_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&vinput->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     virtio_pci_force_virtio_1(vpci_dev);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
index f670aed0a77b47da99fdf02440dd9ddb47add384..dd7d4b74845aa587cd6ade447543305c6b145ae2 100644 (file)
@@ -52,7 +52,7 @@ static void virtio_net_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
 
     virtio_net_set_netclient_name(&dev->vdev, qdev->id,
                                   object_get_typename(OBJECT(qdev)));
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index fe2af00fa1652a7ee9ff20de8d0c757c75d8d712..3c5dd1b87d564af18bf3f2bd220d30201e333918 100644 (file)
@@ -22,7 +22,7 @@ static void virtio_pmem_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
     VirtIOPMEMPCI *pmem_pci = VIRTIO_PMEM_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&pmem_pci->vdev);
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 8aaf54b781d6545d0597912f29f4977c9870572a..048c2aa85b12d51c03eb404e4647e8ad9236012d 100644 (file)
@@ -36,7 +36,7 @@ static void virtio_rng_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
     DeviceState *vdev = DEVICE(&vrng->vdev);
     Error *err = NULL;
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
index 3c55dc19a105dd562a505c64d14c87b9b57a1b88..b4e81ceb46c3a8d5306cf4b29e664cb1f872fc77 100644 (file)
@@ -19,6 +19,7 @@
 #include "hw/virtio/virtio-scsi.h"
 #include "qemu/module.h"
 #include "virtio-pci.h"
+#include "qapi/error.h"
 
 typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
 
@@ -64,7 +65,7 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         g_free(bus_name);
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 953abbd13ab7f0ffca6a5af539ce02991035f916..1f02930002fa4c833a75c64187a082b353e92295 100644 (file)
@@ -21,6 +21,7 @@
 #include "hw/virtio/virtio-serial.h"
 #include "qemu/module.h"
 #include "virtio-pci.h"
+#include "qapi/error.h"
 
 typedef struct VirtIOSerialPCI VirtIOSerialPCI;
 
@@ -65,7 +66,7 @@ static void virtio_serial_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
         g_free(bus_name);
     }
 
-    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
     object_property_set_bool(OBJECT(vdev), true, "realized", errp);
 }
 
index 4412d7aa7639c00b6f54bdd5f5324d6246f73998..d38095acca6766cda2aa3413c2b407a9bc8800d3 100644 (file)
@@ -278,7 +278,7 @@ static struct XenLegacyDevice *xen_be_get_xendev(const char *type, int dom,
     xendev = g_malloc0(ops->size);
     object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
     OBJECT(xendev)->free = g_free;
-    qdev_set_parent_bus(DEVICE(xendev), xen_sysbus);
+    qdev_set_parent_bus(DEVICE(xendev), xen_sysbus, &error_abort);
     qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev));
     qdev_init_nofail(DEVICE(xendev));
     object_unref(OBJECT(xendev));
index 1518495b1e0a953fa1547889f5dcf3da16de35c6..2b0186f0af593deee82a02693589458a6243b270 100644 (file)
@@ -188,13 +188,24 @@ struct BusClass {
     /* FIXME first arg should be BusState */
     void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
     char *(*get_dev_path)(DeviceState *dev);
+
     /*
      * This callback is used to create Open Firmware device path in accordance
      * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
      * bindings can be found at http://playground.sun.com/1275/bindings/.
      */
     char *(*get_fw_dev_path)(DeviceState *dev);
+
     void (*reset)(BusState *bus);
+
+    /*
+     * Return whether the device can be added to @bus,
+     * based on the address that was set (via device properties)
+     * before realize.  If not, on return @errp contains the
+     * human-readable error message.
+     */
+    bool (*check_address)(BusState *bus, DeviceState *dev, Error **errp);
+
     BusRealize realize;
     BusUnrealize unrealize;
 
@@ -450,7 +461,7 @@ const char *qdev_fw_name(DeviceState *dev);
 Object *qdev_get_machine(void);
 
 /* FIXME: make this a link<> */
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
+bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
 
 extern bool qdev_hotplug;
 extern bool qdev_hot_removed;
index e6b112eb0ab0252ecb1d585d3784f858f1adc8ab..dc0323051e33833c4bcb638c7657aed6e060a29b 100644 (file)
@@ -654,7 +654,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
     }
 
     if (bus) {
-        qdev_set_parent_bus(dev, bus);
+        qdev_set_parent_bus(dev, bus, &error_abort);
     } else if (qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) {
         /* No bus, no machine hotplug handler --> device is not hotpluggable */
         error_setg(&err, "Device '%s' can not be hotplugged on this machine",