diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-10-12 22:48:45 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-10-12 22:48:45 +0100 |
commit | 724c1c8bb350d84c097ab2005aad15e125d06b6c (patch) | |
tree | b55ff4dc3e8012e2624d2aa2d1211684bd425656 /hw/core | |
parent | a0bdf866873467271eff9a92f179ab0f77d735cb (diff) | |
parent | a0c9162c8250e121af438aee5ef93e64ec62dae1 (diff) | |
download | qemu-724c1c8bb350d84c097ab2005aad15e125d06b6c.zip qemu-724c1c8bb350d84c097ab2005aad15e125d06b6c.tar.gz qemu-724c1c8bb350d84c097ab2005aad15e125d06b6c.tar.bz2 |
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging
* qtest documentation improvements (Eduardo, myself)
* libqtest event buffering (Maxim)
* use RCU for list of children of a bus (Maxim)
* move more files to softmmu/ (myself)
* meson.build cleanups, qemu-storage-daemon fix (Philippe)
# gpg: Signature made Mon 12 Oct 2020 16:55:19 BST
# gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg: issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini-gitlab/tags/for-upstream: (38 commits)
meson: identify more sections of meson.build
scsi/scsi_bus: fix races in REPORT LUNS
virtio-scsi: use scsi_device_get
scsi/scsi_bus: Add scsi_device_get
scsi/scsi-bus: scsi_device_find: don't return unrealized devices
device-core: use atomic_set on .realized property
scsi: switch to bus->check_address
device-core: use RCU for list of children of a bus
device_core: use drain_call_rcu in in qmp_device_add
scsi/scsi_bus: switch search direction in scsi_device_find
qdev: add "check if address free" callback for buses
qemu-iotests, qtest: rewrite test 067 as a qtest
qtest: check that drives are really appearing and disappearing
qtest: switch users back to qtest_qmp_receive
device-plug-test: use qtest_qmp to send the device_del command
qtest: remove qtest_qmp_receive_success
qtest: Reintroduce qtest_qmp_receive with QMP event buffering
qtest: rename qtest_qmp_receive to qtest_qmp_receive_dict
meson.build: Re-enable KVM support for MIPS
build-sys: fix git version from -version
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/core')
-rw-r--r-- | hw/core/bus.c | 28 | ||||
-rw-r--r-- | hw/core/meson.build | 6 | ||||
-rw-r--r-- | hw/core/qdev.c | 73 |
3 files changed, 73 insertions, 34 deletions
diff --git a/hw/core/bus.c b/hw/core/bus.c index 6b987b6..a048385 100644 --- a/hw/core/bus.c +++ b/hw/core/bus.c @@ -49,12 +49,14 @@ int qbus_walk_children(BusState *bus, } } - QTAILQ_FOREACH(kid, &bus->children, sibling) { - err = qdev_walk_children(kid->child, - pre_devfn, pre_busfn, - post_devfn, post_busfn, opaque); - if (err < 0) { - return err; + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) { + err = qdev_walk_children(kid->child, + pre_devfn, pre_busfn, + post_devfn, post_busfn, opaque); + if (err < 0) { + return err; + } } } @@ -90,8 +92,10 @@ static void bus_reset_child_foreach(Object *obj, ResettableChildCallback cb, BusState *bus = BUS(obj); BusChild *kid; - QTAILQ_FOREACH(kid, &bus->children, sibling) { - cb(OBJECT(kid->child), opaque, type); + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) { + cb(OBJECT(kid->child), opaque, type); + } } } @@ -194,9 +198,11 @@ static void bus_set_realized(Object *obj, bool value, Error **errp) /* TODO: recursive realization */ } else if (!value && bus->realized) { - QTAILQ_FOREACH(kid, &bus->children, sibling) { - DeviceState *dev = kid->child; - qdev_unrealize(dev); + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; + qdev_unrealize(dev); + } } if (bc->unrealize) { bc->unrealize(bus); diff --git a/hw/core/meson.build b/hw/core/meson.build index fc91f98..4a744f3 100644 --- a/hw/core/meson.build +++ b/hw/core/meson.build @@ -14,12 +14,6 @@ hwcore_files = files( 'qdev-clock.c', ) -libhwcore = static_library('hwcore', sources: hwcore_files + genh, - name_suffix: 'fa', - build_by_default: false) -hwcore = declare_dependency(link_whole: libhwcore) -common_ss.add(hwcore) - common_ss.add(files('cpu.c')) common_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c')) common_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c')) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 96772a1..fc4daa3 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -51,6 +51,12 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev) return dc->vmsd; } +static void bus_free_bus_child(BusChild *kid) +{ + object_unref(OBJECT(kid->child)); + g_free(kid); +} + static void bus_remove_child(BusState *bus, DeviceState *child) { BusChild *kid; @@ -60,15 +66,16 @@ static void bus_remove_child(BusState *bus, DeviceState *child) char name[32]; snprintf(name, sizeof(name), "child[%d]", kid->index); - QTAILQ_REMOVE(&bus->children, kid, sibling); + QTAILQ_REMOVE_RCU(&bus->children, kid, sibling); bus->num_children--; /* This gives back ownership of kid->child back to us. */ object_property_del(OBJECT(bus), name); - object_unref(OBJECT(kid->child)); - g_free(kid); - return; + + /* free the bus kid, when it is safe to do so*/ + call_rcu(kid, bus_free_bus_child, rcu); + break; } } } @@ -83,7 +90,7 @@ static void bus_add_child(BusState *bus, DeviceState *child) kid->child = child; object_ref(OBJECT(kid->child)); - QTAILQ_INSERT_HEAD(&bus->children, kid, sibling); + QTAILQ_INSERT_HEAD_RCU(&bus->children, kid, sibling); /* This transfers ownership of kid->child to the property. */ snprintf(name, sizeof(name), "child[%d]", kid->index); @@ -94,13 +101,23 @@ static void bus_add_child(BusState *bus, DeviceState *child) 0); } -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) { BusState *old_parent_bus = dev->parent_bus; DeviceClass *dc = DEVICE_GET_CLASS(dev); assert(dc->bus_type && object_dynamic_cast(OBJECT(bus), dc->bus_type)); + if (!bus_check_address(bus, dev, errp)) { + return false; + } + if (old_parent_bus) { trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)), old_parent_bus, object_get_typename(OBJECT(old_parent_bus)), @@ -126,6 +143,7 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus) object_unref(OBJECT(old_parent_bus)); object_unref(OBJECT(dev)); } + return true; } DeviceState *qdev_new(const char *name) @@ -371,7 +389,9 @@ bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp) assert(!dev->realized && !dev->parent_bus); if (bus) { - qdev_set_parent_bus(dev, bus); + if (!qdev_set_parent_bus(dev, bus, errp)) { + return false; + } } else { assert(!DEVICE_GET_CLASS(dev)->bus_type); } @@ -659,17 +679,19 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id) DeviceState *ret; BusState *child; - QTAILQ_FOREACH(kid, &bus->children, sibling) { - DeviceState *dev = kid->child; + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; - if (dev->id && strcmp(dev->id, id) == 0) { - return dev; - } + if (dev->id && strcmp(dev->id, id) == 0) { + return dev; + } - QLIST_FOREACH(child, &dev->child_bus, sibling) { - ret = qdev_find_recursive(child, id); - if (ret) { - return ret; + QLIST_FOREACH(child, &dev->child_bus, sibling) { + ret = qdev_find_recursive(child, id); + if (ret) { + return ret; + } } } } @@ -924,7 +946,25 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } } + qatomic_store_release(&dev->realized, value); + } else if (!value && dev->realized) { + + /* + * Change the value so that any concurrent users are aware + * that the device is going to be unrealized + * + * TODO: change .realized property to enum that states + * each phase of the device realization/unrealization + */ + + qatomic_set(&dev->realized, value); + /* + * Ensure that concurrent users see this update prior to + * any other changes done by unrealize. + */ + smp_wmb(); + QLIST_FOREACH(bus, &dev->child_bus, sibling) { qbus_unrealize(bus); } @@ -939,7 +979,6 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } assert(local_err == NULL); - dev->realized = value; return; child_realize_fail: |