File qdev-add-check-if-address-free-callback-.patch of Package qemu.21548

From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 6 Oct 2020 15:38:55 +0300
Subject: qdev: add "check if address free" callback for buses

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>
---
 hw/core/qdev.c                  | 15 +++++++++++++--
 hw/core/sysbus.c                |  2 +-
 hw/display/virtio-gpu-pci.c     |  2 +-
 hw/display/virtio-vga.c         |  2 +-
 hw/i386/amd_iommu.c             |  2 +-
 hw/isa/piix4.c                  |  2 +-
 hw/misc/auxbus.c                |  4 ++--
 hw/misc/macio/macio.c           |  6 +++---
 hw/net/virtio-net.c             |  2 +-
 hw/pci-host/designware.c        |  2 +-
 hw/pci-host/gpex.c              |  2 +-
 hw/pci-host/prep.c              |  2 +-
 hw/pci-host/q35.c               |  2 +-
 hw/pci-host/versatile.c         |  3 ++-
 hw/pci-host/xilinx-pcie.c       |  2 +-
 hw/s390x/event-facility.c       |  4 ++--
 hw/s390x/sclp.c                 |  2 +-
 hw/s390x/vhost-vsock-ccw.c      |  2 +-
 hw/s390x/virtio-ccw-9p.c        |  2 +-
 hw/s390x/virtio-ccw-balloon.c   |  2 +-
 hw/s390x/virtio-ccw-blk.c       |  2 +-
 hw/s390x/virtio-ccw-crypto.c    |  2 +-
 hw/s390x/virtio-ccw-gpu.c       |  2 +-
 hw/s390x/virtio-ccw-input.c     |  2 +-
 hw/s390x/virtio-ccw-net.c       |  2 +-
 hw/s390x/virtio-ccw-rng.c       |  2 +-
 hw/s390x/virtio-ccw-scsi.c      |  4 ++--
 hw/s390x/virtio-ccw-serial.c    |  3 ++-
 hw/sd/core.c                    |  3 ++-
 hw/ssi/ssi.c                    |  3 ++-
 hw/virtio/vhost-scsi-pci.c      |  2 +-
 hw/virtio/vhost-user-blk-pci.c  |  2 +-
 hw/virtio/vhost-user-fs-pci.c   |  3 ++-
 hw/virtio/vhost-user-scsi-pci.c |  2 +-
 hw/virtio/vhost-vsock-pci.c     |  3 ++-
 hw/virtio/virtio-9p-pci.c       |  3 ++-
 hw/virtio/virtio-balloon-pci.c  |  2 +-
 hw/virtio/virtio-blk-pci.c      |  2 +-
 hw/virtio/virtio-crypto-pci.c   |  2 +-
 hw/virtio/virtio-input-pci.c    |  3 ++-
 hw/virtio/virtio-net-pci.c      |  2 +-
 hw/virtio/virtio-pmem-pci.c     |  2 +-
 hw/virtio/virtio-rng-pci.c      |  2 +-
 hw/virtio/virtio-scsi-pci.c     |  3 ++-
 hw/virtio/virtio-serial-pci.c   |  3 ++-
 hw/xen/xen-legacy-backend.c     |  2 +-
 include/hw/qdev-core.h          | 13 ++++++++++++-
 qdev-monitor.c                  |  2 +-
 48 files changed, 86 insertions(+), 54 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index cf1ba28fe35346618cb71120576c..342ea8a3feb955c3318616252ead 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -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;
 }
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index 9e69c83aedfe8578e9988ba93e79..1d79960bbaaeba984d0fb7937002 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -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)
diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
index 25e4038874ed091d5d74311cf118..67021040bec57e41ce3e4f9e2986 100644
--- a/hw/display/virtio-gpu-pci.c
+++ b/hw/display/virtio-gpu-pci.c
@@ -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);
 
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index cc6e66ea1c2cfe1f76c05ceebbbf..adca75d7cd055d5442873ed610d6 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -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) {
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index ac5f2fddc5463e4c8776ac2f5036..ff1c870b41bcbb1865d00512504d 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -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);
diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
index a7ed885dc8e49537c1241eaea7e1..0c09c195fe17cc27ba4b7164ab79 100644
--- a/hw/isa/piix4.c
+++ b/hw/isa/piix4.c
@@ -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) {
diff --git a/hw/misc/auxbus.c b/hw/misc/auxbus.c
index f8e7b979712571cdf66565cf4ba2..b35439e3640e4d4981a569ea58ea 100644
--- a/hw/misc/auxbus.c
+++ b/hw/misc/auxbus.c
@@ -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;
 }
 
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 50f20d82066143bedd6c30f4d3be..b22c8597ec238ef90c157993a54b 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -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);
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 7483d11ec2300f483899c24b53bf..4764b83d568dcd5efdd9a95d829e 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -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);
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index f9c5d29d13c86509a3198d214dc6..6a5e677a0c59542937b5c7a73c2f 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -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));
 }
 
diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c
index 0ca604dc628ebccc3f622625bb18..a76587c7f3d0c573325d7fd83a2a 100644
--- a/hw/pci-host/gpex.c
+++ b/hw/pci-host/gpex.c
@@ -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));
 }
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 7f366d9313d8824c52e5cb531b63..ceff1a8e0fe4d8c8aa8023c3bd0c 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -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);
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 158d270b9f0c94490acb57932985..b27a058e50a49d0e3e8f103501ab 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -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));
 }
 
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index b731d0544fa163100fe5f7d128a0..e68a1e1b3c7c510882289ae04a1e 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -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]);
diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c
index 17d502434956e9c6a609d95907b4..56aa94016459566e2fb522ab8d7e 100644
--- a/hw/pci-host/xilinx-pcie.c
+++ b/hw/pci-host/xilinx-pcie.c
@@ -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));
 }
 
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 66205697ae7597a328e97b408e48..17e77fb17390f3f3f1954d47055b 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -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 */
 }
 
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 1c380a49cc7140687329e43e9745..ade09fc9d35cf372d1abeb2a29f7 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -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) {
diff --git a/hw/s390x/vhost-vsock-ccw.c b/hw/s390x/vhost-vsock-ccw.c
index 1835812bd11a7c4c275206f3905c..23c5491223fbb7fffa6effa43954 100644
--- a/hw/s390x/vhost-vsock-ccw.c
+++ b/hw/s390x/vhost-vsock-ccw.c
@@ -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);
 }
 
diff --git a/hw/s390x/virtio-ccw-9p.c b/hw/s390x/virtio-ccw-9p.c
index 5453a964d2dc3f5943f492c2c4e6..f7db31e4f3d23653a1216dca0c30 100644
--- a/hw/s390x/virtio-ccw-9p.c
+++ b/hw/s390x/virtio-ccw-9p.c
@@ -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);
 }
 
diff --git a/hw/s390x/virtio-ccw-balloon.c b/hw/s390x/virtio-ccw-balloon.c
index 7088612f6bce233b18574ad63121..92ebd7bcfbda7da5bc7e6af4a55c 100644
--- a/hw/s390x/virtio-ccw-balloon.c
+++ b/hw/s390x/virtio-ccw-balloon.c
@@ -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);
 }
 
diff --git a/hw/s390x/virtio-ccw-blk.c b/hw/s390x/virtio-ccw-blk.c
index 1512af8974dff0b303cda91e9ad8..9b12fa9e219b808e83e831894252 100644
--- a/hw/s390x/virtio-ccw-blk.c
+++ b/hw/s390x/virtio-ccw-blk.c
@@ -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);
 }
 
diff --git a/hw/s390x/virtio-ccw-crypto.c b/hw/s390x/virtio-ccw-crypto.c
index 086b397ad274e11a69465dc69929..95fd93d5cb6d6f76a947f75a58ba 100644
--- a/hw/s390x/virtio-ccw-crypto.c
+++ b/hw/s390x/virtio-ccw-crypto.c
@@ -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);
diff --git a/hw/s390x/virtio-ccw-gpu.c b/hw/s390x/virtio-ccw-gpu.c
index be46ca7a968c2b9baa44569be689..afa30e330fb9b6bc3559baf82949 100644
--- a/hw/s390x/virtio-ccw-gpu.c
+++ b/hw/s390x/virtio-ccw-gpu.c
@@ -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);
 }
 
diff --git a/hw/s390x/virtio-ccw-input.c b/hw/s390x/virtio-ccw-input.c
index 370b776790c8bca383e78ea4df34..5adfdc3ee47cf364bd701d6ce518 100644
--- a/hw/s390x/virtio-ccw-input.c
+++ b/hw/s390x/virtio-ccw-input.c
@@ -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);
 }
 
diff --git a/hw/s390x/virtio-ccw-net.c b/hw/s390x/virtio-ccw-net.c
index 12c03d73c4dcc081514cac3bc1af..756069b3dfc17963703573dd050c 100644
--- a/hw/s390x/virtio-ccw-net.c
+++ b/hw/s390x/virtio-ccw-net.c
@@ -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);
 }
 
diff --git a/hw/s390x/virtio-ccw-rng.c b/hw/s390x/virtio-ccw-rng.c
index 854254dd50f5e9bc0e45f5d53571..6a5c2dd9b938966be7ee9249168a 100644
--- a/hw/s390x/virtio-ccw-rng.c
+++ b/hw/s390x/virtio-ccw-rng.c
@@ -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);
diff --git a/hw/s390x/virtio-ccw-scsi.c b/hw/s390x/virtio-ccw-scsi.c
index 4662288b5b009da0b2ecf74eaff9..9a01a027210f7d1c372d88a51963 100644
--- a/hw/s390x/virtio-ccw-scsi.c
+++ b/hw/s390x/virtio-ccw-scsi.c
@@ -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);
 }
 
diff --git a/hw/s390x/virtio-ccw-serial.c b/hw/s390x/virtio-ccw-serial.c
index eafb7d5c1f4c799d33980a6db021..c7f4d47aa426f9357e899cef8c88 100644
--- a/hw/s390x/virtio-ccw-serial.c
+++ b/hw/s390x/virtio-ccw-serial.c
@@ -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);
 }
 
diff --git a/hw/sd/core.c b/hw/sd/core.c
index abec48bccb80a92cf3c8e6dee397..371122c120e04268e9ba6644625b 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -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);
 }
diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c
index c6415eb6e329ee78f822f6723192..49e79254ebf703a53ac22197f517 100644
--- a/hw/ssi/ssi.c
+++ b/hw/ssi/ssi.c
@@ -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;
diff --git a/hw/virtio/vhost-scsi-pci.c b/hw/virtio/vhost-scsi-pci.c
index e8dfbfc60f9a5f25b4d7214872d1..9e454801e7a1b66b17eef996f30f 100644
--- a/hw/virtio/vhost-scsi-pci.c
+++ b/hw/virtio/vhost-scsi-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/vhost-user-blk-pci.c b/hw/virtio/vhost-user-blk-pci.c
index 1dc834a3ff153719100cd0fca891..fb4f321acff7c44b941bbaf836f0 100644
--- a/hw/virtio/vhost-user-blk-pci.c
+++ b/hw/virtio/vhost-user-blk-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/vhost-user-fs-pci.c b/hw/virtio/vhost-user-fs-pci.c
index 933a3f265b6a9657d3404a0aa311..65ce9fda95f9dd23de2ae2406973 100644
--- a/hw/virtio/vhost-user-fs-pci.c
+++ b/hw/virtio/vhost-user-fs-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/vhost-user-scsi-pci.c b/hw/virtio/vhost-user-scsi-pci.c
index ff13af70308f7ddadd7874cca185..011afba8582c8f61dbb5176d2944 100644
--- a/hw/virtio/vhost-user-scsi-pci.c
+++ b/hw/virtio/vhost-user-scsi-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/vhost-vsock-pci.c b/hw/virtio/vhost-vsock-pci.c
index 4ca097ffff5a8569245332800ba8..beaee685524608208147ba51fdce 100644
--- a/hw/virtio/vhost-vsock-pci.c
+++ b/hw/virtio/vhost-vsock-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/virtio-9p-pci.c b/hw/virtio/virtio-9p-pci.c
index 22a183cca7e5292f2c90e7938e4d..9d2bc7cd857fd48e681998a2d55e 100644
--- a/hw/virtio/virtio-9p-pci.c
+++ b/hw/virtio/virtio-9p-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/virtio-balloon-pci.c b/hw/virtio/virtio-balloon-pci.c
index 69ca0579110f66bc70464caadbac..894513fbed1b8d0029d049fc07d6 100644
--- a/hw/virtio/virtio-balloon-pci.c
+++ b/hw/virtio/virtio-balloon-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/virtio-blk-pci.c b/hw/virtio/virtio-blk-pci.c
index d9b69a5af351df5c52a6cba1bbc4..6b9e03ef5bec673179c953e53e84 100644
--- a/hw/virtio/virtio-blk-pci.c
+++ b/hw/virtio/virtio-blk-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/virtio-crypto-pci.c b/hw/virtio/virtio-crypto-pci.c
index d853dc460cc5144a8735b3d332b6..46e96ccccf3b0121954869771bce 100644
--- a/hw/virtio/virtio-crypto-pci.c
+++ b/hw/virtio/virtio-crypto-pci.c
@@ -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),
diff --git a/hw/virtio/virtio-input-pci.c b/hw/virtio/virtio-input-pci.c
index 80b1172c90b0d37cb8f23b650069..b7fe75938f5cd0f9f58a1a227d7b 100644
--- a/hw/virtio/virtio-input-pci.c
+++ b/hw/virtio/virtio-input-pci.c
@@ -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);
 }
diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
index f670aed0a77b47da99fdf02440dd..dd7d4b74845aa587cd6ade447543 100644
--- a/hw/virtio/virtio-net-pci.c
+++ b/hw/virtio/virtio-net-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/virtio-pmem-pci.c b/hw/virtio/virtio-pmem-pci.c
index fe2af00fa1652a7ee9ff20de8d0c..3c5dd1b87d564af18bf3f2bd220d 100644
--- a/hw/virtio/virtio-pmem-pci.c
+++ b/hw/virtio/virtio-pmem-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/virtio-rng-pci.c b/hw/virtio/virtio-rng-pci.c
index 8aaf54b781d6545d0597912f29f4..048c2aa85b12d51c03eb404e4647 100644
--- a/hw/virtio/virtio-rng-pci.c
+++ b/hw/virtio/virtio-rng-pci.c
@@ -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);
diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
index 3c55dc19a105dd562a505c64d14c..b4e81ceb46c3a8d5306cf4b29e66 100644
--- a/hw/virtio/virtio-scsi-pci.c
+++ b/hw/virtio/virtio-scsi-pci.c
@@ -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);
 }
 
diff --git a/hw/virtio/virtio-serial-pci.c b/hw/virtio/virtio-serial-pci.c
index 953abbd13ab7f0ffca6a5af539ce..1f02930002fa4c833a75c64187a0 100644
--- a/hw/virtio/virtio-serial-pci.c
+++ b/hw/virtio/virtio-serial-pci.c
@@ -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);
 }
 
diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c
index 4412d7aa7639c00b6f54bdd5f532..d38095acca6766cda2aa3413c2b4 100644
--- a/hw/xen/xen-legacy-backend.c
+++ b/hw/xen/xen-legacy-backend.c
@@ -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));
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 1518495b1e0a953fa1547889f5dc..2b0186f0af593deee82a02693589 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -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;
diff --git a/qdev-monitor.c b/qdev-monitor.c
index e6b112eb0ab0252ecb1d585d3784..dc0323051e33833c4bcb638c7657 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -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",
openSUSE Build Service is sponsored by