From: Paolo Bonzini Date: Tue, 6 Oct 2020 12:38:55 +0000 (+0300) Subject: qdev: add "check if address free" callback for buses X-Git-Tag: upstream/4.2.1~77 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5bb87a4e9f206527e8c50e74672e3cb782a5114f;p=tools%2Fqemu-arm-static.git 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 Message-Id: <20201006123904.610658-5-mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini Signed-off-by: Lin Ma --- diff --git a/hw/core/qdev.c b/hw/core/qdev.c index cf1ba28fe..342ea8a3f 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 9e69c83ae..1d79960bb 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 25e403887..67021040b 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 cc6e66ea1..adca75d7c 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 ac5f2fddc..ff1c870b4 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 a7ed885dc..0c09c195f 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 f8e7b9797..b35439e36 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 50f20d820..b22c8597e 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 7483d11ec..4764b83d5 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 f9c5d29d1..6a5e677a0 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 0ca604dc6..a76587c7f 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 7f366d931..ceff1a8e0 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 158d270b9..b27a058e5 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 b731d0544..e68a1e1b3 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 17d502434..56aa94016 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 66205697a..17e77fb17 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 1c380a49c..ade09fc9d 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 1835812bd..23c549122 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 5453a964d..f7db31e4f 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 7088612f6..92ebd7bcf 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 1512af897..9b12fa9e2 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 086b397ad..95fd93d5c 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 be46ca7a9..afa30e330 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 370b77679..5adfdc3ee 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 12c03d73c..756069b3d 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 854254dd5..6a5c2dd9b 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 4662288b5..9a01a0272 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 eafb7d5c1..c7f4d47aa 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 abec48bcc..371122c12 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 c6415eb6e..49e79254e 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 e8dfbfc60..9e454801e 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 1dc834a3f..fb4f321ac 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 933a3f265..65ce9fda9 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 ff13af703..011afba85 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 4ca097fff..beaee6855 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 22a183cca..9d2bc7cd8 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 69ca05791..894513fbe 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 d9b69a5af..6b9e03ef5 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 d853dc460..46e96cccc 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 80b1172c9..b7fe75938 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 f670aed0a..dd7d4b748 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 fe2af00fa..3c5dd1b87 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 8aaf54b78..048c2aa85 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 3c55dc19a..b4e81ceb4 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 953abbd13..1f0293000 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 4412d7aa7..d38095acc 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 1518495b1..2b0186f0a 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 e6b112eb0..dc0323051 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",