All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism
@ 2019-07-29 14:56 Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface Damien Hedde
                   ` (33 more replies)
  0 siblings, 34 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Hi all,

Here's the third version of the multi-phase reset proposal patches. I've dropped
the RFC tag. Previous version can be found here:
https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg00504.html

The purpose of this series is to split the current reset procedure into 3
phases. We need 2 phases to separate what's local from what's doing external
side effects (IO for example). And we need a 3rd additional phase to handle
staying in reset state.

This serie has side-effects on ~20 files calling reset qdev/device api. In
consequence there is a lot of people in the CC list, most of them because of 2 
simple patches.

# Overview

The phases are:
INIT PHASE: Reset the object internal state, put a resetting flag and do the
    same for the reset subtree. No side effect on other devices to guarantee
    that, in a reset domain, everything get initialized first. This corresponds
    mostly to what is currently done in the device/bus reset method.

HOLD PHASE: This phase allows to control a reset with a IO. When a IO control
    reset procedure based on the IO level (not edge), we may need to assert
    the reset, wait some time, and finally de-assert the reset. The consequence
    is that such a device can stay in a "resetting state" and may need to show
    this state to other devices through its outputs. For example, a clock
    controller will typically shutdown its clocks when it is in resetting state.

EXIT PHASE: This phase sets outputs to state after reset. For a clock controller
     it starts the clocks. It also clears the "resetting" flag. A device should
     not react to inputs until this flag has been cleared. During this phase,
     outputs are propagated.

The reset use a new QOM interface: "Resettable". It is detailed in the added
documentation. Here's an overview, it contains the following methods:
  - 3 methods corresponding to the 3 phases, to be implemented by specialized
    objects.
  - others methods do handle the reset mechanics, implemented by base classes:
    + reset_count getter/modifier methods to know when we enter or leave reset
      if multiple reset sources are enabled at the same time.
    + set_cold method to handle warm/cold reset
    + foreach_child to do something on reset children. This method allow to
      build some reset hirearchy.

The reset order of the phase is the following
  - reset assertation
    1. init phases in parent-to-child order
    2. hold phases in child-to-parent order
  - reset de-assertation
    3. exit phases in child-to-parent order

# Reset deprecation

The switch to multi-phase reset deprecates the current way of handling reset
(for users or developers of Devices). It used a reset method in both
DeviceClass and BusClass.

1. qdev/qbus_reset_all

Theses functions are deprecated by this series and are replaced by included
patches without change of behavior.

2. old's device_reset

There was a few call to this function, I renamed it *device_legacy_reset* to
handle the transition. This function allowed to reset only a given device 
(and not its eventual qbus subtree). This behavior is not possible with
the Resettable interface. I changed existing calls. Most of the time there is
no change of behavior because devices have no sub-buses.
Here the summary after checking each one (I've reproduced the list made by
Peter with some additional commentary of myself):

 hw/audio/intel-hda.c
  -- used by the HDA device to reset the HDACodecDevice, which I think has
     no child buses
 hw/hyperv/hyperv.c
  -- resets the SynICState, which I think has no child buses
 hw/i386/pc.c
  -- resets the APIC, which has no child buses. (This reset is only
     done as a workaround for lack of reset phases: the whole machine
     is reset and then the APIC is re-reset last to undo any changes
     that other devices might have made to it. Probably making the APIC
     support phased reset would allow us to drop this hack.)
 hw/ide/microdrive.c
  -- called here to reset the MicroDriveState object. It does have
     a child bus, but it seems to me that potential children (ide-cd,
     ide-hd or ide-drive) have no implementation of the reset method.
 hw/intc/spapr_xive.c
  -- resets the SpaprXive device, which I think has no child buses
 hw/ppc/pnv_psi.c
  -- resets a XiveSource, which I think has no child buses
 hw/ppc/spapr_pci.c
  -- resets every QOM child of the SpaprPhbState. This one will
     require closer checking, but my guess is that if there's a child
     with a child bus then failure to reset the bus would be a bug.
 hw/ppc/spapr_vio.c
  -- resets an SpaprTceTable, which I think has no child buses.
 hw/s390x/s390-pci-inst.c
  -- resets the S390PCIBusDevice Needs S390 expertise, but probably
     either no child buses or failure to reset them is a bug.
 hw/scsi/vmw_pvscsi.c
  -- resets an individual SCSIDevice. Specialization of this class ("generic"
     or "disks") don't have child buses I think.
 hw/sd/omap_mmc.c
  -- resetting an SDState, which has no child bus
 hw/sd/pl181.c
  -- resetting an SDState, which has no child bus

In my opinion only hw/ppc/spapr_pci.c and hw/s390x/s390-pci-inst.c may imply
behavior changes.

3. DeviceClass's reset and BusClass's methods

This is the major change. The method is deprecated because, methods are now
located in the interface class. In the series, I make the exit phase redirect
to the original reset method of DeviceClass (or BusClass). There a lot of use
of the method and transitioning to 3-phases only reset will need some work I
did not address in this series.

# Migration

For devices, I've added a patch to automate the addition of reset related
subsection. In consequence it is not necessary to explicetely add the
reset subsection in every device specialization requiring it. Right know
this is kind of a hack into qdev to dynamically modify the vmsd before the
registration. There is probably a much cleaner way to do this but I prefered
to demonstrate it by keeping modification local to qdev.
As far as I can tell it's ok to dynamically add subsections at the end. This
does not prevent from further adding subsections in the orignal vmsd: the
subsections order in the array is irrelevant from migration point-of-view.
The loading part just lookup each subsection in the array by name uppon
reception.

For buses, I handle them in the parent parent post_load. It has some limitation
but should work pretty well for most of cases (if we hold reset qdev/qbus
subtree starting from a device not a bus). If we consider holding part of a soc
under reset goes through gpio, it have to be a device.

# Change in qdev/qbus hiearchy

It is possible to change the parent bus of a device with the
qdev_set_parent_bus function. We could add some code to adapt the resetting
count of the device if old and new bus have different reset state. I did not do
it right now because it doesnt not fill the right place do this: as long as reset
hiearchy follows the qdev hiearchy this would be fine place, but there is
nothing enforcing that with Resettable.

Given that, there is actually no bus help in reset. The only case when it can
happen is during the reset of a bus. Running the qom-test which test every
machine (with the initial main reset) gives one case where it happens: the raspi
because sd-card is moved during the reset. IMO, during reset, it's hazardous to
change qdev/qbus hierarchy since reset follows it so I'll try to address this on
a separate patch.

# Test

I tested this using the xilinx-zynq-a9 machine. Reset gpio and migration during
reset works.

# Changes since v2

  - don't call device implementations of reset phase functions multiple times.
  - init phase are executed parent-to-children order, legacy reset method is
    mapped on exit phase in order to keep the legacy order.
  - migration: poc of automatic addition of subsection.
  - migration: basic support for sub-buses.
  - qdev/qbus_reset_all & device_reset replacement

The series is organised as follow:
  - Patch   1 adds Resettable interface
  - Patches 2 and 3 rename device_reset function by device_legacy_reset to
    prepare the transition.
  - Patches 4 to 8 makes the changes in Device and Bus classes.
  - Patche 9 adds some doc
  - Patches 10 to 17 replace qdev/qbus_reset calls
  - Patches 18 to 27 replace device_reset calls
  - Patch 28 cleans remaining legacy reset API
  - Patches 29 to 33 modify the xilinx_zynq to add 3-phases reset support in the
    uart and the slcr (the reset controller of the soc).

Thanks,
Damien

Damien Hedde (33):
  Create Resettable QOM interface
  add temporary device_legacy_reset function to replace device_reset
  Replace all call to device_reset by call to device_legacy_reset
  make Device and Bus Resettable
  Switch to new api in qdev/bus
  add the vmstate description for device reset state
  automatically add vmstate for reset support in devices
  Add function to control reset with gpio inputs
  add doc about Resettable interface
  vl.c: remove qbus_reset_all registration
  hw/s390x/ipl.c: remove qbus_reset_all registration
  hw/pci/: remove qdev/qbus_reset_all call
  hw/scsi/: remove qdev/qbus_reset_all call
  hw/s390x/s390-virtio-ccw.c: remove qdev_reset_all call
  hw/ide/piix.c: remove qdev_reset_all call
  hw/input/adb.c: remove qdev_reset_all call
  hw/usb/dev-uas.c: remove qdev_reset_all call
  hw/audio/intel-hda.c: remove device_legacy_reset call
  hw/sd/pl181.c & omap_mmc.c: remove device_legacy_reset call
  hw/hyperv/hyperv.c: remove device_legacy_reset call
  hw/intc/spapr_xive.c: remove device_legacy_reset call
  hw/ppc/pnv_psi.c: remove device_legacy_reset call
  hw/scsi/vmw_pvscsi.c: remove device_legacy_reset call
  hw/ppc/spapr: remove device_legacy_reset call
  hw/i386/pc.c: remove device_legacy_reset call
  hw/s390x/s390-pci-inst.c: remove device_legacy_reset call
  hw/ide/microdrive.c: remove device_legacy_reset calls
  qdev: Remove unused deprecated reset functions
  hw/misc/zynq_slcr: use standard register definition
  convert cadence_uart to 3-phases reset
  Convert zynq's slcr to 3-phases reset
  Add uart reset support in zynq_slcr
  Connect the uart reset gpios in the zynq platform

 Makefile.objs                  |   1 +
 docs/devel/reset.txt           | 165 ++++++++++
 hw/arm/xilinx_zynq.c           |  14 +-
 hw/audio/intel-hda.c           |   2 +-
 hw/char/cadence_uart.c         |  77 ++++-
 hw/core/Makefile.objs          |   2 +
 hw/core/bus.c                  |  85 ++++++
 hw/core/qdev-vmstate.c         | 101 ++++++
 hw/core/qdev.c                 | 169 ++++++++--
 hw/core/resettable.c           | 220 +++++++++++++
 hw/core/trace-events           |  39 +++
 hw/hyperv/hyperv.c             |   2 +-
 hw/i386/pc.c                   |   2 +-
 hw/ide/microdrive.c            |   8 +-
 hw/ide/piix.c                  |   2 +-
 hw/input/adb.c                 |   2 +-
 hw/intc/spapr_xive.c           |   2 +-
 hw/misc/zynq_slcr.c            | 543 ++++++++++++++++++---------------
 hw/pci/pci.c                   |   6 +-
 hw/pci/pci_bridge.c            |   2 +-
 hw/ppc/pnv_psi.c               |   2 +-
 hw/ppc/spapr_pci.c             |   2 +-
 hw/ppc/spapr_vio.c             |   2 +-
 hw/s390x/ipl.c                 |   6 +-
 hw/s390x/s390-pci-inst.c       |   2 +-
 hw/s390x/s390-virtio-ccw.c     |   2 +-
 hw/scsi/lsi53c895a.c           |   4 +-
 hw/scsi/megasas.c              |   2 +-
 hw/scsi/mptsas.c               |   8 +-
 hw/scsi/spapr_vscsi.c          |   2 +-
 hw/scsi/virtio-scsi.c          |   6 +-
 hw/scsi/vmw_pvscsi.c           |   6 +-
 hw/sd/omap_mmc.c               |   2 +-
 hw/sd/pl181.c                  |   2 +-
 hw/usb/dev-uas.c               |   2 +-
 include/hw/char/cadence_uart.h |  10 +-
 include/hw/qdev-core.h         | 158 +++++++++-
 include/hw/resettable.h        | 126 ++++++++
 stubs/Makefile.objs            |   1 +
 stubs/device.c                 |   7 +
 tests/Makefile.include         |   1 +
 vl.c                           |   6 +-
 42 files changed, 1470 insertions(+), 333 deletions(-)
 create mode 100644 docs/devel/reset.txt
 create mode 100644 hw/core/qdev-vmstate.c
 create mode 100644 hw/core/resettable.c
 create mode 100644 hw/core/trace-events
 create mode 100644 include/hw/resettable.h
 create mode 100644 stubs/device.c

-- 
2.22.0



^ permalink raw reply	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-30 13:42   ` Cornelia Huck
  2019-08-07 14:20   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 02/33] add temporary device_legacy_reset function to replace device_reset Damien Hedde
                   ` (32 subsequent siblings)
  33 siblings, 2 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

This commit defines an interface allowing multi-phase reset.
The phases are INIT, HOLD and EXIT. Each phase has an associated method
in the class.

The reset of a Resettable is controlled with 2 functions:
  - resettable_assert_reset which starts the reset operation.
  - resettable_deassert_reset which ends the reset operation.

There is also a `resettable_reset` helper function which does assert then
deassert allowing to do a proper reset in one call.

In addition, two functions, *resettable_reset_cold_fn* and
*resettable_reset_warm_fn*, are defined. They take only an opaque argument
(for the Resettable object) and can be used as callbacks.

The Resettable interface is "reentrant", _assert_ can be called several
times and _deasert_ must be called the same number of times so that the
Resettable leave reset state. It is supported by keeping a counter of
the current number of _assert_ calls. The counter maintainance is done
though 3 methods get/increment/decrement_count. A method set_cold is used
to set the cold flag of the reset. Another method set_host_needed is used
to ensure hold phase is executed only if required.

Reset hierarchy is also supported. Each Resettable may have
sub-Resettable objects. When resetting a Resettable, it is propagated to
its children using the foreach_child method.

When entering reset, init phases are executed parent-to-child order then
hold phases are executed child-parent order.
When leaving reset, exit phases are executed in child-to-parent order.
This will allow to replace current qdev_reset mechanism by this interface
without side-effects on reset order.

Note: I used an uint32 for the count. This match the type already used
in the existing resetting counter in hw/scsi/vmw_pvscsi.c for the
PVSCSIState.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 Makefile.objs           |   1 +
 hw/core/Makefile.objs   |   1 +
 hw/core/resettable.c    | 220 ++++++++++++++++++++++++++++++++++++++++
 hw/core/trace-events    |  39 +++++++
 include/hw/resettable.h | 126 +++++++++++++++++++++++
 5 files changed, 387 insertions(+)
 create mode 100644 hw/core/resettable.c
 create mode 100644 hw/core/trace-events
 create mode 100644 include/hw/resettable.h

diff --git a/Makefile.objs b/Makefile.objs
index 6a143dcd57..a723a47e14 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -191,6 +191,7 @@ trace-events-subdirs += migration
 trace-events-subdirs += net
 trace-events-subdirs += ui
 endif
+trace-events-subdirs += hw/core
 trace-events-subdirs += hw/display
 trace-events-subdirs += qapi
 trace-events-subdirs += qom
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index f8481d959f..d9234aa98a 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -1,6 +1,7 @@
 # core qdev-related obj files, also used by *-user:
 common-obj-y += qdev.o qdev-properties.o
 common-obj-y += bus.o reset.o
+common-obj-y += resettable.o
 common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
 common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
 # irq.o needed for qdev GPIO handling:
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
new file mode 100644
index 0000000000..d7d631ce8b
--- /dev/null
+++ b/hw/core/resettable.c
@@ -0,0 +1,220 @@
+/*
+ * Resettable interface.
+ *
+ * Copyright (c) 2019 GreenSocs SAS
+ *
+ * Authors:
+ *   Damien Hedde
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "hw/resettable.h"
+#include "trace.h"
+
+#define RESETTABLE_MAX_COUNT 50
+
+#define RESETTABLE_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE)
+
+static void resettable_init_reset(Object *obj, bool cold);
+
+static bool resettable_class_check(ResettableClass *rc)
+{
+    if (!rc->set_cold) {
+        return false;
+    }
+    if (!rc->set_hold_needed) {
+        return false;
+    }
+    if (!rc->increment_count) {
+        return false;
+    }
+    if (!rc->decrement_count) {
+        return false;
+    }
+    if (!rc->get_count) {
+        return false;
+    }
+    return true;
+}
+
+static void resettable_foreach_child(ResettableClass *rc,
+                                     Object *obj,
+                                     void (*func)(Object *))
+{
+    if (rc->foreach_child) {
+        rc->foreach_child(obj, func);
+    }
+}
+
+static void resettable_init_cold_reset(Object *obj)
+{
+    resettable_init_reset(obj, true);
+}
+
+static void resettable_init_warm_reset(Object *obj)
+{
+    resettable_init_reset(obj, false);
+}
+
+static void resettable_init_reset(Object *obj, bool cold)
+{
+    void (*func)(Object *);
+    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
+    uint32_t count;
+    bool action_needed = false;
+    bool prev_cold;
+
+    assert(resettable_class_check(rc));
+
+    count = rc->increment_count(obj);
+    /* this assert is here to catch an eventual reset loop */
+    assert(count <= RESETTABLE_MAX_COUNT);
+
+    /*
+     * only take action if:
+     * + we really enter reset for the 1st time
+     * + or we are in warm reset and start a cold one
+     */
+    prev_cold = rc->set_cold(obj, cold);
+    if (count == 1) {
+        action_needed = true;
+    } else if (cold && !prev_cold) {
+        action_needed = true;
+    }
+    trace_resettable_phase_init(obj, object_get_typename(obj), cold, count,
+                                action_needed);
+
+    /* exec init phase */
+    if (action_needed) {
+        rc->set_hold_needed(obj, true);
+        if (rc->phases.init) {
+            rc->phases.init(obj);
+        }
+    }
+
+    /*
+     * handle the children even if action_needed is at false so that
+     * children counts are incremented too
+     */
+    func = cold ? resettable_init_cold_reset : resettable_init_warm_reset;
+    resettable_foreach_child(rc, obj, func);
+    trace_resettable_phase_init_end(obj);
+}
+
+static void resettable_hold_reset(Object *obj)
+{
+    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
+    bool hold_needed;
+
+    assert(resettable_class_check(rc));
+    trace_resettable_phase_hold(obj, object_get_typename(obj));
+
+    /* handle children first */
+    resettable_foreach_child(rc, obj, resettable_hold_reset);
+
+    /* exec hold phase */
+    hold_needed = rc->set_hold_needed(obj, false);
+    if (hold_needed) {
+        if (rc->phases.hold) {
+            rc->phases.hold(obj);
+        }
+    }
+    trace_resettable_phase_hold_end(obj, hold_needed);
+}
+
+static void resettable_exit_reset(Object *obj)
+{
+    uint32_t count;
+    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
+
+    assert(resettable_class_check(rc));
+    trace_resettable_phase_exit(obj, object_get_typename(obj));
+
+    resettable_foreach_child(rc, obj, resettable_deassert_reset);
+
+    count = rc->get_count(obj);
+    /*
+     * we could assert that count > 0 but there are some corner cases
+     * where we prefer to let it go as it is probably harmless.
+     * For example: if there is reset support addition between
+     * hosts when doing a migration. We may do such things as
+     * deassert a non-existing reset.
+     */
+    if (count > 0) {
+        count = rc->decrement_count(obj);
+    } else {
+        trace_resettable_count_underflow(obj);
+    }
+    if (count == 0) {
+        if (rc->phases.exit) {
+            rc->phases.exit(obj);
+        }
+    }
+    trace_resettable_phase_exit_end(obj, count);
+}
+
+void resettable_assert_reset(Object *obj, bool cold)
+{
+    trace_resettable_reset_assert(obj, object_get_typename(obj), cold);
+    resettable_init_reset(obj, cold);
+    resettable_hold_reset(obj);
+}
+
+void resettable_deassert_reset(Object *obj)
+{
+    trace_resettable_reset_deassert(obj, object_get_typename(obj));
+    resettable_exit_reset(obj);
+}
+
+void resettable_reset(Object *obj, bool cold)
+{
+    trace_resettable_reset(obj, object_get_typename(obj), cold);
+    resettable_assert_reset(obj, cold);
+    resettable_deassert_reset(obj);
+}
+
+void resettable_reset_warm_fn(void *opaque)
+{
+    resettable_reset((Object *) opaque, false);
+}
+
+void resettable_reset_cold_fn(void *opaque)
+{
+    resettable_reset((Object *) opaque, true);
+}
+
+void resettable_class_set_parent_reset_phases(ResettableClass *rc,
+                                              ResettableInitPhase init,
+                                              ResettableHoldPhase hold,
+                                              ResettableExitPhase exit,
+                                              ResettablePhases *parent_phases)
+{
+    *parent_phases = rc->phases;
+    if (init) {
+        rc->phases.init = init;
+    }
+    if (hold) {
+        rc->phases.hold = hold;
+    }
+    if (exit) {
+        rc->phases.exit = exit;
+    }
+}
+
+static const TypeInfo resettable_interface_info = {
+    .name       = TYPE_RESETTABLE,
+    .parent     = TYPE_INTERFACE,
+    .class_size = sizeof(ResettableClass),
+};
+
+static void reset_register_types(void)
+{
+    type_register_static(&resettable_interface_info);
+}
+
+type_init(reset_register_types)
diff --git a/hw/core/trace-events b/hw/core/trace-events
new file mode 100644
index 0000000000..489d96d445
--- /dev/null
+++ b/hw/core/trace-events
@@ -0,0 +1,39 @@
+# See docs/devel/tracing.txt for syntax documentation.
+#
+# This file is processed by the tracetool script during the build.
+#
+# To add a new trace event:
+#
+# 1. Choose a name for the trace event.  Declare its arguments and format
+#    string.
+#
+# 2. Call the trace event from code using trace_##name, e.g. multiwrite_cb() ->
+#    trace_multiwrite_cb().  The source file must #include "trace.h".
+#
+# Format of a trace event:
+#
+# [disable] <name>(<type1> <arg1>[, <type2> <arg2>] ...) "<format-string>"
+#
+# Example: g_malloc(size_t size) "size %zu"
+#
+# The "disable" keyword will build without the trace event.
+#
+# The <name> must be a valid as a C function name.
+#
+# Types should be standard C types.  Use void * for pointers because the trace
+# system may not have the necessary headers included.
+#
+# The <format-string> should be a sprintf()-compatible format string.
+
+# resettable.c
+resettable_reset(void *obj, const char *type, int cold) "obj=%p(%s) cold=%d"
+resettable_reset_assert(void *obj, const char *type, int cold) "obj=%p(%s) cold=%d"
+resettable_reset_deassert(void *obj, const char *type) "obj=%p(%s)"
+resettable_reset_deassert_end(void *obj) "obj=%p"
+resettable_phase_init(void *obj, const char *type, int cold, uint32_t count, int needed) "obj=%p(%s) cold=%d count=%" PRIu32 " needed=%d"
+resettable_phase_init_end(void *obj) "obj=%p"
+resettable_phase_hold(void *obj, const char *type) "obj=%p(%s)"
+resettable_phase_hold_end(void *obj, int needed) "obj=%p needed=%d"
+resettable_phase_exit(void *obj, const char *type) "obj=%p(%s)"
+resettable_phase_exit_end(void *obj, uint32_t count) "obj=%p count=%" PRIu32
+resettable_count_underflow(void *obj) "obj=%p"
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
new file mode 100644
index 0000000000..e617a8e875
--- /dev/null
+++ b/include/hw/resettable.h
@@ -0,0 +1,126 @@
+#ifndef HW_RESETTABLE_H
+#define HW_RESETTABLE_H
+
+#include "qom/object.h"
+
+#define TYPE_RESETTABLE "resettable"
+
+#define RESETTABLE_CLASS(class) \
+    OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE)
+
+/*
+ * ResettableClass:
+ * Interface for resettable objects.
+ *
+ * The reset operation is divided in several phases each represented by a
+ * method.
+ *
+ * Each Ressetable must maintain a reset counter in its state, 3 methods allows
+ * to interact with it.
+ *
+ * @phases.init: should reset local state only. Takes a bool @cold argument
+ * specifying whether the reset is cold or warm. It must not do side-effect
+ * on others objects.
+ *
+ * @phases.hold: side-effects action on others objects due to staying in a
+ * resetting state.
+ *
+ * @phases.exit: leave the reset state, may do side-effects action on others
+ * objects.
+ *
+ * @set_cold: Set whether the current reset is cold or warm. Return the
+ * previous flag value. Return value has no meaning if @get_count returns
+ * a zero value.
+ *
+ * @set_hold_needed: Set hold_needed flag. Return the previous flag value.
+ *
+ * @get_count: Get the current reset count
+ * @increment_count: Increment the reset count, returns the new count
+ * @decrement_count: decrement the reset count, returns the new count
+ *
+ * @foreach_child: Executes a given function on every Resettable child.
+ * A child is not a QOM child, but a child a reset meaning.
+ */
+typedef void (*ResettableInitPhase)(Object *obj);
+typedef void (*ResettableHoldPhase)(Object *obj);
+typedef void (*ResettableExitPhase)(Object *obj);
+typedef bool (*ResettableSetCold)(Object *obj, bool cold);
+typedef bool (*ResettableSetHoldNeeded)(Object *obj, bool hold_needed);
+typedef uint32_t (*ResettableGetCount)(Object *obj);
+typedef uint32_t (*ResettableIncrementCount)(Object *obj);
+typedef uint32_t (*ResettableDecrementCount)(Object *obj);
+typedef void (*ResettableForeachChild)(Object *obj, void (*visitor)(Object *));
+typedef struct ResettableClass {
+    InterfaceClass parent_class;
+
+    struct ResettablePhases {
+        ResettableInitPhase init;
+        ResettableHoldPhase hold;
+        ResettableExitPhase exit;
+    } phases;
+
+    ResettableSetCold set_cold;
+    ResettableSetHoldNeeded set_hold_needed;
+    ResettableGetCount get_count;
+    ResettableIncrementCount increment_count;
+    ResettableDecrementCount decrement_count;
+    ResettableForeachChild foreach_child;
+} ResettableClass;
+typedef struct ResettablePhases ResettablePhases;
+
+/**
+ * resettable_assert_reset:
+ * Increments the reset count and executes the init and hold phases.
+ * Each time resettable_assert_reset is called, resettable_deassert_reset
+ * must eventually be called once.
+ * It will also impact reset children.
+ *
+ * @obj object to reset, must implement Resettable interface.
+ * @cold boolean indicating the type of reset (cold or warm)
+ */
+void resettable_assert_reset(Object *obj, bool cold);
+
+/**
+ * resettable_deassert_reset:
+ * Decrements the reset count by one and executes the exit phase if it hits
+ * zero.
+ * It will also impact reset children.
+ *
+ * @obj object to reset, must implement Resettable interface.
+ */
+void resettable_deassert_reset(Object *obj);
+
+/**
+ * resettable_reset:
+ * Calling this function is equivalent to call @assert_reset then
+ * @deassert_reset.
+ */
+void resettable_reset(Object *obj, bool cold);
+
+/**
+ * resettable_reset_warm_fn:
+ * Helper to call resettable_reset(opaque, false)
+ */
+void resettable_reset_warm_fn(void *opaque);
+
+/**
+ * resettable_reset_cold_fn:
+ * Helper to call resettable_reset(opaque, true)
+ */
+void resettable_reset_cold_fn(void *opaque);
+
+/**
+ * resettable_class_set_parent_reset_phases:
+ *
+ * Save @rc current reset phases into @parent_phases and override @rc phases
+ * by the given new methods (@init, @hold and @exit).
+ * Each phase is overriden only if the new one is not NULL allowing to
+ * override a subset of phases.
+ */
+void resettable_class_set_parent_reset_phases(ResettableClass *rc,
+                                              ResettableInitPhase init,
+                                              ResettableHoldPhase hold,
+                                              ResettableExitPhase exit,
+                                              ResettablePhases *parent_phases);
+
+#endif
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 02/33] add temporary device_legacy_reset function to replace device_reset
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-07 14:27   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 03/33] Replace all call to device_reset by call to device_legacy_reset Damien Hedde
                   ` (31 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Provide a temporary function doing what device_reset does to do the
transition with Resettable API which will trigger a prototype change
of device_reset.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/qdev.c         | 6 +++---
 include/hw/qdev-core.h | 9 +++++++--
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 94ebc0a4a1..043e058396 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -256,7 +256,7 @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
 
 static int qdev_reset_one(DeviceState *dev, void *opaque)
 {
-    device_reset(dev);
+    device_legacy_reset(dev);
 
     return 0;
 }
@@ -864,7 +864,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
             }
         }
         if (dev->hotplugged) {
-            device_reset(dev);
+            device_legacy_reset(dev);
         }
         dev->pending_deleted_event = false;
 
@@ -1086,7 +1086,7 @@ void device_class_set_parent_unrealize(DeviceClass *dc,
     dc->unrealize = dev_unrealize;
 }
 
-void device_reset(DeviceState *dev)
+void device_legacy_reset(DeviceState *dev)
 {
     DeviceClass *klass = DEVICE_GET_CLASS(dev);
 
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index e157fc4acd..690ce72433 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -407,11 +407,16 @@ char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
 void qdev_machine_init(void);
 
 /**
- * @device_reset
+ * device_legacy_reset:
  *
  * Reset a single device (by calling the reset method).
  */
-void device_reset(DeviceState *dev);
+void device_legacy_reset(DeviceState *dev);
+
+static inline void device_reset(DeviceState *dev)
+{
+    device_legacy_reset(dev);
+}
 
 void device_class_set_parent_reset(DeviceClass *dc,
                                    DeviceReset dev_reset,
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 03/33] Replace all call to device_reset by call to device_legacy_reset
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 02/33] add temporary device_legacy_reset function to replace device_reset Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-31  5:52   ` David Gibson
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable Damien Hedde
                   ` (30 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/audio/intel-hda.c     | 2 +-
 hw/hyperv/hyperv.c       | 2 +-
 hw/i386/pc.c             | 2 +-
 hw/ide/microdrive.c      | 8 ++++----
 hw/intc/spapr_xive.c     | 2 +-
 hw/ppc/pnv_psi.c         | 2 +-
 hw/ppc/spapr_pci.c       | 2 +-
 hw/ppc/spapr_vio.c       | 2 +-
 hw/s390x/s390-pci-inst.c | 2 +-
 hw/scsi/vmw_pvscsi.c     | 2 +-
 hw/sd/omap_mmc.c         | 2 +-
 hw/sd/pl181.c            | 2 +-
 12 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index b78baac295..f133684b10 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -1086,7 +1086,7 @@ static void intel_hda_reset(DeviceState *dev)
     QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
         DeviceState *qdev = kid->child;
         cdev = HDA_CODEC_DEVICE(qdev);
-        device_reset(DEVICE(cdev));
+        device_legacy_reset(DEVICE(cdev));
         d->state_sts |= (1 << cdev->cad);
     }
     intel_hda_update_irq(d);
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 6ebf31c310..cd9db3cb5c 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -140,7 +140,7 @@ void hyperv_synic_reset(CPUState *cs)
     SynICState *synic = get_synic(cs);
 
     if (synic) {
-        device_reset(DEVICE(synic));
+        device_legacy_reset(DEVICE(synic));
     }
 }
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 549c437050..c0f20fe8aa 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -2823,7 +2823,7 @@ static void pc_machine_reset(MachineState *machine)
         cpu = X86_CPU(cs);
 
         if (cpu->apic_state) {
-            device_reset(cpu->apic_state);
+            device_legacy_reset(cpu->apic_state);
         }
     }
 }
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index 92ee6e0af8..fc346f5ad5 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -173,7 +173,7 @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
     case 0x00:	/* Configuration Option Register */
         s->opt = value & 0xcf;
         if (value & OPT_SRESET) {
-            device_reset(DEVICE(s));
+            device_legacy_reset(DEVICE(s));
         }
         md_interrupt_update(s);
         break;
@@ -316,7 +316,7 @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
     case 0xe:	/* Device Control */
         s->ctrl = value;
         if (value & CTRL_SRST) {
-            device_reset(DEVICE(s));
+            device_legacy_reset(DEVICE(s));
         }
         md_interrupt_update(s);
         break;
@@ -541,7 +541,7 @@ static int dscm1xxxx_attach(PCMCIACardState *card)
     md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
     md->io_base = 0x0;
 
-    device_reset(DEVICE(md));
+    device_legacy_reset(DEVICE(md));
     md_interrupt_update(md);
 
     return 0;
@@ -551,7 +551,7 @@ static int dscm1xxxx_detach(PCMCIACardState *card)
 {
     MicroDriveState *md = MICRODRIVE(card);
 
-    device_reset(DEVICE(md));
+    device_legacy_reset(DEVICE(md));
     return 0;
 }
 
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 3ae311d9ff..22e11ad10c 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -1511,7 +1511,7 @@ static target_ulong h_int_reset(PowerPCCPU *cpu,
         return H_PARAMETER;
     }
 
-    device_reset(DEVICE(xive));
+    device_legacy_reset(DEVICE(xive));
 
     if (kvm_irqchip_in_kernel()) {
         Error *local_err = NULL;
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index d7b6f5d75b..78eafa353a 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -703,7 +703,7 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
         break;
     case PSIHB9_INTERRUPT_CONTROL:
         if (val & PSIHB9_IRQ_RESET) {
-            device_reset(DEVICE(&psi9->source));
+            device_legacy_reset(DEVICE(&psi9->source));
         }
         psi->regs[reg] = val;
         break;
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 9003fe9010..3c6cf79a5e 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -2029,7 +2029,7 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
     DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
 
     if (dev) {
-        device_reset(dev);
+        device_legacy_reset(dev);
     }
 
     return 0;
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 583c13deda..5a0b5cc35c 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -306,7 +306,7 @@ int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
 static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
 {
     if (dev->tcet) {
-        device_reset(DEVICE(dev->tcet));
+        device_legacy_reset(DEVICE(dev->tcet));
     }
     free_crq(dev);
 }
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 00235148be..93cda37c27 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -242,7 +242,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
                 stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
                 goto out;
             }
-            device_reset(DEVICE(pbdev));
+            device_legacy_reset(DEVICE(pbdev));
             pbdev->fh &= ~FH_MASK_ENABLE;
             pbdev->state = ZPCI_FS_DISABLED;
             stl_p(&ressetpci->fh, pbdev->fh);
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 14641df1c8..cda3fc96a0 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -835,7 +835,7 @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
 
     if (sdev != NULL) {
         s->resetting++;
-        device_reset(&sdev->qdev);
+        device_legacy_reset(&sdev->qdev);
         s->resetting--;
         return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
     }
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index d0c98ca021..24a1edc149 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -317,7 +317,7 @@ void omap_mmc_reset(struct omap_mmc_s *host)
      * into any bus, and we must reset it manually. When omap_mmc is
      * QOMified this must move into the QOM reset function.
      */
-    device_reset(DEVICE(host->card));
+    device_legacy_reset(DEVICE(host->card));
 }
 
 static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 81b406dbf0..15b4aaa67f 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -480,7 +480,7 @@ static void pl181_reset(DeviceState *d)
     /* Since we're still using the legacy SD API the card is not plugged
      * into any bus, and we must reset it manually.
      */
-    device_reset(DEVICE(s->card));
+    device_legacy_reset(DEVICE(s->card));
 }
 
 static void pl181_init(Object *obj)
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (2 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 03/33] Replace all call to device_reset by call to device_legacy_reset Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-31  5:56   ` David Gibson
  2019-08-07 14:41   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus Damien Hedde
                   ` (29 subsequent siblings)
  33 siblings, 2 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

This add Resettable interface implementation for both Bus and Device.

*resetting* counter and *reset_is_cold* flag are added in DeviceState
and BusState.

Compatibility with existing code base is ensured.
The legacy bus or device reset method is called in the new exit phase
and the other 2 phases are let empty. Using the exit phase guarantee that
legacy resets are called in the "post" order (ie: children then parent)
in hierarchical reset. That is the same order as legacy qdev_reset_all
or qbus_reset_all were using.

New *device_reset* and *bus_reset* function are proposed with an
additional boolean argument telling whether the reset is cold or warm.
Helper functions *device_reset_[warm|cold]* and *bus_reset_[warm|cold]*
are defined also as helpers.

Also add a [device|bus]_is_resetting and [device|bus]_is_reset_cold
functions telling respectively whether the object is currently under reset and
if the current reset is cold or not.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/bus.c          | 85 ++++++++++++++++++++++++++++++++++++++++++
 hw/core/qdev.c         | 82 ++++++++++++++++++++++++++++++++++++++++
 include/hw/qdev-core.h | 84 ++++++++++++++++++++++++++++++++++++++---
 tests/Makefile.include |  1 +
 4 files changed, 247 insertions(+), 5 deletions(-)

diff --git a/hw/core/bus.c b/hw/core/bus.c
index 17bc1edcde..08a97addb6 100644
--- a/hw/core/bus.c
+++ b/hw/core/bus.c
@@ -22,6 +22,7 @@
 #include "qemu/module.h"
 #include "hw/qdev.h"
 #include "qapi/error.h"
+#include "hw/resettable.h"
 
 void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
 {
@@ -68,6 +69,75 @@ int qbus_walk_children(BusState *bus,
     return 0;
 }
 
+void bus_reset(BusState *bus, bool cold)
+{
+    resettable_reset(OBJECT(bus), cold);
+}
+
+bool bus_is_resetting(BusState *bus)
+{
+    return (bus->resetting != 0);
+}
+
+bool bus_is_reset_cold(BusState *bus)
+{
+    return bus->reset_is_cold;
+}
+
+static uint32_t bus_get_reset_count(Object *obj)
+{
+    BusState *bus = BUS(obj);
+    return bus->resetting;
+}
+
+static uint32_t bus_increment_reset_count(Object *obj)
+{
+    BusState *bus = BUS(obj);
+    return ++bus->resetting;
+}
+
+static uint32_t bus_decrement_reset_count(Object *obj)
+{
+    BusState *bus = BUS(obj);
+    return --bus->resetting;
+}
+
+static bool bus_set_reset_cold(Object *obj, bool cold)
+{
+    BusState *bus = BUS(obj);
+    bool old = bus->reset_is_cold;
+    bus->reset_is_cold = cold;
+    return old;
+}
+
+static bool bus_set_hold_needed(Object *obj, bool hold_needed)
+{
+    BusState *bus = BUS(obj);
+    bool old = bus->reset_hold_needed;
+    bus->reset_hold_needed = hold_needed;
+    return old;
+}
+
+static void bus_foreach_reset_child(Object *obj, void (*func)(Object *))
+{
+    BusState *bus = BUS(obj);
+    BusChild *kid;
+
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        func(OBJECT(kid->child));
+    }
+}
+
+static void bus_obj_legacy_reset(Object *obj)
+{
+    BusState *bus = BUS(obj);
+    BusClass *bc = BUS_GET_CLASS(obj);
+
+    if (bc->reset) {
+        bc->reset(bus);
+    }
+}
+
 static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
 {
     const char *typename = object_get_typename(OBJECT(bus));
@@ -192,6 +262,8 @@ static void qbus_initfn(Object *obj)
                              NULL);
     object_property_add_bool(obj, "realized",
                              bus_get_realized, bus_set_realized, NULL);
+
+    bus->resetting = 0;
 }
 
 static char *default_bus_get_fw_dev_path(DeviceState *dev)
@@ -202,9 +274,18 @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
 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->phases.exit = bus_obj_legacy_reset;
+    rc->get_count = bus_get_reset_count;
+    rc->increment_count = bus_increment_reset_count;
+    rc->decrement_count = bus_decrement_reset_count;
+    rc->foreach_child = bus_foreach_reset_child;
+    rc->set_cold = bus_set_reset_cold;
+    rc->set_hold_needed = bus_set_hold_needed;
 }
 
 static void qbus_finalize(Object *obj)
@@ -223,6 +304,10 @@ static const TypeInfo bus_info = {
     .instance_init = qbus_initfn,
     .instance_finalize = qbus_finalize,
     .class_init = bus_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_RESETTABLE },
+        { }
+    },
 };
 
 static void bus_register_types(void)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 043e058396..559ced070d 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -254,6 +254,64 @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
     return hotplug_ctrl;
 }
 
+void device_reset(DeviceState *dev, bool cold)
+{
+    resettable_reset(OBJECT(dev), cold);
+}
+
+bool device_is_resetting(DeviceState *dev)
+{
+    return (dev->resetting != 0);
+}
+
+bool device_is_reset_cold(DeviceState *dev)
+{
+    return dev->reset_is_cold;
+}
+
+static uint32_t device_get_reset_count(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+    return dev->resetting;
+}
+
+static uint32_t device_increment_reset_count(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+    return ++dev->resetting;
+}
+
+static uint32_t device_decrement_reset_count(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+    return --dev->resetting;
+}
+
+static bool device_set_reset_cold(Object *obj, bool cold)
+{
+    DeviceState *dev = DEVICE(obj);
+    bool old = dev->reset_is_cold;
+    dev->reset_is_cold = cold;
+    return old;
+}
+
+static bool device_set_hold_needed(Object *obj, bool hold_needed)
+{
+    DeviceState *dev = DEVICE(obj);
+    bool old = dev->reset_hold_needed;
+    dev->reset_hold_needed = hold_needed;
+    return old;
+}
+
+static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
+{
+    DeviceState *dev = DEVICE(obj);
+    BusState *bus;
+    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
+        func(OBJECT(bus));
+    }
+}
+
 static int qdev_reset_one(DeviceState *dev, void *opaque)
 {
     device_legacy_reset(dev);
@@ -954,6 +1012,7 @@ static void device_initfn(Object *obj)
 
     dev->instance_id_alias = -1;
     dev->realized = false;
+    dev->resetting = 0;
 
     object_property_add_bool(obj, "realized",
                              device_get_realized, device_set_realized, NULL);
@@ -1046,9 +1105,20 @@ static void device_unparent(Object *obj)
     }
 }
 
+static void device_obj_legacy_reset(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+    if (dc->reset) {
+        dc->reset(dev);
+    }
+}
+
 static void device_class_init(ObjectClass *class, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(class);
+    ResettableClass *rc = RESETTABLE_CLASS(class);
 
     class->unparent = device_unparent;
 
@@ -1060,6 +1130,14 @@ static void device_class_init(ObjectClass *class, void *data)
      */
     dc->hotpluggable = true;
     dc->user_creatable = true;
+
+    rc->phases.exit = device_obj_legacy_reset;
+    rc->get_count = device_get_reset_count;
+    rc->increment_count = device_increment_reset_count;
+    rc->decrement_count = device_decrement_reset_count;
+    rc->foreach_child = device_foreach_reset_child;
+    rc->set_cold = device_set_reset_cold;
+    rc->set_hold_needed = device_set_hold_needed;
 }
 
 void device_class_set_parent_reset(DeviceClass *dc,
@@ -1117,6 +1195,10 @@ static const TypeInfo device_type_info = {
     .class_init = device_class_init,
     .abstract = true,
     .class_size = sizeof(DeviceClass),
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_RESETTABLE },
+        { }
+    },
 };
 
 static void qdev_register_types(void)
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 690ce72433..eeb75611c8 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -7,6 +7,7 @@
 #include "hw/irq.h"
 #include "hw/hotplug.h"
 #include "sysemu/sysemu.h"
+#include "hw/resettable.h"
 
 enum {
     DEV_NVECTORS_UNSPECIFIED = -1,
@@ -132,6 +133,10 @@ struct NamedGPIOList {
 /**
  * DeviceState:
  * @realized: Indicates whether the device has been fully constructed.
+ * @resetting: Indicates whether the device is under reset. Also
+ * used to count how many times reset has been initiated on the device.
+ * @reset_is_cold: If the device is under reset, indicates whether it is cold
+ * or warm.
  *
  * This structure should not be accessed directly.  We declare it here
  * so that it can be embedded in individual device state structures.
@@ -153,6 +158,9 @@ struct DeviceState {
     int num_child_bus;
     int instance_id_alias;
     int alias_required_for_version;
+    uint32_t resetting;
+    bool reset_is_cold;
+    bool reset_hold_needed;
 };
 
 struct DeviceListener {
@@ -199,6 +207,10 @@ typedef struct BusChild {
 /**
  * BusState:
  * @hotplug_handler: link to a hotplug handler associated with bus.
+ * @resetting: Indicates whether the bus is under reset. Also
+ * used to count how many times reset has been initiated on the bus.
+ * @reset_is_cold: If the bus is under reset, indicates whether it is cold
+ * or warm.
  */
 struct BusState {
     Object obj;
@@ -210,6 +222,9 @@ struct BusState {
     int num_children;
     QTAILQ_HEAD(, BusChild) children;
     QLIST_ENTRY(BusState) sibling;
+    uint32_t resetting;
+    bool reset_is_cold;
+    bool reset_hold_needed;
 };
 
 /**
@@ -376,6 +391,70 @@ int qdev_walk_children(DeviceState *dev,
                        qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
                        void *opaque);
 
+/**
+ * device_reset:
+ * Resets the device @dev, @cold tell whether to do a cold or warm reset.
+ * Uses the ressetable interface.
+ * Base behavior is to reset the device and its qdev/qbus subtree.
+ */
+void device_reset(DeviceState *dev, bool cold);
+
+static inline void device_reset_warm(DeviceState *dev)
+{
+    device_reset(dev, false);
+}
+
+static inline void device_reset_cold(DeviceState *dev)
+{
+    device_reset(dev, true);
+}
+
+/**
+ * bus_reset:
+ * Resets the bus @bus, @cold tell whether to do a cold or warm reset.
+ * Uses the ressetable interface.
+ * Base behavior is to reset the bus and its qdev/qbus subtree.
+ */
+void bus_reset(BusState *bus, bool cold);
+
+static inline void bus_reset_warm(BusState *bus)
+{
+    bus_reset(bus, false);
+}
+
+static inline void bus_reset_cold(BusState *bus)
+{
+    bus_reset(bus, true);
+}
+
+/**
+ * device_is_resetting:
+ * Tell whether the device @dev is currently under reset.
+ */
+bool device_is_resetting(DeviceState *dev);
+
+/**
+ * device_is_reset_cold:
+ * Tell whether the device @dev is currently under reset cold or warm reset.
+ *
+ * Note: only valid when device_is_resetting returns true.
+ */
+bool device_is_reset_cold(DeviceState *dev);
+
+/**
+ * bus_is_resetting:
+ * Tell whether the bus @bus is currently under reset.
+ */
+bool bus_is_resetting(BusState *bus);
+
+/**
+ * bus_is_reset_cold:
+ * Tell whether the bus @bus is currently under reset cold or warm reset.
+ *
+ * Note: only valid when bus_is_resetting returns true.
+ */
+bool bus_is_reset_cold(BusState *bus);
+
 void qdev_reset_all(DeviceState *dev);
 void qdev_reset_all_fn(void *opaque);
 
@@ -413,11 +492,6 @@ void qdev_machine_init(void);
  */
 void device_legacy_reset(DeviceState *dev);
 
-static inline void device_reset(DeviceState *dev)
-{
-    device_legacy_reset(dev);
-}
-
 void device_class_set_parent_reset(DeviceClass *dc,
                                    DeviceReset dev_reset,
                                    DeviceReset *parent_reset);
diff --git a/tests/Makefile.include b/tests/Makefile.include
index fd7fdb8658..1c0a5345b9 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -561,6 +561,7 @@ tests/fp/%:
 
 tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
 	hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
+	hw/core/resettable.o \
 	hw/core/bus.o \
 	hw/core/irq.o \
 	hw/core/fw-path-provider.o \
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (3 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-31  6:05   ` David Gibson
  2019-08-07 14:48   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state Damien Hedde
                   ` (28 subsequent siblings)
  33 siblings, 2 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Deprecate old reset apis and make them use the new one while they
are still used somewhere.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/qdev.c         | 22 +++-------------------
 include/hw/qdev-core.h | 28 ++++++++++++++++++++++------
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 559ced070d..e9e5f2d5f9 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -312,25 +312,9 @@ static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
     }
 }
 
-static int qdev_reset_one(DeviceState *dev, void *opaque)
-{
-    device_legacy_reset(dev);
-
-    return 0;
-}
-
-static int qbus_reset_one(BusState *bus, void *opaque)
-{
-    BusClass *bc = BUS_GET_CLASS(bus);
-    if (bc->reset) {
-        bc->reset(bus);
-    }
-    return 0;
-}
-
 void qdev_reset_all(DeviceState *dev)
 {
-    qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
+    device_reset(dev, false);
 }
 
 void qdev_reset_all_fn(void *opaque)
@@ -340,7 +324,7 @@ void qdev_reset_all_fn(void *opaque)
 
 void qbus_reset_all(BusState *bus)
 {
-    qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
+    bus_reset(bus, false);
 }
 
 void qbus_reset_all_fn(void *opaque)
@@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
             }
         }
         if (dev->hotplugged) {
-            device_legacy_reset(dev);
+            device_reset(dev, true);
         }
         dev->pending_deleted_event = false;
 
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index eeb75611c8..1670ae41bb 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -109,6 +109,11 @@ typedef struct DeviceClass {
     bool hotpluggable;
 
     /* callbacks */
+    /*
+     * Reset method here is deprecated and replaced by methods in the
+     * resettable class interface to implement a multi-phase reset.
+     * TODO: remove once every reset callback is unused
+     */
     DeviceReset reset;
     DeviceRealize realize;
     DeviceUnrealize unrealize;
@@ -455,19 +460,22 @@ bool bus_is_resetting(BusState *bus);
  */
 bool bus_is_reset_cold(BusState *bus);
 
-void qdev_reset_all(DeviceState *dev);
-void qdev_reset_all_fn(void *opaque);
-
 /**
- * @qbus_reset_all:
- * @bus: Bus to be reset.
+ * qbus/qdev_reset_all:
+ * @bus/dev: Bus/Device to be reset.
  *
- * Reset @bus and perform a bus-level ("hard") reset of all devices connected
+ * Reset @bus/dev and perform a bus-level reset of all devices/buses connected
  * to it, including recursive processing of all buses below @bus itself.  A
  * hard reset means that qbus_reset_all will reset all state of the device.
  * For PCI devices, for example, this will include the base address registers
  * or configuration space.
+ *
+ * Theses functions are deprecated, please use device/bus_reset or
+ * resettable_reset_* instead
+ * TODO: remove them when all occurence are removed
  */
+void qdev_reset_all(DeviceState *dev);
+void qdev_reset_all_fn(void *opaque);
 void qbus_reset_all(BusState *bus);
 void qbus_reset_all_fn(void *opaque);
 
@@ -489,9 +497,17 @@ void qdev_machine_init(void);
  * device_legacy_reset:
  *
  * Reset a single device (by calling the reset method).
+ *
+ * This function is deprecated, please use device_reset() instead.
+ * TODO: remove the function when all occurences are removed.
  */
 void device_legacy_reset(DeviceState *dev);
 
+/**
+ * device_class_set_parent_reset:
+ * TODO: remove the function when DeviceClass's reset method
+ * is not used anymore.
+ */
 void device_class_set_parent_reset(DeviceClass *dc,
                                    DeviceReset dev_reset,
                                    DeviceReset *parent_reset);
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (4 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-31  6:08   ` David Gibson
                     ` (2 more replies)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices Damien Hedde
                   ` (27 subsequent siblings)
  33 siblings, 3 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

It contains the resetting counter and cold flag status.

At this point, migration of bus reset related state (counter and cold/warm
flag) is handled by parent device. This done using the post_load
function in the vmsd subsection.

This is last point allow to add an initial support of migration with part of
qdev/qbus tree in reset state under the following condition:
+ time-lasting reset are asserted on Device only

Note that if this condition is not respected, migration will succeed and
no failure will occurs. The only impact is that the resetting counter
of a bus may lower afer a migration.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/Makefile.objs  |  1 +
 hw/core/qdev-vmstate.c | 45 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)
 create mode 100644 hw/core/qdev-vmstate.c

diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index d9234aa98a..49e9be0228 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -4,6 +4,7 @@ common-obj-y += bus.o reset.o
 common-obj-y += resettable.o
 common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
 common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
+common-obj-$(CONFIG_SOFTMMU) += qdev-vmstate.o
 # irq.o needed for qdev GPIO handling:
 common-obj-y += irq.o
 common-obj-y += hotplug.o
diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
new file mode 100644
index 0000000000..07b010811f
--- /dev/null
+++ b/hw/core/qdev-vmstate.c
@@ -0,0 +1,45 @@
+/*
+ * Device vmstate
+ *
+ * Copyright (c) 2019 GreenSocs
+ *
+ * Authors:
+ *   Damien Hedde
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev.h"
+#include "migration/vmstate.h"
+
+static bool device_vmstate_reset_needed(void *opaque)
+{
+    DeviceState *dev = (DeviceState *) opaque;
+    return dev->resetting != 0;
+}
+
+static int device_vmstate_reset_post_load(void *opaque, int version_id)
+{
+    DeviceState *dev = (DeviceState *) opaque;
+    BusState *bus;
+    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
+        bus->resetting = dev->resetting;
+        bus->reset_is_cold = dev->reset_is_cold;
+    }
+    return 0;
+}
+
+const struct VMStateDescription device_vmstate_reset = {
+    .name = "device_reset",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .needed = device_vmstate_reset_needed,
+    .post_load = device_vmstate_reset_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(resetting, DeviceState),
+        VMSTATE_BOOL(reset_is_cold, DeviceState),
+        VMSTATE_END_OF_LIST()
+    },
+};
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (5 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-07 15:07   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs Damien Hedde
                   ` (26 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

This add the reset related sections for every QOM
device.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/qdev-vmstate.c | 41 +++++++++++++++++++++++++++++++++++++++++
 hw/core/qdev.c         | 12 +++++++++++-
 include/hw/qdev-core.h |  3 +++
 stubs/Makefile.objs    |  1 +
 stubs/device.c         |  7 +++++++
 5 files changed, 63 insertions(+), 1 deletion(-)
 create mode 100644 stubs/device.c

diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
index 07b010811f..24f8465c61 100644
--- a/hw/core/qdev-vmstate.c
+++ b/hw/core/qdev-vmstate.c
@@ -43,3 +43,44 @@ const struct VMStateDescription device_vmstate_reset = {
         VMSTATE_END_OF_LIST()
     },
 };
+
+static VMStateDescription *vmsd_duplicate_and_append(
+        const VMStateDescription *old_vmsd,
+        const VMStateDescription *new_subsection)
+{
+    VMStateDescription *vmsd;
+    int n = 0;
+
+    assert(old_vmsd && new_subsection);
+
+    vmsd = (VMStateDescription *) g_memdup(old_vmsd, sizeof(*vmsd));
+
+    if (old_vmsd->subsections) {
+        while (old_vmsd->subsections[n]) {
+            n += 1;
+        }
+    }
+    vmsd->subsections = g_new(const VMStateDescription *, n + 2);
+
+    if (old_vmsd->subsections) {
+        memcpy(vmsd->subsections, old_vmsd->subsections,
+               sizeof(VMStateDescription *) * n);
+    }
+    vmsd->subsections[n] = new_subsection;
+    vmsd->subsections[n + 1] = NULL;
+
+    return vmsd;
+}
+
+void device_class_build_extended_vmsd(DeviceClass *dc)
+{
+    assert(dc->vmsd);
+    assert(!dc->vmsd_ext);
+
+    /* forge a subsection with proper name */
+    VMStateDescription *reset;
+    reset = g_memdup(&device_vmstate_reset, sizeof(*reset));
+    reset->name = g_strdup_printf("%s/device_reset", dc->vmsd->name);
+
+    dc->vmsd_ext = vmsd_duplicate_and_append(dc->vmsd, reset);
+}
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index e9e5f2d5f9..88387d3743 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -45,7 +45,17 @@ bool qdev_hot_removed = false;
 const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
-    return dc->vmsd;
+
+    if (!dc->vmsd) {
+        return NULL;
+    }
+
+    if (!dc->vmsd_ext) {
+        /* build it first time we need it */
+        device_class_build_extended_vmsd(dc);
+    }
+
+    return dc->vmsd_ext;
 }
 
 static void bus_remove_child(BusState *bus, DeviceState *child)
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 1670ae41bb..926d4bbcb1 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -120,6 +120,7 @@ typedef struct DeviceClass {
 
     /* device state */
     const struct VMStateDescription *vmsd;
+    const struct VMStateDescription *vmsd_ext;
 
     /* Private to qdev / bus.  */
     const char *bus_type;
@@ -520,6 +521,8 @@ void device_class_set_parent_unrealize(DeviceClass *dc,
 
 const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
 
+void device_class_build_extended_vmsd(DeviceClass *dc);
+
 const char *qdev_fw_name(DeviceState *dev);
 
 Object *qdev_get_machine(void);
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 9c7393b08c..432b56f290 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -40,4 +40,5 @@ stub-obj-y += pci-host-piix.o
 stub-obj-y += ram-block.o
 stub-obj-y += ramfb.o
 stub-obj-y += fw_cfg.o
+stub-obj-y += device.o
 stub-obj-$(CONFIG_SOFTMMU) += semihost.o
diff --git a/stubs/device.c b/stubs/device.c
new file mode 100644
index 0000000000..e9b4f57e5f
--- /dev/null
+++ b/stubs/device.c
@@ -0,0 +1,7 @@
+#include "qemu/osdep.h"
+#include "hw/qdev-core.h"
+
+void device_class_build_extended_vmsd(DeviceClass *dc)
+{
+    return;
+}
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (6 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-31  6:11   ` David Gibson
  2019-08-07 15:18   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface Damien Hedde
                   ` (25 subsequent siblings)
  33 siblings, 2 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

It adds the possibility to add 2 gpios to control the warm and cold reset.
With theses ios, the reset can be maintained during some time.
Each io is associated with a state to detect level changes.

Vmstate subsections are also added to the existsing device_reset
subsection.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/qdev-vmstate.c | 15 ++++++++++
 hw/core/qdev.c         | 65 ++++++++++++++++++++++++++++++++++++++++++
 include/hw/qdev-core.h | 57 ++++++++++++++++++++++++++++++++++++
 3 files changed, 137 insertions(+)

diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
index 24f8465c61..72f84c6cee 100644
--- a/hw/core/qdev-vmstate.c
+++ b/hw/core/qdev-vmstate.c
@@ -24,10 +24,23 @@ static int device_vmstate_reset_post_load(void *opaque, int version_id)
 {
     DeviceState *dev = (DeviceState *) opaque;
     BusState *bus;
+    uint32_t io_count = 0;
+
     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
         bus->resetting = dev->resetting;
         bus->reset_is_cold = dev->reset_is_cold;
     }
+
+    if (dev->cold_reset_input.state) {
+        io_count += 1;
+    }
+    if (dev->warm_reset_input.state) {
+        io_count += 1;
+    }
+    /* ensure resetting count is coherent with io states */
+    if (dev->resetting < io_count) {
+        return -1;
+    }
     return 0;
 }
 
@@ -40,6 +53,8 @@ const struct VMStateDescription device_vmstate_reset = {
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(resetting, DeviceState),
         VMSTATE_BOOL(reset_is_cold, DeviceState),
+        VMSTATE_BOOL(cold_reset_input.state, DeviceState),
+        VMSTATE_BOOL(warm_reset_input.state, DeviceState),
         VMSTATE_END_OF_LIST()
     },
 };
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 88387d3743..11a4de55ea 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -450,6 +450,67 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
     qdev_init_gpio_in_named(dev, handler, NULL, n);
 }
 
+static DeviceResetInputState *device_get_reset_input_state(DeviceState *dev,
+                                                            bool cold)
+{
+    return cold ? &dev->cold_reset_input : &dev->warm_reset_input;
+}
+
+static void device_reset_handler(DeviceState *dev, bool cold, bool level)
+{
+    DeviceResetInputState *dris = device_get_reset_input_state(dev, cold);
+
+    if (dris->type == DEVICE_RESET_ACTIVE_LOW) {
+        level = !level;
+    }
+
+    if (dris->state == level) {
+        /* io state has not changed */
+        return;
+    }
+
+    dris->state = level;
+
+    if (level) {
+        resettable_assert_reset(OBJECT(dev), cold);
+    } else {
+        resettable_deassert_reset(OBJECT(dev));
+    }
+}
+
+static void device_cold_reset_handler(void *opaque, int n, int level)
+{
+    device_reset_handler((DeviceState *) opaque, true, level);
+}
+
+static void device_warm_reset_handler(void *opaque, int n, int level)
+{
+    device_reset_handler((DeviceState *) opaque, false, level);
+}
+
+void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
+                                   bool cold, DeviceResetActiveType type)
+{
+    DeviceResetInputState *dris = device_get_reset_input_state(dev, cold);
+    qemu_irq_handler handler;
+
+    switch (type) {
+    case DEVICE_RESET_ACTIVE_LOW:
+    case DEVICE_RESET_ACTIVE_HIGH:
+        break;
+    default:
+        assert(false);
+        break;
+    }
+
+    assert(!dris->exists);
+    dris->exists = true;
+    dris->type = type;
+
+    handler = cold ? device_cold_reset_handler : device_warm_reset_handler;
+    qdev_init_gpio_in_named(dev, handler, name, 1);
+}
+
 void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
                               const char *name, int n)
 {
@@ -1007,6 +1068,10 @@ static void device_initfn(Object *obj)
     dev->instance_id_alias = -1;
     dev->realized = false;
     dev->resetting = 0;
+    dev->cold_reset_input.exists = false;
+    dev->cold_reset_input.state = false;
+    dev->warm_reset_input.exists = false;
+    dev->warm_reset_input.state = false;
 
     object_property_add_bool(obj, "realized",
                              device_get_realized, device_set_realized, NULL);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 926d4bbcb1..f724ddc8f4 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -136,6 +136,23 @@ struct NamedGPIOList {
     QLIST_ENTRY(NamedGPIOList) node;
 };
 
+typedef enum DeviceResetActiveType {
+    DEVICE_RESET_ACTIVE_LOW,
+    DEVICE_RESET_ACTIVE_HIGH,
+} DeviceResetActiveType;
+
+/**
+ * DeviceResetInputState:
+ * @exists: tell if io exists
+ * @type: tell whether the io active low or high
+ * @state: true if reset is currently active
+ */
+typedef struct DeviceResetInputState {
+    bool exists;
+    DeviceResetActiveType type;
+    bool state;
+} DeviceResetInputState;
+
 /**
  * DeviceState:
  * @realized: Indicates whether the device has been fully constructed.
@@ -143,6 +160,8 @@ struct NamedGPIOList {
  * used to count how many times reset has been initiated on the device.
  * @reset_is_cold: If the device is under reset, indicates whether it is cold
  * or warm.
+ * @cold_reset_input: state data for cold reset io
+ * @warm_reset_input: state data for warm reset io
  *
  * This structure should not be accessed directly.  We declare it here
  * so that it can be embedded in individual device state structures.
@@ -167,6 +186,8 @@ struct DeviceState {
     uint32_t resetting;
     bool reset_is_cold;
     bool reset_hold_needed;
+    DeviceResetInputState cold_reset_input;
+    DeviceResetInputState warm_reset_input;
 };
 
 struct DeviceListener {
@@ -372,6 +393,42 @@ static inline void qdev_init_gpio_in_named(DeviceState *dev,
 void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
                      const char *name);
 
+/**
+ * qdev_init_reset_gpio_in_named:
+ * Create a gpio controlling the warm or cold reset of the device.
+ *
+ * @cold: specify whether it triggers cold or warm reset
+ * @type: what kind of reset io it is
+ *
+ * Note: the io is considered created in its inactive state. No reset
+ * is started by this function.
+ */
+void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
+                                   bool cold, DeviceResetActiveType type);
+
+/**
+ * qdev_init_warm_reset_gpio:
+ * Create the input to control the device warm reset.
+ */
+static inline void qdev_init_warm_reset_gpio(DeviceState *dev,
+                                             const char *name,
+                                             DeviceResetActiveType type)
+{
+    qdev_init_reset_gpio_in_named(dev, name, false, type);
+}
+
+/**
+ * qdev_init_cold_reset_gpio:
+ * Create the input to control the device cold reset.
+ * It can also be used as a power gate control.
+ */
+static inline void qdev_init_cold_reset_gpio(DeviceState *dev,
+                                             const char *name,
+                                             DeviceResetActiveType type)
+{
+    qdev_init_reset_gpio_in_named(dev, name, true, type);
+}
+
 BusState *qdev_get_parent_bus(DeviceState *dev);
 
 /*** BUS API. ***/
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (7 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-31  6:30   ` David Gibson
                     ` (2 more replies)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 10/33] vl.c: remove qbus_reset_all registration Damien Hedde
                   ` (24 subsequent siblings)
  33 siblings, 3 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 docs/devel/reset.txt | 165 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 165 insertions(+)
 create mode 100644 docs/devel/reset.txt

diff --git a/docs/devel/reset.txt b/docs/devel/reset.txt
new file mode 100644
index 0000000000..c7a1eb068f
--- /dev/null
+++ b/docs/devel/reset.txt
@@ -0,0 +1,165 @@
+
+=====
+Reset
+=====
+
+The reset of qemu objects is handled using the Resettable interface declared
+in *include/hw/resettable.h*.
+As of now DeviceClass and BusClass implement this interface.
+
+
+Triggering reset
+----------------
+
+The function *resettable_reset* is used to trigger a reset on a given
+object.
+void resettable_reset(Object *obj, bool cold)
+
+The parameter *obj* must implement the Resettable interface.
+The parameter *cold* is a boolean specifying whether to do a cold or warm
+reset
+
+For Devices and Buses there is also the corresponding helpers:
+void device_reset(Device *dev, bool cold)
+void bus_reset(Device *dev, bool cold)
+
+If one wants to put an object into a reset state. There is the
+*resettable_assert_reset* function.
+void resettable_assert_reset(Object *obj, bool cold)
+
+One must eventually call the function *resettable_deassert_reset* to end the
+reset state:
+void resettable_deassert_reset(Object *obj, bool cold)
+
+Calling *resettable_assert_reset* then *resettable_deassert_reset* is the
+same as calling *resettable_reset*.
+
+It is possible to interleave multiple calls to
+ - resettable_reset,
+ - resettable_assert_reset, and
+ - resettable_deassert_reset.
+The only constraint is that *resettable_deassert_reset* must be called once
+per *resettable_assert_reset* call so that the object leaves the reset state.
+
+Therefore there may be several reset sources/controllers of a given object.
+The interface handle everything and the controllers do not need to know
+anything about each others. The object will leave reset state only when all
+controllers released their reset.
+
+All theses functions must called while holding the iothread lock.
+
+
+Implementing reset for a Resettable object : Multi-phase reset
+--------------------------------------------------------------
+
+The Resettable uses a multi-phase mechanism to handle some ordering constraints
+when resetting multiple object at the same time. For a given object the reset
+procedure is split into three different phases executed in order:
+ 1 INIT: This phase should set/reset the state of the Resettable it has when is
+         in reset state. Side-effects to others object is forbidden (such as
+         setting IO level).
+ 2 HOLD: This phase corresponds to the external side-effects due to staying into
+         the reset state.
+ 3 EXIT: This phase corresponds to leaving the reset state. It have both
+         local and external effects.
+
+*resettable_assert_reset* does the INIT and HOLD phases. While
+*resettable_deassert_reset* does the EXIT phase.
+
+When resetting multiple object at the same time. The interface executes the
+given phase of the objects before going to the next phase. This guarantee that
+all INIT phases are done before any HOLD phase and so on.
+
+There is three methods in the interface so must be implemented in an object.
+The methods corresponds to the three phases:
+```
+typedef void (*ResettableInitPhase)(Object *obj);
+typedef void (*ResettableHoldPhase)(Object *obj);
+typedef void (*ResettableExitPhase)(Object *obj);
+typedef struct ResettableClass {
+    InterfaceClass parent_class;
+
+    struct ResettablePhases {
+        ResettableInitPhase init;
+        ResettableHoldPhase hold;
+        ResettableExitPhase exit;
+    } phases;
+    [...]
+} ResettableClass;
+```
+
+Theses methods should be updated when specializing an object. For this the
+helper function *resettable_class_set_parent_reset_phases* can be used to
+backup parent methods while changing the specialized ones.
+void resettable_class_set_parent_reset_phases(ResettableClass *rc,
+                                              ResettableInitPhase init,
+                                              ResettableHoldPhase hold,
+                                              ResettableExitPhase exit,
+
+For Devices and Buses, some helper exists to know if a device/bus is under
+reset and what type of reset it is:
+```
+bool device_is_resetting(DeviceState *dev);
+bool device_is_reset_cold(DeviceState *dev);
+bool bus_is_resetting(BusState *bus);
+bool bus_is_reset_cold(BusState *bus);
+```
+
+
+Implementing the base Resettable behavior : Re-entrance, Hierarchy and Cold/Warm
+--------------------------------------------------------------------------------
+
+There is five others methods in the interface to handle the base mechanics
+of the Resettable interface. The methods should be implemented in object
+base class. DeviceClass and BusClass implement them.
+
+```
+typedef bool (*ResettableSetCold)(Object *obj, bool cold);
+typedef bool (*ResettableSetHoldNeeded)(Object *obj, bool hold_needed);
+typedef uint32_t (*ResettableGetCount)(Object *obj);
+typedef uint32_t (*ResettableIncrementCount)(Object *obj);
+typedef uint32_t (*ResettableDecrementCount)(Object *obj);
+typedef void (*ResettableForeachChild)(Object *obj, void (*visitor)(Object *));
+typedef struct ResettableClass {
+    InterfaceClass parent_class;
+
+    [...]
+
+    ResettableSetCold set_cold;
+    ResettableSetHoldNeeded set_hold_needed;
+    ResettableGetCount get_count;
+    ResettableIncrementCount increment_count;
+    ResettableDecrementCount decrement_count;
+    ResettableForeachChild foreach_child;
+} ResettableClass;
+```
+
+*set_cold* is used when entering reset, before calling the init phase, to
+indicate the reset type.
+
+*set_hold_needed* is used to set/clear and retrieve an "hold_needed" flag.
+This flag allows to omly execute the hold pahse when required.
+
+As stated above, several reset procedures can be concurrent on an object.
+This is handled with the three methods *get_count*, *increment_count* and
+*decrement_count*. An object is in reset state if the count is non-zero.
+
+The reset hierarchy is handled using the *foreach_child* method. This method
+executes a given function on every reset "child".
+
+In DeviceClass and BusClass the base behavior is to mimic the legacy qdev
+reset. Reset hierarchy follows the qdev/qbus tree.
+
+Reset control through GPIO
+--------------------------
+
+For devices, two reset inputs can be added: one for the cold, one the warm
+reset. This is done using the following function.
+```
+typedef enum DeviceResetActiveType {
+    DEVICE_RESET_ACTIVE_LOW,
+    DEVICE_RESET_ACTIVE_HIGH,
+} DeviceResetActiveType;
+void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
+                                   bool cold, DeviceResetActiveType type);
+```
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 10/33] vl.c: remove qbus_reset_all registration
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (8 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-07 15:20   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 11/33] hw/s390x/ipl.c: " Damien Hedde
                   ` (23 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace deprecated qbus_reset_all by resettable_reset_cold_fn for
the sysbus reset registration.
This does not impact the behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 vl.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/vl.c b/vl.c
index b426b32134..5a465c8236 100644
--- a/vl.c
+++ b/vl.c
@@ -4421,7 +4421,11 @@ int main(int argc, char **argv, char **envp)
 
     /* TODO: once all bus devices are qdevified, this should be done
      * when bus is created by qdev.c */
-    qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
+    /*
+     * TODO: when we have a main reset container/domain object, use
+     * it to fully benefit from multi-phase reset
+     */
+    qemu_register_reset(resettable_reset_cold_fn, sysbus_get_default());
     qemu_run_machine_init_done_notifiers();
 
     if (rom_check_and_register_reset() != 0) {
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 11/33] hw/s390x/ipl.c: remove qbus_reset_all registration
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (9 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 10/33] vl.c: remove qbus_reset_all registration Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-07 15:24   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 12/33] hw/pci/: remove qdev/qbus_reset_all call Damien Hedde
                   ` (22 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace deprecated qbus_reset_all by resettable_reset_cold_fn for
the ipl registration in the main reset handlers.

This does not impact the behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/s390x/ipl.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 60bd081d3e..402770a2c9 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -234,7 +234,11 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
      */
     ipl->compat_start_addr = ipl->start_addr;
     ipl->compat_bios_start_addr = ipl->bios_start_addr;
-    qemu_register_reset(qdev_reset_all_fn, dev);
+    /*
+     * TODO: when we add some kind of main reset container / domain
+     * switch to it to really benefit from multi-phase.
+     */
+    qemu_register_reset(resettable_reset_cold_fn, dev);
 error:
     error_propagate(errp, err);
 }
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 12/33] hw/pci/: remove qdev/qbus_reset_all call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (10 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 11/33] hw/s390x/ipl.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-07 15:31   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 13/33] hw/scsi/: " Damien Hedde
                   ` (21 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace deprecated qdev/bus_reset_all by device/bus_reset_warm.

This does not impact the behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/pci/pci.c        | 6 +++---
 hw/pci/pci_bridge.c | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 8076a80ab3..f2b9d37754 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -325,14 +325,14 @@ static void pci_do_device_reset(PCIDevice *dev)
  */
 void pci_device_reset(PCIDevice *dev)
 {
-    qdev_reset_all(&dev->qdev);
+    device_reset_warm(&dev->qdev);
     pci_do_device_reset(dev);
 }
 
 /*
  * Trigger pci bus reset under a given bus.
- * Called via qbus_reset_all on RST# assert, after the devices
- * have been reset qdev_reset_all-ed already.
+ * Called via bus_reset on RST# assert, after the devices
+ * have been reset device_reset-ed already.
  */
 static void pcibus_reset(BusState *qbus)
 {
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 715b9a4fe6..695242149f 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -274,7 +274,7 @@ void pci_bridge_write_config(PCIDevice *d,
     newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
     if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
         /* Trigger hot reset on 0->1 transition. */
-        qbus_reset_all(BUS(&s->sec_bus));
+        bus_reset_warm(BUS(&s->sec_bus));
     }
 }
 
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 13/33] hw/scsi/: remove qdev/qbus_reset_all call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (11 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 12/33] hw/pci/: remove qdev/qbus_reset_all call Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 14/33] hw/s390x/s390-virtio-ccw.c: remove qdev_reset_all call Damien Hedde
                   ` (20 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace deprecated qdev/bus_reset_all by device/bus_reset_warm.

This does not impact the behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/scsi/lsi53c895a.c  | 4 ++--
 hw/scsi/megasas.c     | 2 +-
 hw/scsi/mptsas.c      | 8 ++++----
 hw/scsi/spapr_vscsi.c | 2 +-
 hw/scsi/virtio-scsi.c | 6 +++---
 hw/scsi/vmw_pvscsi.c  | 4 ++--
 6 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 10468c1ec1..19197d1fc8 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -1861,7 +1861,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
         }
         if (val & LSI_SCNTL1_RST) {
             if (!(s->sstat0 & LSI_SSTAT0_RST)) {
-                qbus_reset_all(BUS(&s->bus));
+                bus_reset_warm(BUS(&s->bus));
                 s->sstat0 |= LSI_SSTAT0_RST;
                 lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
             }
@@ -1919,7 +1919,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
             lsi_execute_script(s);
         }
         if (val & LSI_ISTAT0_SRST) {
-            qdev_reset_all(DEVICE(s));
+            device_reset_warm(DEVICE(s));
         }
         break;
     case 0x16: /* MBOX0 */
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 0c4399930a..68c5538865 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1438,7 +1438,7 @@ static int megasas_cluster_reset_ld(MegasasState *s, MegasasCmd *cmd)
         MegasasCmd *tmp_cmd = &s->frames[i];
         if (tmp_cmd->req && tmp_cmd->req->dev->id == target_id) {
             SCSIDevice *d = tmp_cmd->req->dev;
-            qdev_reset_all(&d->qdev);
+            device_reset_warm(&d->qdev);
         }
     }
     return MFI_STAT_OK;
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
index 3f94d5ab55..9ae1ebc0f3 100644
--- a/hw/scsi/mptsas.c
+++ b/hw/scsi/mptsas.c
@@ -519,7 +519,7 @@ reply_maybe_async:
             reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;
             goto out;
         }
-        qdev_reset_all(&sdev->qdev);
+        device_reset_warm(&sdev->qdev);
         break;
 
     case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -535,13 +535,13 @@ reply_maybe_async:
         QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
             sdev = SCSI_DEVICE(kid->child);
             if (sdev->channel == 0 && sdev->id == req->TargetID) {
-                qdev_reset_all(kid->child);
+                device_reset_warm(kid->child);
             }
         }
         break;
 
     case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
-        qbus_reset_all(BUS(&s->bus));
+        bus_reset_warm(BUS(&s->bus));
         break;
 
     default:
@@ -804,7 +804,7 @@ static void mptsas_soft_reset(MPTSASState *s)
     s->intr_mask = MPI_HIM_DIM | MPI_HIM_RIM;
     mptsas_update_interrupt(s);
 
-    qbus_reset_all(BUS(&s->bus));
+    bus_reset_warm(BUS(&s->bus));
     s->intr_status = 0;
     s->intr_mask = save_mask;
 
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index 0e491c911d..39c6067f48 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -855,7 +855,7 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
                 break;
             }
 
-            qdev_reset_all(&d->qdev);
+            device_reset_warm(&d->qdev);
             break;
 
         case SRP_TSK_ABORT_TASK_SET:
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 8b9e5e2b49..fcf9e3dbde 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -317,7 +317,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
             goto incorrect_lun;
         }
         s->resetting++;
-        qdev_reset_all(&d->qdev);
+        device_reset_warm(&d->qdev);
         s->resetting--;
         break;
 
@@ -367,7 +367,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
         QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
              d = SCSI_DEVICE(kid->child);
              if (d->channel == 0 && d->id == target) {
-                qdev_reset_all(&d->qdev);
+                device_reset_warm(&d->qdev);
              }
         }
         s->resetting--;
@@ -697,7 +697,7 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
 
     assert(!s->dataplane_started);
     s->resetting++;
-    qbus_reset_all(BUS(&s->bus));
+    bus_reset_warm(BUS(&s->bus));
     s->resetting--;
 
     vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index cda3fc96a0..40fcf808a7 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -441,7 +441,7 @@ static void
 pvscsi_reset_adapter(PVSCSIState *s)
 {
     s->resetting++;
-    qbus_reset_all(BUS(&s->bus));
+    bus_reset_warm(BUS(&s->bus));
     s->resetting--;
     pvscsi_process_completion_queue(s);
     assert(QTAILQ_EMPTY(&s->pending_queue));
@@ -849,7 +849,7 @@ pvscsi_on_cmd_reset_bus(PVSCSIState *s)
     trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_RESET_BUS");
 
     s->resetting++;
-    qbus_reset_all(BUS(&s->bus));
+    bus_reset_warm(BUS(&s->bus));
     s->resetting--;
     return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
 }
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 14/33] hw/s390x/s390-virtio-ccw.c: remove qdev_reset_all call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (12 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 13/33] hw/scsi/: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-08 10:50   ` Cornelia Huck
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 15/33] hw/ide/piix.c: " Damien Hedde
                   ` (19 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace deprecated qdev_reset_all by device_reset_warm.

This does not impact the behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/s390x/s390-virtio-ccw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 5b6a9a4e55..1d6b966817 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -104,7 +104,7 @@ static void subsystem_reset(void)
     for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) {
         dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL));
         if (dev) {
-            qdev_reset_all(dev);
+            device_reset_warm(dev);
         }
     }
 }
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 15/33] hw/ide/piix.c: remove qdev_reset_all call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (13 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 14/33] hw/s390x/s390-virtio-ccw.c: remove qdev_reset_all call Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 16/33] hw/input/adb.c: " Damien Hedde
                   ` (18 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace deprecated qdev_reset_all by device_reset_warm.

This does not impact the behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/ide/piix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index b97e555072..64cb4a52ef 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -196,7 +196,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev, bool aux)
             blk_unref(blk);
         }
     }
-    qdev_reset_all(DEVICE(dev));
+    device_reset_warm(DEVICE(dev));
     return 0;
 }
 
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 16/33] hw/input/adb.c: remove qdev_reset_all call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (14 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 15/33] hw/ide/piix.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 17/33] hw/usb/dev-uas.c: " Damien Hedde
                   ` (17 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace deprecated qdev_reset_all by device_reset_warm.

This does not impact the behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/input/adb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/input/adb.c b/hw/input/adb.c
index 1446f32521..6b35682aba 100644
--- a/hw/input/adb.c
+++ b/hw/input/adb.c
@@ -32,7 +32,7 @@
 
 static void adb_device_reset(ADBDevice *d)
 {
-    qdev_reset_all(DEVICE(d));
+    device_reset_warm(DEVICE(d));
 }
 
 int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 17/33] hw/usb/dev-uas.c: remove qdev_reset_all call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (15 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 16/33] hw/input/adb.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 18/33] hw/audio/intel-hda.c: remove device_legacy_reset call Damien Hedde
                   ` (16 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace deprecated qdev_reset_all by device_reset_warm.

This does not impact the behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/usb/dev-uas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index abd8070d0c..b3a6e470e4 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -777,7 +777,7 @@ static void usb_uas_task(UASDevice *uas, uas_iu *iu)
 
     case UAS_TMF_LOGICAL_UNIT_RESET:
         trace_usb_uas_tmf_logical_unit_reset(uas->dev.addr, tag, lun);
-        qdev_reset_all(&dev->qdev);
+        device_reset_warm(&dev->qdev);
         usb_uas_queue_response(uas, tag, UAS_RC_TMF_COMPLETE);
         break;
 
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 18/33] hw/audio/intel-hda.c: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (16 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 17/33] hw/usb/dev-uas.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 19/33] hw/sd/pl181.c & omap_mmc.c: " Damien Hedde
                   ` (15 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace legacy's reset call by device_reset_warm.

The new function propagates also the reset to the sub-buses tree but this has
no impact since since HDACodecDevice has no child bus.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/audio/intel-hda.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index f133684b10..523bb3e2ca 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -1086,7 +1086,7 @@ static void intel_hda_reset(DeviceState *dev)
     QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
         DeviceState *qdev = kid->child;
         cdev = HDA_CODEC_DEVICE(qdev);
-        device_legacy_reset(DEVICE(cdev));
+        device_reset_warm(DEVICE(cdev));
         d->state_sts |= (1 << cdev->cad);
     }
     intel_hda_update_irq(d);
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 19/33] hw/sd/pl181.c & omap_mmc.c: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (17 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 18/33] hw/audio/intel-hda.c: remove device_legacy_reset call Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-31 15:48   ` Philippe Mathieu-Daudé
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 20/33] hw/hyperv/hyperv.c: " Damien Hedde
                   ` (14 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace legacy's reset call by device_reset_warm.

The new function propagates also the reset to the sub-buses tree but this has
no impact since SDState has no child bus.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/sd/omap_mmc.c | 2 +-
 hw/sd/pl181.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index 24a1edc149..3021e54b8d 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -317,7 +317,7 @@ void omap_mmc_reset(struct omap_mmc_s *host)
      * into any bus, and we must reset it manually. When omap_mmc is
      * QOMified this must move into the QOM reset function.
      */
-    device_legacy_reset(DEVICE(host->card));
+    device_reset_warm(DEVICE(host->card));
 }
 
 static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 15b4aaa67f..a59ef7eb2a 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -480,7 +480,7 @@ static void pl181_reset(DeviceState *d)
     /* Since we're still using the legacy SD API the card is not plugged
      * into any bus, and we must reset it manually.
      */
-    device_legacy_reset(DEVICE(s->card));
+    device_reset_warm(DEVICE(s->card));
 }
 
 static void pl181_init(Object *obj)
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 20/33] hw/hyperv/hyperv.c: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (18 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 19/33] hw/sd/pl181.c & omap_mmc.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 21/33] hw/intc/spapr_xive.c: " Damien Hedde
                   ` (13 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace legacy's reset call by device_reset_warm in
*hyperv_synic_reset*.

The new function propagates also the reset to the sub-buses tree but this has
no impact since SynICState has no child bus.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/hyperv/hyperv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index cd9db3cb5c..ae377934ee 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -140,7 +140,7 @@ void hyperv_synic_reset(CPUState *cs)
     SynICState *synic = get_synic(cs);
 
     if (synic) {
-        device_legacy_reset(DEVICE(synic));
+        device_reset_warm(DEVICE(synic));
     }
 }
 
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 21/33] hw/intc/spapr_xive.c: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (19 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 20/33] hw/hyperv/hyperv.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 22/33] hw/ppc/pnv_psi.c: " Damien Hedde
                   ` (12 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace legacy's reset call by device_reset_warm.

The new function propagates also the reset to the sub-buses tree but this has
no impact since SpaprXive has no child bus.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/intc/spapr_xive.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 22e11ad10c..fbd7ddb06e 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -1511,7 +1511,7 @@ static target_ulong h_int_reset(PowerPCCPU *cpu,
         return H_PARAMETER;
     }
 
-    device_legacy_reset(DEVICE(xive));
+    device_reset_warm(DEVICE(xive));
 
     if (kvm_irqchip_in_kernel()) {
         Error *local_err = NULL;
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 22/33] hw/ppc/pnv_psi.c: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (20 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 21/33] hw/intc/spapr_xive.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 23/33] hw/scsi/vmw_pvscsi.c: " Damien Hedde
                   ` (11 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace legacy's reset call by device_reset_warm.

The new function propagates also the reset to the sub-buses tree but this has
no impact since XiveSource has no child bus.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/ppc/pnv_psi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 78eafa353a..c17e83abe5 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -703,7 +703,7 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
         break;
     case PSIHB9_INTERRUPT_CONTROL:
         if (val & PSIHB9_IRQ_RESET) {
-            device_legacy_reset(DEVICE(&psi9->source));
+            device_reset_warm(DEVICE(&psi9->source));
         }
         psi->regs[reg] = val;
         break;
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 23/33] hw/scsi/vmw_pvscsi.c: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (21 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 22/33] hw/ppc/pnv_psi.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 24/33] hw/ppc/spapr: " Damien Hedde
                   ` (10 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace legacy's reset call by device_reset_warm.

The new function propagates also the reset to the sub-buses tree but this has
no impact since SCSIDevices have no child bus (neither generic device nor
disks).

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/scsi/vmw_pvscsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 40fcf808a7..5be2227cc8 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -835,7 +835,7 @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
 
     if (sdev != NULL) {
         s->resetting++;
-        device_legacy_reset(&sdev->qdev);
+        device_reset_warm(&sdev->qdev);
         s->resetting--;
         return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
     }
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 24/33] hw/ppc/spapr: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (22 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 23/33] hw/scsi/vmw_pvscsi.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 25/33] hw/i386/pc.c: " Damien Hedde
                   ` (9 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace legacy's reset call by device_reset_warm.

The new function propagates also the reset to the sub-buses tree.

In spapr_vio.c, the function resets a SpaprtceTable which does not seem
to have child bus so it should have no impact.

In Spapr_pci.c the functions resets QOM children devices of a SpaprPhbState.
If there is a device with a child bus, then this bus will now be reset
(and all its qdev tree).

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/ppc/spapr_pci.c | 2 +-
 hw/ppc/spapr_vio.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 3c6cf79a5e..946b2b4483 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -2029,7 +2029,7 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
     DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
 
     if (dev) {
-        device_legacy_reset(dev);
+        device_reset_warm(dev);
     }
 
     return 0;
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 5a0b5cc35c..41c17cfdd6 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -306,7 +306,7 @@ int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
 static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
 {
     if (dev->tcet) {
-        device_legacy_reset(DEVICE(dev->tcet));
+        device_reset_warm(DEVICE(dev->tcet));
     }
     free_crq(dev);
 }
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 25/33] hw/i386/pc.c: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (23 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 24/33] hw/ppc/spapr: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 26/33] hw/s390x/s390-pci-inst.c: " Damien Hedde
                   ` (8 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace additional APIC legacy reset by device_reset_cold.

The new function propagates also the reset to the sub-buses tree.
APIC does not have any so it should have no impact on behavior.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/i386/pc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c0f20fe8aa..a175d76819 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -2823,7 +2823,7 @@ static void pc_machine_reset(MachineState *machine)
         cpu = X86_CPU(cs);
 
         if (cpu->apic_state) {
-            device_legacy_reset(cpu->apic_state);
+            device_reset_cold(cpu->apic_state);
         }
     }
 }
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 26/33] hw/s390x/s390-pci-inst.c: remove device_legacy_reset call
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (24 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 25/33] hw/i386/pc.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-08 10:52   ` Cornelia Huck
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 27/33] hw/ide/microdrive.c: remove device_legacy_reset calls Damien Hedde
                   ` (7 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace S390PCIBusDevice legacy reset by device_reset_warm.

The new function propagates also the reset to the sub-buses tree.
I'm not sure whether S390PCIBusDevice has bus children or not.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/s390x/s390-pci-inst.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 93cda37c27..d7bca68245 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -242,7 +242,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
                 stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
                 goto out;
             }
-            device_legacy_reset(DEVICE(pbdev));
+            device_reset_warm(DEVICE(pbdev));
             pbdev->fh &= ~FH_MASK_ENABLE;
             pbdev->state = ZPCI_FS_DISABLED;
             stl_p(&ressetpci->fh, pbdev->fh);
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 27/33] hw/ide/microdrive.c: remove device_legacy_reset calls
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (25 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 26/33] hw/s390x/s390-pci-inst.c: " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 28/33] qdev: Remove unused deprecated reset functions Damien Hedde
                   ` (6 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Replace MicroDriveState legacy reset by device_reset_warm.

The new function propagates also the reset to the sub-buses tree.
The MicroDriveState has a child bus so it is now reset automatically
as well as all the qdev sub tree. It seems to me that IDE_BUS and
IDE_DEVICEs reset methods are not implemented so resetting the
qdev/qbus ide tree will have no effect.

Keep the explicit call to ide_bus_reset (in md_reset function) since
it is not called when using the standard reset method of the IDE_BUS
object.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/ide/microdrive.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index fc346f5ad5..afe2342da8 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -173,7 +173,7 @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
     case 0x00:	/* Configuration Option Register */
         s->opt = value & 0xcf;
         if (value & OPT_SRESET) {
-            device_legacy_reset(DEVICE(s));
+            device_reset_warm(DEVICE(s));
         }
         md_interrupt_update(s);
         break;
@@ -316,7 +316,7 @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
     case 0xe:	/* Device Control */
         s->ctrl = value;
         if (value & CTRL_SRST) {
-            device_legacy_reset(DEVICE(s));
+            device_reset_warm(DEVICE(s));
         }
         md_interrupt_update(s);
         break;
@@ -541,7 +541,7 @@ static int dscm1xxxx_attach(PCMCIACardState *card)
     md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
     md->io_base = 0x0;
 
-    device_legacy_reset(DEVICE(md));
+    device_reset_warm(DEVICE(md));
     md_interrupt_update(md);
 
     return 0;
@@ -551,7 +551,7 @@ static int dscm1xxxx_detach(PCMCIACardState *card)
 {
     MicroDriveState *md = MICRODRIVE(card);
 
-    device_legacy_reset(DEVICE(md));
+    device_reset_warm(DEVICE(md));
     return 0;
 }
 
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 28/33] qdev: Remove unused deprecated reset functions
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (26 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 27/33] hw/ide/microdrive.c: remove device_legacy_reset calls Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-07 15:29   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 29/33] hw/misc/zynq_slcr: use standard register definition Damien Hedde
                   ` (5 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Remove the functions now they are unused:
+ device_legacy_reset
+ qdev_reset_all[_fn]
+ qbus_reset_all[_fn]

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/qdev.c         | 30 ------------------------------
 include/hw/qdev-core.h | 29 -----------------------------
 2 files changed, 59 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 11a4de55ea..896b55f7ba 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -322,27 +322,6 @@ static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
     }
 }
 
-void qdev_reset_all(DeviceState *dev)
-{
-    device_reset(dev, false);
-}
-
-void qdev_reset_all_fn(void *opaque)
-{
-    qdev_reset_all(DEVICE(opaque));
-}
-
-void qbus_reset_all(BusState *bus)
-{
-    bus_reset(bus, false);
-}
-
-void qbus_reset_all_fn(void *opaque)
-{
-    BusState *bus = opaque;
-    qbus_reset_all(bus);
-}
-
 /* can be used as ->unplug() callback for the simple cases */
 void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
                                   DeviceState *dev, Error **errp)
@@ -1223,15 +1202,6 @@ void device_class_set_parent_unrealize(DeviceClass *dc,
     dc->unrealize = dev_unrealize;
 }
 
-void device_legacy_reset(DeviceState *dev)
-{
-    DeviceClass *klass = DEVICE_GET_CLASS(dev);
-
-    if (klass->reset) {
-        klass->reset(dev);
-    }
-}
-
 Object *qdev_get_machine(void)
 {
     static Object *dev;
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index f724ddc8f4..eb6370970e 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -518,25 +518,6 @@ bool bus_is_resetting(BusState *bus);
  */
 bool bus_is_reset_cold(BusState *bus);
 
-/**
- * qbus/qdev_reset_all:
- * @bus/dev: Bus/Device to be reset.
- *
- * Reset @bus/dev and perform a bus-level reset of all devices/buses connected
- * to it, including recursive processing of all buses below @bus itself.  A
- * hard reset means that qbus_reset_all will reset all state of the device.
- * For PCI devices, for example, this will include the base address registers
- * or configuration space.
- *
- * Theses functions are deprecated, please use device/bus_reset or
- * resettable_reset_* instead
- * TODO: remove them when all occurence are removed
- */
-void qdev_reset_all(DeviceState *dev);
-void qdev_reset_all_fn(void *opaque);
-void qbus_reset_all(BusState *bus);
-void qbus_reset_all_fn(void *opaque);
-
 /* This should go away once we get rid of the NULL bus hack */
 BusState *sysbus_get_default(void);
 
@@ -551,16 +532,6 @@ char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
  */
 void qdev_machine_init(void);
 
-/**
- * device_legacy_reset:
- *
- * Reset a single device (by calling the reset method).
- *
- * This function is deprecated, please use device_reset() instead.
- * TODO: remove the function when all occurences are removed.
- */
-void device_legacy_reset(DeviceState *dev);
-
 /**
  * device_class_set_parent_reset:
  * TODO: remove the function when DeviceClass's reset method
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 29/33] hw/misc/zynq_slcr: use standard register definition
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (27 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 28/33] qdev: Remove unused deprecated reset functions Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-08-07 15:33   ` Peter Maydell
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 30/33] convert cadence_uart to 3-phases reset Damien Hedde
                   ` (4 subsequent siblings)
  33 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, Alistair Francis, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, rth,
	Philippe Mathieu-Daudé,
	thuth, ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow,
	david, Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc,
	pbonzini

Replace the zynq_slcr registers enum and macros using the
hw/registerfields.h macros.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
 hw/misc/zynq_slcr.c | 472 ++++++++++++++++++++++----------------------
 1 file changed, 236 insertions(+), 236 deletions(-)

diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 6b51ae5ff1..dd766a6779 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -21,6 +21,7 @@
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "hw/registerfields.h"
 
 #ifndef ZYNQ_SLCR_ERR_DEBUG
 #define ZYNQ_SLCR_ERR_DEBUG 0
@@ -36,138 +37,135 @@
 #define XILINX_LOCK_KEY 0x767b
 #define XILINX_UNLOCK_KEY 0xdf0d
 
-#define R_PSS_RST_CTRL_SOFT_RST 0x1
-
-enum {
-    SCL             = 0x000 / 4,
-    LOCK,
-    UNLOCK,
-    LOCKSTA,
-
-    ARM_PLL_CTRL    = 0x100 / 4,
-    DDR_PLL_CTRL,
-    IO_PLL_CTRL,
-    PLL_STATUS,
-    ARM_PLL_CFG,
-    DDR_PLL_CFG,
-    IO_PLL_CFG,
-
-    ARM_CLK_CTRL    = 0x120 / 4,
-    DDR_CLK_CTRL,
-    DCI_CLK_CTRL,
-    APER_CLK_CTRL,
-    USB0_CLK_CTRL,
-    USB1_CLK_CTRL,
-    GEM0_RCLK_CTRL,
-    GEM1_RCLK_CTRL,
-    GEM0_CLK_CTRL,
-    GEM1_CLK_CTRL,
-    SMC_CLK_CTRL,
-    LQSPI_CLK_CTRL,
-    SDIO_CLK_CTRL,
-    UART_CLK_CTRL,
-    SPI_CLK_CTRL,
-    CAN_CLK_CTRL,
-    CAN_MIOCLK_CTRL,
-    DBG_CLK_CTRL,
-    PCAP_CLK_CTRL,
-    TOPSW_CLK_CTRL,
+REG32(SCL, 0x000)
+REG32(LOCK, 0x004)
+REG32(UNLOCK, 0x008)
+REG32(LOCKSTA, 0x00c)
+
+REG32(ARM_PLL_CTRL, 0x100)
+REG32(DDR_PLL_CTRL, 0x104)
+REG32(IO_PLL_CTRL, 0x108)
+REG32(PLL_STATUS, 0x10c)
+REG32(ARM_PLL_CFG, 0x110)
+REG32(DDR_PLL_CFG, 0x114)
+REG32(IO_PLL_CFG, 0x118)
+
+REG32(ARM_CLK_CTRL, 0x120)
+REG32(DDR_CLK_CTRL, 0x124)
+REG32(DCI_CLK_CTRL, 0x128)
+REG32(APER_CLK_CTRL, 0x12c)
+REG32(USB0_CLK_CTRL, 0x130)
+REG32(USB1_CLK_CTRL, 0x134)
+REG32(GEM0_RCLK_CTRL, 0x138)
+REG32(GEM1_RCLK_CTRL, 0x13c)
+REG32(GEM0_CLK_CTRL, 0x140)
+REG32(GEM1_CLK_CTRL, 0x144)
+REG32(SMC_CLK_CTRL, 0x148)
+REG32(LQSPI_CLK_CTRL, 0x14c)
+REG32(SDIO_CLK_CTRL, 0x150)
+REG32(UART_CLK_CTRL, 0x154)
+REG32(SPI_CLK_CTRL, 0x158)
+REG32(CAN_CLK_CTRL, 0x15c)
+REG32(CAN_MIOCLK_CTRL, 0x160)
+REG32(DBG_CLK_CTRL, 0x164)
+REG32(PCAP_CLK_CTRL, 0x168)
+REG32(TOPSW_CLK_CTRL, 0x16c)
 
 #define FPGA_CTRL_REGS(n, start) \
-    FPGA ## n ## _CLK_CTRL = (start) / 4, \
-    FPGA ## n ## _THR_CTRL, \
-    FPGA ## n ## _THR_CNT, \
-    FPGA ## n ## _THR_STA,
-    FPGA_CTRL_REGS(0, 0x170)
-    FPGA_CTRL_REGS(1, 0x180)
-    FPGA_CTRL_REGS(2, 0x190)
-    FPGA_CTRL_REGS(3, 0x1a0)
-
-    BANDGAP_TRIP    = 0x1b8 / 4,
-    PLL_PREDIVISOR  = 0x1c0 / 4,
-    CLK_621_TRUE,
-
-    PSS_RST_CTRL    = 0x200 / 4,
-    DDR_RST_CTRL,
-    TOPSW_RESET_CTRL,
-    DMAC_RST_CTRL,
-    USB_RST_CTRL,
-    GEM_RST_CTRL,
-    SDIO_RST_CTRL,
-    SPI_RST_CTRL,
-    CAN_RST_CTRL,
-    I2C_RST_CTRL,
-    UART_RST_CTRL,
-    GPIO_RST_CTRL,
-    LQSPI_RST_CTRL,
-    SMC_RST_CTRL,
-    OCM_RST_CTRL,
-    FPGA_RST_CTRL   = 0x240 / 4,
-    A9_CPU_RST_CTRL,
-
-    RS_AWDT_CTRL    = 0x24c / 4,
-    RST_REASON,
-
-    REBOOT_STATUS   = 0x258 / 4,
-    BOOT_MODE,
-
-    APU_CTRL        = 0x300 / 4,
-    WDT_CLK_SEL,
-
-    TZ_DMA_NS       = 0x440 / 4,
-    TZ_DMA_IRQ_NS,
-    TZ_DMA_PERIPH_NS,
-
-    PSS_IDCODE      = 0x530 / 4,
-
-    DDR_URGENT      = 0x600 / 4,
-    DDR_CAL_START   = 0x60c / 4,
-    DDR_REF_START   = 0x614 / 4,
-    DDR_CMD_STA,
-    DDR_URGENT_SEL,
-    DDR_DFI_STATUS,
-
-    MIO             = 0x700 / 4,
+    REG32(FPGA ## n ## _CLK_CTRL, (start)) \
+    REG32(FPGA ## n ## _THR_CTRL, (start) + 0x4)\
+    REG32(FPGA ## n ## _THR_CNT,  (start) + 0x8)\
+    REG32(FPGA ## n ## _THR_STA,  (start) + 0xc)
+FPGA_CTRL_REGS(0, 0x170)
+FPGA_CTRL_REGS(1, 0x180)
+FPGA_CTRL_REGS(2, 0x190)
+FPGA_CTRL_REGS(3, 0x1a0)
+
+REG32(BANDGAP_TRIP, 0x1b8)
+REG32(PLL_PREDIVISOR, 0x1c0)
+REG32(CLK_621_TRUE, 0x1c4)
+
+REG32(PSS_RST_CTRL, 0x200)
+    FIELD(PSS_RST_CTRL, SOFT_RST, 0, 1)
+REG32(DDR_RST_CTRL, 0x204)
+REG32(TOPSW_RESET_CTRL, 0x208)
+REG32(DMAC_RST_CTRL, 0x20c)
+REG32(USB_RST_CTRL, 0x210)
+REG32(GEM_RST_CTRL, 0x214)
+REG32(SDIO_RST_CTRL, 0x218)
+REG32(SPI_RST_CTRL, 0x21c)
+REG32(CAN_RST_CTRL, 0x220)
+REG32(I2C_RST_CTRL, 0x224)
+REG32(UART_RST_CTRL, 0x228)
+REG32(GPIO_RST_CTRL, 0x22c)
+REG32(LQSPI_RST_CTRL, 0x230)
+REG32(SMC_RST_CTRL, 0x234)
+REG32(OCM_RST_CTRL, 0x238)
+REG32(FPGA_RST_CTRL, 0x240)
+REG32(A9_CPU_RST_CTRL, 0x244)
+
+REG32(RS_AWDT_CTRL, 0x24c)
+REG32(RST_REASON, 0x250)
+
+REG32(REBOOT_STATUS, 0x258)
+REG32(BOOT_MODE, 0x25c)
+
+REG32(APU_CTRL, 0x300)
+REG32(WDT_CLK_SEL, 0x304)
+
+REG32(TZ_DMA_NS, 0x440)
+REG32(TZ_DMA_IRQ_NS, 0x444)
+REG32(TZ_DMA_PERIPH_NS, 0x448)
+
+REG32(PSS_IDCODE, 0x530)
+
+REG32(DDR_URGENT, 0x600)
+REG32(DDR_CAL_START, 0x60c)
+REG32(DDR_REF_START, 0x614)
+REG32(DDR_CMD_STA, 0x618)
+REG32(DDR_URGENT_SEL, 0x61c)
+REG32(DDR_DFI_STATUS, 0x620)
+
+REG32(MIO, 0x700)
 #define MIO_LENGTH 54
 
-    MIO_LOOPBACK    = 0x804 / 4,
-    MIO_MST_TRI0,
-    MIO_MST_TRI1,
+REG32(MIO_LOOPBACK, 0x804)
+REG32(MIO_MST_TRI0, 0x808)
+REG32(MIO_MST_TRI1, 0x80c)
 
-    SD0_WP_CD_SEL   = 0x830 / 4,
-    SD1_WP_CD_SEL,
+REG32(SD0_WP_CD_SEL, 0x830)
+REG32(SD1_WP_CD_SEL, 0x834)
 
-    LVL_SHFTR_EN    = 0x900 / 4,
-    OCM_CFG         = 0x910 / 4,
+REG32(LVL_SHFTR_EN, 0x900)
+REG32(OCM_CFG, 0x910)
 
-    CPU_RAM         = 0xa00 / 4,
+REG32(CPU_RAM, 0xa00)
 
-    IOU             = 0xa30 / 4,
+REG32(IOU, 0xa30)
 
-    DMAC_RAM        = 0xa50 / 4,
+REG32(DMAC_RAM, 0xa50)
 
-    AFI0            = 0xa60 / 4,
-    AFI1 = AFI0 + 3,
-    AFI2 = AFI1 + 3,
-    AFI3 = AFI2 + 3,
+REG32(AFI0, 0xa60)
+REG32(AFI1, 0xa6c)
+REG32(AFI2, 0xa78)
+REG32(AFI3, 0xa84)
 #define AFI_LENGTH 3
 
-    OCM             = 0xa90 / 4,
+REG32(OCM, 0xa90)
 
-    DEVCI_RAM       = 0xaa0 / 4,
+REG32(DEVCI_RAM, 0xaa0)
 
-    CSG_RAM         = 0xab0 / 4,
+REG32(CSG_RAM, 0xab0)
 
-    GPIOB_CTRL      = 0xb00 / 4,
-    GPIOB_CFG_CMOS18,
-    GPIOB_CFG_CMOS25,
-    GPIOB_CFG_CMOS33,
-    GPIOB_CFG_HSTL  = 0xb14 / 4,
-    GPIOB_DRVR_BIAS_CTRL,
+REG32(GPIOB_CTRL, 0xb00)
+REG32(GPIOB_CFG_CMOS18, 0xb04)
+REG32(GPIOB_CFG_CMOS25, 0xb08)
+REG32(GPIOB_CFG_CMOS33, 0xb0c)
+REG32(GPIOB_CFG_HSTL, 0xb14)
+REG32(GPIOB_DRVR_BIAS_CTRL, 0xb18)
 
-    DDRIOB          = 0xb40 / 4,
+REG32(DDRIOB, 0xb40)
 #define DDRIOB_LENGTH 14
-};
 
 #define ZYNQ_SLCR_MMIO_SIZE     0x1000
 #define ZYNQ_SLCR_NUM_REGS      (ZYNQ_SLCR_MMIO_SIZE / 4)
@@ -190,150 +188,152 @@ static void zynq_slcr_reset(DeviceState *d)
 
     DB_PRINT("RESET\n");
 
-    s->regs[LOCKSTA] = 1;
+    s->regs[R_LOCKSTA] = 1;
     /* 0x100 - 0x11C */
-    s->regs[ARM_PLL_CTRL]   = 0x0001A008;
-    s->regs[DDR_PLL_CTRL]   = 0x0001A008;
-    s->regs[IO_PLL_CTRL]    = 0x0001A008;
-    s->regs[PLL_STATUS]     = 0x0000003F;
-    s->regs[ARM_PLL_CFG]    = 0x00014000;
-    s->regs[DDR_PLL_CFG]    = 0x00014000;
-    s->regs[IO_PLL_CFG]     = 0x00014000;
+    s->regs[R_ARM_PLL_CTRL]   = 0x0001A008;
+    s->regs[R_DDR_PLL_CTRL]   = 0x0001A008;
+    s->regs[R_IO_PLL_CTRL]    = 0x0001A008;
+    s->regs[R_PLL_STATUS]     = 0x0000003F;
+    s->regs[R_ARM_PLL_CFG]    = 0x00014000;
+    s->regs[R_DDR_PLL_CFG]    = 0x00014000;
+    s->regs[R_IO_PLL_CFG]     = 0x00014000;
 
     /* 0x120 - 0x16C */
-    s->regs[ARM_CLK_CTRL]   = 0x1F000400;
-    s->regs[DDR_CLK_CTRL]   = 0x18400003;
-    s->regs[DCI_CLK_CTRL]   = 0x01E03201;
-    s->regs[APER_CLK_CTRL]  = 0x01FFCCCD;
-    s->regs[USB0_CLK_CTRL]  = s->regs[USB1_CLK_CTRL]    = 0x00101941;
-    s->regs[GEM0_RCLK_CTRL] = s->regs[GEM1_RCLK_CTRL]   = 0x00000001;
-    s->regs[GEM0_CLK_CTRL]  = s->regs[GEM1_CLK_CTRL]    = 0x00003C01;
-    s->regs[SMC_CLK_CTRL]   = 0x00003C01;
-    s->regs[LQSPI_CLK_CTRL] = 0x00002821;
-    s->regs[SDIO_CLK_CTRL]  = 0x00001E03;
-    s->regs[UART_CLK_CTRL]  = 0x00003F03;
-    s->regs[SPI_CLK_CTRL]   = 0x00003F03;
-    s->regs[CAN_CLK_CTRL]   = 0x00501903;
-    s->regs[DBG_CLK_CTRL]   = 0x00000F03;
-    s->regs[PCAP_CLK_CTRL]  = 0x00000F01;
+    s->regs[R_ARM_CLK_CTRL]   = 0x1F000400;
+    s->regs[R_DDR_CLK_CTRL]   = 0x18400003;
+    s->regs[R_DCI_CLK_CTRL]   = 0x01E03201;
+    s->regs[R_APER_CLK_CTRL]  = 0x01FFCCCD;
+    s->regs[R_USB0_CLK_CTRL]  = s->regs[R_USB1_CLK_CTRL]  = 0x00101941;
+    s->regs[R_GEM0_RCLK_CTRL] = s->regs[R_GEM1_RCLK_CTRL] = 0x00000001;
+    s->regs[R_GEM0_CLK_CTRL]  = s->regs[R_GEM1_CLK_CTRL]  = 0x00003C01;
+    s->regs[R_SMC_CLK_CTRL]   = 0x00003C01;
+    s->regs[R_LQSPI_CLK_CTRL] = 0x00002821;
+    s->regs[R_SDIO_CLK_CTRL]  = 0x00001E03;
+    s->regs[R_UART_CLK_CTRL]  = 0x00003F03;
+    s->regs[R_SPI_CLK_CTRL]   = 0x00003F03;
+    s->regs[R_CAN_CLK_CTRL]   = 0x00501903;
+    s->regs[R_DBG_CLK_CTRL]   = 0x00000F03;
+    s->regs[R_PCAP_CLK_CTRL]  = 0x00000F01;
 
     /* 0x170 - 0x1AC */
-    s->regs[FPGA0_CLK_CTRL] = s->regs[FPGA1_CLK_CTRL] = s->regs[FPGA2_CLK_CTRL]
-                            = s->regs[FPGA3_CLK_CTRL] = 0x00101800;
-    s->regs[FPGA0_THR_STA] = s->regs[FPGA1_THR_STA] = s->regs[FPGA2_THR_STA]
-                           = s->regs[FPGA3_THR_STA] = 0x00010000;
+    s->regs[R_FPGA0_CLK_CTRL] = s->regs[R_FPGA1_CLK_CTRL]
+                              = s->regs[R_FPGA2_CLK_CTRL]
+                              = s->regs[R_FPGA3_CLK_CTRL] = 0x00101800;
+    s->regs[R_FPGA0_THR_STA] = s->regs[R_FPGA1_THR_STA]
+                             = s->regs[R_FPGA2_THR_STA]
+                             = s->regs[R_FPGA3_THR_STA] = 0x00010000;
 
     /* 0x1B0 - 0x1D8 */
-    s->regs[BANDGAP_TRIP]   = 0x0000001F;
-    s->regs[PLL_PREDIVISOR] = 0x00000001;
-    s->regs[CLK_621_TRUE]   = 0x00000001;
+    s->regs[R_BANDGAP_TRIP]   = 0x0000001F;
+    s->regs[R_PLL_PREDIVISOR] = 0x00000001;
+    s->regs[R_CLK_621_TRUE]   = 0x00000001;
 
     /* 0x200 - 0x25C */
-    s->regs[FPGA_RST_CTRL]  = 0x01F33F0F;
-    s->regs[RST_REASON]     = 0x00000040;
+    s->regs[R_FPGA_RST_CTRL]  = 0x01F33F0F;
+    s->regs[R_RST_REASON]     = 0x00000040;
 
-    s->regs[BOOT_MODE]      = 0x00000001;
+    s->regs[R_BOOT_MODE]      = 0x00000001;
 
     /* 0x700 - 0x7D4 */
     for (i = 0; i < 54; i++) {
-        s->regs[MIO + i] = 0x00001601;
+        s->regs[R_MIO + i] = 0x00001601;
     }
     for (i = 2; i <= 8; i++) {
-        s->regs[MIO + i] = 0x00000601;
+        s->regs[R_MIO + i] = 0x00000601;
     }
 
-    s->regs[MIO_MST_TRI0] = s->regs[MIO_MST_TRI1] = 0xFFFFFFFF;
+    s->regs[R_MIO_MST_TRI0] = s->regs[R_MIO_MST_TRI1] = 0xFFFFFFFF;
 
-    s->regs[CPU_RAM + 0] = s->regs[CPU_RAM + 1] = s->regs[CPU_RAM + 3]
-                         = s->regs[CPU_RAM + 4] = s->regs[CPU_RAM + 7]
-                         = 0x00010101;
-    s->regs[CPU_RAM + 2] = s->regs[CPU_RAM + 5] = 0x01010101;
-    s->regs[CPU_RAM + 6] = 0x00000001;
+    s->regs[R_CPU_RAM + 0] = s->regs[R_CPU_RAM + 1] = s->regs[R_CPU_RAM + 3]
+                           = s->regs[R_CPU_RAM + 4] = s->regs[R_CPU_RAM + 7]
+                           = 0x00010101;
+    s->regs[R_CPU_RAM + 2] = s->regs[R_CPU_RAM + 5] = 0x01010101;
+    s->regs[R_CPU_RAM + 6] = 0x00000001;
 
-    s->regs[IOU + 0] = s->regs[IOU + 1] = s->regs[IOU + 2] = s->regs[IOU + 3]
-                     = 0x09090909;
-    s->regs[IOU + 4] = s->regs[IOU + 5] = 0x00090909;
-    s->regs[IOU + 6] = 0x00000909;
+    s->regs[R_IOU + 0] = s->regs[R_IOU + 1] = s->regs[R_IOU + 2]
+                       = s->regs[R_IOU + 3] = 0x09090909;
+    s->regs[R_IOU + 4] = s->regs[R_IOU + 5] = 0x00090909;
+    s->regs[R_IOU + 6] = 0x00000909;
 
-    s->regs[DMAC_RAM] = 0x00000009;
+    s->regs[R_DMAC_RAM] = 0x00000009;
 
-    s->regs[AFI0 + 0] = s->regs[AFI0 + 1] = 0x09090909;
-    s->regs[AFI1 + 0] = s->regs[AFI1 + 1] = 0x09090909;
-    s->regs[AFI2 + 0] = s->regs[AFI2 + 1] = 0x09090909;
-    s->regs[AFI3 + 0] = s->regs[AFI3 + 1] = 0x09090909;
-    s->regs[AFI0 + 2] = s->regs[AFI1 + 2] = s->regs[AFI2 + 2]
-                      = s->regs[AFI3 + 2] = 0x00000909;
+    s->regs[R_AFI0 + 0] = s->regs[R_AFI0 + 1] = 0x09090909;
+    s->regs[R_AFI1 + 0] = s->regs[R_AFI1 + 1] = 0x09090909;
+    s->regs[R_AFI2 + 0] = s->regs[R_AFI2 + 1] = 0x09090909;
+    s->regs[R_AFI3 + 0] = s->regs[R_AFI3 + 1] = 0x09090909;
+    s->regs[R_AFI0 + 2] = s->regs[R_AFI1 + 2] = s->regs[R_AFI2 + 2]
+                        = s->regs[R_AFI3 + 2] = 0x00000909;
 
-    s->regs[OCM + 0]    = 0x01010101;
-    s->regs[OCM + 1]    = s->regs[OCM + 2] = 0x09090909;
+    s->regs[R_OCM + 0] = 0x01010101;
+    s->regs[R_OCM + 1] = s->regs[R_OCM + 2] = 0x09090909;
 
-    s->regs[DEVCI_RAM]  = 0x00000909;
-    s->regs[CSG_RAM]    = 0x00000001;
+    s->regs[R_DEVCI_RAM] = 0x00000909;
+    s->regs[R_CSG_RAM]   = 0x00000001;
 
-    s->regs[DDRIOB + 0] = s->regs[DDRIOB + 1] = s->regs[DDRIOB + 2]
-                        = s->regs[DDRIOB + 3] = 0x00000e00;
-    s->regs[DDRIOB + 4] = s->regs[DDRIOB + 5] = s->regs[DDRIOB + 6]
-                        = 0x00000e00;
-    s->regs[DDRIOB + 12] = 0x00000021;
+    s->regs[R_DDRIOB + 0] = s->regs[R_DDRIOB + 1] = s->regs[R_DDRIOB + 2]
+                          = s->regs[R_DDRIOB + 3] = 0x00000e00;
+    s->regs[R_DDRIOB + 4] = s->regs[R_DDRIOB + 5] = s->regs[R_DDRIOB + 6]
+                          = 0x00000e00;
+    s->regs[R_DDRIOB + 12] = 0x00000021;
 }
 
 
 static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
 {
     switch (offset) {
-    case LOCK:
-    case UNLOCK:
-    case DDR_CAL_START:
-    case DDR_REF_START:
+    case R_LOCK:
+    case R_UNLOCK:
+    case R_DDR_CAL_START:
+    case R_DDR_REF_START:
         return !rnw; /* Write only */
-    case LOCKSTA:
-    case FPGA0_THR_STA:
-    case FPGA1_THR_STA:
-    case FPGA2_THR_STA:
-    case FPGA3_THR_STA:
-    case BOOT_MODE:
-    case PSS_IDCODE:
-    case DDR_CMD_STA:
-    case DDR_DFI_STATUS:
-    case PLL_STATUS:
+    case R_LOCKSTA:
+    case R_FPGA0_THR_STA:
+    case R_FPGA1_THR_STA:
+    case R_FPGA2_THR_STA:
+    case R_FPGA3_THR_STA:
+    case R_BOOT_MODE:
+    case R_PSS_IDCODE:
+    case R_DDR_CMD_STA:
+    case R_DDR_DFI_STATUS:
+    case R_PLL_STATUS:
         return rnw;/* read only */
-    case SCL:
-    case ARM_PLL_CTRL ... IO_PLL_CTRL:
-    case ARM_PLL_CFG ... IO_PLL_CFG:
-    case ARM_CLK_CTRL ... TOPSW_CLK_CTRL:
-    case FPGA0_CLK_CTRL ... FPGA0_THR_CNT:
-    case FPGA1_CLK_CTRL ... FPGA1_THR_CNT:
-    case FPGA2_CLK_CTRL ... FPGA2_THR_CNT:
-    case FPGA3_CLK_CTRL ... FPGA3_THR_CNT:
-    case BANDGAP_TRIP:
-    case PLL_PREDIVISOR:
-    case CLK_621_TRUE:
-    case PSS_RST_CTRL ... A9_CPU_RST_CTRL:
-    case RS_AWDT_CTRL:
-    case RST_REASON:
-    case REBOOT_STATUS:
-    case APU_CTRL:
-    case WDT_CLK_SEL:
-    case TZ_DMA_NS ... TZ_DMA_PERIPH_NS:
-    case DDR_URGENT:
-    case DDR_URGENT_SEL:
-    case MIO ... MIO + MIO_LENGTH - 1:
-    case MIO_LOOPBACK ... MIO_MST_TRI1:
-    case SD0_WP_CD_SEL:
-    case SD1_WP_CD_SEL:
-    case LVL_SHFTR_EN:
-    case OCM_CFG:
-    case CPU_RAM:
-    case IOU:
-    case DMAC_RAM:
-    case AFI0 ... AFI3 + AFI_LENGTH - 1:
-    case OCM:
-    case DEVCI_RAM:
-    case CSG_RAM:
-    case GPIOB_CTRL ... GPIOB_CFG_CMOS33:
-    case GPIOB_CFG_HSTL:
-    case GPIOB_DRVR_BIAS_CTRL:
-    case DDRIOB ... DDRIOB + DDRIOB_LENGTH - 1:
+    case R_SCL:
+    case R_ARM_PLL_CTRL ... R_IO_PLL_CTRL:
+    case R_ARM_PLL_CFG ... R_IO_PLL_CFG:
+    case R_ARM_CLK_CTRL ... R_TOPSW_CLK_CTRL:
+    case R_FPGA0_CLK_CTRL ... R_FPGA0_THR_CNT:
+    case R_FPGA1_CLK_CTRL ... R_FPGA1_THR_CNT:
+    case R_FPGA2_CLK_CTRL ... R_FPGA2_THR_CNT:
+    case R_FPGA3_CLK_CTRL ... R_FPGA3_THR_CNT:
+    case R_BANDGAP_TRIP:
+    case R_PLL_PREDIVISOR:
+    case R_CLK_621_TRUE:
+    case R_PSS_RST_CTRL ... R_A9_CPU_RST_CTRL:
+    case R_RS_AWDT_CTRL:
+    case R_RST_REASON:
+    case R_REBOOT_STATUS:
+    case R_APU_CTRL:
+    case R_WDT_CLK_SEL:
+    case R_TZ_DMA_NS ... R_TZ_DMA_PERIPH_NS:
+    case R_DDR_URGENT:
+    case R_DDR_URGENT_SEL:
+    case R_MIO ... R_MIO + MIO_LENGTH - 1:
+    case R_MIO_LOOPBACK ... R_MIO_MST_TRI1:
+    case R_SD0_WP_CD_SEL:
+    case R_SD1_WP_CD_SEL:
+    case R_LVL_SHFTR_EN:
+    case R_OCM_CFG:
+    case R_CPU_RAM:
+    case R_IOU:
+    case R_DMAC_RAM:
+    case R_AFI0 ... R_AFI3 + AFI_LENGTH - 1:
+    case R_OCM:
+    case R_DEVCI_RAM:
+    case R_CSG_RAM:
+    case R_GPIOB_CTRL ... R_GPIOB_CFG_CMOS33:
+    case R_GPIOB_CFG_HSTL:
+    case R_GPIOB_DRVR_BIAS_CTRL:
+    case R_DDRIOB ... R_DDRIOB + DDRIOB_LENGTH - 1:
         return true;
     default:
         return false;
@@ -371,24 +371,24 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
     }
 
     switch (offset) {
-    case SCL:
-        s->regs[SCL] = val & 0x1;
+    case R_SCL:
+        s->regs[R_SCL] = val & 0x1;
         return;
-    case LOCK:
+    case R_LOCK:
         if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
             DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
                 (unsigned)val & 0xFFFF);
-            s->regs[LOCKSTA] = 1;
+            s->regs[R_LOCKSTA] = 1;
         } else {
             DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
                 (int)offset, (unsigned)val & 0xFFFF);
         }
         return;
-    case UNLOCK:
+    case R_UNLOCK:
         if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
             DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
                 (unsigned)val & 0xFFFF);
-            s->regs[LOCKSTA] = 0;
+            s->regs[R_LOCKSTA] = 0;
         } else {
             DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
                 (int)offset, (unsigned)val & 0xFFFF);
@@ -396,7 +396,7 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
         return;
     }
 
-    if (s->regs[LOCKSTA]) {
+    if (s->regs[R_LOCKSTA]) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "SCLR registers are locked. Unlock them first\n");
         return;
@@ -404,8 +404,8 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
     s->regs[offset] = val;
 
     switch (offset) {
-    case PSS_RST_CTRL:
-        if (val & R_PSS_RST_CTRL_SOFT_RST) {
+    case R_PSS_RST_CTRL:
+        if (FIELD_EX32(val, PSS_RST_CTRL, SOFT_RST)) {
             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 30/33] convert cadence_uart to 3-phases reset
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (28 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 29/33] hw/misc/zynq_slcr: use standard register definition Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 31/33] Convert zynq's slcr " Damien Hedde
                   ` (3 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Split the existing reset procedure into 3 phases.
Test the resetting flag to discard register accesses
and character reception.
Also adds a active high reset io.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/char/cadence_uart.c | 77 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 73 insertions(+), 4 deletions(-)

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index fa25fe24da..d7bacc44fe 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -39,6 +39,18 @@
     #define DB_PRINT(...)
 #endif
 
+#define CADENCE_UART_CLASS(class) \
+    OBJECT_CLASS_CHECK(CadenceUartClass, (class), TYPE_CADENCE_UART)
+#define CADENCE_UART_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(CadenceUartClass, (obj), TYPE_CADENCE_UART)
+
+typedef struct CadenceUartClass {
+    /*< private >*/
+    SysBusDeviceClass parent_class;
+
+    struct ResettablePhases parent_reset_phases;
+} CadenceUartClass;
+
 #define UART_SR_INTR_RTRIG     0x00000001
 #define UART_SR_INTR_REMPTY    0x00000002
 #define UART_SR_INTR_RFUL      0x00000004
@@ -223,6 +235,10 @@ static int uart_can_receive(void *opaque)
     int ret = MAX(CADENCE_UART_RX_FIFO_SIZE, CADENCE_UART_TX_FIFO_SIZE);
     uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
 
+    if (device_is_resetting((DeviceState *) opaque)) {
+        return 0;
+    }
+
     if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
         ret = MIN(ret, CADENCE_UART_RX_FIFO_SIZE - s->rx_count);
     }
@@ -338,6 +354,10 @@ static void uart_receive(void *opaque, const uint8_t *buf, int size)
     CadenceUARTState *s = opaque;
     uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
 
+    if (device_is_resetting((DeviceState *) opaque)) {
+        return;
+    }
+
     if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
         uart_write_rx_fifo(opaque, buf, size);
     }
@@ -351,6 +371,10 @@ static void uart_event(void *opaque, int event)
     CadenceUARTState *s = opaque;
     uint8_t buf = '\0';
 
+    if (device_is_resetting((DeviceState *) opaque)) {
+        return;
+    }
+
     if (event == CHR_EVENT_BREAK) {
         uart_write_rx_fifo(opaque, &buf, 1);
     }
@@ -383,6 +407,10 @@ static void uart_write(void *opaque, hwaddr offset,
 {
     CadenceUARTState *s = opaque;
 
+    if (device_is_resetting((DeviceState *)opaque)) {
+        return;
+    }
+
     DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value);
     offset >>= 2;
     if (offset >= CADENCE_UART_R_MAX) {
@@ -441,6 +469,10 @@ static uint64_t uart_read(void *opaque, hwaddr offset,
     CadenceUARTState *s = opaque;
     uint32_t c = 0;
 
+    if (device_is_resetting((DeviceState *)opaque)) {
+        return 0;
+    }
+
     offset >>= 2;
     if (offset >= CADENCE_UART_R_MAX) {
         c = 0;
@@ -460,9 +492,14 @@ static const MemoryRegionOps uart_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void cadence_uart_reset(DeviceState *dev)
+static void cadence_uart_reset_init(Object *obj)
 {
-    CadenceUARTState *s = CADENCE_UART(dev);
+    CadenceUARTState *s = CADENCE_UART(obj);
+    CadenceUartClass *cc = CADENCE_UART_GET_CLASS(obj);
+
+    if (cc->parent_reset_phases.init) {
+        cc->parent_reset_phases.init(obj);
+    }
 
     s->r[R_CR] = 0x00000128;
     s->r[R_IMR] = 0;
@@ -471,6 +508,28 @@ static void cadence_uart_reset(DeviceState *dev)
     s->r[R_BRGR] = 0x0000028B;
     s->r[R_BDIV] = 0x0000000F;
     s->r[R_TTRIG] = 0x00000020;
+}
+
+static void cadence_uart_reset_hold(Object *obj)
+{
+    CadenceUARTState *s = CADENCE_UART(obj);
+    CadenceUartClass *cc = CADENCE_UART_GET_CLASS(obj);
+
+    if (cc->parent_reset_phases.hold) {
+        cc->parent_reset_phases.hold(obj);
+    }
+
+    qemu_set_irq(s->irq, 0);
+}
+
+static void cadence_uart_reset_exit(Object *obj)
+{
+    CadenceUARTState *s = CADENCE_UART(obj);
+    CadenceUartClass *cc = CADENCE_UART_GET_CLASS(obj);
+
+    if (cc->parent_reset_phases.exit) {
+        cc->parent_reset_phases.exit(obj);
+    }
 
     uart_rx_reset(s);
     uart_tx_reset(s);
@@ -499,6 +558,8 @@ static void cadence_uart_init(Object *obj)
     sysbus_init_irq(sbd, &s->irq);
 
     s->char_tx_time = (NANOSECONDS_PER_SECOND / 9600) * 10;
+
+    qdev_init_warm_reset_gpio(DEVICE(obj), "rst", DEVICE_RESET_ACTIVE_HIGH);
 }
 
 static int cadence_uart_post_load(void *opaque, int version_id)
@@ -544,12 +605,19 @@ static Property cadence_uart_properties[] = {
 static void cadence_uart_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+    CadenceUartClass *cc = CADENCE_UART_CLASS(klass);
 
     dc->realize = cadence_uart_realize;
     dc->vmsd = &vmstate_cadence_uart;
-    dc->reset = cadence_uart_reset;
     dc->props = cadence_uart_properties;
-  }
+
+    resettable_class_set_parent_reset_phases(rc,
+                                             cadence_uart_reset_init,
+                                             cadence_uart_reset_hold,
+                                             cadence_uart_reset_exit,
+                                             &cc->parent_reset_phases);
+}
 
 static const TypeInfo cadence_uart_info = {
     .name          = TYPE_CADENCE_UART,
@@ -557,6 +625,7 @@ static const TypeInfo cadence_uart_info = {
     .instance_size = sizeof(CadenceUARTState),
     .instance_init = cadence_uart_init,
     .class_init    = cadence_uart_class_init,
+    .class_size = sizeof(CadenceUartClass),
 };
 
 static void cadence_uart_register_types(void)
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 31/33] Convert zynq's slcr to 3-phases reset
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (29 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 30/33] convert cadence_uart to 3-phases reset Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 32/33] Add uart reset support in zynq_slcr Damien Hedde
                   ` (2 subsequent siblings)
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Change the legacy reset function into the init phase and test the
resetting flag in register accesses.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/misc/zynq_slcr.c | 39 +++++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index dd766a6779..6fcdbce4f0 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -172,6 +172,17 @@ REG32(DDRIOB, 0xb40)
 
 #define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
 #define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
+#define ZYNQ_SLCR_CLASS(class) \
+        OBJECT_CLASS_CHECK(ZynqSLCRClass, (class), TYPE_ZYNQ_SLCR)
+#define ZYNQ_SLCR_GET_CLASS(obj) \
+        OBJECT_GET_CLASS(ZynqSLCRClass, (obj), TYPE_ZYNQ_SLCR)
+
+typedef struct ZynqSLCRClass {
+    /*< private >*/
+    SysBusDeviceClass parent_class;
+
+    struct ResettablePhases parent_reset_phases;
+} ZynqSLCRClass;
 
 typedef struct ZynqSLCRState {
     SysBusDevice parent_obj;
@@ -181,13 +192,18 @@ typedef struct ZynqSLCRState {
     uint32_t regs[ZYNQ_SLCR_NUM_REGS];
 } ZynqSLCRState;
 
-static void zynq_slcr_reset(DeviceState *d)
+static void zynq_slcr_reset_init(Object *obj)
 {
-    ZynqSLCRState *s = ZYNQ_SLCR(d);
+    ZynqSLCRState *s = ZYNQ_SLCR(obj);
+    ZynqSLCRClass *zc = ZYNQ_SLCR_GET_CLASS(obj);
     int i;
 
     DB_PRINT("RESET\n");
 
+    if (zc->parent_reset_phases.init) {
+        zc->parent_reset_phases.init(obj);
+    }
+
     s->regs[R_LOCKSTA] = 1;
     /* 0x100 - 0x11C */
     s->regs[R_ARM_PLL_CTRL]   = 0x0001A008;
@@ -277,7 +293,6 @@ static void zynq_slcr_reset(DeviceState *d)
     s->regs[R_DDRIOB + 12] = 0x00000021;
 }
 
-
 static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
 {
     switch (offset) {
@@ -347,6 +362,10 @@ static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
     offset /= 4;
     uint32_t ret = s->regs[offset];
 
+    if (device_is_resetting((DeviceState *) opaque)) {
+        return 0;
+    }
+
     if (!zynq_slcr_check_offset(offset, true)) {
         qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid read access to "
                       " addr %" HWADDR_PRIx "\n", offset * 4);
@@ -362,6 +381,10 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
     ZynqSLCRState *s = (ZynqSLCRState *)opaque;
     offset /= 4;
 
+    if (device_is_resetting((DeviceState *) opaque)) {
+        return;
+    }
+
     DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx64 "\n", offset * 4, val);
 
     if (!zynq_slcr_check_offset(offset, false)) {
@@ -440,9 +463,16 @@ static const VMStateDescription vmstate_zynq_slcr = {
 static void zynq_slcr_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+    ZynqSLCRClass *zc = ZYNQ_SLCR_CLASS(klass);
 
     dc->vmsd = &vmstate_zynq_slcr;
-    dc->reset = zynq_slcr_reset;
+
+    resettable_class_set_parent_reset_phases(rc,
+                                             zynq_slcr_reset_init,
+                                             NULL,
+                                             NULL,
+                                             &zc->parent_reset_phases);
 }
 
 static const TypeInfo zynq_slcr_info = {
@@ -451,6 +481,7 @@ static const TypeInfo zynq_slcr_info = {
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(ZynqSLCRState),
     .instance_init = zynq_slcr_init,
+    .class_size = sizeof(ZynqSLCRClass),
 };
 
 static void zynq_slcr_register_types(void)
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 32/33] Add uart reset support in zynq_slcr
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (30 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 31/33] Convert zynq's slcr " Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 33/33] Connect the uart reset gpios in the zynq platform Damien Hedde
  2019-07-30 10:14 ` [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Cornelia Huck
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Add two gpio outputs to control the uart resets.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/misc/zynq_slcr.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 6fcdbce4f0..b6c9a281c2 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -97,6 +97,10 @@ REG32(SPI_RST_CTRL, 0x21c)
 REG32(CAN_RST_CTRL, 0x220)
 REG32(I2C_RST_CTRL, 0x224)
 REG32(UART_RST_CTRL, 0x228)
+    FIELD(UART_RST_CTRL, UART0_CPU1X_RST, 0, 1)
+    FIELD(UART_RST_CTRL, UART1_CPU1X_RST, 1, 1)
+    FIELD(UART_RST_CTRL, UART0_REF_RST, 2, 1)
+    FIELD(UART_RST_CTRL, UART1_REF_RST, 3, 1)
 REG32(GPIO_RST_CTRL, 0x22c)
 REG32(LQSPI_RST_CTRL, 0x230)
 REG32(SMC_RST_CTRL, 0x234)
@@ -190,8 +194,14 @@ typedef struct ZynqSLCRState {
     MemoryRegion iomem;
 
     uint32_t regs[ZYNQ_SLCR_NUM_REGS];
+
+    qemu_irq uart0_rst;
+    qemu_irq uart1_rst;
 } ZynqSLCRState;
 
+#define ZYNQ_SLCR_REGFIELD_TO_OUT(state, irq, reg, field) \
+    qemu_set_irq((state)->irq, ARRAY_FIELD_EX32((state)->regs, reg, field) != 0)
+
 static void zynq_slcr_reset_init(Object *obj)
 {
     ZynqSLCRState *s = ZYNQ_SLCR(obj);
@@ -293,6 +303,24 @@ static void zynq_slcr_reset_init(Object *obj)
     s->regs[R_DDRIOB + 12] = 0x00000021;
 }
 
+static void zynq_slcr_compute_uart_reset(ZynqSLCRState *s)
+{
+    ZYNQ_SLCR_REGFIELD_TO_OUT(s, uart0_rst, UART_RST_CTRL, UART0_REF_RST);
+    ZYNQ_SLCR_REGFIELD_TO_OUT(s, uart1_rst, UART_RST_CTRL, UART1_REF_RST);
+}
+
+static void zynq_slcr_reset_hold(Object *obj)
+{
+    ZynqSLCRState *s = ZYNQ_SLCR(obj);
+    ZynqSLCRClass *zc = ZYNQ_SLCR_GET_CLASS(obj);
+
+    if (zc->parent_reset_phases.hold) {
+        zc->parent_reset_phases.hold(obj);
+    }
+
+    zynq_slcr_compute_uart_reset(s);
+}
+
 static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
 {
     switch (offset) {
@@ -432,6 +460,9 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
+    case R_UART_RST_CTRL:
+        zynq_slcr_compute_uart_reset(s);
+        break;
     }
 }
 
@@ -448,6 +479,9 @@ static void zynq_slcr_init(Object *obj)
     memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr",
                           ZYNQ_SLCR_MMIO_SIZE);
     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+
+    qdev_init_gpio_out_named(DEVICE(obj), &s->uart0_rst, "uart0_rst", 1);
+    qdev_init_gpio_out_named(DEVICE(obj), &s->uart1_rst, "uart1_rst", 1);
 }
 
 static const VMStateDescription vmstate_zynq_slcr = {
@@ -470,7 +504,7 @@ static void zynq_slcr_class_init(ObjectClass *klass, void *data)
 
     resettable_class_set_parent_reset_phases(rc,
                                              zynq_slcr_reset_init,
-                                             NULL,
+                                             zynq_slcr_reset_hold,
                                              NULL,
                                              &zc->parent_reset_phases);
 }
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* [Qemu-devel] [PATCH v3 33/33] Connect the uart reset gpios in the zynq platform
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (31 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 32/33] Add uart reset support in zynq_slcr Damien Hedde
@ 2019-07-29 14:56 ` Damien Hedde
  2019-07-30 10:14 ` [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Cornelia Huck
  33 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-29 14:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, rth, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, david,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

Connect the two uart reset inputs to the slcr corresponding outputs.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/arm/xilinx_zynq.c           | 14 ++++++++------
 include/hw/char/cadence_uart.h | 10 +++++++++-
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 89da34808b..bb56f1e03c 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -165,7 +165,7 @@ static void zynq_init(MachineState *machine)
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
     MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
-    DeviceState *dev;
+    DeviceState *dev, *slcr;
     SysBusDevice *busdev;
     qemu_irq pic[64];
     int n;
@@ -210,9 +210,9 @@ static void zynq_init(MachineState *machine)
                           1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
                           0);
 
-    dev = qdev_create(NULL, "xilinx,zynq_slcr");
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
+    slcr = qdev_create(NULL, "xilinx,zynq_slcr");
+    qdev_init_nofail(slcr);
+    sysbus_mmio_map(SYS_BUS_DEVICE(slcr), 0, 0xF8000000);
 
     dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
     qdev_prop_set_uint32(dev, "num-cpu", 1);
@@ -233,8 +233,10 @@ static void zynq_init(MachineState *machine)
     sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
     sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
 
-    cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0));
-    cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1));
+    cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0),
+                        slcr, "uart0_rst", 0);
+    cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1),
+                        slcr, "uart1_rst", 0);
 
     sysbus_create_varargs("cadence_ttc", 0xF8001000,
             pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h
index e1cf33e94c..c03c61a1f2 100644
--- a/include/hw/char/cadence_uart.h
+++ b/include/hw/char/cadence_uart.h
@@ -52,7 +52,10 @@ typedef struct {
 
 static inline DeviceState *cadence_uart_create(hwaddr addr,
                                         qemu_irq irq,
-                                        Chardev *chr)
+                                        Chardev *chr,
+                                        DeviceState *rst_dev,
+                                        const char *rst_name,
+                                        int rst_n)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -64,6 +67,11 @@ static inline DeviceState *cadence_uart_create(hwaddr addr,
     sysbus_mmio_map(s, 0, addr);
     sysbus_connect_irq(s, 0, irq);
 
+    if (rst_dev) {
+        qdev_connect_gpio_out_named(rst_dev, rst_name, rst_n,
+                qdev_get_gpio_in_named(dev, "rst", 0));
+    }
+
     return dev;
 }
 
-- 
2.22.0



^ permalink raw reply related	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism
  2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
                   ` (32 preceding siblings ...)
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 33/33] Connect the uart reset gpios in the zynq platform Damien Hedde
@ 2019-07-30 10:14 ` Cornelia Huck
  33 siblings, 0 replies; 113+ messages in thread
From: Cornelia Huck @ 2019-07-30 10:14 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, rth,
	thuth, ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow,
	david, berrange, mark.burton, qemu-ppc, pbonzini

On Mon, 29 Jul 2019 16:56:21 +0200
Damien Hedde <damien.hedde@greensocs.com> wrote:

(...)

> 2. old's device_reset
> 
> There was a few call to this function, I renamed it *device_legacy_reset* to
> handle the transition. This function allowed to reset only a given device 
> (and not its eventual qbus subtree). This behavior is not possible with
> the Resettable interface. I changed existing calls. Most of the time there is
> no change of behavior because devices have no sub-buses.
> Here the summary after checking each one (I've reproduced the list made by
> Peter with some additional commentary of myself):

(...)

>  hw/s390x/s390-pci-inst.c
>   -- resets the S390PCIBusDevice Needs S390 expertise, but probably
>      either no child buses or failure to reset them is a bug.

That's the 'zpci' device, which holds additional architecture
information for each pci device. Looks fine to me, but additional
confirmation from Collin would be good.


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface Damien Hedde
@ 2019-07-30 13:42   ` Cornelia Huck
  2019-07-30 13:44     ` Peter Maydell
  2019-08-07 14:20   ` Peter Maydell
  1 sibling, 1 reply; 113+ messages in thread
From: Cornelia Huck @ 2019-07-30 13:42 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, rth,
	thuth, ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow,
	david, berrange, mark.burton, qemu-ppc, pbonzini

On Mon, 29 Jul 2019 16:56:22 +0200
Damien Hedde <damien.hedde@greensocs.com> wrote:

(...)

> +/*
> + * ResettableClass:
> + * Interface for resettable objects.
> + *
> + * The reset operation is divided in several phases each represented by a
> + * method.
> + *
> + * Each Ressetable must maintain a reset counter in its state, 3 methods allows
> + * to interact with it.
> + *
> + * @phases.init: should reset local state only. Takes a bool @cold argument
> + * specifying whether the reset is cold or warm. It must not do side-effect
> + * on others objects.

I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
supposed to be... can you add a definition/guideline somewhere?

> + *
> + * @phases.hold: side-effects action on others objects due to staying in a
> + * resetting state.
> + *
> + * @phases.exit: leave the reset state, may do side-effects action on others
> + * objects.
> + *
> + * @set_cold: Set whether the current reset is cold or warm. Return the
> + * previous flag value. Return value has no meaning if @get_count returns
> + * a zero value.

Same here.

> + *
> + * @set_hold_needed: Set hold_needed flag. Return the previous flag value.
> + *
> + * @get_count: Get the current reset count
> + * @increment_count: Increment the reset count, returns the new count
> + * @decrement_count: decrement the reset count, returns the new count
> + *
> + * @foreach_child: Executes a given function on every Resettable child.
> + * A child is not a QOM child, but a child a reset meaning.
> + */

(...)


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-30 13:42   ` Cornelia Huck
@ 2019-07-30 13:44     ` Peter Maydell
  2019-07-30 13:55       ` Cornelia Huck
  0 siblings, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-07-30 13:44 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Damien Hedde, Daniel P. Berrange, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
>
> On Mon, 29 Jul 2019 16:56:22 +0200
> Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> (...)
>
> > +/*
> > + * ResettableClass:
> > + * Interface for resettable objects.
> > + *
> > + * The reset operation is divided in several phases each represented by a
> > + * method.
> > + *
> > + * Each Ressetable must maintain a reset counter in its state, 3 methods allows
> > + * to interact with it.
> > + *
> > + * @phases.init: should reset local state only. Takes a bool @cold argument
> > + * specifying whether the reset is cold or warm. It must not do side-effect
> > + * on others objects.
>
> I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
> supposed to be... can you add a definition/guideline somewhere?

Generally "cold" reset is "power on" and "warm" is "we were already
powered-on, but somebody flipped a reset line somewhere".

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-30 13:44     ` Peter Maydell
@ 2019-07-30 13:55       ` Cornelia Huck
  2019-07-30 13:59         ` Peter Maydell
  0 siblings, 1 reply; 113+ messages in thread
From: Cornelia Huck @ 2019-07-30 13:55 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Damien Hedde, Daniel P. Berrange, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Tue, 30 Jul 2019 14:44:21 +0100
Peter Maydell <peter.maydell@linaro.org> wrote:

> On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
> >
> > On Mon, 29 Jul 2019 16:56:22 +0200
> > Damien Hedde <damien.hedde@greensocs.com> wrote:
> >
> > (...)
> >  
> > > +/*
> > > + * ResettableClass:
> > > + * Interface for resettable objects.
> > > + *
> > > + * The reset operation is divided in several phases each represented by a
> > > + * method.
> > > + *
> > > + * Each Ressetable must maintain a reset counter in its state, 3 methods allows
> > > + * to interact with it.
> > > + *
> > > + * @phases.init: should reset local state only. Takes a bool @cold argument
> > > + * specifying whether the reset is cold or warm. It must not do side-effect
> > > + * on others objects.  
> >
> > I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
> > supposed to be... can you add a definition/guideline somewhere?  
> 
> Generally "cold" reset is "power on" and "warm" is "we were already
> powered-on, but somebody flipped a reset line somewhere".

Ok, that makes sense... my main concern is to distinguish that in a
generic way, as it is a generic interface. What about adding something
like:

"A 'cold' reset means that the object to be reset is initially reset; a 'warm'
reset means that the object to be reset has already been initialized."

Or is that again too generic?


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-30 13:55       ` Cornelia Huck
@ 2019-07-30 13:59         ` Peter Maydell
  2019-07-30 14:08           ` Damien Hedde
  2019-07-31 10:17           ` Christophe de Dinechin
  0 siblings, 2 replies; 113+ messages in thread
From: Peter Maydell @ 2019-07-30 13:59 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Damien Hedde, Daniel P. Berrange, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:
>
> On Tue, 30 Jul 2019 14:44:21 +0100
> Peter Maydell <peter.maydell@linaro.org> wrote:
>
> > On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
> > > I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
> > > supposed to be... can you add a definition/guideline somewhere?
> >
> > Generally "cold" reset is "power on" and "warm" is "we were already
> > powered-on, but somebody flipped a reset line somewhere".
>
> Ok, that makes sense... my main concern is to distinguish that in a
> generic way, as it is a generic interface. What about adding something
> like:
>
> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
> reset means that the object to be reset has already been initialized."
>
> Or is that again too generic?

I think it doesn't quite capture the idea -- an object can have already
been reset and then get a 'cold' reset: this is like having a powered-on
machine and then power-cycling it.

The 'warm' reset is the vaguer one, because the specific behaviour
is somewhat device-dependent (many devices might not have any
difference from 'cold' reset, for those that do the exact detail
of what doesn't get reset on warm-reset will vary). But every
device should have some kind of "as if you power-cycled it" (or
for QEMU, "go back to the same state as if you just started QEMU on the
command line"). Our current "reset" method is really cold-reset.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-30 13:59         ` Peter Maydell
@ 2019-07-30 14:08           ` Damien Hedde
  2019-07-30 15:47             ` Cornelia Huck
  2019-07-31  5:46             ` David Gibson
  2019-07-31 10:17           ` Christophe de Dinechin
  1 sibling, 2 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-30 14:08 UTC (permalink / raw)
  To: Peter Maydell, Cornelia Huck
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Mark Burton, qemu-ppc, Paolo Bonzini


On 7/30/19 3:59 PM, Peter Maydell wrote:
> On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:
>>
>> On Tue, 30 Jul 2019 14:44:21 +0100
>> Peter Maydell <peter.maydell@linaro.org> wrote:
>>
>>> On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
>>>> I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
>>>> supposed to be... can you add a definition/guideline somewhere?
>>>
>>> Generally "cold" reset is "power on" and "warm" is "we were already
>>> powered-on, but somebody flipped a reset line somewhere".
>>
>> Ok, that makes sense... my main concern is to distinguish that in a
>> generic way, as it is a generic interface. What about adding something
>> like:
>>
>> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
>> reset means that the object to be reset has already been initialized."
>>
>> Or is that again too generic?
> 
> I think it doesn't quite capture the idea -- an object can have already
> been reset and then get a 'cold' reset: this is like having a powered-on
> machine and then power-cycling it.
> 
> The 'warm' reset is the vaguer one, because the specific behaviour
> is somewhat device-dependent (many devices might not have any
> difference from 'cold' reset, for those that do the exact detail
> of what doesn't get reset on warm-reset will vary). But every
> device should have some kind of "as if you power-cycled it" (or
> for QEMU, "go back to the same state as if you just started QEMU on the
> command line"). Our current "reset" method is really cold-reset.
> 

Exactly. In the following patches, I've tried to replace existing reset
calls by cold or warm reset depending on whether:
+ it is called through the main system reset -> cold
+ it is called during normal life-time       -> warm

But I definitely can add some docs/comments to better explain that.

--
Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-30 14:08           ` Damien Hedde
@ 2019-07-30 15:47             ` Cornelia Huck
  2019-07-31  5:46             ` David Gibson
  1 sibling, 0 replies; 113+ messages in thread
From: Cornelia Huck @ 2019-07-30 15:47 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Peter Maydell, Collin Walling, Dmitry Fleytman,
	Michael S. Tsirkin, Mark Cave-Ayland, QEMU Developers,
	Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke, Qemu-block,
	David Hildenbrand, Halil Pasic, Christian Borntraeger,
	Marc-André Lureau, Richard Henderson, Thomas Huth,
	Eduardo Habkost, Alistair Francis, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Mark Burton, qemu-ppc, Paolo Bonzini

On Tue, 30 Jul 2019 16:08:59 +0200
Damien Hedde <damien.hedde@greensocs.com> wrote:

> On 7/30/19 3:59 PM, Peter Maydell wrote:
> > On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:  
> >>
> >> On Tue, 30 Jul 2019 14:44:21 +0100
> >> Peter Maydell <peter.maydell@linaro.org> wrote:
> >>  
> >>> On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:  
> >>>> I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
> >>>> supposed to be... can you add a definition/guideline somewhere?  
> >>>
> >>> Generally "cold" reset is "power on" and "warm" is "we were already
> >>> powered-on, but somebody flipped a reset line somewhere".  
> >>
> >> Ok, that makes sense... my main concern is to distinguish that in a
> >> generic way, as it is a generic interface. What about adding something
> >> like:
> >>
> >> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
> >> reset means that the object to be reset has already been initialized."
> >>
> >> Or is that again too generic?  
> > 
> > I think it doesn't quite capture the idea -- an object can have already
> > been reset and then get a 'cold' reset: this is like having a powered-on
> > machine and then power-cycling it.
> > 
> > The 'warm' reset is the vaguer one, because the specific behaviour
> > is somewhat device-dependent (many devices might not have any
> > difference from 'cold' reset, for those that do the exact detail
> > of what doesn't get reset on warm-reset will vary). But every
> > device should have some kind of "as if you power-cycled it" (or
> > for QEMU, "go back to the same state as if you just started QEMU on the
> > command line"). Our current "reset" method is really cold-reset.

Ah ok, that makes sense.

> >   
> 
> Exactly. In the following patches, I've tried to replace existing reset
> calls by cold or warm reset depending on whether:
> + it is called through the main system reset -> cold
> + it is called during normal life-time       -> warm
> 
> But I definitely can add some docs/comments to better explain that.

Yes, that would be great; I think I now understand enough for looking
at the patches.


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-30 14:08           ` Damien Hedde
  2019-07-30 15:47             ` Cornelia Huck
@ 2019-07-31  5:46             ` David Gibson
  2019-08-01  9:35               ` Damien Hedde
  1 sibling, 1 reply; 113+ messages in thread
From: David Gibson @ 2019-07-31  5:46 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Peter Maydell, Collin Walling, Dmitry Fleytman,
	Michael S. Tsirkin, Mark Cave-Ayland, QEMU Developers,
	Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke, Qemu-block,
	David Hildenbrand, Halil Pasic, Christian Borntraeger,
	Marc-André Lureau, Thomas Huth, Eduardo Habkost,
	Alistair Francis, qemu-s390x, qemu-arm, Cédric Le Goater,
	John Snow, Richard Henderson, Daniel P. Berrange, Cornelia Huck,
	Mark Burton, qemu-ppc, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 3010 bytes --]

On Tue, Jul 30, 2019 at 04:08:59PM +0200, Damien Hedde wrote:
> 
> On 7/30/19 3:59 PM, Peter Maydell wrote:
> > On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:
> >>
> >> On Tue, 30 Jul 2019 14:44:21 +0100
> >> Peter Maydell <peter.maydell@linaro.org> wrote:
> >>
> >>> On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
> >>>> I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
> >>>> supposed to be... can you add a definition/guideline somewhere?
> >>>
> >>> Generally "cold" reset is "power on" and "warm" is "we were already
> >>> powered-on, but somebody flipped a reset line somewhere".
> >>
> >> Ok, that makes sense... my main concern is to distinguish that in a
> >> generic way, as it is a generic interface. What about adding something
> >> like:
> >>
> >> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
> >> reset means that the object to be reset has already been initialized."
> >>
> >> Or is that again too generic?
> > 
> > I think it doesn't quite capture the idea -- an object can have already
> > been reset and then get a 'cold' reset: this is like having a powered-on
> > machine and then power-cycling it.
> > 
> > The 'warm' reset is the vaguer one, because the specific behaviour
> > is somewhat device-dependent (many devices might not have any
> > difference from 'cold' reset, for those that do the exact detail
> > of what doesn't get reset on warm-reset will vary). But every
> > device should have some kind of "as if you power-cycled it" (or
> > for QEMU, "go back to the same state as if you just started QEMU on the
> > command line"). Our current "reset" method is really cold-reset.
> > 
> 
> Exactly. In the following patches, I've tried to replace existing reset
> calls by cold or warm reset depending on whether:
> + it is called through the main system reset -> cold
> + it is called during normal life-time       -> warm
> 
> But I definitely can add some docs/comments to better explain that.

Hrm, that helps, but it still seems pretty vague to me.

It's not really my call, but building the concept of warm versus cold
resets into such a generic interface seems pretty dubios to me.  While
it's moderately common for things to have a notion of warm versus cold
reset it's certainly not universal.  There are many devices where
there's no meaningful difference between the two.  There are some
devices where there are > 2 different types of reset suitable for
various different situations.

Is there any way this could work with it usually just presenting the
cold reset (which is the closest to a universal concept), and any warm
or additional resets are handled buy a different instance of the
Resettable interface?

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/33] Replace all call to device_reset by call to device_legacy_reset
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 03/33] Replace all call to device_reset by call to device_legacy_reset Damien Hedde
@ 2019-07-31  5:52   ` David Gibson
  0 siblings, 0 replies; 113+ messages in thread
From: David Gibson @ 2019-07-31  5:52 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 7648 bytes --]

On Mon, Jul 29, 2019 at 04:56:24PM +0200, Damien Hedde wrote:
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>

I don't see a lot of point keeping this patch separate from the
previous one.

> ---
>  hw/audio/intel-hda.c     | 2 +-
>  hw/hyperv/hyperv.c       | 2 +-
>  hw/i386/pc.c             | 2 +-
>  hw/ide/microdrive.c      | 8 ++++----
>  hw/intc/spapr_xive.c     | 2 +-
>  hw/ppc/pnv_psi.c         | 2 +-
>  hw/ppc/spapr_pci.c       | 2 +-
>  hw/ppc/spapr_vio.c       | 2 +-
>  hw/s390x/s390-pci-inst.c | 2 +-
>  hw/scsi/vmw_pvscsi.c     | 2 +-
>  hw/sd/omap_mmc.c         | 2 +-
>  hw/sd/pl181.c            | 2 +-
>  12 files changed, 15 insertions(+), 15 deletions(-)
> 
> diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
> index b78baac295..f133684b10 100644
> --- a/hw/audio/intel-hda.c
> +++ b/hw/audio/intel-hda.c
> @@ -1086,7 +1086,7 @@ static void intel_hda_reset(DeviceState *dev)
>      QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
>          DeviceState *qdev = kid->child;
>          cdev = HDA_CODEC_DEVICE(qdev);
> -        device_reset(DEVICE(cdev));
> +        device_legacy_reset(DEVICE(cdev));
>          d->state_sts |= (1 << cdev->cad);
>      }
>      intel_hda_update_irq(d);
> diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
> index 6ebf31c310..cd9db3cb5c 100644
> --- a/hw/hyperv/hyperv.c
> +++ b/hw/hyperv/hyperv.c
> @@ -140,7 +140,7 @@ void hyperv_synic_reset(CPUState *cs)
>      SynICState *synic = get_synic(cs);
>  
>      if (synic) {
> -        device_reset(DEVICE(synic));
> +        device_legacy_reset(DEVICE(synic));
>      }
>  }
>  
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 549c437050..c0f20fe8aa 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -2823,7 +2823,7 @@ static void pc_machine_reset(MachineState *machine)
>          cpu = X86_CPU(cs);
>  
>          if (cpu->apic_state) {
> -            device_reset(cpu->apic_state);
> +            device_legacy_reset(cpu->apic_state);
>          }
>      }
>  }
> diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
> index 92ee6e0af8..fc346f5ad5 100644
> --- a/hw/ide/microdrive.c
> +++ b/hw/ide/microdrive.c
> @@ -173,7 +173,7 @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
>      case 0x00:	/* Configuration Option Register */
>          s->opt = value & 0xcf;
>          if (value & OPT_SRESET) {
> -            device_reset(DEVICE(s));
> +            device_legacy_reset(DEVICE(s));
>          }
>          md_interrupt_update(s);
>          break;
> @@ -316,7 +316,7 @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
>      case 0xe:	/* Device Control */
>          s->ctrl = value;
>          if (value & CTRL_SRST) {
> -            device_reset(DEVICE(s));
> +            device_legacy_reset(DEVICE(s));
>          }
>          md_interrupt_update(s);
>          break;
> @@ -541,7 +541,7 @@ static int dscm1xxxx_attach(PCMCIACardState *card)
>      md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
>      md->io_base = 0x0;
>  
> -    device_reset(DEVICE(md));
> +    device_legacy_reset(DEVICE(md));
>      md_interrupt_update(md);
>  
>      return 0;
> @@ -551,7 +551,7 @@ static int dscm1xxxx_detach(PCMCIACardState *card)
>  {
>      MicroDriveState *md = MICRODRIVE(card);
>  
> -    device_reset(DEVICE(md));
> +    device_legacy_reset(DEVICE(md));
>      return 0;
>  }
>  
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index 3ae311d9ff..22e11ad10c 100644
> --- a/hw/intc/spapr_xive.c
> +++ b/hw/intc/spapr_xive.c
> @@ -1511,7 +1511,7 @@ static target_ulong h_int_reset(PowerPCCPU *cpu,
>          return H_PARAMETER;
>      }
>  
> -    device_reset(DEVICE(xive));
> +    device_legacy_reset(DEVICE(xive));
>  
>      if (kvm_irqchip_in_kernel()) {
>          Error *local_err = NULL;
> diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
> index d7b6f5d75b..78eafa353a 100644
> --- a/hw/ppc/pnv_psi.c
> +++ b/hw/ppc/pnv_psi.c
> @@ -703,7 +703,7 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
>          break;
>      case PSIHB9_INTERRUPT_CONTROL:
>          if (val & PSIHB9_IRQ_RESET) {
> -            device_reset(DEVICE(&psi9->source));
> +            device_legacy_reset(DEVICE(&psi9->source));
>          }
>          psi->regs[reg] = val;
>          break;
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 9003fe9010..3c6cf79a5e 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -2029,7 +2029,7 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
>      DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
>  
>      if (dev) {
> -        device_reset(dev);
> +        device_legacy_reset(dev);
>      }
>  
>      return 0;
> diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
> index 583c13deda..5a0b5cc35c 100644
> --- a/hw/ppc/spapr_vio.c
> +++ b/hw/ppc/spapr_vio.c
> @@ -306,7 +306,7 @@ int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
>  static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
>  {
>      if (dev->tcet) {
> -        device_reset(DEVICE(dev->tcet));
> +        device_legacy_reset(DEVICE(dev->tcet));
>      }
>      free_crq(dev);
>  }
> diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
> index 00235148be..93cda37c27 100644
> --- a/hw/s390x/s390-pci-inst.c
> +++ b/hw/s390x/s390-pci-inst.c
> @@ -242,7 +242,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
>                  stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
>                  goto out;
>              }
> -            device_reset(DEVICE(pbdev));
> +            device_legacy_reset(DEVICE(pbdev));
>              pbdev->fh &= ~FH_MASK_ENABLE;
>              pbdev->state = ZPCI_FS_DISABLED;
>              stl_p(&ressetpci->fh, pbdev->fh);
> diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
> index 14641df1c8..cda3fc96a0 100644
> --- a/hw/scsi/vmw_pvscsi.c
> +++ b/hw/scsi/vmw_pvscsi.c
> @@ -835,7 +835,7 @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
>  
>      if (sdev != NULL) {
>          s->resetting++;
> -        device_reset(&sdev->qdev);
> +        device_legacy_reset(&sdev->qdev);
>          s->resetting--;
>          return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
>      }
> diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
> index d0c98ca021..24a1edc149 100644
> --- a/hw/sd/omap_mmc.c
> +++ b/hw/sd/omap_mmc.c
> @@ -317,7 +317,7 @@ void omap_mmc_reset(struct omap_mmc_s *host)
>       * into any bus, and we must reset it manually. When omap_mmc is
>       * QOMified this must move into the QOM reset function.
>       */
> -    device_reset(DEVICE(host->card));
> +    device_legacy_reset(DEVICE(host->card));
>  }
>  
>  static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
> diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
> index 81b406dbf0..15b4aaa67f 100644
> --- a/hw/sd/pl181.c
> +++ b/hw/sd/pl181.c
> @@ -480,7 +480,7 @@ static void pl181_reset(DeviceState *d)
>      /* Since we're still using the legacy SD API the card is not plugged
>       * into any bus, and we must reset it manually.
>       */
> -    device_reset(DEVICE(s->card));
> +    device_legacy_reset(DEVICE(s->card));
>  }
>  
>  static void pl181_init(Object *obj)

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable Damien Hedde
@ 2019-07-31  5:56   ` David Gibson
  2019-07-31  9:09     ` Damien Hedde
  2019-08-07 14:41   ` Peter Maydell
  1 sibling, 1 reply; 113+ messages in thread
From: David Gibson @ 2019-07-31  5:56 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 13827 bytes --]

On Mon, Jul 29, 2019 at 04:56:25PM +0200, Damien Hedde wrote:
> This add Resettable interface implementation for both Bus and Device.
> 
> *resetting* counter and *reset_is_cold* flag are added in DeviceState
> and BusState.
> 
> Compatibility with existing code base is ensured.
> The legacy bus or device reset method is called in the new exit phase
> and the other 2 phases are let empty. Using the exit phase guarantee that
> legacy resets are called in the "post" order (ie: children then parent)
> in hierarchical reset. That is the same order as legacy qdev_reset_all
> or qbus_reset_all were using.
> 
> New *device_reset* and *bus_reset* function are proposed with an
> additional boolean argument telling whether the reset is cold or warm.
> Helper functions *device_reset_[warm|cold]* and *bus_reset_[warm|cold]*
> are defined also as helpers.
> 
> Also add a [device|bus]_is_resetting and [device|bus]_is_reset_cold
> functions telling respectively whether the object is currently under reset and
> if the current reset is cold or not.
> 
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/bus.c          | 85 ++++++++++++++++++++++++++++++++++++++++++
>  hw/core/qdev.c         | 82 ++++++++++++++++++++++++++++++++++++++++
>  include/hw/qdev-core.h | 84 ++++++++++++++++++++++++++++++++++++++---
>  tests/Makefile.include |  1 +
>  4 files changed, 247 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/core/bus.c b/hw/core/bus.c
> index 17bc1edcde..08a97addb6 100644
> --- a/hw/core/bus.c
> +++ b/hw/core/bus.c
> @@ -22,6 +22,7 @@
>  #include "qemu/module.h"
>  #include "hw/qdev.h"
>  #include "qapi/error.h"
> +#include "hw/resettable.h"
>  
>  void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
>  {
> @@ -68,6 +69,75 @@ int qbus_walk_children(BusState *bus,
>      return 0;
>  }
>  
> +void bus_reset(BusState *bus, bool cold)
> +{
> +    resettable_reset(OBJECT(bus), cold);
> +}
> +
> +bool bus_is_resetting(BusState *bus)
> +{
> +    return (bus->resetting != 0);
> +}
> +
> +bool bus_is_reset_cold(BusState *bus)
> +{
> +    return bus->reset_is_cold;
> +}
> +
> +static uint32_t bus_get_reset_count(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    return bus->resetting;
> +}
> +
> +static uint32_t bus_increment_reset_count(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    return ++bus->resetting;
> +}
> +
> +static uint32_t bus_decrement_reset_count(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    return --bus->resetting;
> +}
> +
> +static bool bus_set_reset_cold(Object *obj, bool cold)
> +{
> +    BusState *bus = BUS(obj);
> +    bool old = bus->reset_is_cold;
> +    bus->reset_is_cold = cold;
> +    return old;
> +}
> +
> +static bool bus_set_hold_needed(Object *obj, bool hold_needed)
> +{
> +    BusState *bus = BUS(obj);
> +    bool old = bus->reset_hold_needed;
> +    bus->reset_hold_needed = hold_needed;
> +    return old;
> +}
> +
> +static void bus_foreach_reset_child(Object *obj, void (*func)(Object *))
> +{
> +    BusState *bus = BUS(obj);
> +    BusChild *kid;
> +
> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> +        func(OBJECT(kid->child));
> +    }
> +}

IIUC, every resettable class would need more or less identical
implementations of the above.  That seems like an awful lot of
boilerplate.

> +
> +static void bus_obj_legacy_reset(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    BusClass *bc = BUS_GET_CLASS(obj);
> +
> +    if (bc->reset) {
> +        bc->reset(bus);
> +    }
> +}
> +
>  static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
>  {
>      const char *typename = object_get_typename(OBJECT(bus));
> @@ -192,6 +262,8 @@ static void qbus_initfn(Object *obj)
>                               NULL);
>      object_property_add_bool(obj, "realized",
>                               bus_get_realized, bus_set_realized, NULL);
> +
> +    bus->resetting = 0;
>  }
>  
>  static char *default_bus_get_fw_dev_path(DeviceState *dev)
> @@ -202,9 +274,18 @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
>  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->phases.exit = bus_obj_legacy_reset;
> +    rc->get_count = bus_get_reset_count;
> +    rc->increment_count = bus_increment_reset_count;
> +    rc->decrement_count = bus_decrement_reset_count;
> +    rc->foreach_child = bus_foreach_reset_child;
> +    rc->set_cold = bus_set_reset_cold;
> +    rc->set_hold_needed = bus_set_hold_needed;
>  }
>  
>  static void qbus_finalize(Object *obj)
> @@ -223,6 +304,10 @@ static const TypeInfo bus_info = {
>      .instance_init = qbus_initfn,
>      .instance_finalize = qbus_finalize,
>      .class_init = bus_class_init,
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_RESETTABLE },
> +        { }
> +    },
>  };
>  
>  static void bus_register_types(void)
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 043e058396..559ced070d 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -254,6 +254,64 @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
>      return hotplug_ctrl;
>  }
>  
> +void device_reset(DeviceState *dev, bool cold)
> +{
> +    resettable_reset(OBJECT(dev), cold);
> +}
> +
> +bool device_is_resetting(DeviceState *dev)
> +{
> +    return (dev->resetting != 0);
> +}
> +
> +bool device_is_reset_cold(DeviceState *dev)
> +{
> +    return dev->reset_is_cold;
> +}
> +
> +static uint32_t device_get_reset_count(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    return dev->resetting;
> +}
> +
> +static uint32_t device_increment_reset_count(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    return ++dev->resetting;
> +}
> +
> +static uint32_t device_decrement_reset_count(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    return --dev->resetting;
> +}
> +
> +static bool device_set_reset_cold(Object *obj, bool cold)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    bool old = dev->reset_is_cold;
> +    dev->reset_is_cold = cold;
> +    return old;
> +}
> +
> +static bool device_set_hold_needed(Object *obj, bool hold_needed)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    bool old = dev->reset_hold_needed;
> +    dev->reset_hold_needed = hold_needed;
> +    return old;
> +}
> +
> +static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    BusState *bus;
> +    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> +        func(OBJECT(bus));
> +    }
> +}
> +
>  static int qdev_reset_one(DeviceState *dev, void *opaque)
>  {
>      device_legacy_reset(dev);
> @@ -954,6 +1012,7 @@ static void device_initfn(Object *obj)
>  
>      dev->instance_id_alias = -1;
>      dev->realized = false;
> +    dev->resetting = 0;
>  
>      object_property_add_bool(obj, "realized",
>                               device_get_realized, device_set_realized, NULL);
> @@ -1046,9 +1105,20 @@ static void device_unparent(Object *obj)
>      }
>  }
>  
> +static void device_obj_legacy_reset(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> +    if (dc->reset) {
> +        dc->reset(dev);
> +    }
> +}
> +
>  static void device_class_init(ObjectClass *class, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(class);
> +    ResettableClass *rc = RESETTABLE_CLASS(class);
>  
>      class->unparent = device_unparent;
>  
> @@ -1060,6 +1130,14 @@ static void device_class_init(ObjectClass *class, void *data)
>       */
>      dc->hotpluggable = true;
>      dc->user_creatable = true;
> +
> +    rc->phases.exit = device_obj_legacy_reset;
> +    rc->get_count = device_get_reset_count;
> +    rc->increment_count = device_increment_reset_count;
> +    rc->decrement_count = device_decrement_reset_count;
> +    rc->foreach_child = device_foreach_reset_child;
> +    rc->set_cold = device_set_reset_cold;
> +    rc->set_hold_needed = device_set_hold_needed;
>  }
>  
>  void device_class_set_parent_reset(DeviceClass *dc,
> @@ -1117,6 +1195,10 @@ static const TypeInfo device_type_info = {
>      .class_init = device_class_init,
>      .abstract = true,
>      .class_size = sizeof(DeviceClass),
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_RESETTABLE },
> +        { }
> +    },
>  };
>  
>  static void qdev_register_types(void)
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 690ce72433..eeb75611c8 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -7,6 +7,7 @@
>  #include "hw/irq.h"
>  #include "hw/hotplug.h"
>  #include "sysemu/sysemu.h"
> +#include "hw/resettable.h"
>  
>  enum {
>      DEV_NVECTORS_UNSPECIFIED = -1,
> @@ -132,6 +133,10 @@ struct NamedGPIOList {
>  /**
>   * DeviceState:
>   * @realized: Indicates whether the device has been fully constructed.
> + * @resetting: Indicates whether the device is under reset. Also
> + * used to count how many times reset has been initiated on the device.
> + * @reset_is_cold: If the device is under reset, indicates whether it is cold
> + * or warm.
>   *
>   * This structure should not be accessed directly.  We declare it here
>   * so that it can be embedded in individual device state structures.
> @@ -153,6 +158,9 @@ struct DeviceState {
>      int num_child_bus;
>      int instance_id_alias;
>      int alias_required_for_version;
> +    uint32_t resetting;
> +    bool reset_is_cold;
> +    bool reset_hold_needed;
>  };
>  
>  struct DeviceListener {
> @@ -199,6 +207,10 @@ typedef struct BusChild {
>  /**
>   * BusState:
>   * @hotplug_handler: link to a hotplug handler associated with bus.
> + * @resetting: Indicates whether the bus is under reset. Also
> + * used to count how many times reset has been initiated on the bus.
> + * @reset_is_cold: If the bus is under reset, indicates whether it is cold
> + * or warm.
>   */
>  struct BusState {
>      Object obj;
> @@ -210,6 +222,9 @@ struct BusState {
>      int num_children;
>      QTAILQ_HEAD(, BusChild) children;
>      QLIST_ENTRY(BusState) sibling;
> +    uint32_t resetting;
> +    bool reset_is_cold;
> +    bool reset_hold_needed;
>  };
>  
>  /**
> @@ -376,6 +391,70 @@ int qdev_walk_children(DeviceState *dev,
>                         qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
>                         void *opaque);
>  
> +/**
> + * device_reset:
> + * Resets the device @dev, @cold tell whether to do a cold or warm reset.
> + * Uses the ressetable interface.
> + * Base behavior is to reset the device and its qdev/qbus subtree.
> + */
> +void device_reset(DeviceState *dev, bool cold);
> +
> +static inline void device_reset_warm(DeviceState *dev)
> +{
> +    device_reset(dev, false);
> +}
> +
> +static inline void device_reset_cold(DeviceState *dev)
> +{
> +    device_reset(dev, true);
> +}
> +
> +/**
> + * bus_reset:
> + * Resets the bus @bus, @cold tell whether to do a cold or warm reset.
> + * Uses the ressetable interface.
> + * Base behavior is to reset the bus and its qdev/qbus subtree.
> + */
> +void bus_reset(BusState *bus, bool cold);
> +
> +static inline void bus_reset_warm(BusState *bus)
> +{
> +    bus_reset(bus, false);
> +}
> +
> +static inline void bus_reset_cold(BusState *bus)
> +{
> +    bus_reset(bus, true);
> +}
> +
> +/**
> + * device_is_resetting:
> + * Tell whether the device @dev is currently under reset.
> + */
> +bool device_is_resetting(DeviceState *dev);
> +
> +/**
> + * device_is_reset_cold:
> + * Tell whether the device @dev is currently under reset cold or warm reset.
> + *
> + * Note: only valid when device_is_resetting returns true.
> + */
> +bool device_is_reset_cold(DeviceState *dev);
> +
> +/**
> + * bus_is_resetting:
> + * Tell whether the bus @bus is currently under reset.
> + */
> +bool bus_is_resetting(BusState *bus);
> +
> +/**
> + * bus_is_reset_cold:
> + * Tell whether the bus @bus is currently under reset cold or warm reset.
> + *
> + * Note: only valid when bus_is_resetting returns true.
> + */
> +bool bus_is_reset_cold(BusState *bus);
> +
>  void qdev_reset_all(DeviceState *dev);
>  void qdev_reset_all_fn(void *opaque);
>  
> @@ -413,11 +492,6 @@ void qdev_machine_init(void);
>   */
>  void device_legacy_reset(DeviceState *dev);
>  
> -static inline void device_reset(DeviceState *dev)
> -{
> -    device_legacy_reset(dev);
> -}
> -
>  void device_class_set_parent_reset(DeviceClass *dc,
>                                     DeviceReset dev_reset,
>                                     DeviceReset *parent_reset);
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index fd7fdb8658..1c0a5345b9 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -561,6 +561,7 @@ tests/fp/%:
>  
>  tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
>  	hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
> +	hw/core/resettable.o \
>  	hw/core/bus.o \
>  	hw/core/irq.o \
>  	hw/core/fw-path-provider.o \

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus Damien Hedde
@ 2019-07-31  6:05   ` David Gibson
  2019-07-31  9:29     ` Damien Hedde
  2019-08-07 14:48   ` Peter Maydell
  1 sibling, 1 reply; 113+ messages in thread
From: David Gibson @ 2019-07-31  6:05 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 5109 bytes --]

On Mon, Jul 29, 2019 at 04:56:26PM +0200, Damien Hedde wrote:
> Deprecate old reset apis and make them use the new one while they
> are still used somewhere.
> 
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/qdev.c         | 22 +++-------------------
>  include/hw/qdev-core.h | 28 ++++++++++++++++++++++------
>  2 files changed, 25 insertions(+), 25 deletions(-)
> 
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 559ced070d..e9e5f2d5f9 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -312,25 +312,9 @@ static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
>      }
>  }
>  
> -static int qdev_reset_one(DeviceState *dev, void *opaque)
> -{
> -    device_legacy_reset(dev);
> -
> -    return 0;
> -}
> -
> -static int qbus_reset_one(BusState *bus, void *opaque)
> -{
> -    BusClass *bc = BUS_GET_CLASS(bus);
> -    if (bc->reset) {
> -        bc->reset(bus);
> -    }
> -    return 0;
> -}
> -
>  void qdev_reset_all(DeviceState *dev)
>  {
> -    qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
> +    device_reset(dev, false);
>  }
>  
>  void qdev_reset_all_fn(void *opaque)
> @@ -340,7 +324,7 @@ void qdev_reset_all_fn(void *opaque)
>  
>  void qbus_reset_all(BusState *bus)
>  {
> -    qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
> +    bus_reset(bus, false);
>  }
>  
>  void qbus_reset_all_fn(void *opaque)
> @@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
>              }
>          }
>          if (dev->hotplugged) {
> -            device_legacy_reset(dev);
> +            device_reset(dev, true);

So.. is this change in the device_reset() signature really necessary?
Even if there are compelling reasons to handle warm reset in the new
API, that doesn't been you need to change device_reset() itself from
its established meaning of a cold (i.e. as per power cycle) reset.
Warm resets are generally called in rather more specific circumstances
(often under guest software direction) so it seems likely that users
would want to engage with the new reset API directly.  Or we could
just create a device_warm_reset() wrapper.  That would also avoid the
bare boolean parameter, which is not great for readability (you have
to look up the signature to have any idea what it means).

>          }
>          dev->pending_deleted_event = false;
>  
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index eeb75611c8..1670ae41bb 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -109,6 +109,11 @@ typedef struct DeviceClass {
>      bool hotpluggable;
>  
>      /* callbacks */
> +    /*
> +     * Reset method here is deprecated and replaced by methods in the
> +     * resettable class interface to implement a multi-phase reset.
> +     * TODO: remove once every reset callback is unused
> +     */
>      DeviceReset reset;
>      DeviceRealize realize;
>      DeviceUnrealize unrealize;
> @@ -455,19 +460,22 @@ bool bus_is_resetting(BusState *bus);
>   */
>  bool bus_is_reset_cold(BusState *bus);
>  
> -void qdev_reset_all(DeviceState *dev);
> -void qdev_reset_all_fn(void *opaque);
> -
>  /**
> - * @qbus_reset_all:
> - * @bus: Bus to be reset.
> + * qbus/qdev_reset_all:
> + * @bus/dev: Bus/Device to be reset.
>   *
> - * Reset @bus and perform a bus-level ("hard") reset of all devices connected
> + * Reset @bus/dev and perform a bus-level reset of all devices/buses connected
>   * to it, including recursive processing of all buses below @bus itself.  A
>   * hard reset means that qbus_reset_all will reset all state of the device.
>   * For PCI devices, for example, this will include the base address registers
>   * or configuration space.
> + *
> + * Theses functions are deprecated, please use device/bus_reset or
> + * resettable_reset_* instead
> + * TODO: remove them when all occurence are removed
>   */
> +void qdev_reset_all(DeviceState *dev);
> +void qdev_reset_all_fn(void *opaque);
>  void qbus_reset_all(BusState *bus);
>  void qbus_reset_all_fn(void *opaque);
>  
> @@ -489,9 +497,17 @@ void qdev_machine_init(void);
>   * device_legacy_reset:
>   *
>   * Reset a single device (by calling the reset method).
> + *
> + * This function is deprecated, please use device_reset() instead.
> + * TODO: remove the function when all occurences are removed.
>   */
>  void device_legacy_reset(DeviceState *dev);
>  
> +/**
> + * device_class_set_parent_reset:
> + * TODO: remove the function when DeviceClass's reset method
> + * is not used anymore.
> + */
>  void device_class_set_parent_reset(DeviceClass *dc,
>                                     DeviceReset dev_reset,
>                                     DeviceReset *parent_reset);

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state Damien Hedde
@ 2019-07-31  6:08   ` David Gibson
  2019-07-31 11:04     ` Damien Hedde
  2019-08-07 14:53   ` Peter Maydell
  2019-08-07 14:54   ` Peter Maydell
  2 siblings, 1 reply; 113+ messages in thread
From: David Gibson @ 2019-07-31  6:08 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 3282 bytes --]

On Mon, Jul 29, 2019 at 04:56:27PM +0200, Damien Hedde wrote:
> It contains the resetting counter and cold flag status.
> 
> At this point, migration of bus reset related state (counter and cold/warm
> flag) is handled by parent device. This done using the post_load
> function in the vmsd subsection.
> 
> This is last point allow to add an initial support of migration with part of
> qdev/qbus tree in reset state under the following condition:
> + time-lasting reset are asserted on Device only
> 
> Note that if this condition is not respected, migration will succeed and
> no failure will occurs. The only impact is that the resetting counter
> of a bus may lower afer a migration.
> 
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/Makefile.objs  |  1 +
>  hw/core/qdev-vmstate.c | 45 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 46 insertions(+)
>  create mode 100644 hw/core/qdev-vmstate.c
> 
> diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
> index d9234aa98a..49e9be0228 100644
> --- a/hw/core/Makefile.objs
> +++ b/hw/core/Makefile.objs
> @@ -4,6 +4,7 @@ common-obj-y += bus.o reset.o
>  common-obj-y += resettable.o
>  common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
>  common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
> +common-obj-$(CONFIG_SOFTMMU) += qdev-vmstate.o
>  # irq.o needed for qdev GPIO handling:
>  common-obj-y += irq.o
>  common-obj-y += hotplug.o
> diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
> new file mode 100644
> index 0000000000..07b010811f
> --- /dev/null
> +++ b/hw/core/qdev-vmstate.c
> @@ -0,0 +1,45 @@
> +/*
> + * Device vmstate
> + *
> + * Copyright (c) 2019 GreenSocs
> + *
> + * Authors:
> + *   Damien Hedde
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/qdev.h"
> +#include "migration/vmstate.h"
> +
> +static bool device_vmstate_reset_needed(void *opaque)
> +{
> +    DeviceState *dev = (DeviceState *) opaque;
> +    return dev->resetting != 0;
> +}
> +
> +static int device_vmstate_reset_post_load(void *opaque, int version_id)
> +{
> +    DeviceState *dev = (DeviceState *) opaque;
> +    BusState *bus;
> +    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> +        bus->resetting = dev->resetting;

Having redundant copies of the resetting bit in the bridge and every
bus instance seems kind of bogus.

> +        bus->reset_is_cold = dev->reset_is_cold;
> +    }
> +    return 0;
> +}
> +
> +const struct VMStateDescription device_vmstate_reset = {
> +    .name = "device_reset",
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .needed = device_vmstate_reset_needed,
> +    .post_load = device_vmstate_reset_post_load,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32(resetting, DeviceState),
> +        VMSTATE_BOOL(reset_is_cold, DeviceState),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs Damien Hedde
@ 2019-07-31  6:11   ` David Gibson
  2019-07-31 10:09     ` Damien Hedde
  2019-08-07 10:37     ` Peter Maydell
  2019-08-07 15:18   ` Peter Maydell
  1 sibling, 2 replies; 113+ messages in thread
From: David Gibson @ 2019-07-31  6:11 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 8225 bytes --]

On Mon, Jul 29, 2019 at 04:56:29PM +0200, Damien Hedde wrote:
> It adds the possibility to add 2 gpios to control the warm and cold reset.
> With theses ios, the reset can be maintained during some time.
> Each io is associated with a state to detect level changes.
> 
> Vmstate subsections are also added to the existsing device_reset
> subsection.

This doesn't seem like a thing that should be present on every single
DeviceState.

> 
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/qdev-vmstate.c | 15 ++++++++++
>  hw/core/qdev.c         | 65 ++++++++++++++++++++++++++++++++++++++++++
>  include/hw/qdev-core.h | 57 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 137 insertions(+)
> 
> diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
> index 24f8465c61..72f84c6cee 100644
> --- a/hw/core/qdev-vmstate.c
> +++ b/hw/core/qdev-vmstate.c
> @@ -24,10 +24,23 @@ static int device_vmstate_reset_post_load(void *opaque, int version_id)
>  {
>      DeviceState *dev = (DeviceState *) opaque;
>      BusState *bus;
> +    uint32_t io_count = 0;
> +
>      QLIST_FOREACH(bus, &dev->child_bus, sibling) {
>          bus->resetting = dev->resetting;
>          bus->reset_is_cold = dev->reset_is_cold;
>      }
> +
> +    if (dev->cold_reset_input.state) {
> +        io_count += 1;
> +    }
> +    if (dev->warm_reset_input.state) {
> +        io_count += 1;
> +    }
> +    /* ensure resetting count is coherent with io states */
> +    if (dev->resetting < io_count) {
> +        return -1;
> +    }
>      return 0;
>  }
>  
> @@ -40,6 +53,8 @@ const struct VMStateDescription device_vmstate_reset = {
>      .fields = (VMStateField[]) {
>          VMSTATE_UINT32(resetting, DeviceState),
>          VMSTATE_BOOL(reset_is_cold, DeviceState),
> +        VMSTATE_BOOL(cold_reset_input.state, DeviceState),
> +        VMSTATE_BOOL(warm_reset_input.state, DeviceState),
>          VMSTATE_END_OF_LIST()
>      },
>  };
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 88387d3743..11a4de55ea 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -450,6 +450,67 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
>      qdev_init_gpio_in_named(dev, handler, NULL, n);
>  }
>  
> +static DeviceResetInputState *device_get_reset_input_state(DeviceState *dev,
> +                                                            bool cold)
> +{
> +    return cold ? &dev->cold_reset_input : &dev->warm_reset_input;
> +}
> +
> +static void device_reset_handler(DeviceState *dev, bool cold, bool level)
> +{
> +    DeviceResetInputState *dris = device_get_reset_input_state(dev, cold);
> +
> +    if (dris->type == DEVICE_RESET_ACTIVE_LOW) {
> +        level = !level;
> +    }
> +
> +    if (dris->state == level) {
> +        /* io state has not changed */
> +        return;
> +    }
> +
> +    dris->state = level;
> +
> +    if (level) {
> +        resettable_assert_reset(OBJECT(dev), cold);
> +    } else {
> +        resettable_deassert_reset(OBJECT(dev));
> +    }
> +}
> +
> +static void device_cold_reset_handler(void *opaque, int n, int level)
> +{
> +    device_reset_handler((DeviceState *) opaque, true, level);
> +}
> +
> +static void device_warm_reset_handler(void *opaque, int n, int level)
> +{
> +    device_reset_handler((DeviceState *) opaque, false, level);
> +}
> +
> +void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
> +                                   bool cold, DeviceResetActiveType type)
> +{
> +    DeviceResetInputState *dris = device_get_reset_input_state(dev, cold);
> +    qemu_irq_handler handler;
> +
> +    switch (type) {
> +    case DEVICE_RESET_ACTIVE_LOW:
> +    case DEVICE_RESET_ACTIVE_HIGH:
> +        break;
> +    default:
> +        assert(false);
> +        break;
> +    }
> +
> +    assert(!dris->exists);
> +    dris->exists = true;
> +    dris->type = type;
> +
> +    handler = cold ? device_cold_reset_handler : device_warm_reset_handler;
> +    qdev_init_gpio_in_named(dev, handler, name, 1);
> +}
> +
>  void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
>                                const char *name, int n)
>  {
> @@ -1007,6 +1068,10 @@ static void device_initfn(Object *obj)
>      dev->instance_id_alias = -1;
>      dev->realized = false;
>      dev->resetting = 0;
> +    dev->cold_reset_input.exists = false;
> +    dev->cold_reset_input.state = false;
> +    dev->warm_reset_input.exists = false;
> +    dev->warm_reset_input.state = false;
>  
>      object_property_add_bool(obj, "realized",
>                               device_get_realized, device_set_realized, NULL);
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 926d4bbcb1..f724ddc8f4 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -136,6 +136,23 @@ struct NamedGPIOList {
>      QLIST_ENTRY(NamedGPIOList) node;
>  };
>  
> +typedef enum DeviceResetActiveType {
> +    DEVICE_RESET_ACTIVE_LOW,
> +    DEVICE_RESET_ACTIVE_HIGH,
> +} DeviceResetActiveType;
> +
> +/**
> + * DeviceResetInputState:
> + * @exists: tell if io exists
> + * @type: tell whether the io active low or high
> + * @state: true if reset is currently active
> + */
> +typedef struct DeviceResetInputState {
> +    bool exists;
> +    DeviceResetActiveType type;
> +    bool state;
> +} DeviceResetInputState;
> +
>  /**
>   * DeviceState:
>   * @realized: Indicates whether the device has been fully constructed.
> @@ -143,6 +160,8 @@ struct NamedGPIOList {
>   * used to count how many times reset has been initiated on the device.
>   * @reset_is_cold: If the device is under reset, indicates whether it is cold
>   * or warm.
> + * @cold_reset_input: state data for cold reset io
> + * @warm_reset_input: state data for warm reset io
>   *
>   * This structure should not be accessed directly.  We declare it here
>   * so that it can be embedded in individual device state structures.
> @@ -167,6 +186,8 @@ struct DeviceState {
>      uint32_t resetting;
>      bool reset_is_cold;
>      bool reset_hold_needed;
> +    DeviceResetInputState cold_reset_input;
> +    DeviceResetInputState warm_reset_input;
>  };
>  
>  struct DeviceListener {
> @@ -372,6 +393,42 @@ static inline void qdev_init_gpio_in_named(DeviceState *dev,
>  void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
>                       const char *name);
>  
> +/**
> + * qdev_init_reset_gpio_in_named:
> + * Create a gpio controlling the warm or cold reset of the device.
> + *
> + * @cold: specify whether it triggers cold or warm reset
> + * @type: what kind of reset io it is
> + *
> + * Note: the io is considered created in its inactive state. No reset
> + * is started by this function.
> + */
> +void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
> +                                   bool cold, DeviceResetActiveType type);
> +
> +/**
> + * qdev_init_warm_reset_gpio:
> + * Create the input to control the device warm reset.
> + */
> +static inline void qdev_init_warm_reset_gpio(DeviceState *dev,
> +                                             const char *name,
> +                                             DeviceResetActiveType type)
> +{
> +    qdev_init_reset_gpio_in_named(dev, name, false, type);
> +}
> +
> +/**
> + * qdev_init_cold_reset_gpio:
> + * Create the input to control the device cold reset.
> + * It can also be used as a power gate control.
> + */
> +static inline void qdev_init_cold_reset_gpio(DeviceState *dev,
> +                                             const char *name,
> +                                             DeviceResetActiveType type)
> +{
> +    qdev_init_reset_gpio_in_named(dev, name, true, type);
> +}
> +
>  BusState *qdev_get_parent_bus(DeviceState *dev);
>  
>  /*** BUS API. ***/

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface Damien Hedde
@ 2019-07-31  6:30   ` David Gibson
  2019-07-31 10:05     ` Damien Hedde
                       ` (2 more replies)
  2019-08-07 15:58   ` Peter Maydell
  2019-08-07 16:02   ` Peter Maydell
  2 siblings, 3 replies; 113+ messages in thread
From: David Gibson @ 2019-07-31  6:30 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 7980 bytes --]

On Mon, Jul 29, 2019 at 04:56:30PM +0200, Damien Hedde wrote:
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  docs/devel/reset.txt | 165 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 165 insertions(+)
>  create mode 100644 docs/devel/reset.txt
> 
> diff --git a/docs/devel/reset.txt b/docs/devel/reset.txt
> new file mode 100644
> index 0000000000..c7a1eb068f
> --- /dev/null
> +++ b/docs/devel/reset.txt
> @@ -0,0 +1,165 @@
> +
> +=====
> +Reset
> +=====
> +
> +The reset of qemu objects is handled using the Resettable interface declared
> +in *include/hw/resettable.h*.
> +As of now DeviceClass and BusClass implement this interface.
> +
> +
> +Triggering reset
> +----------------
> +
> +The function *resettable_reset* is used to trigger a reset on a given
> +object.
> +void resettable_reset(Object *obj, bool cold)
> +
> +The parameter *obj* must implement the Resettable interface.

And what happens if it doesn't?  This function has no way to report an
error.

> +The parameter *cold* is a boolean specifying whether to do a cold or warm
> +reset

This doc really needs to explain the distinction between cold and warm
reset.

> +For Devices and Buses there is also the corresponding helpers:
> +void device_reset(Device *dev, bool cold)
> +void bus_reset(Device *dev, bool cold)

What's the semantic difference between resetting a bus and resetting
the bridge device which owns it?

> +If one wants to put an object into a reset state. There is the
> +*resettable_assert_reset* function.
> +void resettable_assert_reset(Object *obj, bool cold)
> +
> +One must eventually call the function *resettable_deassert_reset* to end the
> +reset state:
> +void resettable_deassert_reset(Object *obj, bool cold)
> +
> +Calling *resettable_assert_reset* then *resettable_deassert_reset* is the
> +same as calling *resettable_reset*.
> +
> +It is possible to interleave multiple calls to
> + - resettable_reset,
> + - resettable_assert_reset, and
> + - resettable_deassert_reset.
> +The only constraint is that *resettable_deassert_reset* must be called once
> +per *resettable_assert_reset* call so that the object leaves the reset state.
> +
> +Therefore there may be several reset sources/controllers of a given object.
> +The interface handle everything and the controllers do not need to know
> +anything about each others. The object will leave reset state only when all
> +controllers released their reset.
> +
> +All theses functions must called while holding the iothread lock.
> +
> +
> +Implementing reset for a Resettable object : Multi-phase reset
> +--------------------------------------------------------------
> +
> +The Resettable uses a multi-phase mechanism to handle some ordering constraints
> +when resetting multiple object at the same time. For a given object the reset
> +procedure is split into three different phases executed in order:
> + 1 INIT: This phase should set/reset the state of the Resettable it has when is
> +         in reset state. Side-effects to others object is forbidden (such as
> +         setting IO level).
> + 2 HOLD: This phase corresponds to the external side-effects due to staying into
> +         the reset state.
> + 3 EXIT: This phase corresponds to leaving the reset state. It have both
> +         local and external effects.
> +
> +*resettable_assert_reset* does the INIT and HOLD phases. While
> +*resettable_deassert_reset* does the EXIT phase.
> +
> +When resetting multiple object at the same time. The interface executes the
> +given phase of the objects before going to the next phase. This guarantee that
> +all INIT phases are done before any HOLD phase and so on.
> +
> +There is three methods in the interface so must be implemented in an object.
> +The methods corresponds to the three phases:
> +```
> +typedef void (*ResettableInitPhase)(Object *obj);
> +typedef void (*ResettableHoldPhase)(Object *obj);
> +typedef void (*ResettableExitPhase)(Object *obj);
> +typedef struct ResettableClass {
> +    InterfaceClass parent_class;
> +
> +    struct ResettablePhases {
> +        ResettableInitPhase init;
> +        ResettableHoldPhase hold;
> +        ResettableExitPhase exit;
> +    } phases;
> +    [...]
> +} ResettableClass;
> +```
> +
> +Theses methods should be updated when specializing an object. For this the
> +helper function *resettable_class_set_parent_reset_phases* can be used to
> +backup parent methods while changing the specialized ones.
> +void resettable_class_set_parent_reset_phases(ResettableClass *rc,
> +                                              ResettableInitPhase init,
> +                                              ResettableHoldPhase hold,
> +                                              ResettableExitPhase exit,
> +
> +For Devices and Buses, some helper exists to know if a device/bus is under
> +reset and what type of reset it is:
> +```
> +bool device_is_resetting(DeviceState *dev);
> +bool device_is_reset_cold(DeviceState *dev);

It's not really clear to me when *_is_reset_cold() would be useful.

> +bool bus_is_resetting(BusState *bus);
> +bool bus_is_reset_cold(BusState *bus);
> +```
> +
> +
> +Implementing the base Resettable behavior : Re-entrance, Hierarchy and Cold/Warm
> +--------------------------------------------------------------------------------
> +
> +There is five others methods in the interface to handle the base mechanics
> +of the Resettable interface. The methods should be implemented in object
> +base class. DeviceClass and BusClass implement them.
> +
> +```
> +typedef bool (*ResettableSetCold)(Object *obj, bool cold);
> +typedef bool (*ResettableSetHoldNeeded)(Object *obj, bool hold_needed);
> +typedef uint32_t (*ResettableGetCount)(Object *obj);
> +typedef uint32_t (*ResettableIncrementCount)(Object *obj);
> +typedef uint32_t (*ResettableDecrementCount)(Object *obj);
> +typedef void (*ResettableForeachChild)(Object *obj, void (*visitor)(Object *));
> +typedef struct ResettableClass {
> +    InterfaceClass parent_class;
> +
> +    [...]
> +
> +    ResettableSetCold set_cold;
> +    ResettableSetHoldNeeded set_hold_needed;
> +    ResettableGetCount get_count;
> +    ResettableIncrementCount increment_count;
> +    ResettableDecrementCount decrement_count;
> +    ResettableForeachChild foreach_child;
> +} ResettableClass;
> +```
> +
> +*set_cold* is used when entering reset, before calling the init phase, to
> +indicate the reset type.
> +
> +*set_hold_needed* is used to set/clear and retrieve an "hold_needed" flag.
> +This flag allows to omly execute the hold pahse when required.
> +
> +As stated above, several reset procedures can be concurrent on an object.
> +This is handled with the three methods *get_count*, *increment_count* and
> +*decrement_count*. An object is in reset state if the count is non-zero.
> +
> +The reset hierarchy is handled using the *foreach_child* method. This method
> +executes a given function on every reset "child".
> +
> +In DeviceClass and BusClass the base behavior is to mimic the legacy qdev
> +reset. Reset hierarchy follows the qdev/qbus tree.
> +
> +Reset control through GPIO
> +--------------------------
> +
> +For devices, two reset inputs can be added: one for the cold, one the warm
> +reset. This is done using the following function.
> +```
> +typedef enum DeviceResetActiveType {
> +    DEVICE_RESET_ACTIVE_LOW,
> +    DEVICE_RESET_ACTIVE_HIGH,
> +} DeviceResetActiveType;
> +void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
> +                                   bool cold, DeviceResetActiveType type);
> +```

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-07-31  5:56   ` David Gibson
@ 2019-07-31  9:09     ` Damien Hedde
  2019-08-06  0:35       ` David Gibson
  0 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-07-31  9:09 UTC (permalink / raw)
  To: David Gibson
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini



On 7/31/19 7:56 AM, David Gibson wrote:
> On Mon, Jul 29, 2019 at 04:56:25PM +0200, Damien Hedde wrote:
>> This add Resettable interface implementation for both Bus and Device.
>>
>> *resetting* counter and *reset_is_cold* flag are added in DeviceState
>> and BusState.
>>
>> Compatibility with existing code base is ensured.
>> The legacy bus or device reset method is called in the new exit phase
>> and the other 2 phases are let empty. Using the exit phase guarantee that
>> legacy resets are called in the "post" order (ie: children then parent)
>> in hierarchical reset. That is the same order as legacy qdev_reset_all
>> or qbus_reset_all were using.
>>
>> New *device_reset* and *bus_reset* function are proposed with an
>> additional boolean argument telling whether the reset is cold or warm.
>> Helper functions *device_reset_[warm|cold]* and *bus_reset_[warm|cold]*
>> are defined also as helpers.
>>
>> Also add a [device|bus]_is_resetting and [device|bus]_is_reset_cold
>> functions telling respectively whether the object is currently under reset and
>> if the current reset is cold or not.
>>
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>> ---
>>  hw/core/bus.c          | 85 ++++++++++++++++++++++++++++++++++++++++++
>>  hw/core/qdev.c         | 82 ++++++++++++++++++++++++++++++++++++++++
>>  include/hw/qdev-core.h | 84 ++++++++++++++++++++++++++++++++++++++---
>>  tests/Makefile.include |  1 +
>>  4 files changed, 247 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/core/bus.c b/hw/core/bus.c
>> index 17bc1edcde..08a97addb6 100644
>> --- a/hw/core/bus.c
>> +++ b/hw/core/bus.c
>> @@ -22,6 +22,7 @@
>>  #include "qemu/module.h"
>>  #include "hw/qdev.h"
>>  #include "qapi/error.h"
>> +#include "hw/resettable.h"
>>  
>>  void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
>>  {
>> @@ -68,6 +69,75 @@ int qbus_walk_children(BusState *bus,
>>      return 0;
>>  }
>>  
>> +void bus_reset(BusState *bus, bool cold)
>> +{
>> +    resettable_reset(OBJECT(bus), cold);
>> +}
>> +
>> +bool bus_is_resetting(BusState *bus)
>> +{
>> +    return (bus->resetting != 0);
>> +}
>> +
>> +bool bus_is_reset_cold(BusState *bus)
>> +{
>> +    return bus->reset_is_cold;
>> +}
>> +
>> +static uint32_t bus_get_reset_count(Object *obj)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    return bus->resetting;
>> +}
>> +
>> +static uint32_t bus_increment_reset_count(Object *obj)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    return ++bus->resetting;
>> +}
>> +
>> +static uint32_t bus_decrement_reset_count(Object *obj)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    return --bus->resetting;
>> +}
>> +
>> +static bool bus_set_reset_cold(Object *obj, bool cold)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    bool old = bus->reset_is_cold;
>> +    bus->reset_is_cold = cold;
>> +    return old;
>> +}
>> +
>> +static bool bus_set_hold_needed(Object *obj, bool hold_needed)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    bool old = bus->reset_hold_needed;
>> +    bus->reset_hold_needed = hold_needed;
>> +    return old;
>> +}
>> +
>> +static void bus_foreach_reset_child(Object *obj, void (*func)(Object *))
>> +{
>> +    BusState *bus = BUS(obj);
>> +    BusChild *kid;
>> +
>> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
>> +        func(OBJECT(kid->child));
>> +    }
>> +}
> 
> IIUC, every resettable class would need more or less identical
> implementations of the above.  That seems like an awful lot of
> boilerplate.

Do you mean the get/increment_count/decrement_count, set_cold/hold part ?
True, but it's limited to the base classes.
Since Resettable is an interface, we have no state there to store what
we need. Only alternative is to have some kind of single
get_resettable_state method returning a pointer to the state (allowing
us to keep the functions in the interface code).
Beyond Device and Bus, which are done here, there is probably not so
many class candidates for the Resettable interface.

Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-07-31  6:05   ` David Gibson
@ 2019-07-31  9:29     ` Damien Hedde
  2019-07-31 11:31       ` Philippe Mathieu-Daudé
  2019-08-08  6:48       ` David Gibson
  0 siblings, 2 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-31  9:29 UTC (permalink / raw)
  To: David Gibson
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini



On 7/31/19 8:05 AM, David Gibson wrote:
> On Mon, Jul 29, 2019 at 04:56:26PM +0200, Damien Hedde wrote:
>> Deprecate old reset apis and make them use the new one while they
>> are still used somewhere.
>>
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>> ---
>>  hw/core/qdev.c         | 22 +++-------------------
>>  include/hw/qdev-core.h | 28 ++++++++++++++++++++++------
>>  2 files changed, 25 insertions(+), 25 deletions(-)
>>
>> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
>> index 559ced070d..e9e5f2d5f9 100644
>> --- a/hw/core/qdev.c
>> +++ b/hw/core/qdev.c
>> @@ -312,25 +312,9 @@ static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
>>      }
>>  }
>>  
>> -static int qdev_reset_one(DeviceState *dev, void *opaque)
>> -{
>> -    device_legacy_reset(dev);
>> -
>> -    return 0;
>> -}
>> -
>> -static int qbus_reset_one(BusState *bus, void *opaque)
>> -{
>> -    BusClass *bc = BUS_GET_CLASS(bus);
>> -    if (bc->reset) {
>> -        bc->reset(bus);
>> -    }
>> -    return 0;
>> -}
>> -
>>  void qdev_reset_all(DeviceState *dev)
>>  {
>> -    qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
>> +    device_reset(dev, false);
>>  }
>>  
>>  void qdev_reset_all_fn(void *opaque)
>> @@ -340,7 +324,7 @@ void qdev_reset_all_fn(void *opaque)
>>  
>>  void qbus_reset_all(BusState *bus)
>>  {
>> -    qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
>> +    bus_reset(bus, false);
>>  }
>>  
>>  void qbus_reset_all_fn(void *opaque)
>> @@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
>>              }
>>          }
>>          if (dev->hotplugged) {
>> -            device_legacy_reset(dev);
>> +            device_reset(dev, true);
> 
> So.. is this change in the device_reset() signature really necessary?
> Even if there are compelling reasons to handle warm reset in the new
> API, that doesn't been you need to change device_reset() itself from
> its established meaning of a cold (i.e. as per power cycle) reset.
> Warm resets are generally called in rather more specific circumstances
> (often under guest software direction) so it seems likely that users
> would want to engage with the new reset API directly.  Or we could
> just create a device_warm_reset() wrapper.  That would also avoid the
> bare boolean parameter, which is not great for readability (you have
> to look up the signature to have any idea what it means).

I've added device_reset_cold/warm wrapper functions to avoid having to
pass the boolean parameter. it seems I forgot to use them in qdev.c
I suppose, like you said, we could live with
+ no function with the boolean parameter
+ device_reset doing cold reset
+ device_reset_warm (or device_warm_reset) for the warm version

Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-07-31  6:30   ` David Gibson
@ 2019-07-31 10:05     ` Damien Hedde
  2019-08-07 10:34     ` Peter Maydell
  2019-08-07 16:01     ` Peter Maydell
  2 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-31 10:05 UTC (permalink / raw)
  To: David Gibson
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini



On 7/31/19 8:30 AM, David Gibson wrote:
> On Mon, Jul 29, 2019 at 04:56:30PM +0200, Damien Hedde wrote:
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>> ---
>>  docs/devel/reset.txt | 165 +++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 165 insertions(+)
>>  create mode 100644 docs/devel/reset.txt
>>
>> diff --git a/docs/devel/reset.txt b/docs/devel/reset.txt
>> new file mode 100644
>> index 0000000000..c7a1eb068f
>> --- /dev/null
>> +++ b/docs/devel/reset.txt
>> @@ -0,0 +1,165 @@
>> +
>> +=====
>> +Reset
>> +=====
>> +
>> +The reset of qemu objects is handled using the Resettable interface declared
>> +in *include/hw/resettable.h*.
>> +As of now DeviceClass and BusClass implement this interface.
>> +
>> +
>> +Triggering reset
>> +----------------
>> +
>> +The function *resettable_reset* is used to trigger a reset on a given
>> +object.
>> +void resettable_reset(Object *obj, bool cold)
>> +
>> +The parameter *obj* must implement the Resettable interface.
> 
> And what happens if it doesn't?  This function has no way to report an
> error.

In the function, while retrieving the Resettable class, there is an
assert checking the obj is compatible. We could put an error argument
there to report that if that's preferable.
But then it means an error object should be given for every reset call.

> 
>> +The parameter *cold* is a boolean specifying whether to do a cold or warm
>> +reset
> 
> This doc really needs to explain the distinction between cold and warm
> reset.

ok

> 
>> +For Devices and Buses there is also the corresponding helpers:
>> +void device_reset(Device *dev, bool cold)
>> +void bus_reset(Device *dev, bool cold)
> 
> What's the semantic difference between resetting a bus and resetting
> the bridge device which owns it?

I can't speak for specific cases.
BusClass has already a reset method and qbus_reset_all is used as well
as qdev_reset_all in current code base. Currently both devices and buses
are used as reset entry point. I'm just keeping it that way.

> 
>> +If one wants to put an object into a reset state. There is the
>> +*resettable_assert_reset* function.
>> +void resettable_assert_reset(Object *obj, bool cold)
>> +
>> +One must eventually call the function *resettable_deassert_reset* to end the
>> +reset state:
>> +void resettable_deassert_reset(Object *obj, bool cold)
>> +
>> +Calling *resettable_assert_reset* then *resettable_deassert_reset* is the
>> +same as calling *resettable_reset*.
>> +
>> +It is possible to interleave multiple calls to
>> + - resettable_reset,
>> + - resettable_assert_reset, and
>> + - resettable_deassert_reset.
>> +The only constraint is that *resettable_deassert_reset* must be called once
>> +per *resettable_assert_reset* call so that the object leaves the reset state.
>> +
>> +Therefore there may be several reset sources/controllers of a given object.
>> +The interface handle everything and the controllers do not need to know
>> +anything about each others. The object will leave reset state only when all
>> +controllers released their reset.
>> +
>> +All theses functions must called while holding the iothread lock.
>> +
>> +
>> +Implementing reset for a Resettable object : Multi-phase reset
>> +--------------------------------------------------------------
>> +
>> +The Resettable uses a multi-phase mechanism to handle some ordering constraints
>> +when resetting multiple object at the same time. For a given object the reset
>> +procedure is split into three different phases executed in order:
>> + 1 INIT: This phase should set/reset the state of the Resettable it has when is
>> +         in reset state. Side-effects to others object is forbidden (such as
>> +         setting IO level).
>> + 2 HOLD: This phase corresponds to the external side-effects due to staying into
>> +         the reset state.
>> + 3 EXIT: This phase corresponds to leaving the reset state. It have both
>> +         local and external effects.
>> +
>> +*resettable_assert_reset* does the INIT and HOLD phases. While
>> +*resettable_deassert_reset* does the EXIT phase.
>> +
>> +When resetting multiple object at the same time. The interface executes the
>> +given phase of the objects before going to the next phase. This guarantee that
>> +all INIT phases are done before any HOLD phase and so on.
>> +
>> +There is three methods in the interface so must be implemented in an object.
>> +The methods corresponds to the three phases:
>> +```
>> +typedef void (*ResettableInitPhase)(Object *obj);
>> +typedef void (*ResettableHoldPhase)(Object *obj);
>> +typedef void (*ResettableExitPhase)(Object *obj);
>> +typedef struct ResettableClass {
>> +    InterfaceClass parent_class;
>> +
>> +    struct ResettablePhases {
>> +        ResettableInitPhase init;
>> +        ResettableHoldPhase hold;
>> +        ResettableExitPhase exit;
>> +    } phases;
>> +    [...]
>> +} ResettableClass;
>> +```
>> +
>> +Theses methods should be updated when specializing an object. For this the
>> +helper function *resettable_class_set_parent_reset_phases* can be used to
>> +backup parent methods while changing the specialized ones.
>> +void resettable_class_set_parent_reset_phases(ResettableClass *rc,
>> +                                              ResettableInitPhase init,
>> +                                              ResettableHoldPhase hold,
>> +                                              ResettableExitPhase exit,
>> +
>> +For Devices and Buses, some helper exists to know if a device/bus is under
>> +reset and what type of reset it is:
>> +```
>> +bool device_is_resetting(DeviceState *dev);
>> +bool device_is_reset_cold(DeviceState *dev);
> 
> It's not really clear to me when *_is_reset_cold() would be useful.

Useful only for devices/buses that have different cold/warm reset
behavior. In particular this should be used in the reset init phase.

Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-07-31  6:11   ` David Gibson
@ 2019-07-31 10:09     ` Damien Hedde
  2019-08-07 10:37     ` Peter Maydell
  1 sibling, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-31 10:09 UTC (permalink / raw)
  To: David Gibson
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini



On 7/31/19 8:11 AM, David Gibson wrote:
> On Mon, Jul 29, 2019 at 04:56:29PM +0200, Damien Hedde wrote:
>> It adds the possibility to add 2 gpios to control the warm and cold reset.
>> With theses ios, the reset can be maintained during some time.
>> Each io is associated with a state to detect level changes.
>>
>> Vmstate subsections are also added to the existsing device_reset
>> subsection.
> 
> This doesn't seem like a thing that should be present on every single
> DeviceState.

I can revert to previous version where the io state has to be explicitly
added in devices using it.

Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-30 13:59         ` Peter Maydell
  2019-07-30 14:08           ` Damien Hedde
@ 2019-07-31 10:17           ` Christophe de Dinechin
  2019-08-01  9:19             ` Damien Hedde
  1 sibling, 1 reply; 113+ messages in thread
From: Christophe de Dinechin @ 2019-07-31 10:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke,
	Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, David Gibson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini


Peter Maydell writes:

> On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:
>>
>> On Tue, 30 Jul 2019 14:44:21 +0100
>> Peter Maydell <peter.maydell@linaro.org> wrote:
>>
>> > On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
>> > > I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
>> > > supposed to be... can you add a definition/guideline somewhere?
>> >
>> > Generally "cold" reset is "power on" and "warm" is "we were already
>> > powered-on, but somebody flipped a reset line somewhere".
>>
>> Ok, that makes sense... my main concern is to distinguish that in a
>> generic way, as it is a generic interface. What about adding something
>> like:
>>
>> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
>> reset means that the object to be reset has already been initialized."
>>
>> Or is that again too generic?
>
> I think it doesn't quite capture the idea -- an object can have already
> been reset and then get a 'cold' reset: this is like having a powered-on
> machine and then power-cycling it.
>
> The 'warm' reset is the vaguer one, because the specific behaviour
> is somewhat device-dependent (many devices might not have any
> difference from 'cold' reset, for those that do the exact detail
> of what doesn't get reset on warm-reset will vary). But every
> device should have some kind of "as if you power-cycled it" (or
> for QEMU, "go back to the same state as if you just started QEMU on the
> command line"). Our current "reset" method is really cold-reset.

Is there any concept of locality associated with warm reset?
For example, you'd expect a cold reset to happen on the whole system,
but I guess a warm reset could be restricted to a single bus.

The documentation should give examples of how warm reset could be
triggered, and what it could do differently from cold reset.

>
> thanks
> -- PMM


--
Cheers,
Christophe de Dinechin (IRC c3d)


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state
  2019-07-31  6:08   ` David Gibson
@ 2019-07-31 11:04     ` Damien Hedde
  0 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-07-31 11:04 UTC (permalink / raw)
  To: David Gibson
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini



On 7/31/19 8:08 AM, David Gibson wrote:
> On Mon, Jul 29, 2019 at 04:56:27PM +0200, Damien Hedde wrote:
>> It contains the resetting counter and cold flag status.
>>
>> At this point, migration of bus reset related state (counter and cold/warm
>> flag) is handled by parent device. This done using the post_load
>> function in the vmsd subsection.
>>
>> This is last point allow to add an initial support of migration with part of
>> qdev/qbus tree in reset state under the following condition:
>> + time-lasting reset are asserted on Device only
>>
>> Note that if this condition is not respected, migration will succeed and
>> no failure will occurs. The only impact is that the resetting counter
>> of a bus may lower afer a migration.
>>
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>> ---
>>  hw/core/Makefile.objs  |  1 +
>>  hw/core/qdev-vmstate.c | 45 ++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 46 insertions(+)
>>  create mode 100644 hw/core/qdev-vmstate.c
>>
>> diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
>> index d9234aa98a..49e9be0228 100644
>> --- a/hw/core/Makefile.objs
>> +++ b/hw/core/Makefile.objs
>> @@ -4,6 +4,7 @@ common-obj-y += bus.o reset.o
>>  common-obj-y += resettable.o
>>  common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
>>  common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
>> +common-obj-$(CONFIG_SOFTMMU) += qdev-vmstate.o
>>  # irq.o needed for qdev GPIO handling:
>>  common-obj-y += irq.o
>>  common-obj-y += hotplug.o
>> diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
>> new file mode 100644
>> index 0000000000..07b010811f
>> --- /dev/null
>> +++ b/hw/core/qdev-vmstate.c
>> @@ -0,0 +1,45 @@
>> +/*
>> + * Device vmstate
>> + *
>> + * Copyright (c) 2019 GreenSocs
>> + *
>> + * Authors:
>> + *   Damien Hedde
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/qdev.h"
>> +#include "migration/vmstate.h"
>> +
>> +static bool device_vmstate_reset_needed(void *opaque)
>> +{
>> +    DeviceState *dev = (DeviceState *) opaque;
>> +    return dev->resetting != 0;
>> +}
>> +
>> +static int device_vmstate_reset_post_load(void *opaque, int version_id)
>> +{
>> +    DeviceState *dev = (DeviceState *) opaque;
>> +    BusState *bus;
>> +    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
>> +        bus->resetting = dev->resetting;
> 
> Having redundant copies of the resetting bit in the bridge and every
> bus instance seems kind of bogus.

Currently we duplicate the resetting bit of parent into children when we
do the reset propagation into the tree. It means resetting count of an
device/bus contains the value of its parent plus any additional bit
local to the object (due to a reset from an gpio for example).

I'm not sure if we can avoid that. It would require the
"get_resetting_count" somehow to be recursive and fetch parent value and
so on. I need to work on it to know if it's really possible.

> 
>> +        bus->reset_is_cold = dev->reset_is_cold;
>> +    }
>> +    return 0;
>> +}
>> +
>> +const struct VMStateDescription device_vmstate_reset = {
>> +    .name = "device_reset",
>> +    .version_id = 0,
>> +    .minimum_version_id = 0,
>> +    .needed = device_vmstate_reset_needed,
>> +    .post_load = device_vmstate_reset_post_load,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_UINT32(resetting, DeviceState),
>> +        VMSTATE_BOOL(reset_is_cold, DeviceState),
>> +        VMSTATE_END_OF_LIST()
>> +    },
>> +};
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-07-31  9:29     ` Damien Hedde
@ 2019-07-31 11:31       ` Philippe Mathieu-Daudé
  2019-08-08  6:47         ` David Gibson
  2019-08-08  6:48       ` David Gibson
  1 sibling, 1 reply; 113+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-31 11:31 UTC (permalink / raw)
  To: Damien Hedde, David Gibson
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

On 7/31/19 11:29 AM, Damien Hedde wrote:
> On 7/31/19 8:05 AM, David Gibson wrote:
>> On Mon, Jul 29, 2019 at 04:56:26PM +0200, Damien Hedde wrote:
>>> Deprecate old reset apis and make them use the new one while they
>>> are still used somewhere.
>>>
>>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>>> ---
>>>  hw/core/qdev.c         | 22 +++-------------------
>>>  include/hw/qdev-core.h | 28 ++++++++++++++++++++++------
>>>  2 files changed, 25 insertions(+), 25 deletions(-)
>>>
>>> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
>>> index 559ced070d..e9e5f2d5f9 100644
>>> --- a/hw/core/qdev.c
>>> +++ b/hw/core/qdev.c
>>> @@ -312,25 +312,9 @@ static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
>>>      }
>>>  }
>>>  
>>> -static int qdev_reset_one(DeviceState *dev, void *opaque)
>>> -{
>>> -    device_legacy_reset(dev);
>>> -
>>> -    return 0;
>>> -}
>>> -
>>> -static int qbus_reset_one(BusState *bus, void *opaque)
>>> -{
>>> -    BusClass *bc = BUS_GET_CLASS(bus);
>>> -    if (bc->reset) {
>>> -        bc->reset(bus);
>>> -    }
>>> -    return 0;
>>> -}
>>> -
>>>  void qdev_reset_all(DeviceState *dev)
>>>  {
>>> -    qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
>>> +    device_reset(dev, false);
>>>  }
>>>  
>>>  void qdev_reset_all_fn(void *opaque)
>>> @@ -340,7 +324,7 @@ void qdev_reset_all_fn(void *opaque)
>>>  
>>>  void qbus_reset_all(BusState *bus)
>>>  {
>>> -    qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
>>> +    bus_reset(bus, false);
>>>  }
>>>  
>>>  void qbus_reset_all_fn(void *opaque)
>>> @@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
>>>              }
>>>          }
>>>          if (dev->hotplugged) {
>>> -            device_legacy_reset(dev);
>>> +            device_reset(dev, true);
>>
>> So.. is this change in the device_reset() signature really necessary?
>> Even if there are compelling reasons to handle warm reset in the new
>> API, that doesn't been you need to change device_reset() itself from
>> its established meaning of a cold (i.e. as per power cycle) reset.
>> Warm resets are generally called in rather more specific circumstances
>> (often under guest software direction) so it seems likely that users
>> would want to engage with the new reset API directly.  Or we could
>> just create a device_warm_reset() wrapper.  That would also avoid the
>> bare boolean parameter, which is not great for readability (you have
>> to look up the signature to have any idea what it means).

If the boolean is not meaningful, we can use an enum...

> I've added device_reset_cold/warm wrapper functions to avoid having to
> pass the boolean parameter. it seems I forgot to use them in qdev.c
> I suppose, like you said, we could live with
> + no function with the boolean parameter
> + device_reset doing cold reset
> + device_reset_warm (or device_warm_reset) for the warm version
> 
> Damien
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 19/33] hw/sd/pl181.c & omap_mmc.c: remove device_legacy_reset call
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 19/33] hw/sd/pl181.c & omap_mmc.c: " Damien Hedde
@ 2019-07-31 15:48   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 113+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-31 15:48 UTC (permalink / raw)
  To: Damien Hedde, qemu-devel
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, kraxel, edgar.iglesias, hare, qemu-block,
	david, pasic, borntraeger, marcandre.lureau, david, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

On 7/29/19 4:56 PM, Damien Hedde wrote:
> Replace legacy's reset call by device_reset_warm.
> 
> The new function propagates also the reset to the sub-buses tree but this has
> no impact since SDState has no child bus.
> 
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/sd/omap_mmc.c | 2 +-
>  hw/sd/pl181.c    | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
> index 24a1edc149..3021e54b8d 100644
> --- a/hw/sd/omap_mmc.c
> +++ b/hw/sd/omap_mmc.c
> @@ -317,7 +317,7 @@ void omap_mmc_reset(struct omap_mmc_s *host)
>       * into any bus, and we must reset it manually. When omap_mmc is
>       * QOMified this must move into the QOM reset function.
>       */
> -    device_legacy_reset(DEVICE(host->card));
> +    device_reset_warm(DEVICE(host->card));
>  }
>  
>  static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
> diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
> index 15b4aaa67f..a59ef7eb2a 100644
> --- a/hw/sd/pl181.c
> +++ b/hw/sd/pl181.c
> @@ -480,7 +480,7 @@ static void pl181_reset(DeviceState *d)
>      /* Since we're still using the legacy SD API the card is not plugged
>       * into any bus, and we must reset it manually.
>       */
> -    device_legacy_reset(DEVICE(s->card));
> +    device_reset_warm(DEVICE(s->card));

We need to define what is a sdcard 'warm' reset.

>  }
>  
>  static void pl181_init(Object *obj)
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-31 10:17           ` Christophe de Dinechin
@ 2019-08-01  9:19             ` Damien Hedde
  2019-08-01  9:30               ` Christophe de Dinechin
  0 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-08-01  9:19 UTC (permalink / raw)
  To: Christophe de Dinechin, qemu-devel
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke,
	Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, David Gibson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, Richard Henderson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini


On 7/31/19 12:17 PM, Christophe de Dinechin wrote:
> 
> Peter Maydell writes:
> 
>> On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:
>>>
>>> On Tue, 30 Jul 2019 14:44:21 +0100
>>> Peter Maydell <peter.maydell@linaro.org> wrote:
>>>
>>>> On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
>>>>> I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
>>>>> supposed to be... can you add a definition/guideline somewhere?
>>>>
>>>> Generally "cold" reset is "power on" and "warm" is "we were already
>>>> powered-on, but somebody flipped a reset line somewhere".
>>>
>>> Ok, that makes sense... my main concern is to distinguish that in a
>>> generic way, as it is a generic interface. What about adding something
>>> like:
>>>
>>> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
>>> reset means that the object to be reset has already been initialized."
>>>
>>> Or is that again too generic?
>>
>> I think it doesn't quite capture the idea -- an object can have already
>> been reset and then get a 'cold' reset: this is like having a powered-on
>> machine and then power-cycling it.
>>
>> The 'warm' reset is the vaguer one, because the specific behaviour
>> is somewhat device-dependent (many devices might not have any
>> difference from 'cold' reset, for those that do the exact detail
>> of what doesn't get reset on warm-reset will vary). But every
>> device should have some kind of "as if you power-cycled it" (or
>> for QEMU, "go back to the same state as if you just started QEMU on the
>> command line"). Our current "reset" method is really cold-reset.
> 
> Is there any concept of locality associated with warm reset?
> For example, you'd expect a cold reset to happen on the whole system,
> but I guess a warm reset could be restricted to a single bus.
> 
> The documentation should give examples of how warm reset could be
> triggered, and what it could do differently from cold reset.
> 

Not sure we really have some locality difference between cold/warm
resets. I think, most generally, locality of reset is on a per-device
scale with different grouping level (up to the whole system). But buses
are not always the way things are grouped.

Inside a soc (and microcontrollers in general) it follows more the clock
tree than the internal bus tree. For example on the the machine I worked
here (xilinx-zynq-a9) and, you can control by software the reset of
basically every single device and the bus too (but resetting the bus
does not reset devices on it).

On the other hand, there is some buses, like pci, which explicitly
defines some bus reset mechanism with differences between cold and warm
(some registers keep their values). (see
https://wiki.qemu.org/Features/ResetAPI)

Regarding cold reset, if a soc supports some power gating, you'll
probably have non-global cold reset in the process.

Do you mean "real world" example ?


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-08-01  9:19             ` Damien Hedde
@ 2019-08-01  9:30               ` Christophe de Dinechin
  0 siblings, 0 replies; 113+ messages in thread
From: Christophe de Dinechin @ 2019-08-01  9:30 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, qemu-devel, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



> On 1 Aug 2019, at 11:19, Damien Hedde <damien.hedde@greensocs.com> wrote:
> 
> 
> On 7/31/19 12:17 PM, Christophe de Dinechin wrote:
>> 
>> Peter Maydell writes:
>> 
>>> On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:
>>>> 
>>>> On Tue, 30 Jul 2019 14:44:21 +0100
>>>> Peter Maydell <peter.maydell@linaro.org> wrote:
>>>> 
>>>>> On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
>>>>>> I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
>>>>>> supposed to be... can you add a definition/guideline somewhere?
>>>>> 
>>>>> Generally "cold" reset is "power on" and "warm" is "we were already
>>>>> powered-on, but somebody flipped a reset line somewhere".
>>>> 
>>>> Ok, that makes sense... my main concern is to distinguish that in a
>>>> generic way, as it is a generic interface. What about adding something
>>>> like:
>>>> 
>>>> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
>>>> reset means that the object to be reset has already been initialized."
>>>> 
>>>> Or is that again too generic?
>>> 
>>> I think it doesn't quite capture the idea -- an object can have already
>>> been reset and then get a 'cold' reset: this is like having a powered-on
>>> machine and then power-cycling it.
>>> 
>>> The 'warm' reset is the vaguer one, because the specific behaviour
>>> is somewhat device-dependent (many devices might not have any
>>> difference from 'cold' reset, for those that do the exact detail
>>> of what doesn't get reset on warm-reset will vary). But every
>>> device should have some kind of "as if you power-cycled it" (or
>>> for QEMU, "go back to the same state as if you just started QEMU on the
>>> command line"). Our current "reset" method is really cold-reset.
>> 
>> Is there any concept of locality associated with warm reset?
>> For example, you'd expect a cold reset to happen on the whole system,
>> but I guess a warm reset could be restricted to a single bus.
>> 
>> The documentation should give examples of how warm reset could be
>> triggered, and what it could do differently from cold reset.
>> 
> 
> Not sure we really have some locality difference between cold/warm
> resets. I think, most generally, locality of reset is on a per-device
> scale with different grouping level (up to the whole system). But buses
> are not always the way things are grouped.
> 
> Inside a soc (and microcontrollers in general) it follows more the clock
> tree than the internal bus tree. For example on the the machine I worked
> here (xilinx-zynq-a9) and, you can control by software the reset of
> basically every single device and the bus too (but resetting the bus
> does not reset devices on it).
> 
> On the other hand, there is some buses, like pci, which explicitly
> defines some bus reset mechanism with differences between cold and warm
> (some registers keep their values). (see
> https://wiki.qemu.org/Features/ResetAPI)
> 
> Regarding cold reset, if a soc supports some power gating, you'll
> probably have non-global cold reset in the process.
> 
> Do you mean "real world" example ?

I think that a variant of what you just wrote would be fine.
I was not aware for example that you could have non-global cold reset.


Thanks
Christophe




^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-31  5:46             ` David Gibson
@ 2019-08-01  9:35               ` Damien Hedde
  2019-08-12 10:27                 ` David Gibson
  0 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-08-01  9:35 UTC (permalink / raw)
  To: David Gibson
  Cc: Fam Zheng, Peter Maydell, Collin Walling, Dmitry Fleytman,
	Michael S. Tsirkin, Mark Cave-Ayland, QEMU Developers,
	Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke, Qemu-block,
	David Hildenbrand, Halil Pasic, Christian Borntraeger,
	Marc-André Lureau, Thomas Huth, Eduardo Habkost,
	Alistair Francis, qemu-s390x, qemu-arm, Cédric Le Goater,
	John Snow, Richard Henderson, Daniel P. Berrange, Cornelia Huck,
	Mark Burton, qemu-ppc, Paolo Bonzini



On 7/31/19 7:46 AM, David Gibson wrote:
> On Tue, Jul 30, 2019 at 04:08:59PM +0200, Damien Hedde wrote:
>>
>> On 7/30/19 3:59 PM, Peter Maydell wrote:
>>> On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:
>>>>
>>>> On Tue, 30 Jul 2019 14:44:21 +0100
>>>> Peter Maydell <peter.maydell@linaro.org> wrote:
>>>>
>>>>> On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
>>>>>> I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
>>>>>> supposed to be... can you add a definition/guideline somewhere?
>>>>>
>>>>> Generally "cold" reset is "power on" and "warm" is "we were already
>>>>> powered-on, but somebody flipped a reset line somewhere".
>>>>
>>>> Ok, that makes sense... my main concern is to distinguish that in a
>>>> generic way, as it is a generic interface. What about adding something
>>>> like:
>>>>
>>>> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
>>>> reset means that the object to be reset has already been initialized."
>>>>
>>>> Or is that again too generic?
>>>
>>> I think it doesn't quite capture the idea -- an object can have already
>>> been reset and then get a 'cold' reset: this is like having a powered-on
>>> machine and then power-cycling it.
>>>
>>> The 'warm' reset is the vaguer one, because the specific behaviour
>>> is somewhat device-dependent (many devices might not have any
>>> difference from 'cold' reset, for those that do the exact detail
>>> of what doesn't get reset on warm-reset will vary). But every
>>> device should have some kind of "as if you power-cycled it" (or
>>> for QEMU, "go back to the same state as if you just started QEMU on the
>>> command line"). Our current "reset" method is really cold-reset.
>>>
>>
>> Exactly. In the following patches, I've tried to replace existing reset
>> calls by cold or warm reset depending on whether:
>> + it is called through the main system reset -> cold
>> + it is called during normal life-time       -> warm
>>
>> But I definitely can add some docs/comments to better explain that.
> 
> Hrm, that helps, but it still seems pretty vague to me.
> 
> It's not really my call, but building the concept of warm versus cold
> resets into such a generic interface seems pretty dubios to me.  While
> it's moderately common for things to have a notion of warm versus cold
> reset it's certainly not universal.  There are many devices where
> there's no meaningful difference between the two.  There are some
> devices where there are > 2 different types of reset suitable for
> various different situations.
> 
> Is there any way this could work with it usually just presenting the
> cold reset (which is the closest to a universal concept), and any warm
> or additional resets are handled buy a different instance of the
> Resettable interface?
> 

In my current implementation, cold/warm is only a question of setting a
flag before calling the reset methods. I rely and the reset methods to
check that flag if necessary. The feature can be added/removed without
pain (if we stick with device_reset to do a cold one). So if it's
better, I can put it aside for now.

IMO handling warm reset with another interface is probably not a good
idea because it will need another load of methods.

--
Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-07-31  9:09     ` Damien Hedde
@ 2019-08-06  0:35       ` David Gibson
  2019-08-07  7:55         ` Damien Hedde
  0 siblings, 1 reply; 113+ messages in thread
From: David Gibson @ 2019-08-06  0:35 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 4703 bytes --]

On Wed, Jul 31, 2019 at 11:09:05AM +0200, Damien Hedde wrote:
> 
> 
> On 7/31/19 7:56 AM, David Gibson wrote:
> > On Mon, Jul 29, 2019 at 04:56:25PM +0200, Damien Hedde wrote:
> >> This add Resettable interface implementation for both Bus and Device.
> >>
> >> *resetting* counter and *reset_is_cold* flag are added in DeviceState
> >> and BusState.
> >>
> >> Compatibility with existing code base is ensured.
> >> The legacy bus or device reset method is called in the new exit phase
> >> and the other 2 phases are let empty. Using the exit phase guarantee that
> >> legacy resets are called in the "post" order (ie: children then parent)
> >> in hierarchical reset. That is the same order as legacy qdev_reset_all
> >> or qbus_reset_all were using.
> >>
> >> New *device_reset* and *bus_reset* function are proposed with an
> >> additional boolean argument telling whether the reset is cold or warm.
> >> Helper functions *device_reset_[warm|cold]* and *bus_reset_[warm|cold]*
> >> are defined also as helpers.
> >>
> >> Also add a [device|bus]_is_resetting and [device|bus]_is_reset_cold
> >> functions telling respectively whether the object is currently under reset and
> >> if the current reset is cold or not.
> >>
> >> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> >> ---
> >>  hw/core/bus.c          | 85 ++++++++++++++++++++++++++++++++++++++++++
> >>  hw/core/qdev.c         | 82 ++++++++++++++++++++++++++++++++++++++++
> >>  include/hw/qdev-core.h | 84 ++++++++++++++++++++++++++++++++++++++---
> >>  tests/Makefile.include |  1 +
> >>  4 files changed, 247 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/hw/core/bus.c b/hw/core/bus.c
> >> index 17bc1edcde..08a97addb6 100644
> >> --- a/hw/core/bus.c
> >> +++ b/hw/core/bus.c
> >> @@ -22,6 +22,7 @@
> >>  #include "qemu/module.h"
> >>  #include "hw/qdev.h"
> >>  #include "qapi/error.h"
> >> +#include "hw/resettable.h"
> >>  
> >>  void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
> >>  {
> >> @@ -68,6 +69,75 @@ int qbus_walk_children(BusState *bus,
> >>      return 0;
> >>  }
> >>  
> >> +void bus_reset(BusState *bus, bool cold)
> >> +{
> >> +    resettable_reset(OBJECT(bus), cold);
> >> +}
> >> +
> >> +bool bus_is_resetting(BusState *bus)
> >> +{
> >> +    return (bus->resetting != 0);
> >> +}
> >> +
> >> +bool bus_is_reset_cold(BusState *bus)
> >> +{
> >> +    return bus->reset_is_cold;
> >> +}
> >> +
> >> +static uint32_t bus_get_reset_count(Object *obj)
> >> +{
> >> +    BusState *bus = BUS(obj);
> >> +    return bus->resetting;
> >> +}
> >> +
> >> +static uint32_t bus_increment_reset_count(Object *obj)
> >> +{
> >> +    BusState *bus = BUS(obj);
> >> +    return ++bus->resetting;
> >> +}
> >> +
> >> +static uint32_t bus_decrement_reset_count(Object *obj)
> >> +{
> >> +    BusState *bus = BUS(obj);
> >> +    return --bus->resetting;
> >> +}
> >> +
> >> +static bool bus_set_reset_cold(Object *obj, bool cold)
> >> +{
> >> +    BusState *bus = BUS(obj);
> >> +    bool old = bus->reset_is_cold;
> >> +    bus->reset_is_cold = cold;
> >> +    return old;
> >> +}
> >> +
> >> +static bool bus_set_hold_needed(Object *obj, bool hold_needed)
> >> +{
> >> +    BusState *bus = BUS(obj);
> >> +    bool old = bus->reset_hold_needed;
> >> +    bus->reset_hold_needed = hold_needed;
> >> +    return old;
> >> +}
> >> +
> >> +static void bus_foreach_reset_child(Object *obj, void (*func)(Object *))
> >> +{
> >> +    BusState *bus = BUS(obj);
> >> +    BusChild *kid;
> >> +
> >> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> >> +        func(OBJECT(kid->child));
> >> +    }
> >> +}
> > 
> > IIUC, every resettable class would need more or less identical
> > implementations of the above.  That seems like an awful lot of
> > boilerplate.
> 
> Do you mean the get/increment_count/decrement_count, set_cold/hold part ?
> True, but it's limited to the base classes.
> Since Resettable is an interface, we have no state there to store what
> we need. Only alternative is to have some kind of single
> get_resettable_state method returning a pointer to the state (allowing
> us to keep the functions in the interface code).
> Beyond Device and Bus, which are done here, there is probably not so
> many class candidates for the Resettable interface.

Right.  I can't immediately see a better way to handle this, but it
still seems like a mild code smell.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-08-06  0:35       ` David Gibson
@ 2019-08-07  7:55         ` Damien Hedde
  2019-08-12 10:28           ` David Gibson
  0 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-08-07  7:55 UTC (permalink / raw)
  To: David Gibson
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini



On 8/6/19 2:35 AM, David Gibson wrote:
> On Wed, Jul 31, 2019 at 11:09:05AM +0200, Damien Hedde wrote:
>>
>>
>> On 7/31/19 7:56 AM, David Gibson wrote:
>>> On Mon, Jul 29, 2019 at 04:56:25PM +0200, Damien Hedde wrote:
>>>> This add Resettable interface implementation for both Bus and Device.
>>>>
>>>> *resetting* counter and *reset_is_cold* flag are added in DeviceState
>>>> and BusState.
>>>>
>>>> Compatibility with existing code base is ensured.
>>>> The legacy bus or device reset method is called in the new exit phase
>>>> and the other 2 phases are let empty. Using the exit phase guarantee that
>>>> legacy resets are called in the "post" order (ie: children then parent)
>>>> in hierarchical reset. That is the same order as legacy qdev_reset_all
>>>> or qbus_reset_all were using.
>>>>
>>>> New *device_reset* and *bus_reset* function are proposed with an
>>>> additional boolean argument telling whether the reset is cold or warm.
>>>> Helper functions *device_reset_[warm|cold]* and *bus_reset_[warm|cold]*
>>>> are defined also as helpers.
>>>>
>>>> Also add a [device|bus]_is_resetting and [device|bus]_is_reset_cold
>>>> functions telling respectively whether the object is currently under reset and
>>>> if the current reset is cold or not.
>>>>
>>>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>>>> ---
>>>>  hw/core/bus.c          | 85 ++++++++++++++++++++++++++++++++++++++++++
>>>>  hw/core/qdev.c         | 82 ++++++++++++++++++++++++++++++++++++++++
>>>>  include/hw/qdev-core.h | 84 ++++++++++++++++++++++++++++++++++++++---
>>>>  tests/Makefile.include |  1 +
>>>>  4 files changed, 247 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/hw/core/bus.c b/hw/core/bus.c
>>>> index 17bc1edcde..08a97addb6 100644
>>>> --- a/hw/core/bus.c
>>>> +++ b/hw/core/bus.c
>>>> @@ -22,6 +22,7 @@
>>>>  #include "qemu/module.h"
>>>>  #include "hw/qdev.h"
>>>>  #include "qapi/error.h"
>>>> +#include "hw/resettable.h"
>>>>  
>>>>  void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
>>>>  {
>>>> @@ -68,6 +69,75 @@ int qbus_walk_children(BusState *bus,
>>>>      return 0;
>>>>  }
>>>>  
>>>> +void bus_reset(BusState *bus, bool cold)
>>>> +{
>>>> +    resettable_reset(OBJECT(bus), cold);
>>>> +}
>>>> +
>>>> +bool bus_is_resetting(BusState *bus)
>>>> +{
>>>> +    return (bus->resetting != 0);
>>>> +}
>>>> +
>>>> +bool bus_is_reset_cold(BusState *bus)
>>>> +{
>>>> +    return bus->reset_is_cold;
>>>> +}
>>>> +
>>>> +static uint32_t bus_get_reset_count(Object *obj)
>>>> +{
>>>> +    BusState *bus = BUS(obj);
>>>> +    return bus->resetting;
>>>> +}
>>>> +
>>>> +static uint32_t bus_increment_reset_count(Object *obj)
>>>> +{
>>>> +    BusState *bus = BUS(obj);
>>>> +    return ++bus->resetting;
>>>> +}
>>>> +
>>>> +static uint32_t bus_decrement_reset_count(Object *obj)
>>>> +{
>>>> +    BusState *bus = BUS(obj);
>>>> +    return --bus->resetting;
>>>> +}
>>>> +
>>>> +static bool bus_set_reset_cold(Object *obj, bool cold)
>>>> +{
>>>> +    BusState *bus = BUS(obj);
>>>> +    bool old = bus->reset_is_cold;
>>>> +    bus->reset_is_cold = cold;
>>>> +    return old;
>>>> +}
>>>> +
>>>> +static bool bus_set_hold_needed(Object *obj, bool hold_needed)
>>>> +{
>>>> +    BusState *bus = BUS(obj);
>>>> +    bool old = bus->reset_hold_needed;
>>>> +    bus->reset_hold_needed = hold_needed;
>>>> +    return old;
>>>> +}
>>>> +
>>>> +static void bus_foreach_reset_child(Object *obj, void (*func)(Object *))
>>>> +{
>>>> +    BusState *bus = BUS(obj);
>>>> +    BusChild *kid;
>>>> +
>>>> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
>>>> +        func(OBJECT(kid->child));
>>>> +    }
>>>> +}
>>>
>>> IIUC, every resettable class would need more or less identical
>>> implementations of the above.  That seems like an awful lot of
>>> boilerplate.
>>
>> Do you mean the get/increment_count/decrement_count, set_cold/hold part ?
>> True, but it's limited to the base classes.
>> Since Resettable is an interface, we have no state there to store what
>> we need. Only alternative is to have some kind of single
>> get_resettable_state method returning a pointer to the state (allowing
>> us to keep the functions in the interface code).
>> Beyond Device and Bus, which are done here, there is probably not so
>> many class candidates for the Resettable interface.
> 
> Right.  I can't immediately see a better way to handle this, but it
> still seems like a mild code smell.
> 

Only definitive solution to this would be to make DeviceClass and
BusClass inherit from a common Resettable object.

Would it be better if I use a common struct (eg: ResettableState)
holding the different fields ?
Then I can have a single implementation of the method and do for example:
static uint32_t bus_decrement_reset_count(Object *obj)
{
     return decrement_reset_count(&(BUS(obj))->reset_state);
}
static uint32_t device_decrement_reset_count(Object *obj)
{
     return decrement_reset_count(&(DEV(dev))->reset_state);
}

I can also merge the 3 count related method into one if it helps.

--
Damien



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-07-31  6:30   ` David Gibson
  2019-07-31 10:05     ` Damien Hedde
@ 2019-08-07 10:34     ` Peter Maydell
  2019-08-08  6:49       ` David Gibson
  2019-08-07 16:01     ` Peter Maydell
  2 siblings, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 10:34 UTC (permalink / raw)
  To: David Gibson
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Thomas Huth,
	Eduardo Habkost, Alistair Francis, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

On Wed, 31 Jul 2019 at 07:33, David Gibson <david@gibson.dropbear.id.au> wrote:
>
> On Mon, Jul 29, 2019 at 04:56:30PM +0200, Damien Hedde wrote:
> > +The function *resettable_reset* is used to trigger a reset on a given
> > +object.
> > +void resettable_reset(Object *obj, bool cold)
> > +
> > +The parameter *obj* must implement the Resettable interface.
>
> And what happens if it doesn't?  This function has no way to report an
> error.

Trying to reset an object that isn't actually resettable would
be a programming error -- I think asserting is a reasonable
response to that.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-07-31  6:11   ` David Gibson
  2019-07-31 10:09     ` Damien Hedde
@ 2019-08-07 10:37     ` Peter Maydell
  2019-08-09  5:51       ` David Gibson
  1 sibling, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 10:37 UTC (permalink / raw)
  To: David Gibson
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Thomas Huth,
	Eduardo Habkost, Alistair Francis, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

On Wed, 31 Jul 2019 at 07:33, David Gibson <david@gibson.dropbear.id.au> wrote:
>
> On Mon, Jul 29, 2019 at 04:56:29PM +0200, Damien Hedde wrote:
> > It adds the possibility to add 2 gpios to control the warm and cold reset.
> > With theses ios, the reset can be maintained during some time.
> > Each io is associated with a state to detect level changes.
> >
> > Vmstate subsections are also added to the existsing device_reset
> > subsection.
>
> This doesn't seem like a thing that should be present on every single
> DeviceState.

It's a facility that's going to be useful to multiple different
subclasses of DeviceState, so it seems to me cleaner to
have base class support for the common feature rather than
to reimplement it entirely from scratch in every subclass
that wants it.

(The patch as written breaks migration compatibility -- the
new fields need to go in their own vmstate subsection
with a suitable 'needed' function -- but that can be fixed.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface Damien Hedde
  2019-07-30 13:42   ` Cornelia Huck
@ 2019-08-07 14:20   ` Peter Maydell
  2019-08-07 15:03     ` Damien Hedde
  1 sibling, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 14:20 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> This commit defines an interface allowing multi-phase reset.
> The phases are INIT, HOLD and EXIT. Each phase has an associated method
> in the class.
>
> The reset of a Resettable is controlled with 2 functions:
>   - resettable_assert_reset which starts the reset operation.
>   - resettable_deassert_reset which ends the reset operation.
>
> There is also a `resettable_reset` helper function which does assert then
> deassert allowing to do a proper reset in one call.
>
> In addition, two functions, *resettable_reset_cold_fn* and
> *resettable_reset_warm_fn*, are defined. They take only an opaque argument
> (for the Resettable object) and can be used as callbacks.
>
> The Resettable interface is "reentrant", _assert_ can be called several
> times and _deasert_ must be called the same number of times so that the

deassert

> Resettable leave reset state. It is supported by keeping a counter of
> the current number of _assert_ calls. The counter maintainance is done
> though 3 methods get/increment/decrement_count. A method set_cold is used
> to set the cold flag of the reset. Another method set_host_needed is used
> to ensure hold phase is executed only if required.
>
> Reset hierarchy is also supported. Each Resettable may have
> sub-Resettable objects. When resetting a Resettable, it is propagated to
> its children using the foreach_child method.
>
> When entering reset, init phases are executed parent-to-child order then
> hold phases are executed child-parent order.

Why do we execute the hold phase in child-to-parent order? I would
have expected this to follow the same order as the init phase.

> When leaving reset, exit phases are executed in child-to-parent order.
> This will allow to replace current qdev_reset mechanism by this interface
> without side-effects on reset order.

It makes sense that the exit phase is child-to-parent.

> Note: I used an uint32 for the count. This match the type already used
> in the existing resetting counter in hw/scsi/vmw_pvscsi.c for the
> PVSCSIState.
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  Makefile.objs           |   1 +
>  hw/core/Makefile.objs   |   1 +
>  hw/core/resettable.c    | 220 ++++++++++++++++++++++++++++++++++++++++
>  hw/core/trace-events    |  39 +++++++
>  include/hw/resettable.h | 126 +++++++++++++++++++++++
>  5 files changed, 387 insertions(+)
>  create mode 100644 hw/core/resettable.c
>  create mode 100644 hw/core/trace-events
>  create mode 100644 include/hw/resettable.h
>
> diff --git a/Makefile.objs b/Makefile.objs
> index 6a143dcd57..a723a47e14 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -191,6 +191,7 @@ trace-events-subdirs += migration
>  trace-events-subdirs += net
>  trace-events-subdirs += ui
>  endif
> +trace-events-subdirs += hw/core
>  trace-events-subdirs += hw/display
>  trace-events-subdirs += qapi
>  trace-events-subdirs += qom
> diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
> index f8481d959f..d9234aa98a 100644
> --- a/hw/core/Makefile.objs
> +++ b/hw/core/Makefile.objs
> @@ -1,6 +1,7 @@
>  # core qdev-related obj files, also used by *-user:
>  common-obj-y += qdev.o qdev-properties.o
>  common-obj-y += bus.o reset.o
> +common-obj-y += resettable.o
>  common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
>  common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
>  # irq.o needed for qdev GPIO handling:
> diff --git a/hw/core/resettable.c b/hw/core/resettable.c
> new file mode 100644
> index 0000000000..d7d631ce8b
> --- /dev/null
> +++ b/hw/core/resettable.c
> @@ -0,0 +1,220 @@
> +/*
> + * Resettable interface.
> + *
> + * Copyright (c) 2019 GreenSocs SAS
> + *
> + * Authors:
> + *   Damien Hedde
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/module.h"
> +#include "hw/resettable.h"
> +#include "trace.h"
> +
> +#define RESETTABLE_MAX_COUNT 50
> +
> +#define RESETTABLE_GET_CLASS(obj) \
> +    OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE)

Since this is an interface and not a complete class,
we should name it TYPE_RESETTABLE_INTERFACE. We're rather
inconsistent about naming of interfaces (in the codebase you
can find "_INTERFACE suffix", "_IF suffix" and "no suffix").
I think _INTERFACE suffix is best of these.
(There's some discussion of this in this mailing list thread:
https://lists.gnu.org/archive/html/qemu-devel/2019-03/msg03840.html
 -- the idea is that it avoids confusion between whether an
implementation of the type needs to be a subclass of it or
if it has to be added as an interface to some other type.)

> +
> +static void resettable_init_reset(Object *obj, bool cold);
> +
> +static bool resettable_class_check(ResettableClass *rc)
> +{
> +    if (!rc->set_cold) {
> +        return false;
> +    }
> +    if (!rc->set_hold_needed) {
> +        return false;
> +    }
> +    if (!rc->increment_count) {
> +        return false;
> +    }
> +    if (!rc->decrement_count) {
> +        return false;
> +    }
> +    if (!rc->get_count) {
> +        return false;
> +    }
> +    return true;
> +}

I don't think we really need to do this -- this is only used
as an assert(), and the code is in any case going to exercise
all the methods. Plus we only implement these methods in a couple
of classes and we don't expect a lot of new implementations of them.

> +
> +static void resettable_foreach_child(ResettableClass *rc,
> +                                     Object *obj,
> +                                     void (*func)(Object *))
> +{
> +    if (rc->foreach_child) {
> +        rc->foreach_child(obj, func);
> +    }
> +}
> +
> +static void resettable_init_cold_reset(Object *obj)
> +{
> +    resettable_init_reset(obj, true);
> +}
> +
> +static void resettable_init_warm_reset(Object *obj)
> +{
> +    resettable_init_reset(obj, false);
> +}
> +
> +static void resettable_init_reset(Object *obj, bool cold)
> +{
> +    void (*func)(Object *);
> +    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
> +    uint32_t count;
> +    bool action_needed = false;
> +    bool prev_cold;
> +
> +    assert(resettable_class_check(rc));
> +
> +    count = rc->increment_count(obj);
> +    /* this assert is here to catch an eventual reset loop */
> +    assert(count <= RESETTABLE_MAX_COUNT);

I think I understand what this assert is for, but a slightly
expanded comment would help.

> +
> +    /*
> +     * only take action if:
> +     * + we really enter reset for the 1st time
> +     * + or we are in warm reset and start a cold one
> +     */
> +    prev_cold = rc->set_cold(obj, cold);
> +    if (count == 1) {
> +        action_needed = true;
> +    } else if (cold && !prev_cold) {
> +        action_needed = true;
> +    }
> +    trace_resettable_phase_init(obj, object_get_typename(obj), cold, count,
> +                                action_needed);
> +
> +    /* exec init phase */
> +    if (action_needed) {
> +        rc->set_hold_needed(obj, true);
> +        if (rc->phases.init) {
> +            rc->phases.init(obj);
> +        }
> +    }
> +
> +    /*
> +     * handle the children even if action_needed is at false so that
> +     * children counts are incremented too
> +     */
> +    func = cold ? resettable_init_cold_reset : resettable_init_warm_reset;
> +    resettable_foreach_child(rc, obj, func);
> +    trace_resettable_phase_init_end(obj);
> +}
> +
> +static void resettable_hold_reset(Object *obj)
> +{
> +    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
> +    bool hold_needed;
> +
> +    assert(resettable_class_check(rc));
> +    trace_resettable_phase_hold(obj, object_get_typename(obj));
> +
> +    /* handle children first */
> +    resettable_foreach_child(rc, obj, resettable_hold_reset);
> +
> +    /* exec hold phase */
> +    hold_needed = rc->set_hold_needed(obj, false);
> +    if (hold_needed) {
> +        if (rc->phases.hold) {
> +            rc->phases.hold(obj);
> +        }
> +    }
> +    trace_resettable_phase_hold_end(obj, hold_needed);
> +}
> +
> +static void resettable_exit_reset(Object *obj)
> +{
> +    uint32_t count;
> +    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
> +
> +    assert(resettable_class_check(rc));
> +    trace_resettable_phase_exit(obj, object_get_typename(obj));
> +
> +    resettable_foreach_child(rc, obj, resettable_deassert_reset);
> +
> +    count = rc->get_count(obj);
> +    /*
> +     * we could assert that count > 0 but there are some corner cases
> +     * where we prefer to let it go as it is probably harmless.
> +     * For example: if there is reset support addition between
> +     * hosts when doing a migration. We may do such things as
> +     * deassert a non-existing reset.
> +     */
> +    if (count > 0) {
> +        count = rc->decrement_count(obj);
> +    } else {
> +        trace_resettable_count_underflow(obj);
> +    }
> +    if (count == 0) {
> +        if (rc->phases.exit) {
> +            rc->phases.exit(obj);
> +        }
> +    }
> +    trace_resettable_phase_exit_end(obj, count);
> +}
> +
> +void resettable_assert_reset(Object *obj, bool cold)
> +{
> +    trace_resettable_reset_assert(obj, object_get_typename(obj), cold);
> +    resettable_init_reset(obj, cold);
> +    resettable_hold_reset(obj);
> +}
> +
> +void resettable_deassert_reset(Object *obj)
> +{
> +    trace_resettable_reset_deassert(obj, object_get_typename(obj));
> +    resettable_exit_reset(obj);
> +}
> +
> +void resettable_reset(Object *obj, bool cold)
> +{
> +    trace_resettable_reset(obj, object_get_typename(obj), cold);
> +    resettable_assert_reset(obj, cold);
> +    resettable_deassert_reset(obj);
> +}
> +
> +void resettable_reset_warm_fn(void *opaque)
> +{
> +    resettable_reset((Object *) opaque, false);
> +}
> +
> +void resettable_reset_cold_fn(void *opaque)
> +{
> +    resettable_reset((Object *) opaque, true);
> +}
> +
> +void resettable_class_set_parent_reset_phases(ResettableClass *rc,
> +                                              ResettableInitPhase init,
> +                                              ResettableHoldPhase hold,
> +                                              ResettableExitPhase exit,
> +                                              ResettablePhases *parent_phases)
> +{
> +    *parent_phases = rc->phases;
> +    if (init) {
> +        rc->phases.init = init;
> +    }
> +    if (hold) {
> +        rc->phases.hold = hold;
> +    }
> +    if (exit) {
> +        rc->phases.exit = exit;
> +    }
> +}
> +
> +static const TypeInfo resettable_interface_info = {
> +    .name       = TYPE_RESETTABLE,
> +    .parent     = TYPE_INTERFACE,
> +    .class_size = sizeof(ResettableClass),
> +};
> +
> +static void reset_register_types(void)
> +{
> +    type_register_static(&resettable_interface_info);
> +}
> +
> +type_init(reset_register_types)
> diff --git a/hw/core/trace-events b/hw/core/trace-events
> new file mode 100644
> index 0000000000..489d96d445
> --- /dev/null
> +++ b/hw/core/trace-events
> @@ -0,0 +1,39 @@
> +# See docs/devel/tracing.txt for syntax documentation.
> +#
> +# This file is processed by the tracetool script during the build.
> +#
> +# To add a new trace event:
> +#
> +# 1. Choose a name for the trace event.  Declare its arguments and format
> +#    string.
> +#
> +# 2. Call the trace event from code using trace_##name, e.g. multiwrite_cb() ->
> +#    trace_multiwrite_cb().  The source file must #include "trace.h".
> +#
> +# Format of a trace event:
> +#
> +# [disable] <name>(<type1> <arg1>[, <type2> <arg2>] ...) "<format-string>"
> +#
> +# Example: g_malloc(size_t size) "size %zu"
> +#
> +# The "disable" keyword will build without the trace event.
> +#
> +# The <name> must be a valid as a C function name.
> +#
> +# Types should be standard C types.  Use void * for pointers because the trace
> +# system may not have the necessary headers included.
> +#
> +# The <format-string> should be a sprintf()-compatible format string.
> +
> +# resettable.c
> +resettable_reset(void *obj, const char *type, int cold) "obj=%p(%s) cold=%d"
> +resettable_reset_assert(void *obj, const char *type, int cold) "obj=%p(%s) cold=%d"
> +resettable_reset_deassert(void *obj, const char *type) "obj=%p(%s)"
> +resettable_reset_deassert_end(void *obj) "obj=%p"
> +resettable_phase_init(void *obj, const char *type, int cold, uint32_t count, int needed) "obj=%p(%s) cold=%d count=%" PRIu32 " needed=%d"
> +resettable_phase_init_end(void *obj) "obj=%p"
> +resettable_phase_hold(void *obj, const char *type) "obj=%p(%s)"
> +resettable_phase_hold_end(void *obj, int needed) "obj=%p needed=%d"
> +resettable_phase_exit(void *obj, const char *type) "obj=%p(%s)"
> +resettable_phase_exit_end(void *obj, uint32_t count) "obj=%p count=%" PRIu32
> +resettable_count_underflow(void *obj) "obj=%p"
> diff --git a/include/hw/resettable.h b/include/hw/resettable.h
> new file mode 100644
> index 0000000000..e617a8e875
> --- /dev/null
> +++ b/include/hw/resettable.h
> @@ -0,0 +1,126 @@
> +#ifndef HW_RESETTABLE_H
> +#define HW_RESETTABLE_H
> +
> +#include "qom/object.h"
> +
> +#define TYPE_RESETTABLE "resettable"
> +
> +#define RESETTABLE_CLASS(class) \
> +    OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE)
> +
> +/*
> + * ResettableClass:
> + * Interface for resettable objects.
> + *
> + * The reset operation is divided in several phases each represented by a
> + * method.
> + *
> + * Each Ressetable must maintain a reset counter in its state, 3 methods allows

"resettable"

> + * to interact with it.

I think we could improve this comment to be a bit clearer about
who we expect to implement which methods. Something like:

/*
 * ResettableClass:
 * Interface for resettable objects.
 *
 * See docs/devel/reset.rst for more detailed information about
 * how QEMU models reset.
 *
 * All objects which can be reset must implement this interface;
 * it is usually provided by a base class such as DeviceClass or BusClass.
 * Every Resettable object must maintain some state tracking the
 * progress of a reset operation:
 *  - a reset count, which is incremented when the reset operation
 *    starts and decremented when it finishes
 *  - a 'cold' flag, which tracks whether the in-progress reset is
 *    a warm reset or a cold reset
 *  - a 'hold_needed' flag, which indicates that we need to
 *    invoke the 'hold' phase handler for this object
 * The base class implementation of the interface provides this
 * state and implements the associated methods: set_cold,
 * set_hold_needed, get_count, increment_count and decrement_count.
 *
 * Concrete object implementations (typically specific devices
 * such as a UART model) should provide the functions
 * for the phases.init, phases.hold and phases.exit methods, which
 * they can set in their class init function, either directly or
 * by calling resettable_class_set_parent_reset_phases().
 * The phase methods are guaranteed to only only ever be called once
 * for any reset event, in the order 'init', 'hold', 'exit'.
 * An object will always move quickly from 'init' to 'hold'
 * but might remain in 'hold' for an arbitrary period of time
 * before eventually reset is deasserted and the 'exit' phase is called.
 * Object implementations should be prepared for functions handling
 * inbound connections from other devices (such as qemu_irq handler
 * functions) to be called at any point during reset after their
 * 'init' method has been called.
 *
 * Users of a resettable object should not call these methods
 * directly, but instead use the functions resettable_assert_reset(),
 * resettable_deassert_reset() or resettable_reset().


> + *
> + * @phases.init: should reset local state only. Takes a bool @cold argument
> + * specifying whether the reset is cold or warm. It must not do side-effect
> + * on others objects.

This says that phases.init takes a 'cold' argument, but the prototype
doesn't have one.

"This phase is called when the object enters reset. It should reset
local state of the object, but it must not do anything that has a
side-effect on other objects, such as raising or lowering a qemu_irq line
or reading or writing guest memory."

> + *
> + * @phases.hold: side-effects action on others objects due to staying in a
> + * resetting state.

"This phase is called for entry into reset, once every object in the
system which is being reset has had its @phases.init method called.
At this point devices can do actions that affect other objects."


> + *
> + * @phases.exit: leave the reset state, may do side-effects action on others
> + * objects.

"This phase is called when the object leaves the reset state. Actions
affecting other objects are permitted."

> + *
> + * @set_cold: Set whether the current reset is cold or warm. Return the
> + * previous flag value. Return value has no meaning if @get_count returns
> + * a zero value.
> + *
> + * @set_hold_needed: Set hold_needed flag. Return the previous flag value.
> + *
> + * @get_count: Get the current reset count
> + * @increment_count: Increment the reset count, returns the new count
> + * @decrement_count: decrement the reset count, returns the new count
> + *
> + * @foreach_child: Executes a given function on every Resettable child.
> + * A child is not a QOM child, but a child a reset meaning.

"Child in this context means a child in the qbus tree, so the
children of a qbus are the devices on it, and the children of
a device are all the buses it owns. This is not the same as the
QOM object hierarchy."

> + */
> +typedef void (*ResettableInitPhase)(Object *obj);
> +typedef void (*ResettableHoldPhase)(Object *obj);
> +typedef void (*ResettableExitPhase)(Object *obj);
> +typedef bool (*ResettableSetCold)(Object *obj, bool cold);
> +typedef bool (*ResettableSetHoldNeeded)(Object *obj, bool hold_needed);
> +typedef uint32_t (*ResettableGetCount)(Object *obj);
> +typedef uint32_t (*ResettableIncrementCount)(Object *obj);
> +typedef uint32_t (*ResettableDecrementCount)(Object *obj);
> +typedef void (*ResettableForeachChild)(Object *obj, void (*visitor)(Object *));
> +typedef struct ResettableClass {
> +    InterfaceClass parent_class;
> +
> +    struct ResettablePhases {
> +        ResettableInitPhase init;
> +        ResettableHoldPhase hold;
> +        ResettableExitPhase exit;
> +    } phases;
> +
> +    ResettableSetCold set_cold;
> +    ResettableSetHoldNeeded set_hold_needed;
> +    ResettableGetCount get_count;
> +    ResettableIncrementCount increment_count;
> +    ResettableDecrementCount decrement_count;
> +    ResettableForeachChild foreach_child;
> +} ResettableClass;
> +typedef struct ResettablePhases ResettablePhases;
> +
> +/**
> + * resettable_assert_reset:

"Put the object into reset, and hold it there until
the caller later calls resettable_deassert_reset()."

> + * Increments the reset count and executes the init and hold phases.
> + * Each time resettable_assert_reset is called, resettable_deassert_reset
> + * must eventually be called once.
> + * It will also impact reset children.

"This will reset the specified object and all of its reset children."

> + *
> + * @obj object to reset, must implement Resettable interface.
> + * @cold boolean indicating the type of reset (cold or warm)
> + */
> +void resettable_assert_reset(Object *obj, bool cold);
> +
> +/**
> + * resettable_deassert_reset:

"Take the object out of reset."

> + * Decrements the reset count by one and executes the exit phase if it hits
> + * zero.
> + * It will also impact reset children.
> + *
> + * @obj object to reset, must implement Resettable interface.
> + */
> +void resettable_deassert_reset(Object *obj);
> +
> +/**
> + * resettable_reset:
> + * Calling this function is equivalent to call @assert_reset then

"to calling"

> + * @deassert_reset.
> + */
> +void resettable_reset(Object *obj, bool cold);
> +
> +/**
> + * resettable_reset_warm_fn:
> + * Helper to call resettable_reset(opaque, false)
> + */
> +void resettable_reset_warm_fn(void *opaque);
> +
> +/**
> + * resettable_reset_cold_fn:
> + * Helper to call resettable_reset(opaque, true)
> + */
> +void resettable_reset_cold_fn(void *opaque);
> +
> +/**
> + * resettable_class_set_parent_reset_phases:
> + *
> + * Save @rc current reset phases into @parent_phases and override @rc phases
> + * by the given new methods (@init, @hold and @exit).
> + * Each phase is overriden only if the new one is not NULL allowing to

"overridden"

> + * override a subset of phases.
> + */
> +void resettable_class_set_parent_reset_phases(ResettableClass *rc,
> +                                              ResettableInitPhase init,
> +                                              ResettableHoldPhase hold,
> +                                              ResettableExitPhase exit,
> +                                              ResettablePhases *parent_phases);
> +
> +#endif

This function name is quite long -- I think we could reasonably
call it resettable_class_set_parent_phases().

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/33] add temporary device_legacy_reset function to replace device_reset
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 02/33] add temporary device_legacy_reset function to replace device_reset Damien Hedde
@ 2019-08-07 14:27   ` Peter Maydell
  2019-08-09  9:20     ` Damien Hedde
  0 siblings, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 14:27 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> Provide a temporary function doing what device_reset does to do the
> transition with Resettable API which will trigger a prototype change
> of device_reset.

The other point here is that device_legacy_reset() resets
only that device, not any of its qbus children, right?
So the new function which we eventually replace the callsites
with also has different semantics, which is why we do the
changes one by one in patches 10-28.

So you could add:

The new resettable API function also has different semantics
(resetting child buses as well as the specified device).
Subsequent commits will make the changeover for each callsite
individually; once that is complete device_legacy_reset() will be
removed.

> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>

I agree with David that patch 3 could be squashed into this one.

If you do that and tweak the commit message you can have
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable Damien Hedde
  2019-07-31  5:56   ` David Gibson
@ 2019-08-07 14:41   ` Peter Maydell
  2019-08-07 15:23     ` Damien Hedde
  2019-08-12  9:08     ` Damien Hedde
  1 sibling, 2 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 14:41 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> This add Resettable interface implementation for both Bus and Device.
>
> *resetting* counter and *reset_is_cold* flag are added in DeviceState
> and BusState.
>
> Compatibility with existing code base is ensured.
> The legacy bus or device reset method is called in the new exit phase
> and the other 2 phases are let empty. Using the exit phase guarantee that

"left". "guarantees"

> legacy resets are called in the "post" order (ie: children then parent)
> in hierarchical reset. That is the same order as legacy qdev_reset_all
> or qbus_reset_all were using.

This is true, but on the other hand the semantics of most device
reset methods match "init", not "exit" -- they just set device
internal fields to the correct reset state.

> New *device_reset* and *bus_reset* function are proposed with an
> additional boolean argument telling whether the reset is cold or warm.
> Helper functions *device_reset_[warm|cold]* and *bus_reset_[warm|cold]*
> are defined also as helpers.
>
> Also add a [device|bus]_is_resetting and [device|bus]_is_reset_cold
> functions telling respectively whether the object is currently under reset and
> if the current reset is cold or not.

I was expecting this patch to contain handling for migration
of the new data fields. That's in a later patch, so the
commit message here should say something like:

"This commit adds new fields to BusState and DeviceState, but
does not set up migration handling for them; so the new functions
can only be called after the subsequent commit which adds the
migration support."

> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/bus.c          | 85 ++++++++++++++++++++++++++++++++++++++++++
>  hw/core/qdev.c         | 82 ++++++++++++++++++++++++++++++++++++++++
>  include/hw/qdev-core.h | 84 ++++++++++++++++++++++++++++++++++++++---
>  tests/Makefile.include |  1 +
>  4 files changed, 247 insertions(+), 5 deletions(-)
>
> diff --git a/hw/core/bus.c b/hw/core/bus.c
> index 17bc1edcde..08a97addb6 100644
> --- a/hw/core/bus.c
> +++ b/hw/core/bus.c
> @@ -22,6 +22,7 @@
>  #include "qemu/module.h"
>  #include "hw/qdev.h"
>  #include "qapi/error.h"
> +#include "hw/resettable.h"
>
>  void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
>  {
> @@ -68,6 +69,75 @@ int qbus_walk_children(BusState *bus,
>      return 0;
>  }
>
> +void bus_reset(BusState *bus, bool cold)
> +{
> +    resettable_reset(OBJECT(bus), cold);
> +}
> +
> +bool bus_is_resetting(BusState *bus)
> +{
> +    return (bus->resetting != 0);
> +}
> +
> +bool bus_is_reset_cold(BusState *bus)
> +{
> +    return bus->reset_is_cold;
> +}
> +
> +static uint32_t bus_get_reset_count(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    return bus->resetting;
> +}
> +
> +static uint32_t bus_increment_reset_count(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    return ++bus->resetting;
> +}
> +
> +static uint32_t bus_decrement_reset_count(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    return --bus->resetting;
> +}
> +
> +static bool bus_set_reset_cold(Object *obj, bool cold)
> +{
> +    BusState *bus = BUS(obj);
> +    bool old = bus->reset_is_cold;
> +    bus->reset_is_cold = cold;
> +    return old;
> +}
> +
> +static bool bus_set_hold_needed(Object *obj, bool hold_needed)
> +{
> +    BusState *bus = BUS(obj);
> +    bool old = bus->reset_hold_needed;
> +    bus->reset_hold_needed = hold_needed;
> +    return old;
> +}
> +
> +static void bus_foreach_reset_child(Object *obj, void (*func)(Object *))
> +{
> +    BusState *bus = BUS(obj);
> +    BusChild *kid;
> +
> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> +        func(OBJECT(kid->child));
> +    }
> +}
> +
> +static void bus_obj_legacy_reset(Object *obj)
> +{
> +    BusState *bus = BUS(obj);
> +    BusClass *bc = BUS_GET_CLASS(obj);
> +
> +    if (bc->reset) {
> +        bc->reset(bus);
> +    }
> +}
> +
>  static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
>  {
>      const char *typename = object_get_typename(OBJECT(bus));
> @@ -192,6 +262,8 @@ static void qbus_initfn(Object *obj)
>                               NULL);
>      object_property_add_bool(obj, "realized",
>                               bus_get_realized, bus_set_realized, NULL);
> +
> +    bus->resetting = 0;
>  }
>
>  static char *default_bus_get_fw_dev_path(DeviceState *dev)
> @@ -202,9 +274,18 @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
>  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->phases.exit = bus_obj_legacy_reset;
> +    rc->get_count = bus_get_reset_count;
> +    rc->increment_count = bus_increment_reset_count;
> +    rc->decrement_count = bus_decrement_reset_count;
> +    rc->foreach_child = bus_foreach_reset_child;
> +    rc->set_cold = bus_set_reset_cold;
> +    rc->set_hold_needed = bus_set_hold_needed;
>  }
>
>  static void qbus_finalize(Object *obj)
> @@ -223,6 +304,10 @@ static const TypeInfo bus_info = {
>      .instance_init = qbus_initfn,
>      .instance_finalize = qbus_finalize,
>      .class_init = bus_class_init,
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_RESETTABLE },
> +        { }
> +    },
>  };
>
>  static void bus_register_types(void)
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 043e058396..559ced070d 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -254,6 +254,64 @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
>      return hotplug_ctrl;
>  }
>
> +void device_reset(DeviceState *dev, bool cold)
> +{
> +    resettable_reset(OBJECT(dev), cold);
> +}
> +
> +bool device_is_resetting(DeviceState *dev)
> +{
> +    return (dev->resetting != 0);
> +}
> +
> +bool device_is_reset_cold(DeviceState *dev)
> +{
> +    return dev->reset_is_cold;
> +}
> +
> +static uint32_t device_get_reset_count(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    return dev->resetting;
> +}
> +
> +static uint32_t device_increment_reset_count(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    return ++dev->resetting;
> +}
> +
> +static uint32_t device_decrement_reset_count(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    return --dev->resetting;
> +}
> +
> +static bool device_set_reset_cold(Object *obj, bool cold)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    bool old = dev->reset_is_cold;
> +    dev->reset_is_cold = cold;
> +    return old;
> +}
> +
> +static bool device_set_hold_needed(Object *obj, bool hold_needed)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    bool old = dev->reset_hold_needed;
> +    dev->reset_hold_needed = hold_needed;
> +    return old;
> +}
> +
> +static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    BusState *bus;
> +    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> +        func(OBJECT(bus));
> +    }
> +}
> +
>  static int qdev_reset_one(DeviceState *dev, void *opaque)
>  {
>      device_legacy_reset(dev);
> @@ -954,6 +1012,7 @@ static void device_initfn(Object *obj)
>
>      dev->instance_id_alias = -1;
>      dev->realized = false;
> +    dev->resetting = 0;
>
>      object_property_add_bool(obj, "realized",
>                               device_get_realized, device_set_realized, NULL);
> @@ -1046,9 +1105,20 @@ static void device_unparent(Object *obj)
>      }
>  }
>
> +static void device_obj_legacy_reset(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> +    if (dc->reset) {
> +        dc->reset(dev);
> +    }
> +}
> +
>  static void device_class_init(ObjectClass *class, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(class);
> +    ResettableClass *rc = RESETTABLE_CLASS(class);
>
>      class->unparent = device_unparent;
>
> @@ -1060,6 +1130,14 @@ static void device_class_init(ObjectClass *class, void *data)
>       */
>      dc->hotpluggable = true;
>      dc->user_creatable = true;
> +
> +    rc->phases.exit = device_obj_legacy_reset;
> +    rc->get_count = device_get_reset_count;
> +    rc->increment_count = device_increment_reset_count;
> +    rc->decrement_count = device_decrement_reset_count;
> +    rc->foreach_child = device_foreach_reset_child;
> +    rc->set_cold = device_set_reset_cold;
> +    rc->set_hold_needed = device_set_hold_needed;
>  }
>
>  void device_class_set_parent_reset(DeviceClass *dc,
> @@ -1117,6 +1195,10 @@ static const TypeInfo device_type_info = {
>      .class_init = device_class_init,
>      .abstract = true,
>      .class_size = sizeof(DeviceClass),
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_RESETTABLE },
> +        { }
> +    },
>  };
>
>  static void qdev_register_types(void)
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 690ce72433..eeb75611c8 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -7,6 +7,7 @@
>  #include "hw/irq.h"
>  #include "hw/hotplug.h"
>  #include "sysemu/sysemu.h"
> +#include "hw/resettable.h"
>
>  enum {
>      DEV_NVECTORS_UNSPECIFIED = -1,
> @@ -132,6 +133,10 @@ struct NamedGPIOList {
>  /**
>   * DeviceState:
>   * @realized: Indicates whether the device has been fully constructed.
> + * @resetting: Indicates whether the device is under reset. Also
> + * used to count how many times reset has been initiated on the device.
> + * @reset_is_cold: If the device is under reset, indicates whether it is cold
> + * or warm.

We should put a doc comment entry for @reset_hold_needed here too.

>   *
>   * This structure should not be accessed directly.  We declare it here
>   * so that it can be embedded in individual device state structures.
> @@ -153,6 +158,9 @@ struct DeviceState {
>      int num_child_bus;
>      int instance_id_alias;
>      int alias_required_for_version;
> +    uint32_t resetting;
> +    bool reset_is_cold;
> +    bool reset_hold_needed;
>  };
>
>  struct DeviceListener {
> @@ -199,6 +207,10 @@ typedef struct BusChild {
>  /**
>   * BusState:
>   * @hotplug_handler: link to a hotplug handler associated with bus.
> + * @resetting: Indicates whether the bus is under reset. Also
> + * used to count how many times reset has been initiated on the bus.
> + * @reset_is_cold: If the bus is under reset, indicates whether it is cold
> + * or warm.

@reset_hold_needed missing.

>   */
>  struct BusState {
>      Object obj;
> @@ -210,6 +222,9 @@ struct BusState {
>      int num_children;
>      QTAILQ_HEAD(, BusChild) children;
>      QLIST_ENTRY(BusState) sibling;
> +    uint32_t resetting;
> +    bool reset_is_cold;
> +    bool reset_hold_needed;
>  };
>
>  /**
> @@ -376,6 +391,70 @@ int qdev_walk_children(DeviceState *dev,
>                         qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
>                         void *opaque);
>
> +/**
> + * device_reset:
> + * Resets the device @dev, @cold tell whether to do a cold or warm reset.

"Resets the device @dev. @cold is true if this is a cold reset."


> + * Uses the ressetable interface.

"Resettable".

> + * Base behavior is to reset the device and its qdev/qbus subtree.

What do you mean by "base behavior" here? When would this ever
do anything else?

> + */
> +void device_reset(DeviceState *dev, bool cold);
> +
> +static inline void device_reset_warm(DeviceState *dev)
> +{
> +    device_reset(dev, false);
> +}
> +
> +static inline void device_reset_cold(DeviceState *dev)
> +{
> +    device_reset(dev, true);
> +}
> +
> +/**
> + * bus_reset:
> + * Resets the bus @bus, @cold tell whether to do a cold or warm reset.
> + * Uses the ressetable interface.
> + * Base behavior is to reset the bus and its qdev/qbus subtree.

Same remarks as for device_reset above.

> + */
> +void bus_reset(BusState *bus, bool cold);
> +
> +static inline void bus_reset_warm(BusState *bus)
> +{
> +    bus_reset(bus, false);
> +}
> +
> +static inline void bus_reset_cold(BusState *bus)
> +{
> +    bus_reset(bus, true);
> +}
> +
> +/**
> + * device_is_resetting:
> + * Tell whether the device @dev is currently under reset.

"Return true if the device @dev is currently being reset."

> + */
> +bool device_is_resetting(DeviceState *dev);
> +
> +/**
> + * device_is_reset_cold:
> + * Tell whether the device @dev is currently under reset cold or warm reset.

"Return true if the reset currently in progress for @dev is
a cold reset."

> + *
> + * Note: only valid when device_is_resetting returns true.
> + */
> +bool device_is_reset_cold(DeviceState *dev);
> +
> +/**
> + * bus_is_resetting:
> + * Tell whether the bus @bus is currently under reset.

[similar rephrasings as above for 'tell whether']

> + */
> +bool bus_is_resetting(BusState *bus);
> +
> +/**
> + * bus_is_reset_cold:
> + * Tell whether the bus @bus is currently under reset cold or warm reset.
> + *
> + * Note: only valid when bus_is_resetting returns true.
> + */
> +bool bus_is_reset_cold(BusState *bus);
> +
>  void qdev_reset_all(DeviceState *dev);
>  void qdev_reset_all_fn(void *opaque);
>
> @@ -413,11 +492,6 @@ void qdev_machine_init(void);
>   */
>  void device_legacy_reset(DeviceState *dev);
>
> -static inline void device_reset(DeviceState *dev)
> -{
> -    device_legacy_reset(dev);
> -}
> -
>  void device_class_set_parent_reset(DeviceClass *dc,
>                                     DeviceReset dev_reset,
>                                     DeviceReset *parent_reset);
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index fd7fdb8658..1c0a5345b9 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -561,6 +561,7 @@ tests/fp/%:
>
>  tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
>         hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
> +       hw/core/resettable.o \
>         hw/core/bus.o \
>         hw/core/irq.o \
>         hw/core/fw-path-provider.o \
> --
> 2.22.0

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus Damien Hedde
  2019-07-31  6:05   ` David Gibson
@ 2019-08-07 14:48   ` Peter Maydell
  1 sibling, 0 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 14:48 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> Deprecate old reset apis and make them use the new one while they
> are still used somewhere.
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/qdev.c         | 22 +++-------------------
>  include/hw/qdev-core.h | 28 ++++++++++++++++++++++------
>  2 files changed, 25 insertions(+), 25 deletions(-)
>
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 559ced070d..e9e5f2d5f9 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -312,25 +312,9 @@ static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
>      }
>  }
>
> -static int qdev_reset_one(DeviceState *dev, void *opaque)
> -{
> -    device_legacy_reset(dev);
> -
> -    return 0;
> -}
> -
> -static int qbus_reset_one(BusState *bus, void *opaque)
> -{
> -    BusClass *bc = BUS_GET_CLASS(bus);
> -    if (bc->reset) {
> -        bc->reset(bus);
> -    }
> -    return 0;
> -}
> -
>  void qdev_reset_all(DeviceState *dev)
>  {
> -    qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
> +    device_reset(dev, false);
>  }
>
>  void qdev_reset_all_fn(void *opaque)
> @@ -340,7 +324,7 @@ void qdev_reset_all_fn(void *opaque)
>
>  void qbus_reset_all(BusState *bus)
>  {
> -    qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
> +    bus_reset(bus, false);
>  }
>
>  void qbus_reset_all_fn(void *opaque)
> @@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
>              }
>          }
>          if (dev->hotplugged) {
> -            device_legacy_reset(dev);
> +            device_reset(dev, true);
>          }
>          dev->pending_deleted_event = false;

The other changes here don't change the semantics, but this
one does -- previously we were only resetting this specific
device and now we're resetting both the device and its children.
I think it belongs as its own patch in with the other
"remove device_legacy_reset call" patches.

>
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index eeb75611c8..1670ae41bb 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -109,6 +109,11 @@ typedef struct DeviceClass {
>      bool hotpluggable;
>
>      /* callbacks */
> +    /*
> +     * Reset method here is deprecated and replaced by methods in the
> +     * resettable class interface to implement a multi-phase reset.
> +     * TODO: remove once every reset callback is unused
> +     */
>      DeviceReset reset;
>      DeviceRealize realize;
>      DeviceUnrealize unrealize;
> @@ -455,19 +460,22 @@ bool bus_is_resetting(BusState *bus);
>   */
>  bool bus_is_reset_cold(BusState *bus);
>
> -void qdev_reset_all(DeviceState *dev);
> -void qdev_reset_all_fn(void *opaque);
> -
>  /**
> - * @qbus_reset_all:
> - * @bus: Bus to be reset.
> + * qbus/qdev_reset_all:
> + * @bus/dev: Bus/Device to be reset.
>   *
> - * Reset @bus and perform a bus-level ("hard") reset of all devices connected
> + * Reset @bus/dev and perform a bus-level reset of all devices/buses connected
>   * to it, including recursive processing of all buses below @bus itself.  A
>   * hard reset means that qbus_reset_all will reset all state of the device.
>   * For PCI devices, for example, this will include the base address registers
>   * or configuration space.
> + *
> + * Theses functions are deprecated, please use device/bus_reset or

"these"

> + * resettable_reset_* instead
> + * TODO: remove them when all occurence are removed

"occurrences" (two 'r's, plural with 's'), here and below

>   */

The comment here says that qbus_reset_all() does a "hard" reset,
which presumably is equivalent to a 'cold' reset, but the
code in our new implementation passes cold = false.

> +void qdev_reset_all(DeviceState *dev);
> +void qdev_reset_all_fn(void *opaque);
>  void qbus_reset_all(BusState *bus);
>  void qbus_reset_all_fn(void *opaque);
>
> @@ -489,9 +497,17 @@ void qdev_machine_init(void);
>   * device_legacy_reset:
>   *
>   * Reset a single device (by calling the reset method).
> + *
> + * This function is deprecated, please use device_reset() instead.
> + * TODO: remove the function when all occurences are removed.
>   */
>  void device_legacy_reset(DeviceState *dev);
>
> +/**
> + * device_class_set_parent_reset:
> + * TODO: remove the function when DeviceClass's reset method
> + * is not used anymore.
> + */
>  void device_class_set_parent_reset(DeviceClass *dc,
>                                     DeviceReset dev_reset,
>                                     DeviceReset *parent_reset);
> --
> 2.22.0

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state Damien Hedde
  2019-07-31  6:08   ` David Gibson
@ 2019-08-07 14:53   ` Peter Maydell
  2019-08-07 14:54   ` Peter Maydell
  2 siblings, 0 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 14:53 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> It contains the resetting counter and cold flag status.
>
> At this point, migration of bus reset related state (counter and cold/warm
> flag) is handled by parent device. This done using the post_load

"is done"

> function in the vmsd subsection.
>
> This is last point allow to add an initial support of migration with part of
> qdev/qbus tree in reset state under the following condition:
> + time-lasting reset are asserted on Device only
>
> Note that if this condition is not respected, migration will succeed and
> no failure will occurs. The only impact is that the resetting counter
> of a bus may lower afer a migration.

We should just migrate the bus state correctly -- see below.

> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/Makefile.objs  |  1 +
>  hw/core/qdev-vmstate.c | 45 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 46 insertions(+)
>  create mode 100644 hw/core/qdev-vmstate.c
>
> diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
> index d9234aa98a..49e9be0228 100644
> --- a/hw/core/Makefile.objs
> +++ b/hw/core/Makefile.objs
> @@ -4,6 +4,7 @@ common-obj-y += bus.o reset.o
>  common-obj-y += resettable.o
>  common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
>  common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
> +common-obj-$(CONFIG_SOFTMMU) += qdev-vmstate.o
>  # irq.o needed for qdev GPIO handling:
>  common-obj-y += irq.o
>  common-obj-y += hotplug.o
> diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
> new file mode 100644
> index 0000000000..07b010811f
> --- /dev/null
> +++ b/hw/core/qdev-vmstate.c
> @@ -0,0 +1,45 @@
> +/*
> + * Device vmstate
> + *
> + * Copyright (c) 2019 GreenSocs
> + *
> + * Authors:
> + *   Damien Hedde
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/qdev.h"
> +#include "migration/vmstate.h"
> +
> +static bool device_vmstate_reset_needed(void *opaque)
> +{
> +    DeviceState *dev = (DeviceState *) opaque;
> +    return dev->resetting != 0;
> +}
> +
> +static int device_vmstate_reset_post_load(void *opaque, int version_id)
> +{
> +    DeviceState *dev = (DeviceState *) opaque;
> +    BusState *bus;
> +    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
> +        bus->resetting = dev->resetting;
> +        bus->reset_is_cold = dev->reset_is_cold;
> +    }

Bus reset state might not be the same as the parent device's
reset state, so we need to migrate them both separately.

The way to do this is that in a pre-save hook we iterate
through the child buses and capture their state into
an array. Then we can migrate the array. In the post-load
hook we can set the bus state fields from the array contents.
VMSTATE_WITH_TMP is useful for this kind of situation.

One thing I'm slightly wary of here is that this will mean
that the ordering of child buses within the child_bus
array becomes significant to avoid migration compat breaks.
I think this is OK, though.

> +    return 0;
> +}
> +
> +const struct VMStateDescription device_vmstate_reset = {
> +    .name = "device_reset",
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .needed = device_vmstate_reset_needed,
> +    .post_load = device_vmstate_reset_post_load,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32(resetting, DeviceState),
> +        VMSTATE_BOOL(reset_is_cold, DeviceState),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};

This isn't used -- I think you should squash patch 7 in
with this one.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state Damien Hedde
  2019-07-31  6:08   ` David Gibson
  2019-08-07 14:53   ` Peter Maydell
@ 2019-08-07 14:54   ` Peter Maydell
  2019-08-07 15:27     ` Damien Hedde
  2 siblings, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 14:54 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> It contains the resetting counter and cold flag status.
>
> At this point, migration of bus reset related state (counter and cold/warm
> flag) is handled by parent device. This done using the post_load
> function in the vmsd subsection.
>
> This is last point allow to add an initial support of migration with part of
> qdev/qbus tree in reset state under the following condition:
> + time-lasting reset are asserted on Device only
>
> Note that if this condition is not respected, migration will succeed and
> no failure will occurs. The only impact is that the resetting counter
> of a bus may lower afer a migration.
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>


> +const struct VMStateDescription device_vmstate_reset = {
> +    .name = "device_reset",
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .needed = device_vmstate_reset_needed,
> +    .post_load = device_vmstate_reset_post_load,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32(resetting, DeviceState),
> +        VMSTATE_BOOL(reset_is_cold, DeviceState),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> -

Forgot to ask -- why don't we migrate the hold_needed flags?

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-08-07 14:20   ` Peter Maydell
@ 2019-08-07 15:03     ` Damien Hedde
  0 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-08-07 15:03 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



On 8/7/19 4:20 PM, Peter Maydell wrote:
> On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> This commit defines an interface allowing multi-phase reset.
>> The phases are INIT, HOLD and EXIT. Each phase has an associated method
>> in the class.
>>
>> The reset of a Resettable is controlled with 2 functions:
>>   - resettable_assert_reset which starts the reset operation.
>>   - resettable_deassert_reset which ends the reset operation.
>>
>> There is also a `resettable_reset` helper function which does assert then
>> deassert allowing to do a proper reset in one call.
>>
>> In addition, two functions, *resettable_reset_cold_fn* and
>> *resettable_reset_warm_fn*, are defined. They take only an opaque argument
>> (for the Resettable object) and can be used as callbacks.
>>
>> The Resettable interface is "reentrant", _assert_ can be called several
>> times and _deasert_ must be called the same number of times so that the
> 
> deassert
> 
>> Resettable leave reset state. It is supported by keeping a counter of
>> the current number of _assert_ calls. The counter maintainance is done
>> though 3 methods get/increment/decrement_count. A method set_cold is used
>> to set the cold flag of the reset. Another method set_host_needed is used
>> to ensure hold phase is executed only if required.
>>
>> Reset hierarchy is also supported. Each Resettable may have
>> sub-Resettable objects. When resetting a Resettable, it is propagated to
>> its children using the foreach_child method.
>>
>> When entering reset, init phases are executed parent-to-child order then
>> hold phases are executed child-parent order.
> 
> Why do we execute the hold phase in child-to-parent order? I would
> have expected this to follow the same order as the init phase.

No particular reason, I just thought it was better that way. But I don't
have a use case where it matters.

If we do only an assert_reset, then top-level phases are
called first and last:
parent's init
  child A's init
  child_B's init
  child_A's hold
  child_B's hold
parent's hold

I can switch it.

> 
>> When leaving reset, exit phases are executed in child-to-parent order.
>> This will allow to replace current qdev_reset mechanism by this interface
>> without side-effects on reset order.
> 
> It makes sense that the exit phase is child-to-parent.
> 
>> Note: I used an uint32 for the count. This match the type already used
>> in the existing resetting counter in hw/scsi/vmw_pvscsi.c for the
>> PVSCSIState.
>>
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>> ---
>>  Makefile.objs           |   1 +
>>  hw/core/Makefile.objs   |   1 +
>>  hw/core/resettable.c    | 220 ++++++++++++++++++++++++++++++++++++++++
>>  hw/core/trace-events    |  39 +++++++
>>  include/hw/resettable.h | 126 +++++++++++++++++++++++
>>  5 files changed, 387 insertions(+)
>>  create mode 100644 hw/core/resettable.c
>>  create mode 100644 hw/core/trace-events
>>  create mode 100644 include/hw/resettable.h
>>
>> diff --git a/Makefile.objs b/Makefile.objs
>> index 6a143dcd57..a723a47e14 100644
>> --- a/Makefile.objs
>> +++ b/Makefile.objs
>> @@ -191,6 +191,7 @@ trace-events-subdirs += migration
>>  trace-events-subdirs += net
>>  trace-events-subdirs += ui
>>  endif
>> +trace-events-subdirs += hw/core
>>  trace-events-subdirs += hw/display
>>  trace-events-subdirs += qapi
>>  trace-events-subdirs += qom
>> diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
>> index f8481d959f..d9234aa98a 100644
>> --- a/hw/core/Makefile.objs
>> +++ b/hw/core/Makefile.objs
>> @@ -1,6 +1,7 @@
>>  # core qdev-related obj files, also used by *-user:
>>  common-obj-y += qdev.o qdev-properties.o
>>  common-obj-y += bus.o reset.o
>> +common-obj-y += resettable.o
>>  common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
>>  common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
>>  # irq.o needed for qdev GPIO handling:
>> diff --git a/hw/core/resettable.c b/hw/core/resettable.c
>> new file mode 100644
>> index 0000000000..d7d631ce8b
>> --- /dev/null
>> +++ b/hw/core/resettable.c
>> @@ -0,0 +1,220 @@
>> +/*
>> + * Resettable interface.
>> + *
>> + * Copyright (c) 2019 GreenSocs SAS
>> + *
>> + * Authors:
>> + *   Damien Hedde
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qemu/module.h"
>> +#include "hw/resettable.h"
>> +#include "trace.h"
>> +
>> +#define RESETTABLE_MAX_COUNT 50
>> +
>> +#define RESETTABLE_GET_CLASS(obj) \
>> +    OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE)
> 
> Since this is an interface and not a complete class,
> we should name it TYPE_RESETTABLE_INTERFACE. We're rather
> inconsistent about naming of interfaces (in the codebase you
> can find "_INTERFACE suffix", "_IF suffix" and "no suffix").
> I think _INTERFACE suffix is best of these.
> (There's some discussion of this in this mailing list thread:
> https://lists.gnu.org/archive/html/qemu-devel/2019-03/msg03840.html
>  -- the idea is that it avoids confusion between whether an
> implementation of the type needs to be a subclass of it or
> if it has to be added as an interface to some other type.)
> 
>> +
>> +static void resettable_init_reset(Object *obj, bool cold);
>> +
>> +static bool resettable_class_check(ResettableClass *rc)
>> +{
>> +    if (!rc->set_cold) {
>> +        return false;
>> +    }
>> +    if (!rc->set_hold_needed) {
>> +        return false;
>> +    }
>> +    if (!rc->increment_count) {
>> +        return false;
>> +    }
>> +    if (!rc->decrement_count) {
>> +        return false;
>> +    }
>> +    if (!rc->get_count) {
>> +        return false;
>> +    }
>> +    return true;
>> +}
> 
> I don't think we really need to do this -- this is only used
> as an assert(), and the code is in any case going to exercise
> all the methods. Plus we only implement these methods in a couple
> of classes and we don't expect a lot of new implementations of them.
> 
>> +
>> +static void resettable_foreach_child(ResettableClass *rc,
>> +                                     Object *obj,
>> +                                     void (*func)(Object *))
>> +{
>> +    if (rc->foreach_child) {
>> +        rc->foreach_child(obj, func);
>> +    }
>> +}
>> +
>> +static void resettable_init_cold_reset(Object *obj)
>> +{
>> +    resettable_init_reset(obj, true);
>> +}
>> +
>> +static void resettable_init_warm_reset(Object *obj)
>> +{
>> +    resettable_init_reset(obj, false);
>> +}
>> +
>> +static void resettable_init_reset(Object *obj, bool cold)
>> +{
>> +    void (*func)(Object *);
>> +    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
>> +    uint32_t count;
>> +    bool action_needed = false;
>> +    bool prev_cold;
>> +
>> +    assert(resettable_class_check(rc));
>> +
>> +    count = rc->increment_count(obj);
>> +    /* this assert is here to catch an eventual reset loop */
>> +    assert(count <= RESETTABLE_MAX_COUNT);
> 
> I think I understand what this assert is for, but a slightly
> expanded comment would help.

is this better ?
/*
 * We limit the count to an arbitrary "big" value. The value is big
 * enough not to be triggered nominally.
 * The assert will catch a cycle in the reset tree which triggers
 * an infinite loop.
 */

Maybe I should drop the macro here, it will be more explicit.

> 
>> +
>> +    /*
>> +     * only take action if:
>> +     * + we really enter reset for the 1st time
>> +     * + or we are in warm reset and start a cold one
>> +     */
>> +    prev_cold = rc->set_cold(obj, cold);
>> +    if (count == 1) {
>> +        action_needed = true;
>> +    } else if (cold && !prev_cold) {
>> +        action_needed = true;
>> +    }
>> +    trace_resettable_phase_init(obj, object_get_typename(obj), cold, count,
>> +                                action_needed);
>> +
>> +    /* exec init phase */
>> +    if (action_needed) {
>> +        rc->set_hold_needed(obj, true);
>> +        if (rc->phases.init) {
>> +            rc->phases.init(obj);
>> +        }
>> +    }
>> +
>> +    /*
>> +     * handle the children even if action_needed is at false so that
>> +     * children counts are incremented too
>> +     */
>> +    func = cold ? resettable_init_cold_reset : resettable_init_warm_reset;
>> +    resettable_foreach_child(rc, obj, func);
>> +    trace_resettable_phase_init_end(obj);
>> +}
>> +
>> +static void resettable_hold_reset(Object *obj)
>> +{
>> +    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
>> +    bool hold_needed;
>> +
>> +    assert(resettable_class_check(rc));
>> +    trace_resettable_phase_hold(obj, object_get_typename(obj));
>> +
>> +    /* handle children first */
>> +    resettable_foreach_child(rc, obj, resettable_hold_reset);
>> +
>> +    /* exec hold phase */
>> +    hold_needed = rc->set_hold_needed(obj, false);
>> +    if (hold_needed) {
>> +        if (rc->phases.hold) {
>> +            rc->phases.hold(obj);
>> +        }
>> +    }
>> +    trace_resettable_phase_hold_end(obj, hold_needed);
>> +}
>> +
>> +static void resettable_exit_reset(Object *obj)
>> +{
>> +    uint32_t count;
>> +    ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
>> +
>> +    assert(resettable_class_check(rc));
>> +    trace_resettable_phase_exit(obj, object_get_typename(obj));
>> +
>> +    resettable_foreach_child(rc, obj, resettable_deassert_reset);
>> +
>> +    count = rc->get_count(obj);
>> +    /*
>> +     * we could assert that count > 0 but there are some corner cases
>> +     * where we prefer to let it go as it is probably harmless.
>> +     * For example: if there is reset support addition between
>> +     * hosts when doing a migration. We may do such things as
>> +     * deassert a non-existing reset.
>> +     */
>> +    if (count > 0) {
>> +        count = rc->decrement_count(obj);
>> +    } else {
>> +        trace_resettable_count_underflow(obj);
>> +    }
>> +    if (count == 0) {
>> +        if (rc->phases.exit) {
>> +            rc->phases.exit(obj);
>> +        }
>> +    }
>> +    trace_resettable_phase_exit_end(obj, count);
>> +}
>> +
>> +void resettable_assert_reset(Object *obj, bool cold)
>> +{
>> +    trace_resettable_reset_assert(obj, object_get_typename(obj), cold);
>> +    resettable_init_reset(obj, cold);
>> +    resettable_hold_reset(obj);
>> +}
>> +
>> +void resettable_deassert_reset(Object *obj)
>> +{
>> +    trace_resettable_reset_deassert(obj, object_get_typename(obj));
>> +    resettable_exit_reset(obj);
>> +}
>> +
>> +void resettable_reset(Object *obj, bool cold)
>> +{
>> +    trace_resettable_reset(obj, object_get_typename(obj), cold);
>> +    resettable_assert_reset(obj, cold);
>> +    resettable_deassert_reset(obj);
>> +}
>> +
>> +void resettable_reset_warm_fn(void *opaque)
>> +{
>> +    resettable_reset((Object *) opaque, false);
>> +}
>> +
>> +void resettable_reset_cold_fn(void *opaque)
>> +{
>> +    resettable_reset((Object *) opaque, true);
>> +}
>> +
>> +void resettable_class_set_parent_reset_phases(ResettableClass *rc,
>> +                                              ResettableInitPhase init,
>> +                                              ResettableHoldPhase hold,
>> +                                              ResettableExitPhase exit,
>> +                                              ResettablePhases *parent_phases)
>> +{
>> +    *parent_phases = rc->phases;
>> +    if (init) {
>> +        rc->phases.init = init;
>> +    }
>> +    if (hold) {
>> +        rc->phases.hold = hold;
>> +    }
>> +    if (exit) {
>> +        rc->phases.exit = exit;
>> +    }
>> +}
>> +
>> +static const TypeInfo resettable_interface_info = {
>> +    .name       = TYPE_RESETTABLE,
>> +    .parent     = TYPE_INTERFACE,
>> +    .class_size = sizeof(ResettableClass),
>> +};
>> +
>> +static void reset_register_types(void)
>> +{
>> +    type_register_static(&resettable_interface_info);
>> +}
>> +
>> +type_init(reset_register_types)
>> diff --git a/hw/core/trace-events b/hw/core/trace-events
>> new file mode 100644
>> index 0000000000..489d96d445
>> --- /dev/null
>> +++ b/hw/core/trace-events
>> @@ -0,0 +1,39 @@
>> +# See docs/devel/tracing.txt for syntax documentation.
>> +#
>> +# This file is processed by the tracetool script during the build.
>> +#
>> +# To add a new trace event:
>> +#
>> +# 1. Choose a name for the trace event.  Declare its arguments and format
>> +#    string.
>> +#
>> +# 2. Call the trace event from code using trace_##name, e.g. multiwrite_cb() ->
>> +#    trace_multiwrite_cb().  The source file must #include "trace.h".
>> +#
>> +# Format of a trace event:
>> +#
>> +# [disable] <name>(<type1> <arg1>[, <type2> <arg2>] ...) "<format-string>"
>> +#
>> +# Example: g_malloc(size_t size) "size %zu"
>> +#
>> +# The "disable" keyword will build without the trace event.
>> +#
>> +# The <name> must be a valid as a C function name.
>> +#
>> +# Types should be standard C types.  Use void * for pointers because the trace
>> +# system may not have the necessary headers included.
>> +#
>> +# The <format-string> should be a sprintf()-compatible format string.
>> +
>> +# resettable.c
>> +resettable_reset(void *obj, const char *type, int cold) "obj=%p(%s) cold=%d"
>> +resettable_reset_assert(void *obj, const char *type, int cold) "obj=%p(%s) cold=%d"
>> +resettable_reset_deassert(void *obj, const char *type) "obj=%p(%s)"
>> +resettable_reset_deassert_end(void *obj) "obj=%p"
>> +resettable_phase_init(void *obj, const char *type, int cold, uint32_t count, int needed) "obj=%p(%s) cold=%d count=%" PRIu32 " needed=%d"
>> +resettable_phase_init_end(void *obj) "obj=%p"
>> +resettable_phase_hold(void *obj, const char *type) "obj=%p(%s)"
>> +resettable_phase_hold_end(void *obj, int needed) "obj=%p needed=%d"
>> +resettable_phase_exit(void *obj, const char *type) "obj=%p(%s)"
>> +resettable_phase_exit_end(void *obj, uint32_t count) "obj=%p count=%" PRIu32
>> +resettable_count_underflow(void *obj) "obj=%p"
>> diff --git a/include/hw/resettable.h b/include/hw/resettable.h
>> new file mode 100644
>> index 0000000000..e617a8e875
>> --- /dev/null
>> +++ b/include/hw/resettable.h
>> @@ -0,0 +1,126 @@
>> +#ifndef HW_RESETTABLE_H
>> +#define HW_RESETTABLE_H
>> +
>> +#include "qom/object.h"
>> +
>> +#define TYPE_RESETTABLE "resettable"
>> +
>> +#define RESETTABLE_CLASS(class) \
>> +    OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE)
>> +
>> +/*
>> + * ResettableClass:
>> + * Interface for resettable objects.
>> + *
>> + * The reset operation is divided in several phases each represented by a
>> + * method.
>> + *
>> + * Each Ressetable must maintain a reset counter in its state, 3 methods allows
> 
> "resettable"
> 
>> + * to interact with it.
> 
> I think we could improve this comment to be a bit clearer about
> who we expect to implement which methods. Something like:
> 
> /*
>  * ResettableClass:
>  * Interface for resettable objects.
>  *
>  * See docs/devel/reset.rst for more detailed information about
>  * how QEMU models reset.
>  *
>  * All objects which can be reset must implement this interface;
>  * it is usually provided by a base class such as DeviceClass or BusClass.
>  * Every Resettable object must maintain some state tracking the
>  * progress of a reset operation:
>  *  - a reset count, which is incremented when the reset operation
>  *    starts and decremented when it finishes
>  *  - a 'cold' flag, which tracks whether the in-progress reset is
>  *    a warm reset or a cold reset
>  *  - a 'hold_needed' flag, which indicates that we need to
>  *    invoke the 'hold' phase handler for this object
>  * The base class implementation of the interface provides this
>  * state and implements the associated methods: set_cold,
>  * set_hold_needed, get_count, increment_count and decrement_count.
>  *
>  * Concrete object implementations (typically specific devices
>  * such as a UART model) should provide the functions
>  * for the phases.init, phases.hold and phases.exit methods, which
>  * they can set in their class init function, either directly or
>  * by calling resettable_class_set_parent_reset_phases().
>  * The phase methods are guaranteed to only only ever be called once
>  * for any reset event, in the order 'init', 'hold', 'exit'.
>  * An object will always move quickly from 'init' to 'hold'
>  * but might remain in 'hold' for an arbitrary period of time
>  * before eventually reset is deasserted and the 'exit' phase is called.
>  * Object implementations should be prepared for functions handling
>  * inbound connections from other devices (such as qemu_irq handler
>  * functions) to be called at any point during reset after their
>  * 'init' method has been called.
>  *
>  * Users of a resettable object should not call these methods
>  * directly, but instead use the functions resettable_assert_reset(),
>  * resettable_deassert_reset() or resettable_reset().
> 
> 
>> + *
>> + * @phases.init: should reset local state only. Takes a bool @cold argument
>> + * specifying whether the reset is cold or warm. It must not do side-effect
>> + * on others objects.
> 
> This says that phases.init takes a 'cold' argument, but the prototype
> doesn't have one.

I finally removed the argument and forgot to change this bit.

> 
> "This phase is called when the object enters reset. It should reset
> local state of the object, but it must not do anything that has a
> side-effect on other objects, such as raising or lowering a qemu_irq line
> or reading or writing guest memory."
> 
>> + *
>> + * @phases.hold: side-effects action on others objects due to staying in a
>> + * resetting state.
> 
> "This phase is called for entry into reset, once every object in the
> system which is being reset has had its @phases.init method called.
> At this point devices can do actions that affect other objects."
> 
> 
>> + *
>> + * @phases.exit: leave the reset state, may do side-effects action on others
>> + * objects.
> 
> "This phase is called when the object leaves the reset state. Actions
> affecting other objects are permitted."
> 
>> + *
>> + * @set_cold: Set whether the current reset is cold or warm. Return the
>> + * previous flag value. Return value has no meaning if @get_count returns
>> + * a zero value.
>> + *
>> + * @set_hold_needed: Set hold_needed flag. Return the previous flag value.
>> + *
>> + * @get_count: Get the current reset count
>> + * @increment_count: Increment the reset count, returns the new count
>> + * @decrement_count: decrement the reset count, returns the new count
>> + *
>> + * @foreach_child: Executes a given function on every Resettable child.
>> + * A child is not a QOM child, but a child a reset meaning.
> 
> "Child in this context means a child in the qbus tree, so the
> children of a qbus are the devices on it, and the children of
> a device are all the buses it owns. This is not the same as the
> QOM object hierarchy."
> 
>> + */
>> +typedef void (*ResettableInitPhase)(Object *obj);
>> +typedef void (*ResettableHoldPhase)(Object *obj);
>> +typedef void (*ResettableExitPhase)(Object *obj);
>> +typedef bool (*ResettableSetCold)(Object *obj, bool cold);
>> +typedef bool (*ResettableSetHoldNeeded)(Object *obj, bool hold_needed);
>> +typedef uint32_t (*ResettableGetCount)(Object *obj);
>> +typedef uint32_t (*ResettableIncrementCount)(Object *obj);
>> +typedef uint32_t (*ResettableDecrementCount)(Object *obj);
>> +typedef void (*ResettableForeachChild)(Object *obj, void (*visitor)(Object *));
>> +typedef struct ResettableClass {
>> +    InterfaceClass parent_class;
>> +
>> +    struct ResettablePhases {
>> +        ResettableInitPhase init;
>> +        ResettableHoldPhase hold;
>> +        ResettableExitPhase exit;
>> +    } phases;
>> +
>> +    ResettableSetCold set_cold;
>> +    ResettableSetHoldNeeded set_hold_needed;
>> +    ResettableGetCount get_count;
>> +    ResettableIncrementCount increment_count;
>> +    ResettableDecrementCount decrement_count;
>> +    ResettableForeachChild foreach_child;
>> +} ResettableClass;
>> +typedef struct ResettablePhases ResettablePhases;
>> +
>> +/**
>> + * resettable_assert_reset:
> 
> "Put the object into reset, and hold it there until
> the caller later calls resettable_deassert_reset()."
> 
>> + * Increments the reset count and executes the init and hold phases.
>> + * Each time resettable_assert_reset is called, resettable_deassert_reset
>> + * must eventually be called once.
>> + * It will also impact reset children.
> 
> "This will reset the specified object and all of its reset children."
> 
>> + *
>> + * @obj object to reset, must implement Resettable interface.
>> + * @cold boolean indicating the type of reset (cold or warm)
>> + */
>> +void resettable_assert_reset(Object *obj, bool cold);
>> +
>> +/**
>> + * resettable_deassert_reset:
> 
> "Take the object out of reset."
> 
>> + * Decrements the reset count by one and executes the exit phase if it hits
>> + * zero.
>> + * It will also impact reset children.
>> + *
>> + * @obj object to reset, must implement Resettable interface.
>> + */
>> +void resettable_deassert_reset(Object *obj);
>> +
>> +/**
>> + * resettable_reset:
>> + * Calling this function is equivalent to call @assert_reset then
> 
> "to calling"
> 
>> + * @deassert_reset.
>> + */
>> +void resettable_reset(Object *obj, bool cold);
>> +
>> +/**
>> + * resettable_reset_warm_fn:
>> + * Helper to call resettable_reset(opaque, false)
>> + */
>> +void resettable_reset_warm_fn(void *opaque);
>> +
>> +/**
>> + * resettable_reset_cold_fn:
>> + * Helper to call resettable_reset(opaque, true)
>> + */
>> +void resettable_reset_cold_fn(void *opaque);
>> +
>> +/**
>> + * resettable_class_set_parent_reset_phases:
>> + *
>> + * Save @rc current reset phases into @parent_phases and override @rc phases
>> + * by the given new methods (@init, @hold and @exit).
>> + * Each phase is overriden only if the new one is not NULL allowing to
> 
> "overridden"
> 
>> + * override a subset of phases.
>> + */
>> +void resettable_class_set_parent_reset_phases(ResettableClass *rc,
>> +                                              ResettableInitPhase init,
>> +                                              ResettableHoldPhase hold,
>> +                                              ResettableExitPhase exit,
>> +                                              ResettablePhases *parent_phases);
>> +
>> +#endif
> 
> This function name is quite long -- I think we could reasonably
> call it resettable_class_set_parent_phases().
> 
> thanks
> -- PMM
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices Damien Hedde
@ 2019-08-07 15:07   ` Peter Maydell
  2019-08-07 17:22     ` Damien Hedde
  2019-08-08 15:42     ` Dr. David Alan Gilbert
  0 siblings, 2 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:07 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis,
	Dr. David Alan Gilbert, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> This add the reset related sections for every QOM
> device.

A bit more detail in the commit message would help, I think --
this is adding extra machinery which has to copy and modify
the VMStateDescription passed in by the device in order to
add the subsection that handles reset.

I've added Dave Gilbert to the already long cc list since this
is migration related.

> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/qdev-vmstate.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  hw/core/qdev.c         | 12 +++++++++++-
>  include/hw/qdev-core.h |  3 +++
>  stubs/Makefile.objs    |  1 +
>  stubs/device.c         |  7 +++++++
>  5 files changed, 63 insertions(+), 1 deletion(-)
>  create mode 100644 stubs/device.c
>
> diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
> index 07b010811f..24f8465c61 100644
> --- a/hw/core/qdev-vmstate.c
> +++ b/hw/core/qdev-vmstate.c
> @@ -43,3 +43,44 @@ const struct VMStateDescription device_vmstate_reset = {
>          VMSTATE_END_OF_LIST()
>      },
>  };
> +
> +static VMStateDescription *vmsd_duplicate_and_append(
> +        const VMStateDescription *old_vmsd,
> +        const VMStateDescription *new_subsection)
> +{
> +    VMStateDescription *vmsd;
> +    int n = 0;
> +
> +    assert(old_vmsd && new_subsection);
> +
> +    vmsd = (VMStateDescription *) g_memdup(old_vmsd, sizeof(*vmsd));
> +
> +    if (old_vmsd->subsections) {
> +        while (old_vmsd->subsections[n]) {
> +            n += 1;
> +        }
> +    }
> +    vmsd->subsections = g_new(const VMStateDescription *, n + 2);
> +
> +    if (old_vmsd->subsections) {
> +        memcpy(vmsd->subsections, old_vmsd->subsections,
> +               sizeof(VMStateDescription *) * n);
> +    }
> +    vmsd->subsections[n] = new_subsection;
> +    vmsd->subsections[n + 1] = NULL;
> +
> +    return vmsd;
> +}
> +
> +void device_class_build_extended_vmsd(DeviceClass *dc)
> +{
> +    assert(dc->vmsd);
> +    assert(!dc->vmsd_ext);
> +
> +    /* forge a subsection with proper name */
> +    VMStateDescription *reset;
> +    reset = g_memdup(&device_vmstate_reset, sizeof(*reset));
> +    reset->name = g_strdup_printf("%s/device_reset", dc->vmsd->name);
> +
> +    dc->vmsd_ext = vmsd_duplicate_and_append(dc->vmsd, reset);
> +}

This will allocate memory, but there is no corresponding
code which frees it. This means you'll have a memory leak
across device realize->unrealize for hotplug devices.

> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index e9e5f2d5f9..88387d3743 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -45,7 +45,17 @@ bool qdev_hot_removed = false;
>  const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
>  {
>      DeviceClass *dc = DEVICE_GET_CLASS(dev);
> -    return dc->vmsd;
> +
> +    if (!dc->vmsd) {
> +        return NULL;
> +    }
> +
> +    if (!dc->vmsd_ext) {
> +        /* build it first time we need it */
> +        device_class_build_extended_vmsd(dc);
> +    }
> +
> +    return dc->vmsd_ext;
>  }

Unfortunately not everything that wants the VMSD calls
this function. migration/savevm.c:dump_vmstate_json_to_file()
does a direct access to dc->vmsd, so we need to fix that first.

Devices which don't use dc->vmsd won't get this and so
their reset state won't be migrated. That's OK for anything
that's still not yet a QOM device, I guess -- it's not possible
for them to be in a 'held in reset' state anyway, so the
extra subsection would never be needed.

The one I'm less sure about is the 'virtio' devices, which
have to do something odd with migration state for backwards
compat reasons. At the moment they can't be in a situation
where they're being held in reset when we do a migration,
but since they're PCI devices they might in future be possible
to put into new boards/pci controllers that would let them
be in that situation.

>  static void bus_remove_child(BusState *bus, DeviceState *child)
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 1670ae41bb..926d4bbcb1 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -120,6 +120,7 @@ typedef struct DeviceClass {
>
>      /* device state */
>      const struct VMStateDescription *vmsd;
> +    const struct VMStateDescription *vmsd_ext;
>
>      /* Private to qdev / bus.  */
>      const char *bus_type;
> @@ -520,6 +521,8 @@ void device_class_set_parent_unrealize(DeviceClass *dc,
>
>  const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
>
> +void device_class_build_extended_vmsd(DeviceClass *dc);
> +
>  const char *qdev_fw_name(DeviceState *dev);
>
>  Object *qdev_get_machine(void);
> diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
> index 9c7393b08c..432b56f290 100644
> --- a/stubs/Makefile.objs
> +++ b/stubs/Makefile.objs
> @@ -40,4 +40,5 @@ stub-obj-y += pci-host-piix.o
>  stub-obj-y += ram-block.o
>  stub-obj-y += ramfb.o
>  stub-obj-y += fw_cfg.o
> +stub-obj-y += device.o
>  stub-obj-$(CONFIG_SOFTMMU) += semihost.o
> diff --git a/stubs/device.c b/stubs/device.c
> new file mode 100644
> index 0000000000..e9b4f57e5f
> --- /dev/null
> +++ b/stubs/device.c
> @@ -0,0 +1,7 @@
> +#include "qemu/osdep.h"
> +#include "hw/qdev-core.h"
> +
> +void device_class_build_extended_vmsd(DeviceClass *dc)
> +{
> +    return;
> +}
> --
> 2.22.0


thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs Damien Hedde
  2019-07-31  6:11   ` David Gibson
@ 2019-08-07 15:18   ` Peter Maydell
  2019-08-07 16:56     ` Damien Hedde
  1 sibling, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:18 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> It adds the possibility to add 2 gpios to control the warm and cold reset.
> With theses ios, the reset can be maintained during some time.
> Each io is associated with a state to detect level changes.
>
> Vmstate subsections are also added to the existsing device_reset
> subsection.
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/core/qdev-vmstate.c | 15 ++++++++++
>  hw/core/qdev.c         | 65 ++++++++++++++++++++++++++++++++++++++++++
>  include/hw/qdev-core.h | 57 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 137 insertions(+)
>
> diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
> index 24f8465c61..72f84c6cee 100644
> --- a/hw/core/qdev-vmstate.c
> +++ b/hw/core/qdev-vmstate.c
> @@ -24,10 +24,23 @@ static int device_vmstate_reset_post_load(void *opaque, int version_id)
>  {
>      DeviceState *dev = (DeviceState *) opaque;
>      BusState *bus;
> +    uint32_t io_count = 0;
> +
>      QLIST_FOREACH(bus, &dev->child_bus, sibling) {
>          bus->resetting = dev->resetting;
>          bus->reset_is_cold = dev->reset_is_cold;
>      }
> +
> +    if (dev->cold_reset_input.state) {
> +        io_count += 1;
> +    }
> +    if (dev->warm_reset_input.state) {
> +        io_count += 1;
> +    }
> +    /* ensure resetting count is coherent with io states */
> +    if (dev->resetting < io_count) {
> +        return -1;
> +    }
>      return 0;
>  }
>
> @@ -40,6 +53,8 @@ const struct VMStateDescription device_vmstate_reset = {
>      .fields = (VMStateField[]) {
>          VMSTATE_UINT32(resetting, DeviceState),
>          VMSTATE_BOOL(reset_is_cold, DeviceState),
> +        VMSTATE_BOOL(cold_reset_input.state, DeviceState),
> +        VMSTATE_BOOL(warm_reset_input.state, DeviceState),

If we're just adding these fields to this VMStateDescription
then this patch should come earlier in the series than the
patch where we create and start using the fields. Otherwise
there's a migration compat break between a QEMU just
before this patch and a QEMU with it. I think the simplest
fix is to put this patch before patches 6/7 and have a note
in the commit message that this functionality can't be used
until after the patch which adds the migration support.

>          VMSTATE_END_OF_LIST()
>      },
>  };
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 88387d3743..11a4de55ea 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -450,6 +450,67 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
>      qdev_init_gpio_in_named(dev, handler, NULL, n);
>  }
>
> +static DeviceResetInputState *device_get_reset_input_state(DeviceState *dev,
> +                                                            bool cold)
> +{
> +    return cold ? &dev->cold_reset_input : &dev->warm_reset_input;
> +}
> +
> +static void device_reset_handler(DeviceState *dev, bool cold, bool level)
> +{
> +    DeviceResetInputState *dris = device_get_reset_input_state(dev, cold);
> +
> +    if (dris->type == DEVICE_RESET_ACTIVE_LOW) {
> +        level = !level;
> +    }
> +
> +    if (dris->state == level) {
> +        /* io state has not changed */
> +        return;
> +    }
> +
> +    dris->state = level;
> +
> +    if (level) {
> +        resettable_assert_reset(OBJECT(dev), cold);
> +    } else {
> +        resettable_deassert_reset(OBJECT(dev));
> +    }
> +}
> +
> +static void device_cold_reset_handler(void *opaque, int n, int level)
> +{
> +    device_reset_handler((DeviceState *) opaque, true, level);
> +}
> +
> +static void device_warm_reset_handler(void *opaque, int n, int level)
> +{
> +    device_reset_handler((DeviceState *) opaque, false, level);
> +}
> +
> +void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
> +                                   bool cold, DeviceResetActiveType type)
> +{
> +    DeviceResetInputState *dris = device_get_reset_input_state(dev, cold);
> +    qemu_irq_handler handler;
> +
> +    switch (type) {
> +    case DEVICE_RESET_ACTIVE_LOW:
> +    case DEVICE_RESET_ACTIVE_HIGH:
> +        break;
> +    default:
> +        assert(false);
> +        break;

The usual way to write this is
    g_assert_not_reached();
(and no following 'break').


But the whole switch statement seems to be a complicated way
of writing
   assert(type == DEVICE_RESET_ACTIVE_LOW || type == DEVICE_RESET_ACTIVE_HIGH);

> +    }
> +
> +    assert(!dris->exists);
> +    dris->exists = true;
> +    dris->type = type;
> +
> +    handler = cold ? device_cold_reset_handler : device_warm_reset_handler;
> +    qdev_init_gpio_in_named(dev, handler, name, 1);
> +}

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 10/33] vl.c: remove qbus_reset_all registration
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 10/33] vl.c: remove qbus_reset_all registration Damien Hedde
@ 2019-08-07 15:20   ` Peter Maydell
  0 siblings, 0 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:20 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> Replace deprecated qbus_reset_all by resettable_reset_cold_fn for
> the sysbus reset registration.
> This does not impact the behavior.
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  vl.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/vl.c b/vl.c
> index b426b32134..5a465c8236 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -4421,7 +4421,11 @@ int main(int argc, char **argv, char **envp)
>
>      /* TODO: once all bus devices are qdevified, this should be done
>       * when bus is created by qdev.c */
> -    qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
> +    /*
> +     * TODO: when we have a main reset container/domain object, use
> +     * it to fully benefit from multi-phase reset
> +     */

Let's be a bit more specific with the todo comment while the
detail is fresh in our minds:

/*
 * TODO: If we had a main 'reset container' that the whole system
 * lived in, we could reset that using the multi-phase reset
 * APIs. For the moment, we just reset the sysbus, which will cause
 * all devices hanging off it (and all their child buses, recursively)
 * to be reset. Note that this will *not* reset any Device objects
 * which are not attached to some part of the qbus tree!
 */

> +    qemu_register_reset(resettable_reset_cold_fn, sysbus_get_default());
>      qemu_run_machine_init_done_notifiers();
>
>      if (rom_check_and_register_reset() != 0) {
> --
> 2.22.0

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-08-07 14:41   ` Peter Maydell
@ 2019-08-07 15:23     ` Damien Hedde
  2019-08-07 15:28       ` Peter Maydell
  2019-08-12  9:08     ` Damien Hedde
  1 sibling, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-08-07 15:23 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



On 8/7/19 4:41 PM, Peter Maydell wrote:
> On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> This add Resettable interface implementation for both Bus and Device.
>>
>> *resetting* counter and *reset_is_cold* flag are added in DeviceState
>> and BusState.
>>
>> Compatibility with existing code base is ensured.
>> The legacy bus or device reset method is called in the new exit phase
>> and the other 2 phases are let empty. Using the exit phase guarantee that
> 
> "left". "guarantees"
> 
>> legacy resets are called in the "post" order (ie: children then parent)
>> in hierarchical reset. That is the same order as legacy qdev_reset_all
>> or qbus_reset_all were using.
> 
> This is true, but on the other hand the semantics of most device
> reset methods match "init", not "exit" -- they just set device
> internal fields to the correct reset state.

I changed from "init" to "exit" due to the change of the init phase call
order to parent-then-children.

This is a consequence of what I found about the raspi reset: it changes
the reset hierarchy during reset. The only way I saw to have a chance
allowing this kind of things cleanly is: do parent init first so that it
can setup its children before they are considered for reset.

I can put the legacy reset method to the hold phase which is part of the
"enter reset state". Otherwise I need to change back the order of init
phase.

My other concern with putting it in init phase is that some device do
things we forbid in it (like setting irq).


> 
>> New *device_reset* and *bus_reset* function are proposed with an
>> additional boolean argument telling whether the reset is cold or warm.
>> Helper functions *device_reset_[warm|cold]* and *bus_reset_[warm|cold]*
>> are defined also as helpers.
>>
>> Also add a [device|bus]_is_resetting and [device|bus]_is_reset_cold
>> functions telling respectively whether the object is currently under reset and
>> if the current reset is cold or not.
> 
> I was expecting this patch to contain handling for migration
> of the new data fields. That's in a later patch, so the
> commit message here should say something like:
> 
> "This commit adds new fields to BusState and DeviceState, but
> does not set up migration handling for them; so the new functions
> can only be called after the subsequent commit which adds the
> migration support."
> 
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>> ---
>>  hw/core/bus.c          | 85 ++++++++++++++++++++++++++++++++++++++++++
>>  hw/core/qdev.c         | 82 ++++++++++++++++++++++++++++++++++++++++
>>  include/hw/qdev-core.h | 84 ++++++++++++++++++++++++++++++++++++++---
>>  tests/Makefile.include |  1 +
>>  4 files changed, 247 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/core/bus.c b/hw/core/bus.c
>> index 17bc1edcde..08a97addb6 100644
>> --- a/hw/core/bus.c
>> +++ b/hw/core/bus.c
>> @@ -22,6 +22,7 @@
>>  #include "qemu/module.h"
>>  #include "hw/qdev.h"
>>  #include "qapi/error.h"
>> +#include "hw/resettable.h"
>>
>>  void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
>>  {
>> @@ -68,6 +69,75 @@ int qbus_walk_children(BusState *bus,
>>      return 0;
>>  }
>>
>> +void bus_reset(BusState *bus, bool cold)
>> +{
>> +    resettable_reset(OBJECT(bus), cold);
>> +}
>> +
>> +bool bus_is_resetting(BusState *bus)
>> +{
>> +    return (bus->resetting != 0);
>> +}
>> +
>> +bool bus_is_reset_cold(BusState *bus)
>> +{
>> +    return bus->reset_is_cold;
>> +}
>> +
>> +static uint32_t bus_get_reset_count(Object *obj)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    return bus->resetting;
>> +}
>> +
>> +static uint32_t bus_increment_reset_count(Object *obj)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    return ++bus->resetting;
>> +}
>> +
>> +static uint32_t bus_decrement_reset_count(Object *obj)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    return --bus->resetting;
>> +}
>> +
>> +static bool bus_set_reset_cold(Object *obj, bool cold)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    bool old = bus->reset_is_cold;
>> +    bus->reset_is_cold = cold;
>> +    return old;
>> +}
>> +
>> +static bool bus_set_hold_needed(Object *obj, bool hold_needed)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    bool old = bus->reset_hold_needed;
>> +    bus->reset_hold_needed = hold_needed;
>> +    return old;
>> +}
>> +
>> +static void bus_foreach_reset_child(Object *obj, void (*func)(Object *))
>> +{
>> +    BusState *bus = BUS(obj);
>> +    BusChild *kid;
>> +
>> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
>> +        func(OBJECT(kid->child));
>> +    }
>> +}
>> +
>> +static void bus_obj_legacy_reset(Object *obj)
>> +{
>> +    BusState *bus = BUS(obj);
>> +    BusClass *bc = BUS_GET_CLASS(obj);
>> +
>> +    if (bc->reset) {
>> +        bc->reset(bus);
>> +    }
>> +}
>> +
>>  static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
>>  {
>>      const char *typename = object_get_typename(OBJECT(bus));
>> @@ -192,6 +262,8 @@ static void qbus_initfn(Object *obj)
>>                               NULL);
>>      object_property_add_bool(obj, "realized",
>>                               bus_get_realized, bus_set_realized, NULL);
>> +
>> +    bus->resetting = 0;
>>  }
>>
>>  static char *default_bus_get_fw_dev_path(DeviceState *dev)
>> @@ -202,9 +274,18 @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
>>  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->phases.exit = bus_obj_legacy_reset;
>> +    rc->get_count = bus_get_reset_count;
>> +    rc->increment_count = bus_increment_reset_count;
>> +    rc->decrement_count = bus_decrement_reset_count;
>> +    rc->foreach_child = bus_foreach_reset_child;
>> +    rc->set_cold = bus_set_reset_cold;
>> +    rc->set_hold_needed = bus_set_hold_needed;
>>  }
>>
>>  static void qbus_finalize(Object *obj)
>> @@ -223,6 +304,10 @@ static const TypeInfo bus_info = {
>>      .instance_init = qbus_initfn,
>>      .instance_finalize = qbus_finalize,
>>      .class_init = bus_class_init,
>> +    .interfaces = (InterfaceInfo[]) {
>> +        { TYPE_RESETTABLE },
>> +        { }
>> +    },
>>  };
>>
>>  static void bus_register_types(void)
>> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
>> index 043e058396..559ced070d 100644
>> --- a/hw/core/qdev.c
>> +++ b/hw/core/qdev.c
>> @@ -254,6 +254,64 @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
>>      return hotplug_ctrl;
>>  }
>>
>> +void device_reset(DeviceState *dev, bool cold)
>> +{
>> +    resettable_reset(OBJECT(dev), cold);
>> +}
>> +
>> +bool device_is_resetting(DeviceState *dev)
>> +{
>> +    return (dev->resetting != 0);
>> +}
>> +
>> +bool device_is_reset_cold(DeviceState *dev)
>> +{
>> +    return dev->reset_is_cold;
>> +}
>> +
>> +static uint32_t device_get_reset_count(Object *obj)
>> +{
>> +    DeviceState *dev = DEVICE(obj);
>> +    return dev->resetting;
>> +}
>> +
>> +static uint32_t device_increment_reset_count(Object *obj)
>> +{
>> +    DeviceState *dev = DEVICE(obj);
>> +    return ++dev->resetting;
>> +}
>> +
>> +static uint32_t device_decrement_reset_count(Object *obj)
>> +{
>> +    DeviceState *dev = DEVICE(obj);
>> +    return --dev->resetting;
>> +}
>> +
>> +static bool device_set_reset_cold(Object *obj, bool cold)
>> +{
>> +    DeviceState *dev = DEVICE(obj);
>> +    bool old = dev->reset_is_cold;
>> +    dev->reset_is_cold = cold;
>> +    return old;
>> +}
>> +
>> +static bool device_set_hold_needed(Object *obj, bool hold_needed)
>> +{
>> +    DeviceState *dev = DEVICE(obj);
>> +    bool old = dev->reset_hold_needed;
>> +    dev->reset_hold_needed = hold_needed;
>> +    return old;
>> +}
>> +
>> +static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
>> +{
>> +    DeviceState *dev = DEVICE(obj);
>> +    BusState *bus;
>> +    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
>> +        func(OBJECT(bus));
>> +    }
>> +}
>> +
>>  static int qdev_reset_one(DeviceState *dev, void *opaque)
>>  {
>>      device_legacy_reset(dev);
>> @@ -954,6 +1012,7 @@ static void device_initfn(Object *obj)
>>
>>      dev->instance_id_alias = -1;
>>      dev->realized = false;
>> +    dev->resetting = 0;
>>
>>      object_property_add_bool(obj, "realized",
>>                               device_get_realized, device_set_realized, NULL);
>> @@ -1046,9 +1105,20 @@ static void device_unparent(Object *obj)
>>      }
>>  }
>>
>> +static void device_obj_legacy_reset(Object *obj)
>> +{
>> +    DeviceState *dev = DEVICE(obj);
>> +    DeviceClass *dc = DEVICE_GET_CLASS(dev);
>> +
>> +    if (dc->reset) {
>> +        dc->reset(dev);
>> +    }
>> +}
>> +
>>  static void device_class_init(ObjectClass *class, void *data)
>>  {
>>      DeviceClass *dc = DEVICE_CLASS(class);
>> +    ResettableClass *rc = RESETTABLE_CLASS(class);
>>
>>      class->unparent = device_unparent;
>>
>> @@ -1060,6 +1130,14 @@ static void device_class_init(ObjectClass *class, void *data)
>>       */
>>      dc->hotpluggable = true;
>>      dc->user_creatable = true;
>> +
>> +    rc->phases.exit = device_obj_legacy_reset;
>> +    rc->get_count = device_get_reset_count;
>> +    rc->increment_count = device_increment_reset_count;
>> +    rc->decrement_count = device_decrement_reset_count;
>> +    rc->foreach_child = device_foreach_reset_child;
>> +    rc->set_cold = device_set_reset_cold;
>> +    rc->set_hold_needed = device_set_hold_needed;
>>  }
>>
>>  void device_class_set_parent_reset(DeviceClass *dc,
>> @@ -1117,6 +1195,10 @@ static const TypeInfo device_type_info = {
>>      .class_init = device_class_init,
>>      .abstract = true,
>>      .class_size = sizeof(DeviceClass),
>> +    .interfaces = (InterfaceInfo[]) {
>> +        { TYPE_RESETTABLE },
>> +        { }
>> +    },
>>  };
>>
>>  static void qdev_register_types(void)
>> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
>> index 690ce72433..eeb75611c8 100644
>> --- a/include/hw/qdev-core.h
>> +++ b/include/hw/qdev-core.h
>> @@ -7,6 +7,7 @@
>>  #include "hw/irq.h"
>>  #include "hw/hotplug.h"
>>  #include "sysemu/sysemu.h"
>> +#include "hw/resettable.h"
>>
>>  enum {
>>      DEV_NVECTORS_UNSPECIFIED = -1,
>> @@ -132,6 +133,10 @@ struct NamedGPIOList {
>>  /**
>>   * DeviceState:
>>   * @realized: Indicates whether the device has been fully constructed.
>> + * @resetting: Indicates whether the device is under reset. Also
>> + * used to count how many times reset has been initiated on the device.
>> + * @reset_is_cold: If the device is under reset, indicates whether it is cold
>> + * or warm.
> 
> We should put a doc comment entry for @reset_hold_needed here too.
> 
>>   *
>>   * This structure should not be accessed directly.  We declare it here
>>   * so that it can be embedded in individual device state structures.
>> @@ -153,6 +158,9 @@ struct DeviceState {
>>      int num_child_bus;
>>      int instance_id_alias;
>>      int alias_required_for_version;
>> +    uint32_t resetting;
>> +    bool reset_is_cold;
>> +    bool reset_hold_needed;
>>  };
>>
>>  struct DeviceListener {
>> @@ -199,6 +207,10 @@ typedef struct BusChild {
>>  /**
>>   * BusState:
>>   * @hotplug_handler: link to a hotplug handler associated with bus.
>> + * @resetting: Indicates whether the bus is under reset. Also
>> + * used to count how many times reset has been initiated on the bus.
>> + * @reset_is_cold: If the bus is under reset, indicates whether it is cold
>> + * or warm.
> 
> @reset_hold_needed missing.
> 
>>   */
>>  struct BusState {
>>      Object obj;
>> @@ -210,6 +222,9 @@ struct BusState {
>>      int num_children;
>>      QTAILQ_HEAD(, BusChild) children;
>>      QLIST_ENTRY(BusState) sibling;
>> +    uint32_t resetting;
>> +    bool reset_is_cold;
>> +    bool reset_hold_needed;
>>  };
>>
>>  /**
>> @@ -376,6 +391,70 @@ int qdev_walk_children(DeviceState *dev,
>>                         qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
>>                         void *opaque);
>>
>> +/**
>> + * device_reset:
>> + * Resets the device @dev, @cold tell whether to do a cold or warm reset.
> 
> "Resets the device @dev. @cold is true if this is a cold reset."
> 
> 
>> + * Uses the ressetable interface.
> 
> "Resettable".
> 
>> + * Base behavior is to reset the device and its qdev/qbus subtree.
> 
> What do you mean by "base behavior" here? When would this ever
> do anything else?
> 
>> + */
>> +void device_reset(DeviceState *dev, bool cold);
>> +
>> +static inline void device_reset_warm(DeviceState *dev)
>> +{
>> +    device_reset(dev, false);
>> +}
>> +
>> +static inline void device_reset_cold(DeviceState *dev)
>> +{
>> +    device_reset(dev, true);
>> +}
>> +
>> +/**
>> + * bus_reset:
>> + * Resets the bus @bus, @cold tell whether to do a cold or warm reset.
>> + * Uses the ressetable interface.
>> + * Base behavior is to reset the bus and its qdev/qbus subtree.
> 
> Same remarks as for device_reset above.
> 
>> + */
>> +void bus_reset(BusState *bus, bool cold);
>> +
>> +static inline void bus_reset_warm(BusState *bus)
>> +{
>> +    bus_reset(bus, false);
>> +}
>> +
>> +static inline void bus_reset_cold(BusState *bus)
>> +{
>> +    bus_reset(bus, true);
>> +}
>> +
>> +/**
>> + * device_is_resetting:
>> + * Tell whether the device @dev is currently under reset.
> 
> "Return true if the device @dev is currently being reset."
> 
>> + */
>> +bool device_is_resetting(DeviceState *dev);
>> +
>> +/**
>> + * device_is_reset_cold:
>> + * Tell whether the device @dev is currently under reset cold or warm reset.
> 
> "Return true if the reset currently in progress for @dev is
> a cold reset."
> 
>> + *
>> + * Note: only valid when device_is_resetting returns true.
>> + */
>> +bool device_is_reset_cold(DeviceState *dev);
>> +
>> +/**
>> + * bus_is_resetting:
>> + * Tell whether the bus @bus is currently under reset.
> 
> [similar rephrasings as above for 'tell whether']
> 
>> + */
>> +bool bus_is_resetting(BusState *bus);
>> +
>> +/**
>> + * bus_is_reset_cold:
>> + * Tell whether the bus @bus is currently under reset cold or warm reset.
>> + *
>> + * Note: only valid when bus_is_resetting returns true.
>> + */
>> +bool bus_is_reset_cold(BusState *bus);
>> +
>>  void qdev_reset_all(DeviceState *dev);
>>  void qdev_reset_all_fn(void *opaque);
>>
>> @@ -413,11 +492,6 @@ void qdev_machine_init(void);
>>   */
>>  void device_legacy_reset(DeviceState *dev);
>>
>> -static inline void device_reset(DeviceState *dev)
>> -{
>> -    device_legacy_reset(dev);
>> -}
>> -
>>  void device_class_set_parent_reset(DeviceClass *dc,
>>                                     DeviceReset dev_reset,
>>                                     DeviceReset *parent_reset);
>> diff --git a/tests/Makefile.include b/tests/Makefile.include
>> index fd7fdb8658..1c0a5345b9 100644
>> --- a/tests/Makefile.include
>> +++ b/tests/Makefile.include
>> @@ -561,6 +561,7 @@ tests/fp/%:
>>
>>  tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
>>         hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
>> +       hw/core/resettable.o \
>>         hw/core/bus.o \
>>         hw/core/irq.o \
>>         hw/core/fw-path-provider.o \
>> --
>> 2.22.0
> 
> thanks
> -- PMM
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/33] hw/s390x/ipl.c: remove qbus_reset_all registration
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 11/33] hw/s390x/ipl.c: " Damien Hedde
@ 2019-08-07 15:24   ` Peter Maydell
  2019-08-08 10:25     ` Cornelia Huck
  0 siblings, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:24 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> Replace deprecated qbus_reset_all by resettable_reset_cold_fn for
> the ipl registration in the main reset handlers.
>
> This does not impact the behavior.
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/s390x/ipl.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
> index 60bd081d3e..402770a2c9 100644
> --- a/hw/s390x/ipl.c
> +++ b/hw/s390x/ipl.c
> @@ -234,7 +234,11 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
>       */
>      ipl->compat_start_addr = ipl->start_addr;
>      ipl->compat_bios_start_addr = ipl->bios_start_addr;
> -    qemu_register_reset(qdev_reset_all_fn, dev);
> +    /*
> +     * TODO: when we add some kind of main reset container / domain
> +     * switch to it to really benefit from multi-phase.
> +     */

I think this comment misses the mark a bit. Here's my suggestion:

/*
 * Because this Device is not on any bus in the qbus tree (it is
 * not a sysbus device and it's not on some other bus like a PCI
 * bus) it will not be automatically reset by the 'reset the
 * sysbus' hook registered by vl.c like most devices. So we must
 * manually register a reset hook for it.
 * TODO: there should be a better way to do this.
 */

> +    qemu_register_reset(resettable_reset_cold_fn, dev);
>  error:
>      error_propagate(errp, err);
>  }
> --
> 2.22.0
>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state
  2019-08-07 14:54   ` Peter Maydell
@ 2019-08-07 15:27     ` Damien Hedde
  0 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-08-07 15:27 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



On 8/7/19 4:54 PM, Peter Maydell wrote:
> On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> It contains the resetting counter and cold flag status.
>>
>> At this point, migration of bus reset related state (counter and cold/warm
>> flag) is handled by parent device. This done using the post_load
>> function in the vmsd subsection.
>>
>> This is last point allow to add an initial support of migration with part of
>> qdev/qbus tree in reset state under the following condition:
>> + time-lasting reset are asserted on Device only
>>
>> Note that if this condition is not respected, migration will succeed and
>> no failure will occurs. The only impact is that the resetting counter
>> of a bus may lower afer a migration.
>>
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> 
> 
>> +const struct VMStateDescription device_vmstate_reset = {
>> +    .name = "device_reset",
>> +    .version_id = 0,
>> +    .minimum_version_id = 0,
>> +    .needed = device_vmstate_reset_needed,
>> +    .post_load = device_vmstate_reset_post_load,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_UINT32(resetting, DeviceState),
>> +        VMSTATE_BOOL(reset_is_cold, DeviceState),
>> +        VMSTATE_END_OF_LIST()
>> +    },
>> +};
>> -
> 
> Forgot to ask -- why don't we migrate the hold_needed flags?

The flag is only used to keep the info between executing the init
and hold phases. We can't interrupt the code in between since this
mess is during resettable_assert_reset method which is atomic.
I can add a comment to explain that.

> 
> thanks
> -- PMM
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-08-07 15:23     ` Damien Hedde
@ 2019-08-07 15:28       ` Peter Maydell
  0 siblings, 0 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:28 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Wed, 7 Aug 2019 at 16:23, Damien Hedde <damien.hedde@greensocs.com> wrote:
> On 8/7/19 4:41 PM, Peter Maydell wrote:
> > On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
> >> legacy resets are called in the "post" order (ie: children then parent)
> >> in hierarchical reset. That is the same order as legacy qdev_reset_all
> >> or qbus_reset_all were using.
> >
> > This is true, but on the other hand the semantics of most device
> > reset methods match "init", not "exit" -- they just set device
> > internal fields to the correct reset state.
>
> I changed from "init" to "exit" due to the change of the init phase call
> order to parent-then-children.
>
> This is a consequence of what I found about the raspi reset: it changes
> the reset hierarchy during reset. The only way I saw to have a chance
> allowing this kind of things cleanly is: do parent init first so that it
> can setup its children before they are considered for reset.

Changing the reset hierarchy during reset is a bit awkward;
I'll have to have a look at the email you sent about the raspi.

I can't decide whether there's an obvious "natural" order to
want the phases to be done in for parent vs children. I guess
it only matters for controller devices and the things on their
bus (eg pci controller vs pci devices, scsi controller vs scsi
devices). We should figure out what the right semantics for our
new multi phase setup are by looking at those, I suppose.

> I can put the legacy reset method to the hold phase which is part of the
> "enter reset state". Otherwise I need to change back the order of init
> phase.
>
> My other concern with putting it in init phase is that some device do
> things we forbid in it (like setting irq).

Yes, but those devices are broken today, because we forbid
setting IRQs in a 'legacy' device reset method as well!
The correct fix for those (eventually) would be to split the 'set irq'
part out into new-style 'init' and 'hold' methods.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 28/33] qdev: Remove unused deprecated reset functions
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 28/33] qdev: Remove unused deprecated reset functions Damien Hedde
@ 2019-08-07 15:29   ` Peter Maydell
  0 siblings, 0 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:29 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> Remove the functions now they are unused:
> + device_legacy_reset
> + qdev_reset_all[_fn]
> + qbus_reset_all[_fn]
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 12/33] hw/pci/: remove qdev/qbus_reset_all call
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 12/33] hw/pci/: remove qdev/qbus_reset_all call Damien Hedde
@ 2019-08-07 15:31   ` Peter Maydell
  2019-08-09  9:47     ` Damien Hedde
  0 siblings, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:31 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> Replace deprecated qdev/bus_reset_all by device/bus_reset_warm.
>
> This does not impact the behavior.
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>

I'll come back to patches 12-28 later. They're all ok
in principle, we just need to check that in each individual
case:
 * we've made the right choice of cold vs warm reset
 * we're ok to switch to 'reset including children' from
   the legacy 'reset not including children' semantics

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 29/33] hw/misc/zynq_slcr: use standard register definition
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 29/33] hw/misc/zynq_slcr: use standard register definition Damien Hedde
@ 2019-08-07 15:33   ` Peter Maydell
  0 siblings, 0 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:33 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Alistair Francis,
	Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke, Qemu-block,
	David Hildenbrand, Halil Pasic, Christian Borntraeger,
	Marc-André Lureau, Richard Henderson,
	Philippe Mathieu-Daudé,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> Replace the zynq_slcr registers enum and macros using the
> hw/registerfields.h macros.
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> ---
>  hw/misc/zynq_slcr.c | 472 ++++++++++++++++++++++----------------------
>  1 file changed, 236 insertions(+), 236 deletions(-)
>

Since this patch has been reviewed and it's unrelated to the
reset APIs, I'm going to pull it into target-arm.next, and
then you can stop carrying it around in your patchset
(well, once it's gone into master and you've rebased on that,
which will probably be in a week or two).

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface Damien Hedde
  2019-07-31  6:30   ` David Gibson
@ 2019-08-07 15:58   ` Peter Maydell
  2019-08-07 16:02   ` Peter Maydell
  2 siblings, 0 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 15:58 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  docs/devel/reset.txt | 165 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 165 insertions(+)
>  create mode 100644 docs/devel/reset.txt
>
> diff --git a/docs/devel/reset.txt b/docs/devel/reset.txt
> new file mode 100644
> index 0000000000..c7a1eb068f
> --- /dev/null
> +++ b/docs/devel/reset.txt
> @@ -0,0 +1,165 @@
> +
> +=====
> +Reset
> +=====
> +
> +The reset of qemu objects is handled using the Resettable interface declared
> +in *include/hw/resettable.h*.
> +As of now DeviceClass and BusClass implement this interface.
> +> +
> +Triggering reset
> +----------------

I think this would be clearer if we documented it the other way around:

  This section documents the APIs which "users" of a resettable
  object should use to control it.

  A resettable object can be put into its "in reset" state and
  held there indefinitely.

  [documentation for resettable_assert/deassert_reset goes here]

  If you want to just trigger a reset event but not leave the
  object in reset for any period of time, you can use
  resettable_reset(), which is a convenience function identical
  in behaviour to calling resettable_assert() and then immediately
  calling resettable_deassert().

  [resettable_reset() docs here]

> +
> +The function *resettable_reset* is used to trigger a reset on a given
> +object.
> +void resettable_reset(Object *obj, bool cold)
> +
> +The parameter *obj* must implement the Resettable interface.
> +The parameter *cold* is a boolean specifying whether to do a cold or warm
> +reset
> +
> +For Devices and Buses there is also the corresponding helpers:
> +void device_reset(Device *dev, bool cold)
> +void bus_reset(Device *dev, bool cold)

We should explain what these do.

> +
> +If one wants to put an object into a reset state. There is the
> +*resettable_assert_reset* function.
> +void resettable_assert_reset(Object *obj, bool cold)
> +
> +One must eventually call the function *resettable_deassert_reset* to end the
> +reset state:
> +void resettable_deassert_reset(Object *obj, bool cold)
> +
> +Calling *resettable_assert_reset* then *resettable_deassert_reset* is the
> +same as calling *resettable_reset*.
> +
> +It is possible to interleave multiple calls to
> + - resettable_reset,
> + - resettable_assert_reset, and
> + - resettable_deassert_reset.
> +The only constraint is that *resettable_deassert_reset* must be called once
> +per *resettable_assert_reset* call so that the object leaves the reset state.
> +
> +Therefore there may be several reset sources/controllers of a given object.
> +The interface handle everything and the controllers do not need to know

"handles"

> +anything about each others. The object will leave reset state only when all

"each other"

> +controllers released their reset.

"release"

> +
> +All theses functions must called while holding the iothread lock.

"these"; "be called"

> +
> +
> +Implementing reset for a Resettable object : Multi-phase reset
> +--------------------------------------------------------------

  This section documents the APIs that an implementation of a
  resettable object must provide.

> +
> +The Resettable uses a multi-phase mechanism to handle some ordering constraints
> +when resetting multiple object at the same time. For a given object the reset

"objects"

> +procedure is split into three different phases executed in order:
> + 1 INIT: This phase should set/reset the state of the Resettable it has when is
> +         in reset state. Side-effects to others object is forbidden (such as
> +         setting IO level).
> + 2 HOLD: This phase corresponds to the external side-effects due to staying into
> +         the reset state.
> + 3 EXIT: This phase corresponds to leaving the reset state. It have both
> +         local and external effects.

We should be a bit more detailed here. I had some text in
my review of patch 1 for the doc-comments which we can put here too.

> +
> +*resettable_assert_reset* does the INIT and HOLD phases. While
> +*resettable_deassert_reset* does the EXIT phase.

Delete this bit -- we don't want to muddle the reader up between
the 'user' APIs and the 'implementer' APIs.

> +
> +When resetting multiple object at the same time. The interface executes the

Comma, not full stop.

> +given phase of the objects before going to the next phase. This guarantee that

"guarantees"

> +all INIT phases are done before any HOLD phase and so on.
> +
> +There is three methods in the interface so must be implemented in an object.

"are"; "that must"

> +The methods corresponds to the three phases:

"correspond"

> +```
> +typedef void (*ResettableInitPhase)(Object *obj);
> +typedef void (*ResettableHoldPhase)(Object *obj);
> +typedef void (*ResettableExitPhase)(Object *obj);
> +typedef struct ResettableClass {
> +    InterfaceClass parent_class;
> +
> +    struct ResettablePhases {
> +        ResettableInitPhase init;
> +        ResettableHoldPhase hold;
> +        ResettableExitPhase exit;
> +    } phases;
> +    [...]
> +} ResettableClass;
> +```
> +
> +Theses methods should be updated when specializing an object. For this the

"These"

> +helper function *resettable_class_set_parent_reset_phases* can be used to
> +backup parent methods while changing the specialized ones.
> +void resettable_class_set_parent_reset_phases(ResettableClass *rc,
> +                                              ResettableInitPhase init,
> +                                              ResettableHoldPhase hold,
> +                                              ResettableExitPhase exit,
> +
> +For Devices and Buses, some helper exists to know if a device/bus is under

"helpers"

> +reset and what type of reset it is:
> +```
> +bool device_is_resetting(DeviceState *dev);
> +bool device_is_reset_cold(DeviceState *dev);
> +bool bus_is_resetting(BusState *bus);
> +bool bus_is_reset_cold(BusState *bus);
> +```

What are these for? Are they part of the API intended for 'users'
of a resettable device', or something that the 'implementor' might
want to use as part of their implementation. More detail would be good.

> +
> +
> +Implementing the base Resettable behavior : Re-entrance, Hierarchy and Cold/Warm
> +--------------------------------------------------------------------------------

  This section documents parts of the reset mechanism that you only
  need to know about if you are extending it to work with a new
  base class other than DeviceClass or BusClass, or maintaining
  the existing code in those classes. Most people can ignore it.

> +
> +There is five others methods in the interface to handle the base mechanics

"are five other methods"

> +of the Resettable interface. The methods should be implemented in object
> +base class. DeviceClass and BusClass implement them.
> +
> +```
> +typedef bool (*ResettableSetCold)(Object *obj, bool cold);
> +typedef bool (*ResettableSetHoldNeeded)(Object *obj, bool hold_needed);
> +typedef uint32_t (*ResettableGetCount)(Object *obj);
> +typedef uint32_t (*ResettableIncrementCount)(Object *obj);
> +typedef uint32_t (*ResettableDecrementCount)(Object *obj);
> +typedef void (*ResettableForeachChild)(Object *obj, void (*visitor)(Object *));
> +typedef struct ResettableClass {
> +    InterfaceClass parent_class;
> +
> +    [...]
> +
> +    ResettableSetCold set_cold;
> +    ResettableSetHoldNeeded set_hold_needed;
> +    ResettableGetCount get_count;
> +    ResettableIncrementCount increment_count;
> +    ResettableDecrementCount decrement_count;
> +    ResettableForeachChild foreach_child;
> +} ResettableClass;
> +```
> +
> +*set_cold* is used when entering reset, before calling the init phase, to
> +indicate the reset type.
> +
> +*set_hold_needed* is used to set/clear and retrieve an "hold_needed" flag.
> +This flag allows to omly execute the hold pahse when required.
> +
> +As stated above, several reset procedures can be concurrent on an object.
> +This is handled with the three methods *get_count*, *increment_count* and
> +*decrement_count*. An object is in reset state if the count is non-zero.
> +
> +The reset hierarchy is handled using the *foreach_child* method. This method
> +executes a given function on every reset "child".
> +
> +In DeviceClass and BusClass the base behavior is to mimic the legacy qdev
> +reset. Reset hierarchy follows the qdev/qbus tree.

We should document the behaviour of the new system specifically,
without saying it's like the old legacy reset. After all the idea
is that the legacy reset is going to go away, so readers should be
able to understand the new system without first knowing about the
old one.

> +
> +Reset control through GPIO
> +--------------------------
> +
> +For devices, two reset inputs can be added: one for the cold, one the warm
> +reset. This is done using the following function.
> +```
> +typedef enum DeviceResetActiveType {
> +    DEVICE_RESET_ACTIVE_LOW,
> +    DEVICE_RESET_ACTIVE_HIGH,
> +} DeviceResetActiveType;
> +void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
> +                                   bool cold, DeviceResetActiveType type);
> +```

Rather than just quoting the prototype of the function, we should
provide a more descriptive documentation of what this feature is
for and why you'd want to use it. Then we can just refer the
reader to the function (which should have its own doc comment)
for the exact details of how the API works.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-07-31  6:30   ` David Gibson
  2019-07-31 10:05     ` Damien Hedde
  2019-08-07 10:34     ` Peter Maydell
@ 2019-08-07 16:01     ` Peter Maydell
  2019-08-12 10:15       ` David Gibson
  2 siblings, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 16:01 UTC (permalink / raw)
  To: David Gibson
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Thomas Huth,
	Eduardo Habkost, Alistair Francis, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

On Wed, 31 Jul 2019 at 07:33, David Gibson <david@gibson.dropbear.id.au> wrote:
>
> On Mon, Jul 29, 2019 at 04:56:30PM +0200, Damien Hedde wrote:
> > Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> > +For Devices and Buses there is also the corresponding helpers:
> > +void device_reset(Device *dev, bool cold)
> > +void bus_reset(Device *dev, bool cold)
>
> What's the semantic difference between resetting a bus and resetting
> the bridge device which owns it?

We should definitely explain this in the documentation, but
consider for instance a SCSI controller. Resetting the
SCSI controller puts all its registers back into whatever
the reset state is for the device, as well as resetting
everything on the SCSI bus. Resetting just the SCSI bus
resets the disks and so on on the bus, but doesn't change
the state of the controller itself, which remains programmed
with whatever state the guest has set up.

PCI has a similar distinction between resetting the controller
and resetting the bus.

Note that we have this distinction in the current APIs too:
qbus_reset_all() vs qdev_reset_all().


thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface Damien Hedde
  2019-07-31  6:30   ` David Gibson
  2019-08-07 15:58   ` Peter Maydell
@ 2019-08-07 16:02   ` Peter Maydell
  2 siblings, 0 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-07 16:02 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:

> +For Devices and Buses there is also the corresponding helpers:
> +void device_reset(Device *dev, bool cold)
> +void bus_reset(Device *dev, bool cold

Just noticed, but the prototype here is wrong: bus_reset() takes
a BusState*, not a Device*.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-08-07 15:18   ` Peter Maydell
@ 2019-08-07 16:56     ` Damien Hedde
  0 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-08-07 16:56 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



On 8/7/19 5:18 PM, Peter Maydell wrote:
> On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> It adds the possibility to add 2 gpios to control the warm and cold reset.
>> With theses ios, the reset can be maintained during some time.
>> Each io is associated with a state to detect level changes.
>>
>> Vmstate subsections are also added to the existsing device_reset
>> subsection.
>>
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>> ---
>>  hw/core/qdev-vmstate.c | 15 ++++++++++
>>  hw/core/qdev.c         | 65 ++++++++++++++++++++++++++++++++++++++++++
>>  include/hw/qdev-core.h | 57 ++++++++++++++++++++++++++++++++++++
>>  3 files changed, 137 insertions(+)
>>
>> diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
>> index 24f8465c61..72f84c6cee 100644
>> --- a/hw/core/qdev-vmstate.c
>> +++ b/hw/core/qdev-vmstate.c
>> @@ -24,10 +24,23 @@ static int device_vmstate_reset_post_load(void *opaque, int version_id)
>>  {
>>      DeviceState *dev = (DeviceState *) opaque;
>>      BusState *bus;
>> +    uint32_t io_count = 0;
>> +
>>      QLIST_FOREACH(bus, &dev->child_bus, sibling) {
>>          bus->resetting = dev->resetting;
>>          bus->reset_is_cold = dev->reset_is_cold;
>>      }
>> +
>> +    if (dev->cold_reset_input.state) {
>> +        io_count += 1;
>> +    }
>> +    if (dev->warm_reset_input.state) {
>> +        io_count += 1;
>> +    }
>> +    /* ensure resetting count is coherent with io states */
>> +    if (dev->resetting < io_count) {
>> +        return -1;
>> +    }
>>      return 0;
>>  }
>>
>> @@ -40,6 +53,8 @@ const struct VMStateDescription device_vmstate_reset = {
>>      .fields = (VMStateField[]) {
>>          VMSTATE_UINT32(resetting, DeviceState),
>>          VMSTATE_BOOL(reset_is_cold, DeviceState),
>> +        VMSTATE_BOOL(cold_reset_input.state, DeviceState),
>> +        VMSTATE_BOOL(warm_reset_input.state, DeviceState),
> 
> If we're just adding these fields to this VMStateDescription
> then this patch should come earlier in the series than the
> patch where we create and start using the fields. Otherwise
> there's a migration compat break between a QEMU just
> before this patch and a QEMU with it. I think the simplest
> fix is to put this patch before patches 6/7 and have a note
> in the commit message that this functionality can't be used
> until after the patch which adds the migration support.

Independently of the compat break you mention, maybe it is better to
have 'conditional' subsection for each input ?

> 
>>          VMSTATE_END_OF_LIST()
>>      },
>>  };
>> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
>> index 88387d3743..11a4de55ea 100644
>> --- a/hw/core/qdev.c
>> +++ b/hw/core/qdev.c
>> @@ -450,6 +450,67 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
>>      qdev_init_gpio_in_named(dev, handler, NULL, n);
>>  }
>>
>> +static DeviceResetInputState *device_get_reset_input_state(DeviceState *dev,
>> +                                                            bool cold)
>> +{
>> +    return cold ? &dev->cold_reset_input : &dev->warm_reset_input;
>> +}
>> +
>> +static void device_reset_handler(DeviceState *dev, bool cold, bool level)
>> +{
>> +    DeviceResetInputState *dris = device_get_reset_input_state(dev, cold);
>> +
>> +    if (dris->type == DEVICE_RESET_ACTIVE_LOW) {
>> +        level = !level;
>> +    }
>> +
>> +    if (dris->state == level) {
>> +        /* io state has not changed */
>> +        return;
>> +    }
>> +
>> +    dris->state = level;
>> +
>> +    if (level) {
>> +        resettable_assert_reset(OBJECT(dev), cold);
>> +    } else {
>> +        resettable_deassert_reset(OBJECT(dev));
>> +    }
>> +}
>> +
>> +static void device_cold_reset_handler(void *opaque, int n, int level)
>> +{
>> +    device_reset_handler((DeviceState *) opaque, true, level);
>> +}
>> +
>> +static void device_warm_reset_handler(void *opaque, int n, int level)
>> +{
>> +    device_reset_handler((DeviceState *) opaque, false, level);
>> +}
>> +
>> +void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name,
>> +                                   bool cold, DeviceResetActiveType type)
>> +{
>> +    DeviceResetInputState *dris = device_get_reset_input_state(dev, cold);
>> +    qemu_irq_handler handler;
>> +
>> +    switch (type) {
>> +    case DEVICE_RESET_ACTIVE_LOW:
>> +    case DEVICE_RESET_ACTIVE_HIGH:
>> +        break;
>> +    default:
>> +        assert(false);
>> +        break;
> 
> The usual way to write this is
>     g_assert_not_reached();
> (and no following 'break').
> 
> 
> But the whole switch statement seems to be a complicated way
> of writing
>    assert(type == DEVICE_RESET_ACTIVE_LOW || type == DEVICE_RESET_ACTIVE_HIGH);
> 
>> +    }
>> +
>> +    assert(!dris->exists);
>> +    dris->exists = true;
>> +    dris->type = type;
>> +
>> +    handler = cold ? device_cold_reset_handler : device_warm_reset_handler;
>> +    qdev_init_gpio_in_named(dev, handler, name, 1);
>> +}
> 
> thanks
> -- PMM
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-07 15:07   ` Peter Maydell
@ 2019-08-07 17:22     ` Damien Hedde
  2019-08-08 15:42     ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-08-07 17:22 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis,
	Dr. David Alan Gilbert, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



On 8/7/19 5:07 PM, Peter Maydell wrote:
> On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> This add the reset related sections for every QOM
>> device.
> 
> A bit more detail in the commit message would help, I think --
> this is adding extra machinery which has to copy and modify
> the VMStateDescription passed in by the device in order to
> add the subsection that handles reset.

Sorry for that, thought I've added some...

I've kept this patch separate from previous one because this it is
awkward. I'm not sure this is the right place (I mean in qdev files) do
this kind of stuff. It basically replaces every static vmsd by dynamic
ones, so it makes it harder to follow when debugging since there is no
symbol associated to them. But on the other hand, I don't see an
alternative.

I copy there what I've put in the cover-letter:
For devices, I've added a patch to automate the addition of reset
related subsection. In consequence it is not necessary to explicitly add
the reset subsection in every device specialization requiring it.
Right know this is kind of a hack into qdev to dynamically modify the
vmsd before the registration. There is probably a much cleaner way to do
this but I prefered to demonstrate it by keeping modification local to qdev.
As far as I can tell it's ok to dynamically add subsections at the end.
This does not prevent from further adding subsections in the orignal
vmsd: the subsections order in the array is irrelevant from migration
point-of-view. The loading part just lookup each subsection in the array
by name uppon reception.

> 
> I've added Dave Gilbert to the already long cc list since this
> is migration related.
> 
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
>> ---
>>  hw/core/qdev-vmstate.c | 41 +++++++++++++++++++++++++++++++++++++++++
>>  hw/core/qdev.c         | 12 +++++++++++-
>>  include/hw/qdev-core.h |  3 +++
>>  stubs/Makefile.objs    |  1 +
>>  stubs/device.c         |  7 +++++++
>>  5 files changed, 63 insertions(+), 1 deletion(-)
>>  create mode 100644 stubs/device.c
>>
>> diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
>> index 07b010811f..24f8465c61 100644
>> --- a/hw/core/qdev-vmstate.c
>> +++ b/hw/core/qdev-vmstate.c
>> @@ -43,3 +43,44 @@ const struct VMStateDescription device_vmstate_reset = {
>>          VMSTATE_END_OF_LIST()
>>      },
>>  };
>> +
>> +static VMStateDescription *vmsd_duplicate_and_append(
>> +        const VMStateDescription *old_vmsd,
>> +        const VMStateDescription *new_subsection)
>> +{
>> +    VMStateDescription *vmsd;
>> +    int n = 0;
>> +
>> +    assert(old_vmsd && new_subsection);
>> +
>> +    vmsd = (VMStateDescription *) g_memdup(old_vmsd, sizeof(*vmsd));
>> +
>> +    if (old_vmsd->subsections) {
>> +        while (old_vmsd->subsections[n]) {
>> +            n += 1;
>> +        }
>> +    }
>> +    vmsd->subsections = g_new(const VMStateDescription *, n + 2);
>> +
>> +    if (old_vmsd->subsections) {
>> +        memcpy(vmsd->subsections, old_vmsd->subsections,
>> +               sizeof(VMStateDescription *) * n);
>> +    }
>> +    vmsd->subsections[n] = new_subsection;
>> +    vmsd->subsections[n + 1] = NULL;
>> +
>> +    return vmsd;
>> +}
>> +
>> +void device_class_build_extended_vmsd(DeviceClass *dc)
>> +{
>> +    assert(dc->vmsd);
>> +    assert(!dc->vmsd_ext);
>> +
>> +    /* forge a subsection with proper name */
>> +    VMStateDescription *reset;
>> +    reset = g_memdup(&device_vmstate_reset, sizeof(*reset));
>> +    reset->name = g_strdup_printf("%s/device_reset", dc->vmsd->name);
>> +
>> +    dc->vmsd_ext = vmsd_duplicate_and_append(dc->vmsd, reset);
>> +}
> 
> This will allocate memory, but there is no corresponding
> code which frees it. This means you'll have a memory leak
> across device realize->unrealize for hotplug devices.

Right. I'll handle this along with the existing vmsd_unregister
in realize/unrealize method.

> 
>> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
>> index e9e5f2d5f9..88387d3743 100644
>> --- a/hw/core/qdev.c
>> +++ b/hw/core/qdev.c
>> @@ -45,7 +45,17 @@ bool qdev_hot_removed = false;
>>  const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
>>  {
>>      DeviceClass *dc = DEVICE_GET_CLASS(dev);
>> -    return dc->vmsd;
>> +
>> +    if (!dc->vmsd) {
>> +        return NULL;
>> +    }
>> +
>> +    if (!dc->vmsd_ext) {
>> +        /* build it first time we need it */
>> +        device_class_build_extended_vmsd(dc);
>> +    }
>> +
>> +    return dc->vmsd_ext;
>>  }
> 
> Unfortunately not everything that wants the VMSD calls
> this function. migration/savevm.c:dump_vmstate_json_to_file()
> does a direct access to dc->vmsd, so we need to fix that first.
> 
> Devices which don't use dc->vmsd won't get this and so
> their reset state won't be migrated. That's OK for anything
> that's still not yet a QOM device, I guess -- it's not possible
> for them to be in a 'held in reset' state anyway, so the
> extra subsection would never be needed.
> 
> The one I'm less sure about is the 'virtio' devices, which
> have to do something odd with migration state for backwards
> compat reasons. At the moment they can't be in a situation
> where they're being held in reset when we do a migration,
> but since they're PCI devices they might in future be possible
> to put into new boards/pci controllers that would let them
> be in that situation.
> 
>>  static void bus_remove_child(BusState *bus, DeviceState *child)
>> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
>> index 1670ae41bb..926d4bbcb1 100644
>> --- a/include/hw/qdev-core.h
>> +++ b/include/hw/qdev-core.h
>> @@ -120,6 +120,7 @@ typedef struct DeviceClass {
>>
>>      /* device state */
>>      const struct VMStateDescription *vmsd;
>> +    const struct VMStateDescription *vmsd_ext;
>>
>>      /* Private to qdev / bus.  */
>>      const char *bus_type;
>> @@ -520,6 +521,8 @@ void device_class_set_parent_unrealize(DeviceClass *dc,
>>
>>  const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
>>
>> +void device_class_build_extended_vmsd(DeviceClass *dc);
>> +
>>  const char *qdev_fw_name(DeviceState *dev);
>>
>>  Object *qdev_get_machine(void);
>> diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
>> index 9c7393b08c..432b56f290 100644
>> --- a/stubs/Makefile.objs
>> +++ b/stubs/Makefile.objs
>> @@ -40,4 +40,5 @@ stub-obj-y += pci-host-piix.o
>>  stub-obj-y += ram-block.o
>>  stub-obj-y += ramfb.o
>>  stub-obj-y += fw_cfg.o
>> +stub-obj-y += device.o
>>  stub-obj-$(CONFIG_SOFTMMU) += semihost.o
>> diff --git a/stubs/device.c b/stubs/device.c
>> new file mode 100644
>> index 0000000000..e9b4f57e5f
>> --- /dev/null
>> +++ b/stubs/device.c
>> @@ -0,0 +1,7 @@
>> +#include "qemu/osdep.h"
>> +#include "hw/qdev-core.h"
>> +
>> +void device_class_build_extended_vmsd(DeviceClass *dc)
>> +{
>> +    return;
>> +}
>> --
>> 2.22.0
> 
> 
> thanks
> -- PMM
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-07-31 11:31       ` Philippe Mathieu-Daudé
@ 2019-08-08  6:47         ` David Gibson
  2019-08-09 11:08           ` Peter Maydell
  0 siblings, 1 reply; 113+ messages in thread
From: David Gibson @ 2019-08-08  6:47 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 3657 bytes --]

On Wed, Jul 31, 2019 at 01:31:28PM +0200, Philippe Mathieu-Daudé wrote:
> On 7/31/19 11:29 AM, Damien Hedde wrote:
> > On 7/31/19 8:05 AM, David Gibson wrote:
> >> On Mon, Jul 29, 2019 at 04:56:26PM +0200, Damien Hedde wrote:
> >>> Deprecate old reset apis and make them use the new one while they
> >>> are still used somewhere.
> >>>
> >>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> >>> ---
> >>>  hw/core/qdev.c         | 22 +++-------------------
> >>>  include/hw/qdev-core.h | 28 ++++++++++++++++++++++------
> >>>  2 files changed, 25 insertions(+), 25 deletions(-)
> >>>
> >>> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> >>> index 559ced070d..e9e5f2d5f9 100644
> >>> --- a/hw/core/qdev.c
> >>> +++ b/hw/core/qdev.c
> >>> @@ -312,25 +312,9 @@ static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
> >>>      }
> >>>  }
> >>>  
> >>> -static int qdev_reset_one(DeviceState *dev, void *opaque)
> >>> -{
> >>> -    device_legacy_reset(dev);
> >>> -
> >>> -    return 0;
> >>> -}
> >>> -
> >>> -static int qbus_reset_one(BusState *bus, void *opaque)
> >>> -{
> >>> -    BusClass *bc = BUS_GET_CLASS(bus);
> >>> -    if (bc->reset) {
> >>> -        bc->reset(bus);
> >>> -    }
> >>> -    return 0;
> >>> -}
> >>> -
> >>>  void qdev_reset_all(DeviceState *dev)
> >>>  {
> >>> -    qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
> >>> +    device_reset(dev, false);
> >>>  }
> >>>  
> >>>  void qdev_reset_all_fn(void *opaque)
> >>> @@ -340,7 +324,7 @@ void qdev_reset_all_fn(void *opaque)
> >>>  
> >>>  void qbus_reset_all(BusState *bus)
> >>>  {
> >>> -    qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
> >>> +    bus_reset(bus, false);
> >>>  }
> >>>  
> >>>  void qbus_reset_all_fn(void *opaque)
> >>> @@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
> >>>              }
> >>>          }
> >>>          if (dev->hotplugged) {
> >>> -            device_legacy_reset(dev);
> >>> +            device_reset(dev, true);
> >>
> >> So.. is this change in the device_reset() signature really necessary?
> >> Even if there are compelling reasons to handle warm reset in the new
> >> API, that doesn't been you need to change device_reset() itself from
> >> its established meaning of a cold (i.e. as per power cycle) reset.
> >> Warm resets are generally called in rather more specific circumstances
> >> (often under guest software direction) so it seems likely that users
> >> would want to engage with the new reset API directly.  Or we could
> >> just create a device_warm_reset() wrapper.  That would also avoid the
> >> bare boolean parameter, which is not great for readability (you have
> >> to look up the signature to have any idea what it means).
> 
> If the boolean is not meaningful, we can use an enum...

That's certainly better, but I'm not seeing a compelling reason not to
have separate function names.  It's just as clear and means less churn.

> 
> > I've added device_reset_cold/warm wrapper functions to avoid having to
> > pass the boolean parameter. it seems I forgot to use them in qdev.c
> > I suppose, like you said, we could live with
> > + no function with the boolean parameter
> > + device_reset doing cold reset
> > + device_reset_warm (or device_warm_reset) for the warm version
> > 
> > Damien
> > 
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-07-31  9:29     ` Damien Hedde
  2019-07-31 11:31       ` Philippe Mathieu-Daudé
@ 2019-08-08  6:48       ` David Gibson
  2019-08-09 11:39         ` Cédric Le Goater
  1 sibling, 1 reply; 113+ messages in thread
From: David Gibson @ 2019-08-08  6:48 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 3451 bytes --]

On Wed, Jul 31, 2019 at 11:29:36AM +0200, Damien Hedde wrote:
> 
> 
> On 7/31/19 8:05 AM, David Gibson wrote:
> > On Mon, Jul 29, 2019 at 04:56:26PM +0200, Damien Hedde wrote:
> >> Deprecate old reset apis and make them use the new one while they
> >> are still used somewhere.
> >>
> >> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> >> ---
> >>  hw/core/qdev.c         | 22 +++-------------------
> >>  include/hw/qdev-core.h | 28 ++++++++++++++++++++++------
> >>  2 files changed, 25 insertions(+), 25 deletions(-)
> >>
> >> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> >> index 559ced070d..e9e5f2d5f9 100644
> >> --- a/hw/core/qdev.c
> >> +++ b/hw/core/qdev.c
> >> @@ -312,25 +312,9 @@ static void device_foreach_reset_child(Object *obj, void (*func)(Object *))
> >>      }
> >>  }
> >>  
> >> -static int qdev_reset_one(DeviceState *dev, void *opaque)
> >> -{
> >> -    device_legacy_reset(dev);
> >> -
> >> -    return 0;
> >> -}
> >> -
> >> -static int qbus_reset_one(BusState *bus, void *opaque)
> >> -{
> >> -    BusClass *bc = BUS_GET_CLASS(bus);
> >> -    if (bc->reset) {
> >> -        bc->reset(bus);
> >> -    }
> >> -    return 0;
> >> -}
> >> -
> >>  void qdev_reset_all(DeviceState *dev)
> >>  {
> >> -    qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
> >> +    device_reset(dev, false);
> >>  }
> >>  
> >>  void qdev_reset_all_fn(void *opaque)
> >> @@ -340,7 +324,7 @@ void qdev_reset_all_fn(void *opaque)
> >>  
> >>  void qbus_reset_all(BusState *bus)
> >>  {
> >> -    qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
> >> +    bus_reset(bus, false);
> >>  }
> >>  
> >>  void qbus_reset_all_fn(void *opaque)
> >> @@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
> >>              }
> >>          }
> >>          if (dev->hotplugged) {
> >> -            device_legacy_reset(dev);
> >> +            device_reset(dev, true);
> > 
> > So.. is this change in the device_reset() signature really necessary?
> > Even if there are compelling reasons to handle warm reset in the new
> > API, that doesn't been you need to change device_reset() itself from
> > its established meaning of a cold (i.e. as per power cycle) reset.
> > Warm resets are generally called in rather more specific circumstances
> > (often under guest software direction) so it seems likely that users
> > would want to engage with the new reset API directly.  Or we could
> > just create a device_warm_reset() wrapper.  That would also avoid the
> > bare boolean parameter, which is not great for readability (you have
> > to look up the signature to have any idea what it means).
> 
> I've added device_reset_cold/warm wrapper functions to avoid having to
> pass the boolean parameter. it seems I forgot to use them in qdev.c
> I suppose, like you said, we could live with
> + no function with the boolean parameter
> + device_reset doing cold reset
> + device_reset_warm (or device_warm_reset) for the warm version

Ok, good.

I'm afraid the whole series still makes me pretty uncomfortable,
though, since the whole "warm reset" concept still seems way to vague
to me.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-08-07 10:34     ` Peter Maydell
@ 2019-08-08  6:49       ` David Gibson
  0 siblings, 0 replies; 113+ messages in thread
From: David Gibson @ 2019-08-08  6:49 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Thomas Huth,
	Eduardo Habkost, Alistair Francis, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 910 bytes --]

On Wed, Aug 07, 2019 at 11:34:41AM +0100, Peter Maydell wrote:
> On Wed, 31 Jul 2019 at 07:33, David Gibson <david@gibson.dropbear.id.au> wrote:
> >
> > On Mon, Jul 29, 2019 at 04:56:30PM +0200, Damien Hedde wrote:
> > > +The function *resettable_reset* is used to trigger a reset on a given
> > > +object.
> > > +void resettable_reset(Object *obj, bool cold)
> > > +
> > > +The parameter *obj* must implement the Resettable interface.
> >
> > And what happens if it doesn't?  This function has no way to report an
> > error.
> 
> Trying to reset an object that isn't actually resettable would
> be a programming error -- I think asserting is a reasonable
> response to that.

Yeah, fair enough.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/33] hw/s390x/ipl.c: remove qbus_reset_all registration
  2019-08-07 15:24   ` Peter Maydell
@ 2019-08-08 10:25     ` Cornelia Huck
  0 siblings, 0 replies; 113+ messages in thread
From: Cornelia Huck @ 2019-08-08 10:25 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Damien Hedde, Daniel P. Berrange, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Wed, 7 Aug 2019 16:24:30 +0100
Peter Maydell <peter.maydell@linaro.org> wrote:

> On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
> >
> > Replace deprecated qbus_reset_all by resettable_reset_cold_fn for
> > the ipl registration in the main reset handlers.
> >
> > This does not impact the behavior.
> >
> > Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> > ---
> >  hw/s390x/ipl.c | 6 +++++-
> >  1 file changed, 5 insertions(+), 1 deletion(-)
> >
> > diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
> > index 60bd081d3e..402770a2c9 100644
> > --- a/hw/s390x/ipl.c
> > +++ b/hw/s390x/ipl.c
> > @@ -234,7 +234,11 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
> >       */
> >      ipl->compat_start_addr = ipl->start_addr;
> >      ipl->compat_bios_start_addr = ipl->bios_start_addr;
> > -    qemu_register_reset(qdev_reset_all_fn, dev);
> > +    /*
> > +     * TODO: when we add some kind of main reset container / domain
> > +     * switch to it to really benefit from multi-phase.
> > +     */  
> 
> I think this comment misses the mark a bit. Here's my suggestion:
> 
> /*
>  * Because this Device is not on any bus in the qbus tree (it is
>  * not a sysbus device and it's not on some other bus like a PCI
>  * bus) it will not be automatically reset by the 'reset the
>  * sysbus' hook registered by vl.c like most devices. So we must
>  * manually register a reset hook for it.
>  * TODO: there should be a better way to do this.
>  */

Agreed, that explains much better why we're doing this.

> 
> > +    qemu_register_reset(resettable_reset_cold_fn, dev);

This is fine for the conversion done within this series; but resetting
the ipl device is one case where the cold vs. warm distinction falls a
bit short (there's a s390_reset enum which covers more cases). Not sure
if we want some custom reset types?

> >  error:
> >      error_propagate(errp, err);
> >  }
> > --
> > 2.22.0
> >  
> 
> thanks
> -- PMM



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 14/33] hw/s390x/s390-virtio-ccw.c: remove qdev_reset_all call
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 14/33] hw/s390x/s390-virtio-ccw.c: remove qdev_reset_all call Damien Hedde
@ 2019-08-08 10:50   ` Cornelia Huck
  2019-08-09  8:31     ` Damien Hedde
  0 siblings, 1 reply; 113+ messages in thread
From: Cornelia Huck @ 2019-08-08 10:50 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, rth,
	thuth, ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow,
	david, berrange, mark.burton, qemu-ppc, pbonzini

On Mon, 29 Jul 2019 16:56:35 +0200
Damien Hedde <damien.hedde@greensocs.com> wrote:

> Replace deprecated qdev_reset_all by device_reset_warm.
> 
> This does not impact the behavior.

Not so sure about that; see below.

> 
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/s390x/s390-virtio-ccw.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
> index 5b6a9a4e55..1d6b966817 100644
> --- a/hw/s390x/s390-virtio-ccw.c
> +++ b/hw/s390x/s390-virtio-ccw.c
> @@ -104,7 +104,7 @@ static void subsystem_reset(void)
>      for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) {
>          dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL));
>          if (dev) {
> -            qdev_reset_all(dev);
> +            device_reset_warm(dev);
>          }
>      }
>  }

This resets various different devices:

- the diag288 watchdog, which does not have kids
- the flic also seems fine (both non-kvm and kvm versions)
- the sclp event facility, however, does have kids:
  - I'm a bit unsure about the sclp cpu hotplug thing; it does not have
    a ->reset function, though
  - the quiesce event does have a ->reset callback; so presumably this
    is already called in a different path
- the css bridge is basically the root of all things css; its ->reset
  function currently calls css_reset(), which resets some state of the
  css per se, but does not call down into the device tree
  - might we end up with calling some stuff twice for devices in the
    css?

Would be good if someone else from the s390 folks could take a look,
just to make sure I'm not confused here.


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 26/33] hw/s390x/s390-pci-inst.c: remove device_legacy_reset call
  2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 26/33] hw/s390x/s390-pci-inst.c: " Damien Hedde
@ 2019-08-08 10:52   ` Cornelia Huck
  0 siblings, 0 replies; 113+ messages in thread
From: Cornelia Huck @ 2019-08-08 10:52 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, rth,
	thuth, ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow,
	david, berrange, mark.burton, qemu-ppc, pbonzini

On Mon, 29 Jul 2019 16:56:47 +0200
Damien Hedde <damien.hedde@greensocs.com> wrote:

> Replace S390PCIBusDevice legacy reset by device_reset_warm.
> 
> The new function propagates also the reset to the sub-buses tree.
> I'm not sure whether S390PCIBusDevice has bus children or not.

This should be fine, I think.

> 
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> ---
>  hw/s390x/s390-pci-inst.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
> index 93cda37c27..d7bca68245 100644
> --- a/hw/s390x/s390-pci-inst.c
> +++ b/hw/s390x/s390-pci-inst.c
> @@ -242,7 +242,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
>                  stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
>                  goto out;
>              }
> -            device_legacy_reset(DEVICE(pbdev));
> +            device_reset_warm(DEVICE(pbdev));
>              pbdev->fh &= ~FH_MASK_ENABLE;
>              pbdev->state = ZPCI_FS_DISABLED;
>              stl_p(&ressetpci->fh, pbdev->fh);



^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-07 15:07   ` Peter Maydell
  2019-08-07 17:22     ` Damien Hedde
@ 2019-08-08 15:42     ` Dr. David Alan Gilbert
  2019-08-09 10:07       ` Peter Maydell
  1 sibling, 1 reply; 113+ messages in thread
From: Dr. David Alan Gilbert @ 2019-08-08 15:42 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, quintela, David Hildenbrand,
	Halil Pasic, Christian Borntraeger, Marc-André Lureau,
	Richard Henderson, Thomas Huth, Eduardo Habkost,
	Alistair Francis, qemu-s390x, qemu-arm, Cédric Le Goater,
	John Snow, David Gibson, Damien Hedde, Daniel P. Berrange,
	Cornelia Huck, Mark Burton, qemu-ppc, Paolo Bonzini

* Peter Maydell (peter.maydell@linaro.org) wrote:
> On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
> >
> > This add the reset related sections for every QOM
> > device.
> 
> A bit more detail in the commit message would help, I think --
> this is adding extra machinery which has to copy and modify
> the VMStateDescription passed in by the device in order to
> add the subsection that handles reset.
> 
> I've added Dave Gilbert to the already long cc list since this
> is migration related.

I don't like dynamically modifying all the vmsds.
Aren't you going to have to understand each devices reset behaviour
and make sure it does something sane? e.g. it might have a postload
that registers a timer or something that you wouldn't want to do if it's
in reset.

The easiest way is to write a macro that you can easily add to devices
you've checked subsection list (like the way we have a
VMSTATE_USB_DEVICE).

Dave

> 
> > Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> > ---
> >  hw/core/qdev-vmstate.c | 41 +++++++++++++++++++++++++++++++++++++++++
> >  hw/core/qdev.c         | 12 +++++++++++-
> >  include/hw/qdev-core.h |  3 +++
> >  stubs/Makefile.objs    |  1 +
> >  stubs/device.c         |  7 +++++++
> >  5 files changed, 63 insertions(+), 1 deletion(-)
> >  create mode 100644 stubs/device.c
> >
> > diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c
> > index 07b010811f..24f8465c61 100644
> > --- a/hw/core/qdev-vmstate.c
> > +++ b/hw/core/qdev-vmstate.c
> > @@ -43,3 +43,44 @@ const struct VMStateDescription device_vmstate_reset = {
> >          VMSTATE_END_OF_LIST()
> >      },
> >  };
> > +
> > +static VMStateDescription *vmsd_duplicate_and_append(
> > +        const VMStateDescription *old_vmsd,
> > +        const VMStateDescription *new_subsection)
> > +{
> > +    VMStateDescription *vmsd;
> > +    int n = 0;
> > +
> > +    assert(old_vmsd && new_subsection);
> > +
> > +    vmsd = (VMStateDescription *) g_memdup(old_vmsd, sizeof(*vmsd));
> > +
> > +    if (old_vmsd->subsections) {
> > +        while (old_vmsd->subsections[n]) {
> > +            n += 1;
> > +        }
> > +    }
> > +    vmsd->subsections = g_new(const VMStateDescription *, n + 2);
> > +
> > +    if (old_vmsd->subsections) {
> > +        memcpy(vmsd->subsections, old_vmsd->subsections,
> > +               sizeof(VMStateDescription *) * n);
> > +    }
> > +    vmsd->subsections[n] = new_subsection;
> > +    vmsd->subsections[n + 1] = NULL;
> > +
> > +    return vmsd;
> > +}
> > +
> > +void device_class_build_extended_vmsd(DeviceClass *dc)
> > +{
> > +    assert(dc->vmsd);
> > +    assert(!dc->vmsd_ext);
> > +
> > +    /* forge a subsection with proper name */
> > +    VMStateDescription *reset;
> > +    reset = g_memdup(&device_vmstate_reset, sizeof(*reset));
> > +    reset->name = g_strdup_printf("%s/device_reset", dc->vmsd->name);
> > +
> > +    dc->vmsd_ext = vmsd_duplicate_and_append(dc->vmsd, reset);
> > +}
> 
> This will allocate memory, but there is no corresponding
> code which frees it. This means you'll have a memory leak
> across device realize->unrealize for hotplug devices.
> 
> > diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> > index e9e5f2d5f9..88387d3743 100644
> > --- a/hw/core/qdev.c
> > +++ b/hw/core/qdev.c
> > @@ -45,7 +45,17 @@ bool qdev_hot_removed = false;
> >  const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
> >  {
> >      DeviceClass *dc = DEVICE_GET_CLASS(dev);
> > -    return dc->vmsd;
> > +
> > +    if (!dc->vmsd) {
> > +        return NULL;
> > +    }
> > +
> > +    if (!dc->vmsd_ext) {
> > +        /* build it first time we need it */
> > +        device_class_build_extended_vmsd(dc);
> > +    }
> > +
> > +    return dc->vmsd_ext;
> >  }
> 
> Unfortunately not everything that wants the VMSD calls
> this function. migration/savevm.c:dump_vmstate_json_to_file()
> does a direct access to dc->vmsd, so we need to fix that first.
> 
> Devices which don't use dc->vmsd won't get this and so
> their reset state won't be migrated. That's OK for anything
> that's still not yet a QOM device, I guess -- it's not possible
> for them to be in a 'held in reset' state anyway, so the
> extra subsection would never be needed.
> 
> The one I'm less sure about is the 'virtio' devices, which
> have to do something odd with migration state for backwards
> compat reasons. At the moment they can't be in a situation
> where they're being held in reset when we do a migration,
> but since they're PCI devices they might in future be possible
> to put into new boards/pci controllers that would let them
> be in that situation.
> 
> >  static void bus_remove_child(BusState *bus, DeviceState *child)
> > diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> > index 1670ae41bb..926d4bbcb1 100644
> > --- a/include/hw/qdev-core.h
> > +++ b/include/hw/qdev-core.h
> > @@ -120,6 +120,7 @@ typedef struct DeviceClass {
> >
> >      /* device state */
> >      const struct VMStateDescription *vmsd;
> > +    const struct VMStateDescription *vmsd_ext;
> >
> >      /* Private to qdev / bus.  */
> >      const char *bus_type;
> > @@ -520,6 +521,8 @@ void device_class_set_parent_unrealize(DeviceClass *dc,
> >
> >  const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
> >
> > +void device_class_build_extended_vmsd(DeviceClass *dc);
> > +
> >  const char *qdev_fw_name(DeviceState *dev);
> >
> >  Object *qdev_get_machine(void);
> > diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
> > index 9c7393b08c..432b56f290 100644
> > --- a/stubs/Makefile.objs
> > +++ b/stubs/Makefile.objs
> > @@ -40,4 +40,5 @@ stub-obj-y += pci-host-piix.o
> >  stub-obj-y += ram-block.o
> >  stub-obj-y += ramfb.o
> >  stub-obj-y += fw_cfg.o
> > +stub-obj-y += device.o
> >  stub-obj-$(CONFIG_SOFTMMU) += semihost.o
> > diff --git a/stubs/device.c b/stubs/device.c
> > new file mode 100644
> > index 0000000000..e9b4f57e5f
> > --- /dev/null
> > +++ b/stubs/device.c
> > @@ -0,0 +1,7 @@
> > +#include "qemu/osdep.h"
> > +#include "hw/qdev-core.h"
> > +
> > +void device_class_build_extended_vmsd(DeviceClass *dc)
> > +{
> > +    return;
> > +}
> > --
> > 2.22.0
> 
> 
> thanks
> -- PMM
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-08-07 10:37     ` Peter Maydell
@ 2019-08-09  5:51       ` David Gibson
  2019-08-09  8:45         ` Damien Hedde
  0 siblings, 1 reply; 113+ messages in thread
From: David Gibson @ 2019-08-09  5:51 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Thomas Huth,
	Eduardo Habkost, Alistair Francis, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 1273 bytes --]

On Wed, Aug 07, 2019 at 11:37:51AM +0100, Peter Maydell wrote:
> On Wed, 31 Jul 2019 at 07:33, David Gibson <david@gibson.dropbear.id.au> wrote:
> >
> > On Mon, Jul 29, 2019 at 04:56:29PM +0200, Damien Hedde wrote:
> > > It adds the possibility to add 2 gpios to control the warm and cold reset.
> > > With theses ios, the reset can be maintained during some time.
> > > Each io is associated with a state to detect level changes.
> > >
> > > Vmstate subsections are also added to the existsing device_reset
> > > subsection.
> >
> > This doesn't seem like a thing that should be present on every single
> > DeviceState.
> 
> It's a facility that's going to be useful to multiple different
> subclasses of DeviceState, so it seems to me cleaner to
> have base class support for the common feature rather than
> to reimplement it entirely from scratch in every subclass
> that wants it.

Hm, I suppose so.  Would it really have to be from scratch, though?
Couldn't some suitable helper functions make adding such GPIOs to a
device pretty straightforward?

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 14/33] hw/s390x/s390-virtio-ccw.c: remove qdev_reset_all call
  2019-08-08 10:50   ` Cornelia Huck
@ 2019-08-09  8:31     ` Damien Hedde
  0 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-08-09  8:31 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, rth,
	thuth, ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow,
	david, berrange, mark.burton, qemu-ppc, pbonzini



On 8/8/19 12:50 PM, Cornelia Huck wrote:
> On Mon, 29 Jul 2019 16:56:35 +0200
> Damien Hedde <damien.hedde@greensocs.com> wrote:
> 
>> Replace deprecated qdev_reset_all by device_reset_warm.
>>
>> This does not impact the behavior.
> 
> Not so sure about that; see below.

In this case, qdev_reset_all is used. The qdev subtree is already reset.
device_reset_* does keep the same children-then-parent call order for
the legacy reset method. This is why the behavior is unchanged.

I will add this point in the commit message of this patch (and also in
other qdev/qbus_reset_all replacement patches) so it will be more clear.

--
Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-08-09  5:51       ` David Gibson
@ 2019-08-09  8:45         ` Damien Hedde
  2019-08-12 10:29           ` David Gibson
  0 siblings, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-08-09  8:45 UTC (permalink / raw)
  To: David Gibson, Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Thomas Huth,
	Eduardo Habkost, Alistair Francis, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, Richard Henderson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



On 8/9/19 7:51 AM, David Gibson wrote:
> On Wed, Aug 07, 2019 at 11:37:51AM +0100, Peter Maydell wrote:
>> On Wed, 31 Jul 2019 at 07:33, David Gibson <david@gibson.dropbear.id.au> wrote:
>>>
>>> On Mon, Jul 29, 2019 at 04:56:29PM +0200, Damien Hedde wrote:
>>>> It adds the possibility to add 2 gpios to control the warm and cold reset.
>>>> With theses ios, the reset can be maintained during some time.
>>>> Each io is associated with a state to detect level changes.
>>>>
>>>> Vmstate subsections are also added to the existsing device_reset
>>>> subsection.
>>>
>>> This doesn't seem like a thing that should be present on every single
>>> DeviceState.
>>
>> It's a facility that's going to be useful to multiple different
>> subclasses of DeviceState, so it seems to me cleaner to
>> have base class support for the common feature rather than
>> to reimplement it entirely from scratch in every subclass
>> that wants it.
> 
> Hm, I suppose so.  Would it really have to be from scratch, though?
> Couldn't some suitable helper functions make adding such GPIOs to a
> device pretty straightforward?
> 

This patch does that. A device does have to use the helper to add the
gpio. Either qdev_init_warm_reset_gpio(...) or
qdev_init_cold_reset_gpio(...) , like any another gpio.

The mechanics to control the reset with gpio change is done in the base
class and there is some state pre-allocated (and associated vmstate
description) to it.

If that's a problem I can only provide helpers and let devices handle
state allocation and vmstate addition.

Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/33] add temporary device_legacy_reset function to replace device_reset
  2019-08-07 14:27   ` Peter Maydell
@ 2019-08-09  9:20     ` Damien Hedde
  0 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-08-09  9:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, David Gibson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, Richard Henderson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini


On 8/7/19 4:27 PM, Peter Maydell wrote:
> On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> Provide a temporary function doing what device_reset does to do the
>> transition with Resettable API which will trigger a prototype change
>> of device_reset.
> 
> The other point here is that device_legacy_reset() resets
> only that device, not any of its qbus children, right?
> So the new function which we eventually replace the callsites
> with also has different semantics, which is why we do the
> changes one by one in patches 10-28.

Yes, for device_reset there is a change of scope.

> 
> So you could add:
> 
> The new resettable API function also has different semantics
> (resetting child buses as well as the specified device).
> Subsequent commits will make the changeover for each callsite
> individually; once that is complete device_legacy_reset() will be
> removed.

sure

> 
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> 
> I agree with David that patch 3 could be squashed into this one.

ok

> 
> If you do that and tweak the commit message you can have
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> 
> thanks
> -- PMM
> 


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 12/33] hw/pci/: remove qdev/qbus_reset_all call
  2019-08-07 15:31   ` Peter Maydell
@ 2019-08-09  9:47     ` Damien Hedde
  0 siblings, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-08-09  9:47 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, David Gibson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, Richard Henderson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



On 8/7/19 5:31 PM, Peter Maydell wrote:
> On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> Replace deprecated qdev/bus_reset_all by device/bus_reset_warm.
>>
>> This does not impact the behavior.
>>
>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> 
> I'll come back to patches 12-28 later. They're all ok
> in principle, we just need to check that in each individual
> case:
>  * we've made the right choice of cold vs warm reset
>  * we're ok to switch to 'reset including children' from
>    the legacy 'reset not including children' semantics

I'm working on a patch reroll to fix what's been reviewed so far. Should
I put aside the patches 12-28 for now ? They could be part of 1 or 2
separate following series or I can re-add them later on when we agree on
the api.

--
Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-08 15:42     ` Dr. David Alan Gilbert
@ 2019-08-09 10:07       ` Peter Maydell
  2019-08-09 10:29         ` Damien Hedde
  2019-08-09 13:50         ` Dr. David Alan Gilbert
  0 siblings, 2 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-09 10:07 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, Juan Quintela, David Hildenbrand,
	Halil Pasic, Christian Borntraeger, Marc-André Lureau,
	Richard Henderson, Thomas Huth, Eduardo Habkost,
	Alistair Francis, qemu-s390x, qemu-arm, Cédric Le Goater,
	John Snow, David Gibson, Damien Hedde, Daniel P. Berrange,
	Cornelia Huck, Mark Burton, qemu-ppc, Paolo Bonzini

On Thu, 8 Aug 2019 at 16:42, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
>
> * Peter Maydell (peter.maydell@linaro.org) wrote:
> > On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
> > >
> > > This add the reset related sections for every QOM
> > > device.
> >
> > A bit more detail in the commit message would help, I think --
> > this is adding extra machinery which has to copy and modify
> > the VMStateDescription passed in by the device in order to
> > add the subsection that handles reset.
> >
> > I've added Dave Gilbert to the already long cc list since this
> > is migration related.
>
> I don't like dynamically modifying all the vmsds.

Yeah, I'm not a huge fan of it either, but it does mean that
the state gets migrated and we don't have a pile of really
easy to miss bugs where we forgot to say "this device needs to
migrate the reset state" and it means we don't have every
device we ever write in the future needing to say "this device
needs to migrate reset state"...

> Aren't you going to have to understand each devices reset behaviour
> and make sure it does something sane? e.g. it might have a postload
> that registers a timer or something that you wouldn't want to do if it's
> in reset.
>
> The easiest way is to write a macro that you can easily add to devices
> you've checked subsection list (like the way we have a
> VMSTATE_USB_DEVICE).

One problem is that as soon as somebody writes a USB controller
or PCI controller model that can be held in reset, every
device that could sat behind it automatically now could find
that it's migrated while it's in reset.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-09 10:07       ` Peter Maydell
@ 2019-08-09 10:29         ` Damien Hedde
  2019-08-09 10:32           ` Peter Maydell
  2019-08-09 13:50         ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-08-09 10:29 UTC (permalink / raw)
  To: Peter Maydell, Dr. David Alan Gilbert
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, Juan Quintela, David Hildenbrand,
	Halil Pasic, Christian Borntraeger, Marc-André Lureau,
	Richard Henderson, Thomas Huth, Eduardo Habkost,
	Alistair Francis, qemu-s390x, qemu-arm, Cédric Le Goater,
	John Snow, David Gibson, Daniel P. Berrange, Cornelia Huck,
	Mark Burton, qemu-ppc, Paolo Bonzini



On 8/9/19 12:07 PM, Peter Maydell wrote:
> On Thu, 8 Aug 2019 at 16:42, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
>>
>> * Peter Maydell (peter.maydell@linaro.org) wrote:
>>> On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>>>
>>>> This add the reset related sections for every QOM
>>>> device.
>>>
>>> A bit more detail in the commit message would help, I think --
>>> this is adding extra machinery which has to copy and modify
>>> the VMStateDescription passed in by the device in order to
>>> add the subsection that handles reset.
>>>
>>> I've added Dave Gilbert to the already long cc list since this
>>> is migration related.
>>
>> I don't like dynamically modifying all the vmsds.
> 
> Yeah, I'm not a huge fan of it either, but it does mean that
> the state gets migrated and we don't have a pile of really
> easy to miss bugs where we forgot to say "this device needs to
> migrate the reset state" and it means we don't have every
> device we ever write in the future needing to say "this device
> needs to migrate reset state"...
> 
>> Aren't you going to have to understand each devices reset behaviour
>> and make sure it does something sane? e.g. it might have a postload
>> that registers a timer or something that you wouldn't want to do if it's
>> in reset.
>>
>> The easiest way is to write a macro that you can easily add to devices
>> you've checked subsection list (like the way we have a
>> VMSTATE_USB_DEVICE).
> 
> One problem is that as soon as somebody writes a USB controller
> or PCI controller model that can be held in reset, every
> device that could sat behind it automatically now could find
> that it's migrated while it's in reset.
> 

One way to keep the feature without copy-pasting vmsd would be to add
a new vmstate_register with an additional argument to pass the base
class vmsd section and handle the whole thing there.

--
Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-09 10:29         ` Damien Hedde
@ 2019-08-09 10:32           ` Peter Maydell
  2019-08-09 10:46             ` Damien Hedde
  2019-08-09 13:01             ` Juan Quintela
  0 siblings, 2 replies; 113+ messages in thread
From: Peter Maydell @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, Juan Quintela, David Hildenbrand,
	Halil Pasic, Christian Borntraeger, Marc-André Lureau,
	Richard Henderson, Thomas Huth, Eduardo Habkost,
	Alistair Francis, Dr. David Alan Gilbert, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

On Fri, 9 Aug 2019 at 11:29, Damien Hedde <damien.hedde@greensocs.com> wrote:
>
> One way to keep the feature without copy-pasting vmsd would be to add
> a new vmstate_register with an additional argument to pass the base
> class vmsd section and handle the whole thing there.

If we have a vmstate section which contains no actual data,
only subsections with 'needed' functions, is it migration
compatible with previous versions in the same way that
tacking a subsection onto an existing function is?

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-09 10:32           ` Peter Maydell
@ 2019-08-09 10:46             ` Damien Hedde
  2019-08-09 13:02               ` Juan Quintela
  2019-08-09 13:01             ` Juan Quintela
  1 sibling, 1 reply; 113+ messages in thread
From: Damien Hedde @ 2019-08-09 10:46 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, Juan Quintela, David Hildenbrand,
	Halil Pasic, Christian Borntraeger, Marc-André Lureau,
	Richard Henderson, Thomas Huth, Eduardo Habkost,
	Alistair Francis, Dr. David Alan Gilbert, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini


On 8/9/19 12:32 PM, Peter Maydell wrote:
> On Fri, 9 Aug 2019 at 11:29, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> One way to keep the feature without copy-pasting vmsd would be to add
>> a new vmstate_register with an additional argument to pass the base
>> class vmsd section and handle the whole thing there.
> 
> If we have a vmstate section which contains no actual data,
> only subsections with 'needed' functions, is it migration
> compatible with previous versions in the same way that
> tacking a subsection onto an existing function is?

I don't think so because of the naming schema. I had to forge the
correct name for the reset subsection for every device.
Each subsection must be named after its parent section plus '/something'.

--
Damien


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-08-08  6:47         ` David Gibson
@ 2019-08-09 11:08           ` Peter Maydell
  2019-08-12 10:34             ` David Gibson
  0 siblings, 1 reply; 113+ messages in thread
From: Peter Maydell @ 2019-08-09 11:08 UTC (permalink / raw)
  To: David Gibson
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau,
	Philippe Mathieu-Daudé,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

On Fri, 9 Aug 2019 at 01:10, David Gibson <david@gibson.dropbear.id.au> wrote:
>
> On Wed, Jul 31, 2019 at 01:31:28PM +0200, Philippe Mathieu-Daudé wrote:
> > On 7/31/19 11:29 AM, Damien Hedde wrote:
> > > On 7/31/19 8:05 AM, David Gibson wrote:
> > >> On Mon, Jul 29, 2019 at 04:56:26PM +0200, Damien Hedde wrote:
> > >>> @@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
> > >>>              }
> > >>>          }
> > >>>          if (dev->hotplugged) {
> > >>> -            device_legacy_reset(dev);
> > >>> +            device_reset(dev, true);
> > >>
> > >> So.. is this change in the device_reset() signature really necessary?
> > >> Even if there are compelling reasons to handle warm reset in the new
> > >> API, that doesn't been you need to change device_reset() itself from
> > >> its established meaning of a cold (i.e. as per power cycle) reset.

So, I don't think that actually is the established meaning of
device_reset(). I think our current semantics for this function are
"reset of some sort, probably cold, but in practice called in
lots of places which really wanted some other kind of reset,
because our current reset semantics are not well-defined".

For instance in s390-pci-inst.c the handling of CLP_SET_DISABLE_PCI_FN
calls device_reset() on a device. I bet that's not really intentionally
trying to model "we powered it off and on again".
hw/scsi/vmw_pvscsi.c uses device_reset() in its handling of
the guest "reset the SCSI bus" command. I know that isn't literally
powering off the SCSI disks and powering them on again.

The advantage of an actual API change here is that it means we go
and look at all the call sites and find out what the semantics
they actually wanted were, and hopefully that then feeds into the
design of the new API and we make sure we can handle those
semantics in a non-confused way.

> > >> Warm resets are generally called in rather more specific circumstances
> > >> (often under guest software direction) so it seems likely that users
> > >> would want to engage with the new reset API directly.  Or we could
> > >> just create a device_warm_reset() wrapper.  That would also avoid the
> > >> bare boolean parameter, which is not great for readability (you have
> > >> to look up the signature to have any idea what it means).
> >
> > If the boolean is not meaningful, we can use an enum...
>
> That's certainly better, but I'm not seeing a compelling reason not to
> have separate function names.  It's just as clear and means less churn.

One advantage of an enum is that we have an extendable API,
so we could say something like "all devices support reset types
'cold' and 'warm', but individual devices or families of devices
can also support other kinds of reset". So the relevant s390
devices could directly support the kinds of reset currently
enumerated by the enum s390_reset, and then if you know you're
dealing with an s390 device you can ask it to reset with the
right semantics rather than fudging it with one of the generic ones.
Or devices with "if I'm reset by the guest writing to a register then
I reset less stuff than a reset via external reset line" have a
way to model that.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-08-08  6:48       ` David Gibson
@ 2019-08-09 11:39         ` Cédric Le Goater
  2019-08-12 10:36           ` David Gibson
  0 siblings, 1 reply; 113+ messages in thread
From: Cédric Le Goater @ 2019-08-09 11:39 UTC (permalink / raw)
  To: David Gibson, Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, jsnow, rth, berrange,
	cohuck, mark.burton, qemu-ppc, pbonzini


>>> So.. is this change in the device_reset() signature really necessary?
>>> Even if there are compelling reasons to handle warm reset in the new
>>> API, that doesn't been you need to change device_reset() itself from
>>> its established meaning of a cold (i.e. as per power cycle) reset.
>>> Warm resets are generally called in rather more specific circumstances
>>> (often under guest software direction) so it seems likely that users
>>> would want to engage with the new reset API directly.  Or we could
>>> just create a device_warm_reset() wrapper.  That would also avoid the
>>> bare boolean parameter, which is not great for readability (you have
>>> to look up the signature to have any idea what it means).
>>
>> I've added device_reset_cold/warm wrapper functions to avoid having to
>> pass the boolean parameter. it seems I forgot to use them in qdev.c
>> I suppose, like you said, we could live with
>> + no function with the boolean parameter
>> + device_reset doing cold reset
>> + device_reset_warm (or device_warm_reset) for the warm version
> 
> Ok, good.
> 
> I'm afraid the whole series still makes me pretty uncomfortable,
> though, since the whole "warm reset" concept still seems way to vague
> to me.

Isn't the reset after the CAS negotiation sequence between the hypervisor
and the pseries machine some sort of warm reset driven by SW ? 


C.  


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-09 10:32           ` Peter Maydell
  2019-08-09 10:46             ` Damien Hedde
@ 2019-08-09 13:01             ` Juan Quintela
  1 sibling, 0 replies; 113+ messages in thread
From: Juan Quintela @ 2019-08-09 13:01 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis,
	Dr. David Alan Gilbert, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, David Gibson, Damien Hedde,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini

Peter Maydell <peter.maydell@linaro.org> wrote:
> On Fri, 9 Aug 2019 at 11:29, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>> One way to keep the feature without copy-pasting vmsd would be to add
>> a new vmstate_register with an additional argument to pass the base
>> class vmsd section and handle the whole thing there.
>
> If we have a vmstate section which contains no actual data,
> only subsections with 'needed' functions, is it migration
> compatible with previous versions in the same way that
> tacking a subsection onto an existing function is?

Not now, but we can make it happen.

Right now, we first send the VMSD "header", and then we sent whatever
data is in it.

We can it make work the way you want.  Not sure if that is the best way,
though.  Sections that can(or can't) be there make just reasoning about
the stream more difficult.

Later, Juan.


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-09 10:46             ` Damien Hedde
@ 2019-08-09 13:02               ` Juan Quintela
  0 siblings, 0 replies; 113+ messages in thread
From: Juan Quintela @ 2019-08-09 13:02 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Peter Maydell, Collin Walling, Dmitry Fleytman,
	Michael S. Tsirkin, Mark Cave-Ayland, QEMU Developers,
	Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke, Qemu-block,
	David Hildenbrand, Halil Pasic, Christian Borntraeger,
	Marc-André Lureau, Richard Henderson, Thomas Huth,
	Eduardo Habkost, Alistair Francis, Dr. David Alan Gilbert,
	qemu-s390x, qemu-arm, Cédric Le Goater, John Snow,
	David Gibson, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

Damien Hedde <damien.hedde@greensocs.com> wrote:
> On 8/9/19 12:32 PM, Peter Maydell wrote:
>> On Fri, 9 Aug 2019 at 11:29, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>>
>>> One way to keep the feature without copy-pasting vmsd would be to add
>>> a new vmstate_register with an additional argument to pass the base
>>> class vmsd section and handle the whole thing there.
>> 
>> If we have a vmstate section which contains no actual data,
>> only subsections with 'needed' functions, is it migration
>> compatible with previous versions in the same way that
>> tacking a subsection onto an existing function is?
>
> I don't think so because of the naming schema. I had to forge the
> correct name for the reset subsection for every device.
> Each subsection must be named after its parent section plus '/something'.

That bit is easy.  You jsut named it: "parent_name/subsection_name", no?

Later, Juan.


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices
  2019-08-09 10:07       ` Peter Maydell
  2019-08-09 10:29         ` Damien Hedde
@ 2019-08-09 13:50         ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 113+ messages in thread
From: Dr. David Alan Gilbert @ 2019-08-09 13:50 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, Juan Quintela, David Hildenbrand,
	Halil Pasic, Christian Borntraeger, Marc-André Lureau,
	Richard Henderson, Thomas Huth, Eduardo Habkost,
	Alistair Francis, qemu-s390x, qemu-arm, Cédric Le Goater,
	John Snow, David Gibson, Damien Hedde, Daniel P. Berrange,
	Cornelia Huck, Mark Burton, qemu-ppc, Paolo Bonzini

* Peter Maydell (peter.maydell@linaro.org) wrote:
> On Thu, 8 Aug 2019 at 16:42, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
> >
> > * Peter Maydell (peter.maydell@linaro.org) wrote:
> > > On Mon, 29 Jul 2019 at 15:59, Damien Hedde <damien.hedde@greensocs.com> wrote:
> > > >
> > > > This add the reset related sections for every QOM
> > > > device.
> > >
> > > A bit more detail in the commit message would help, I think --
> > > this is adding extra machinery which has to copy and modify
> > > the VMStateDescription passed in by the device in order to
> > > add the subsection that handles reset.
> > >
> > > I've added Dave Gilbert to the already long cc list since this
> > > is migration related.
> >
> > I don't like dynamically modifying all the vmsds.
> 
> Yeah, I'm not a huge fan of it either, but it does mean that
> the state gets migrated and we don't have a pile of really
> easy to miss bugs where we forgot to say "this device needs to
> migrate the reset state" and it means we don't have every
> device we ever write in the future needing to say "this device
> needs to migrate reset state"...
> 
> > Aren't you going to have to understand each devices reset behaviour
> > and make sure it does something sane? e.g. it might have a postload
> > that registers a timer or something that you wouldn't want to do if it's
> > in reset.
> >
> > The easiest way is to write a macro that you can easily add to devices
> > you've checked subsection list (like the way we have a
> > VMSTATE_USB_DEVICE).
> 
> One problem is that as soon as somebody writes a USB controller
> or PCI controller model that can be held in reset, every
> device that could sat behind it automatically now could find
> that it's migrated while it's in reset.

I'm not convinced though that they'll all be fixed by adding this
subsection; I think some of those devices you're going to have to
look at and see what they do.

Dave

> thanks
> -- PMM
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-08-07 14:41   ` Peter Maydell
  2019-08-07 15:23     ` Damien Hedde
@ 2019-08-12  9:08     ` Damien Hedde
  1 sibling, 0 replies; 113+ messages in thread
From: Damien Hedde @ 2019-08-12  9:08 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Richard Henderson,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, David Gibson,
	Daniel P. Berrange, Cornelia Huck, Mark Burton, qemu-ppc,
	Paolo Bonzini



On 8/7/19 4:41 PM, Peter Maydell wrote:
> On Mon, 29 Jul 2019 at 15:58, Damien Hedde <damien.hedde@greensocs.com> wrote:
>>
>>
>> +/**
>> + * device_reset:
>> + * Resets the device @dev, @cold tell whether to do a cold or warm reset.
>> + * Base behavior is to reset the device and its qdev/qbus subtree.
> 
> What do you mean by "base behavior" here? When would this ever
> do anything else?
> 

Oops, just noticed I missed this comment.

Since I had to use a method "foreach_child" to call reset on children,
the behavior depends on it. Default implementation in base classes
follows the qdev tree. But a specialization can change that.
That's more a side-effect than a wanted feature.


^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface
  2019-08-07 16:01     ` Peter Maydell
@ 2019-08-12 10:15       ` David Gibson
  0 siblings, 0 replies; 113+ messages in thread
From: David Gibson @ 2019-08-12 10:15 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau, Thomas Huth,
	Eduardo Habkost, Alistair Francis, qemu-s390x, qemu-arm,
	Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 1718 bytes --]

On Wed, Aug 07, 2019 at 05:01:42PM +0100, Peter Maydell wrote:
> On Wed, 31 Jul 2019 at 07:33, David Gibson <david@gibson.dropbear.id.au> wrote:
> >
> > On Mon, Jul 29, 2019 at 04:56:30PM +0200, Damien Hedde wrote:
> > > Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> > > +For Devices and Buses there is also the corresponding helpers:
> > > +void device_reset(Device *dev, bool cold)
> > > +void bus_reset(Device *dev, bool cold)
> >
> > What's the semantic difference between resetting a bus and resetting
> > the bridge device which owns it?
> 
> We should definitely explain this in the documentation, but
> consider for instance a SCSI controller. Resetting the
> SCSI controller puts all its registers back into whatever
> the reset state is for the device, as well as resetting
> everything on the SCSI bus. Resetting just the SCSI bus
> resets the disks and so on on the bus, but doesn't change
> the state of the controller itself, which remains programmed
> with whatever state the guest has set up.
> 
> PCI has a similar distinction between resetting the controller
> and resetting the bus.
> 
> Note that we have this distinction in the current APIs too:
> qbus_reset_all() vs qdev_reset_all().

Yeah, sorry, I didn't express my concern very well... and now I've
kind of forgotten the details of it.  I think the oddities you also
pointed out with the state saving made me think the two were
sorta equivalent in this patchset, but the interface suggested otherwise.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface
  2019-08-01  9:35               ` Damien Hedde
@ 2019-08-12 10:27                 ` David Gibson
  0 siblings, 0 replies; 113+ messages in thread
From: David Gibson @ 2019-08-12 10:27 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Peter Maydell, Collin Walling, Dmitry Fleytman,
	Michael S. Tsirkin, Mark Cave-Ayland, QEMU Developers,
	Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke, Qemu-block,
	David Hildenbrand, Halil Pasic, Christian Borntraeger,
	Marc-André Lureau, Thomas Huth, Eduardo Habkost,
	Alistair Francis, qemu-s390x, qemu-arm, Cédric Le Goater,
	John Snow, Richard Henderson, Daniel P. Berrange, Cornelia Huck,
	Mark Burton, qemu-ppc, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 4446 bytes --]

On Thu, Aug 01, 2019 at 11:35:20AM +0200, Damien Hedde wrote:
> 
> 
> On 7/31/19 7:46 AM, David Gibson wrote:
> > On Tue, Jul 30, 2019 at 04:08:59PM +0200, Damien Hedde wrote:
> >>
> >> On 7/30/19 3:59 PM, Peter Maydell wrote:
> >>> On Tue, 30 Jul 2019 at 14:56, Cornelia Huck <cohuck@redhat.com> wrote:
> >>>>
> >>>> On Tue, 30 Jul 2019 14:44:21 +0100
> >>>> Peter Maydell <peter.maydell@linaro.org> wrote:
> >>>>
> >>>>> On Tue, 30 Jul 2019 at 14:42, Cornelia Huck <cohuck@redhat.com> wrote:
> >>>>>> I'm having a hard time figuring out what a 'cold' or a 'warm' reset is
> >>>>>> supposed to be... can you add a definition/guideline somewhere?
> >>>>>
> >>>>> Generally "cold" reset is "power on" and "warm" is "we were already
> >>>>> powered-on, but somebody flipped a reset line somewhere".
> >>>>
> >>>> Ok, that makes sense... my main concern is to distinguish that in a
> >>>> generic way, as it is a generic interface. What about adding something
> >>>> like:
> >>>>
> >>>> "A 'cold' reset means that the object to be reset is initially reset; a 'warm'
> >>>> reset means that the object to be reset has already been initialized."
> >>>>
> >>>> Or is that again too generic?
> >>>
> >>> I think it doesn't quite capture the idea -- an object can have already
> >>> been reset and then get a 'cold' reset: this is like having a powered-on
> >>> machine and then power-cycling it.
> >>>
> >>> The 'warm' reset is the vaguer one, because the specific behaviour
> >>> is somewhat device-dependent (many devices might not have any
> >>> difference from 'cold' reset, for those that do the exact detail
> >>> of what doesn't get reset on warm-reset will vary). But every
> >>> device should have some kind of "as if you power-cycled it" (or
> >>> for QEMU, "go back to the same state as if you just started QEMU on the
> >>> command line"). Our current "reset" method is really cold-reset.
> >>>
> >>
> >> Exactly. In the following patches, I've tried to replace existing reset
> >> calls by cold or warm reset depending on whether:
> >> + it is called through the main system reset -> cold
> >> + it is called during normal life-time       -> warm
> >>
> >> But I definitely can add some docs/comments to better explain that.
> > 
> > Hrm, that helps, but it still seems pretty vague to me.
> > 
> > It's not really my call, but building the concept of warm versus cold
> > resets into such a generic interface seems pretty dubios to me.  While
> > it's moderately common for things to have a notion of warm versus cold
> > reset it's certainly not universal.  There are many devices where
> > there's no meaningful difference between the two.  There are some
> > devices where there are > 2 different types of reset suitable for
> > various different situations.
> > 
> > Is there any way this could work with it usually just presenting the
> > cold reset (which is the closest to a universal concept), and any warm
> > or additional resets are handled buy a different instance of the
> > Resettable interface?
> > 
> 
> In my current implementation, cold/warm is only a question of setting a
> flag before calling the reset methods. I rely and the reset methods to
> check that flag if necessary. The feature can be added/removed without
> pain (if we stick with device_reset to do a cold one). So if it's
> better, I can put it aside for now.
> 
> IMO handling warm reset with another interface is probably not a good
> idea because it will need another load of methods.

I was thinking of a different instance of the same interface, not a
new interface.  But on consideration that probably means dummy objects
so that's also ugly.


Here's another way to look at things though: I can see why a common
interface for cold resets is useful; we use it during system resets
and bus resets and so forth.  But AIUI, in order to do a warm reset
whatever is initiating it is going to need to know what a warm reset
means for this device - in which case it doesn't really need a uniform
interface for it.

So, would we be better off with helper functions to make implementing
a multi-phase reset easy for devices that do have one or more notions
of a warm reset.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable
  2019-08-07  7:55         ` Damien Hedde
@ 2019-08-12 10:28           ` David Gibson
  0 siblings, 0 replies; 113+ messages in thread
From: David Gibson @ 2019-08-12 10:28 UTC (permalink / raw)
  To: Damien Hedde
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, clg, jsnow, rth,
	berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 5758 bytes --]

On Wed, Aug 07, 2019 at 09:55:13AM +0200, Damien Hedde wrote:
> 
> 
> On 8/6/19 2:35 AM, David Gibson wrote:
> > On Wed, Jul 31, 2019 at 11:09:05AM +0200, Damien Hedde wrote:
> >>
> >>
> >> On 7/31/19 7:56 AM, David Gibson wrote:
> >>> On Mon, Jul 29, 2019 at 04:56:25PM +0200, Damien Hedde wrote:
> >>>> This add Resettable interface implementation for both Bus and Device.
> >>>>
> >>>> *resetting* counter and *reset_is_cold* flag are added in DeviceState
> >>>> and BusState.
> >>>>
> >>>> Compatibility with existing code base is ensured.
> >>>> The legacy bus or device reset method is called in the new exit phase
> >>>> and the other 2 phases are let empty. Using the exit phase guarantee that
> >>>> legacy resets are called in the "post" order (ie: children then parent)
> >>>> in hierarchical reset. That is the same order as legacy qdev_reset_all
> >>>> or qbus_reset_all were using.
> >>>>
> >>>> New *device_reset* and *bus_reset* function are proposed with an
> >>>> additional boolean argument telling whether the reset is cold or warm.
> >>>> Helper functions *device_reset_[warm|cold]* and *bus_reset_[warm|cold]*
> >>>> are defined also as helpers.
> >>>>
> >>>> Also add a [device|bus]_is_resetting and [device|bus]_is_reset_cold
> >>>> functions telling respectively whether the object is currently under reset and
> >>>> if the current reset is cold or not.
> >>>>
> >>>> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> >>>> ---
> >>>>  hw/core/bus.c          | 85 ++++++++++++++++++++++++++++++++++++++++++
> >>>>  hw/core/qdev.c         | 82 ++++++++++++++++++++++++++++++++++++++++
> >>>>  include/hw/qdev-core.h | 84 ++++++++++++++++++++++++++++++++++++++---
> >>>>  tests/Makefile.include |  1 +
> >>>>  4 files changed, 247 insertions(+), 5 deletions(-)
> >>>>
> >>>> diff --git a/hw/core/bus.c b/hw/core/bus.c
> >>>> index 17bc1edcde..08a97addb6 100644
> >>>> --- a/hw/core/bus.c
> >>>> +++ b/hw/core/bus.c
> >>>> @@ -22,6 +22,7 @@
> >>>>  #include "qemu/module.h"
> >>>>  #include "hw/qdev.h"
> >>>>  #include "qapi/error.h"
> >>>> +#include "hw/resettable.h"
> >>>>  
> >>>>  void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
> >>>>  {
> >>>> @@ -68,6 +69,75 @@ int qbus_walk_children(BusState *bus,
> >>>>      return 0;
> >>>>  }
> >>>>  
> >>>> +void bus_reset(BusState *bus, bool cold)
> >>>> +{
> >>>> +    resettable_reset(OBJECT(bus), cold);
> >>>> +}
> >>>> +
> >>>> +bool bus_is_resetting(BusState *bus)
> >>>> +{
> >>>> +    return (bus->resetting != 0);
> >>>> +}
> >>>> +
> >>>> +bool bus_is_reset_cold(BusState *bus)
> >>>> +{
> >>>> +    return bus->reset_is_cold;
> >>>> +}
> >>>> +
> >>>> +static uint32_t bus_get_reset_count(Object *obj)
> >>>> +{
> >>>> +    BusState *bus = BUS(obj);
> >>>> +    return bus->resetting;
> >>>> +}
> >>>> +
> >>>> +static uint32_t bus_increment_reset_count(Object *obj)
> >>>> +{
> >>>> +    BusState *bus = BUS(obj);
> >>>> +    return ++bus->resetting;
> >>>> +}
> >>>> +
> >>>> +static uint32_t bus_decrement_reset_count(Object *obj)
> >>>> +{
> >>>> +    BusState *bus = BUS(obj);
> >>>> +    return --bus->resetting;
> >>>> +}
> >>>> +
> >>>> +static bool bus_set_reset_cold(Object *obj, bool cold)
> >>>> +{
> >>>> +    BusState *bus = BUS(obj);
> >>>> +    bool old = bus->reset_is_cold;
> >>>> +    bus->reset_is_cold = cold;
> >>>> +    return old;
> >>>> +}
> >>>> +
> >>>> +static bool bus_set_hold_needed(Object *obj, bool hold_needed)
> >>>> +{
> >>>> +    BusState *bus = BUS(obj);
> >>>> +    bool old = bus->reset_hold_needed;
> >>>> +    bus->reset_hold_needed = hold_needed;
> >>>> +    return old;
> >>>> +}
> >>>> +
> >>>> +static void bus_foreach_reset_child(Object *obj, void (*func)(Object *))
> >>>> +{
> >>>> +    BusState *bus = BUS(obj);
> >>>> +    BusChild *kid;
> >>>> +
> >>>> +    QTAILQ_FOREACH(kid, &bus->children, sibling) {
> >>>> +        func(OBJECT(kid->child));
> >>>> +    }
> >>>> +}
> >>>
> >>> IIUC, every resettable class would need more or less identical
> >>> implementations of the above.  That seems like an awful lot of
> >>> boilerplate.
> >>
> >> Do you mean the get/increment_count/decrement_count, set_cold/hold part ?
> >> True, but it's limited to the base classes.
> >> Since Resettable is an interface, we have no state there to store what
> >> we need. Only alternative is to have some kind of single
> >> get_resettable_state method returning a pointer to the state (allowing
> >> us to keep the functions in the interface code).
> >> Beyond Device and Bus, which are done here, there is probably not so
> >> many class candidates for the Resettable interface.
> > 
> > Right.  I can't immediately see a better way to handle this, but it
> > still seems like a mild code smell.
> > 
> 
> Only definitive solution to this would be to make DeviceClass and
> BusClass inherit from a common Resettable object.
> 
> Would it be better if I use a common struct (eg: ResettableState)
> holding the different fields ?

Maybe, yeah.

> Then I can have a single implementation of the method and do for example:
> static uint32_t bus_decrement_reset_count(Object *obj)
> {
>      return decrement_reset_count(&(BUS(obj))->reset_state);
> }
> static uint32_t device_decrement_reset_count(Object *obj)
> {
>      return decrement_reset_count(&(DEV(dev))->reset_state);
> }
> 
> I can also merge the 3 count related method into one if it helps.



-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs
  2019-08-09  8:45         ` Damien Hedde
@ 2019-08-12 10:29           ` David Gibson
  0 siblings, 0 replies; 113+ messages in thread
From: David Gibson @ 2019-08-12 10:29 UTC (permalink / raw)
  To: Damien Hedde
  Cc: Fam Zheng, Peter Maydell, Collin Walling, Dmitry Fleytman,
	Michael S. Tsirkin, Mark Cave-Ayland, QEMU Developers,
	Gerd Hoffmann, Edgar Iglesias, Hannes Reinecke, Qemu-block,
	David Hildenbrand, Halil Pasic, Christian Borntraeger,
	Marc-André Lureau, Thomas Huth, Eduardo Habkost,
	Alistair Francis, qemu-s390x, qemu-arm, Cédric Le Goater,
	John Snow, Richard Henderson, Daniel P. Berrange, Cornelia Huck,
	Mark Burton, qemu-ppc, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 2000 bytes --]

On Fri, Aug 09, 2019 at 10:45:43AM +0200, Damien Hedde wrote:
> 
> 
> On 8/9/19 7:51 AM, David Gibson wrote:
> > On Wed, Aug 07, 2019 at 11:37:51AM +0100, Peter Maydell wrote:
> >> On Wed, 31 Jul 2019 at 07:33, David Gibson <david@gibson.dropbear.id.au> wrote:
> >>>
> >>> On Mon, Jul 29, 2019 at 04:56:29PM +0200, Damien Hedde wrote:
> >>>> It adds the possibility to add 2 gpios to control the warm and cold reset.
> >>>> With theses ios, the reset can be maintained during some time.
> >>>> Each io is associated with a state to detect level changes.
> >>>>
> >>>> Vmstate subsections are also added to the existsing device_reset
> >>>> subsection.
> >>>
> >>> This doesn't seem like a thing that should be present on every single
> >>> DeviceState.
> >>
> >> It's a facility that's going to be useful to multiple different
> >> subclasses of DeviceState, so it seems to me cleaner to
> >> have base class support for the common feature rather than
> >> to reimplement it entirely from scratch in every subclass
> >> that wants it.
> > 
> > Hm, I suppose so.  Would it really have to be from scratch, though?
> > Couldn't some suitable helper functions make adding such GPIOs to a
> > device pretty straightforward?
> > 
> 
> This patch does that. A device does have to use the helper to add the
> gpio. Either qdev_init_warm_reset_gpio(...) or
> qdev_init_cold_reset_gpio(...) , like any another gpio.

Ah, sorry, I misunderstood.

That seems ok then.

> 
> The mechanics to control the reset with gpio change is done in the base
> class and there is some state pre-allocated (and associated vmstate
> description) to it.
> 
> If that's a problem I can only provide helpers and let devices handle
> state allocation and vmstate addition.
> 
> Damien
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-08-09 11:08           ` Peter Maydell
@ 2019-08-12 10:34             ` David Gibson
  0 siblings, 0 replies; 113+ messages in thread
From: David Gibson @ 2019-08-12 10:34 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Fam Zheng, Collin Walling, Dmitry Fleytman, Michael S. Tsirkin,
	Mark Cave-Ayland, QEMU Developers, Gerd Hoffmann, Edgar Iglesias,
	Hannes Reinecke, Qemu-block, David Hildenbrand, Halil Pasic,
	Christian Borntraeger, Marc-André Lureau,
	Philippe Mathieu-Daudé,
	Thomas Huth, Eduardo Habkost, Alistair Francis, qemu-s390x,
	qemu-arm, Cédric Le Goater, John Snow, Richard Henderson,
	Damien Hedde, Daniel P. Berrange, Cornelia Huck, Mark Burton,
	qemu-ppc, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 4051 bytes --]

On Fri, Aug 09, 2019 at 12:08:43PM +0100, Peter Maydell wrote:
> On Fri, 9 Aug 2019 at 01:10, David Gibson <david@gibson.dropbear.id.au> wrote:
> >
> > On Wed, Jul 31, 2019 at 01:31:28PM +0200, Philippe Mathieu-Daudé wrote:
> > > On 7/31/19 11:29 AM, Damien Hedde wrote:
> > > > On 7/31/19 8:05 AM, David Gibson wrote:
> > > >> On Mon, Jul 29, 2019 at 04:56:26PM +0200, Damien Hedde wrote:
> > > >>> @@ -922,7 +906,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
> > > >>>              }
> > > >>>          }
> > > >>>          if (dev->hotplugged) {
> > > >>> -            device_legacy_reset(dev);
> > > >>> +            device_reset(dev, true);
> > > >>
> > > >> So.. is this change in the device_reset() signature really necessary?
> > > >> Even if there are compelling reasons to handle warm reset in the new
> > > >> API, that doesn't been you need to change device_reset() itself from
> > > >> its established meaning of a cold (i.e. as per power cycle) reset.
> 
> So, I don't think that actually is the established meaning of
> device_reset(). I think our current semantics for this function are
> "reset of some sort, probably cold, but in practice called in
> lots of places which really wanted some other kind of reset,
> because our current reset semantics are not well-defined".
> 
> For instance in s390-pci-inst.c the handling of CLP_SET_DISABLE_PCI_FN
> calls device_reset() on a device. I bet that's not really intentionally
> trying to model "we powered it off and on again".
> hw/scsi/vmw_pvscsi.c uses device_reset() in its handling of
> the guest "reset the SCSI bus" command. I know that isn't literally
> powering off the SCSI disks and powering them on again.
> 
> The advantage of an actual API change here is that it means we go
> and look at all the call sites and find out what the semantics
> they actually wanted were, and hopefully that then feeds into the
> design of the new API and we make sure we can handle those
> semantics in a non-confused way.

That's a fair point.

> > > >> Warm resets are generally called in rather more specific circumstances
> > > >> (often under guest software direction) so it seems likely that users
> > > >> would want to engage with the new reset API directly.  Or we could
> > > >> just create a device_warm_reset() wrapper.  That would also avoid the
> > > >> bare boolean parameter, which is not great for readability (you have
> > > >> to look up the signature to have any idea what it means).
> > >
> > > If the boolean is not meaningful, we can use an enum...
> >
> > That's certainly better, but I'm not seeing a compelling reason not to
> > have separate function names.  It's just as clear and means less churn.
> 
> One advantage of an enum is that we have an extendable API,
> so we could say something like "all devices support reset types
> 'cold' and 'warm', but individual devices or families of devices
> can also support other kinds of reset". So the relevant s390
> devices could directly support the kinds of reset currently
> enumerated by the enum s390_reset, and then if you know you're
> dealing with an s390 device you can ask it to reset with the
> right semantics rather than fudging it with one of the generic ones.
> Or devices with "if I'm reset by the guest writing to a register then
> I reset less stuff than a reset via external reset line" have a
> way to model that.

Ok, I can see the value in that.  I guess the way I'd prefer to
approach it though, is to start out with just a single-value enum for
(roughly) a cold reset.  Then when we find a subset of devices for
which we can consistently define a warm reset of some type, we add an
enum value for it.

I guess we'd also need some way of introspecting what reset types are
supported by a device.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus
  2019-08-09 11:39         ` Cédric Le Goater
@ 2019-08-12 10:36           ` David Gibson
  0 siblings, 0 replies; 113+ messages in thread
From: David Gibson @ 2019-08-12 10:36 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: fam, peter.maydell, walling, dmitry.fleytman, mst,
	mark.cave-ayland, qemu-devel, kraxel, edgar.iglesias, hare,
	qemu-block, david, pasic, borntraeger, marcandre.lureau, thuth,
	ehabkost, alistair, qemu-s390x, qemu-arm, jsnow, rth,
	Damien Hedde, berrange, cohuck, mark.burton, qemu-ppc, pbonzini

[-- Attachment #1: Type: text/plain, Size: 2114 bytes --]

On Fri, Aug 09, 2019 at 01:39:46PM +0200, Cédric Le Goater wrote:
> 
> >>> So.. is this change in the device_reset() signature really necessary?
> >>> Even if there are compelling reasons to handle warm reset in the new
> >>> API, that doesn't been you need to change device_reset() itself from
> >>> its established meaning of a cold (i.e. as per power cycle) reset.
> >>> Warm resets are generally called in rather more specific circumstances
> >>> (often under guest software direction) so it seems likely that users
> >>> would want to engage with the new reset API directly.  Or we could
> >>> just create a device_warm_reset() wrapper.  That would also avoid the
> >>> bare boolean parameter, which is not great for readability (you have
> >>> to look up the signature to have any idea what it means).
> >>
> >> I've added device_reset_cold/warm wrapper functions to avoid having to
> >> pass the boolean parameter. it seems I forgot to use them in qdev.c
> >> I suppose, like you said, we could live with
> >> + no function with the boolean parameter
> >> + device_reset doing cold reset
> >> + device_reset_warm (or device_warm_reset) for the warm version
> > 
> > Ok, good.
> > 
> > I'm afraid the whole series still makes me pretty uncomfortable,
> > though, since the whole "warm reset" concept still seems way to vague
> > to me.
> 
> Isn't the reset after the CAS negotiation sequence between the hypervisor
> and the pseries machine some sort of warm reset driven by SW ?

Yes.. and?  The fact that something as messy as CAS can come under the
category of warm reset only re-inforces that what a warm reset is
isn't really well defined.

[That said, in the case of CAS, I'd really like it if we can change
things to avoid the pseudo-reset and just rewrite the dt instead.
The sorta-reboot causes us problems with -no-reboot and with disabling
the SLOF autoboot flag]

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 113+ messages in thread

end of thread, other threads:[~2019-08-12 13:58 UTC | newest]

Thread overview: 113+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-29 14:56 [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 01/33] Create Resettable QOM interface Damien Hedde
2019-07-30 13:42   ` Cornelia Huck
2019-07-30 13:44     ` Peter Maydell
2019-07-30 13:55       ` Cornelia Huck
2019-07-30 13:59         ` Peter Maydell
2019-07-30 14:08           ` Damien Hedde
2019-07-30 15:47             ` Cornelia Huck
2019-07-31  5:46             ` David Gibson
2019-08-01  9:35               ` Damien Hedde
2019-08-12 10:27                 ` David Gibson
2019-07-31 10:17           ` Christophe de Dinechin
2019-08-01  9:19             ` Damien Hedde
2019-08-01  9:30               ` Christophe de Dinechin
2019-08-07 14:20   ` Peter Maydell
2019-08-07 15:03     ` Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 02/33] add temporary device_legacy_reset function to replace device_reset Damien Hedde
2019-08-07 14:27   ` Peter Maydell
2019-08-09  9:20     ` Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 03/33] Replace all call to device_reset by call to device_legacy_reset Damien Hedde
2019-07-31  5:52   ` David Gibson
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 04/33] make Device and Bus Resettable Damien Hedde
2019-07-31  5:56   ` David Gibson
2019-07-31  9:09     ` Damien Hedde
2019-08-06  0:35       ` David Gibson
2019-08-07  7:55         ` Damien Hedde
2019-08-12 10:28           ` David Gibson
2019-08-07 14:41   ` Peter Maydell
2019-08-07 15:23     ` Damien Hedde
2019-08-07 15:28       ` Peter Maydell
2019-08-12  9:08     ` Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 05/33] Switch to new api in qdev/bus Damien Hedde
2019-07-31  6:05   ` David Gibson
2019-07-31  9:29     ` Damien Hedde
2019-07-31 11:31       ` Philippe Mathieu-Daudé
2019-08-08  6:47         ` David Gibson
2019-08-09 11:08           ` Peter Maydell
2019-08-12 10:34             ` David Gibson
2019-08-08  6:48       ` David Gibson
2019-08-09 11:39         ` Cédric Le Goater
2019-08-12 10:36           ` David Gibson
2019-08-07 14:48   ` Peter Maydell
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 06/33] add the vmstate description for device reset state Damien Hedde
2019-07-31  6:08   ` David Gibson
2019-07-31 11:04     ` Damien Hedde
2019-08-07 14:53   ` Peter Maydell
2019-08-07 14:54   ` Peter Maydell
2019-08-07 15:27     ` Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 07/33] automatically add vmstate for reset support in devices Damien Hedde
2019-08-07 15:07   ` Peter Maydell
2019-08-07 17:22     ` Damien Hedde
2019-08-08 15:42     ` Dr. David Alan Gilbert
2019-08-09 10:07       ` Peter Maydell
2019-08-09 10:29         ` Damien Hedde
2019-08-09 10:32           ` Peter Maydell
2019-08-09 10:46             ` Damien Hedde
2019-08-09 13:02               ` Juan Quintela
2019-08-09 13:01             ` Juan Quintela
2019-08-09 13:50         ` Dr. David Alan Gilbert
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 08/33] Add function to control reset with gpio inputs Damien Hedde
2019-07-31  6:11   ` David Gibson
2019-07-31 10:09     ` Damien Hedde
2019-08-07 10:37     ` Peter Maydell
2019-08-09  5:51       ` David Gibson
2019-08-09  8:45         ` Damien Hedde
2019-08-12 10:29           ` David Gibson
2019-08-07 15:18   ` Peter Maydell
2019-08-07 16:56     ` Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 09/33] add doc about Resettable interface Damien Hedde
2019-07-31  6:30   ` David Gibson
2019-07-31 10:05     ` Damien Hedde
2019-08-07 10:34     ` Peter Maydell
2019-08-08  6:49       ` David Gibson
2019-08-07 16:01     ` Peter Maydell
2019-08-12 10:15       ` David Gibson
2019-08-07 15:58   ` Peter Maydell
2019-08-07 16:02   ` Peter Maydell
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 10/33] vl.c: remove qbus_reset_all registration Damien Hedde
2019-08-07 15:20   ` Peter Maydell
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 11/33] hw/s390x/ipl.c: " Damien Hedde
2019-08-07 15:24   ` Peter Maydell
2019-08-08 10:25     ` Cornelia Huck
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 12/33] hw/pci/: remove qdev/qbus_reset_all call Damien Hedde
2019-08-07 15:31   ` Peter Maydell
2019-08-09  9:47     ` Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 13/33] hw/scsi/: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 14/33] hw/s390x/s390-virtio-ccw.c: remove qdev_reset_all call Damien Hedde
2019-08-08 10:50   ` Cornelia Huck
2019-08-09  8:31     ` Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 15/33] hw/ide/piix.c: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 16/33] hw/input/adb.c: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 17/33] hw/usb/dev-uas.c: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 18/33] hw/audio/intel-hda.c: remove device_legacy_reset call Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 19/33] hw/sd/pl181.c & omap_mmc.c: " Damien Hedde
2019-07-31 15:48   ` Philippe Mathieu-Daudé
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 20/33] hw/hyperv/hyperv.c: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 21/33] hw/intc/spapr_xive.c: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 22/33] hw/ppc/pnv_psi.c: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 23/33] hw/scsi/vmw_pvscsi.c: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 24/33] hw/ppc/spapr: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 25/33] hw/i386/pc.c: " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 26/33] hw/s390x/s390-pci-inst.c: " Damien Hedde
2019-08-08 10:52   ` Cornelia Huck
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 27/33] hw/ide/microdrive.c: remove device_legacy_reset calls Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 28/33] qdev: Remove unused deprecated reset functions Damien Hedde
2019-08-07 15:29   ` Peter Maydell
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 29/33] hw/misc/zynq_slcr: use standard register definition Damien Hedde
2019-08-07 15:33   ` Peter Maydell
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 30/33] convert cadence_uart to 3-phases reset Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 31/33] Convert zynq's slcr " Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 32/33] Add uart reset support in zynq_slcr Damien Hedde
2019-07-29 14:56 ` [Qemu-devel] [PATCH v3 33/33] Connect the uart reset gpios in the zynq platform Damien Hedde
2019-07-30 10:14 ` [Qemu-devel] [PATCH v3 00/33] Multi-phase reset mechanism Cornelia Huck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.