summary refs log tree commit diff stats
path: root/hw/core/bus.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-01-30 16:19:04 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-01-30 16:19:04 +0000
commit928173659d6e5dc368284f73f90ea1d129e1f57d (patch)
treea7c20f44a7f47478a8b475fb42609af5d2977f64 /hw/core/bus.c
parent204aa60b37c23a89e690d418f49787d274303ca7 (diff)
parentdea101a1ae9968c9fec6ab0291489dad7c49f36f (diff)
downloadfocaccia-qemu-928173659d6e5dc368284f73f90ea1d129e1f57d.tar.gz
focaccia-qemu-928173659d6e5dc368284f73f90ea1d129e1f57d.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200130' into staging
target-arm queue:
 * hw/core/or-irq: Fix incorrect assert forbidding num-lines == MAX_OR_LINES
 * target/arm/arm-semi: Don't let the guest close stdin/stdout/stderr
 * aspeed: some minor bugfixes
 * aspeed: add eMMC controller model for AST2600 SoC
 * hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
 * New 3-phase reset API for device models
 * hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
 * Arm KVM: stop/restart the guest counter when the VM is stopped and started

# gpg: Signature made Thu 30 Jan 2020 16:14:45 GMT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20200130: (26 commits)
  target/arm/cpu: Add the kvm-no-adjvtime CPU property
  target/arm/kvm: Implement virtual time adjustment
  tests/arm-cpu-features: Check feature default values
  target/arm/kvm64: kvm64 cpus have timer registers
  hw/arm/virt: Add missing 5.0 options call to 4.2 options
  target/arm/kvm: trivial: Clean up header documentation
  hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
  hw/s390x/ipl: replace deprecated qdev_reset_all registration
  vl: replace deprecated qbus_reset_all registration
  docs/devel/reset.rst: add doc about Resettable interface
  hw/core: deprecate old reset functions and introduce new ones
  hw/core/qdev: update hotplug reset regarding resettable
  hw/core/qdev: handle parent bus change regarding resettable
  hw/core/resettable: add support for changing parent
  hw/core: add Resettable support to BusClass and DeviceClass
  hw/core: create Resettable QOM interface
  hw/core/qdev: add trace events to help with resettable transition
  add device_legacy_reset function to prepare for reset api change
  hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
  misc/pca9552: Add qom set and get
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/core/bus.c')
-rw-r--r--hw/core/bus.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/hw/core/bus.c b/hw/core/bus.c
index 7f3d2a3dbd..3dc0a825f0 100644
--- a/hw/core/bus.c
+++ b/hw/core/bus.c
@@ -68,6 +68,33 @@ int qbus_walk_children(BusState *bus,
     return 0;
 }
 
+void bus_cold_reset(BusState *bus)
+{
+    resettable_reset(OBJECT(bus), RESET_TYPE_COLD);
+}
+
+bool bus_is_in_reset(BusState *bus)
+{
+    return resettable_is_in_reset(OBJECT(bus));
+}
+
+static ResettableState *bus_get_reset_state(Object *obj)
+{
+    BusState *bus = BUS(obj);
+    return &bus->reset;
+}
+
+static void bus_reset_child_foreach(Object *obj, ResettableChildCallback cb,
+                                    void *opaque, ResetType type)
+{
+    BusState *bus = BUS(obj);
+    BusChild *kid;
+
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        cb(OBJECT(kid->child), opaque, type);
+    }
+}
+
 static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
 {
     const char *typename = object_get_typename(OBJECT(bus));
@@ -199,12 +226,83 @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
     return g_strdup(object_get_typename(OBJECT(dev)));
 }
 
+/**
+ * bus_phases_reset:
+ * Transition reset method for buses to allow moving
+ * smoothly from legacy reset method to multi-phases
+ */
+static void bus_phases_reset(BusState *bus)
+{
+    ResettableClass *rc = RESETTABLE_GET_CLASS(bus);
+
+    if (rc->phases.enter) {
+        rc->phases.enter(OBJECT(bus), RESET_TYPE_COLD);
+    }
+    if (rc->phases.hold) {
+        rc->phases.hold(OBJECT(bus));
+    }
+    if (rc->phases.exit) {
+        rc->phases.exit(OBJECT(bus));
+    }
+}
+
+static void bus_transitional_reset(Object *obj)
+{
+    BusClass *bc = BUS_GET_CLASS(obj);
+
+    /*
+     * This will call either @bus_phases_reset (for multi-phases transitioned
+     * buses) or a bus's specific method for not-yet transitioned buses.
+     * In both case, it does not reset children.
+     */
+    if (bc->reset) {
+        bc->reset(BUS(obj));
+    }
+}
+
+/**
+ * bus_get_transitional_reset:
+ * check if the bus's class is ready for multi-phase
+ */
+static ResettableTrFunction bus_get_transitional_reset(Object *obj)
+{
+    BusClass *dc = BUS_GET_CLASS(obj);
+    if (dc->reset != bus_phases_reset) {
+        /*
+         * dc->reset has been overridden by a subclass,
+         * the bus is not ready for multi phase yet.
+         */
+        return bus_transitional_reset;
+    }
+    return NULL;
+}
+
 static void bus_class_init(ObjectClass *class, void *data)
 {
     BusClass *bc = BUS_CLASS(class);
+    ResettableClass *rc = RESETTABLE_CLASS(class);
 
     class->unparent = bus_unparent;
     bc->get_fw_dev_path = default_bus_get_fw_dev_path;
+
+    rc->get_state = bus_get_reset_state;
+    rc->child_foreach = bus_reset_child_foreach;
+
+    /*
+     * @bus_phases_reset is put as the default reset method below, allowing
+     * to do the multi-phase transition from base classes to leaf classes. It
+     * allows a legacy-reset Bus class to extend a multi-phases-reset
+     * Bus class for the following reason:
+     * + If a base class B has been moved to multi-phase, then it does not
+     *   override this default reset method and may have defined phase methods.
+     * + A child class C (extending class B) which uses
+     *   bus_class_set_parent_reset() (or similar means) to override the
+     *   reset method will still work as expected. @bus_phases_reset function
+     *   will be registered as the parent reset method and effectively call
+     *   parent reset phases.
+     */
+    bc->reset = bus_phases_reset;
+    rc->get_transitional_function = bus_get_transitional_reset;
 }
 
 static void qbus_finalize(Object *obj)
@@ -223,6 +321,10 @@ static const TypeInfo bus_info = {
     .instance_init = qbus_initfn,
     .instance_finalize = qbus_finalize,
     .class_init = bus_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_RESETTABLE_INTERFACE },
+        { }
+    },
 };
 
 static void bus_register_types(void)