summary refs log tree commit diff stats
path: root/hw/core/reset.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-02-27 15:34:41 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-02-27 15:34:41 +0000
commit158a054c4d1a40179f5e83cd7e1cfe65de457b92 (patch)
tree9ea0b0ef7cc79286585c014b6075fe77f5a83f9b /hw/core/reset.c
parentb48ff1bfacd6982e26eb8718b61b1b9c3e3e18fe (diff)
parent9c5c959dd748f2972e46a84b8d5f77794f515014 (diff)
downloadfocaccia-qemu-158a054c4d1a40179f5e83cd7e1cfe65de457b92.tar.gz
focaccia-qemu-158a054c4d1a40179f5e83cd7e1cfe65de457b92.zip
Merge tag 'pull-target-arm-20240227-1' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue:
 * Handle atomic updates of page tables entries in MMIO during PTW
 * Advertise Cortex-A53 erratum #843419 fix via REVIDR
 * MAINTAINERS: Cover hw/ide/ahci-allwinner.c with AllWinner A10 machine
 * misc: m48t59: replace qemu_system_reset_request() call with watchdog_perform_action()
 * misc: pxa2xx_timer: replace qemu_system_reset_request() call with watchdog_perform_action()
 * xlnx-versal-ospi: disable reentrancy detection for iomem_dac
 * sbsa-ref: Simplify init since PCIe is always enabled
 * stm32l4x5: Use TYPE_OR_IRQ when connecting STM32L4x5 EXTI fan-in IRQs
 * pl031: Update last RTCLR value on write in case it's read back
 * block: m25p80: Add support of mt35xu02gbba
 * xlnx-versal-virt: Add machine property ospi-flash
 * reset: refactor system reset to be three-phase aware
 * new board model raspi4b

# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmXeAMEZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3syyD/4lJzzstbDIAsu94Z4Hi0So
# CFLAMJFsPy3fMsU2IqVP+TDTyhUeMPebwfj7sQHUtQcXVh5i1/HlYgdUgXsnjGWQ
# pc6BxycpW6uJWYb7Ma3CdSGS+hxEpQ+U8Qeijwqg0kAqhjNtrSIkTRQ4u8p8T+kN
# dWtQzp7D15BpEVhWl/2dLWWJwV3H6TThmr1FbK5wl/c7hJzy2uaXqmmCvercU0Zo
# 6ab3SnGyhaujdd/FsDvhnVEYqcmcO2p9UtSnGAbdfw0zsf4p8cS2Q6M9q4DHBFYn
# 6Bt51DFP5D+114VpqRSXF2Lv9K8swjTgqhDld9vCoios6pS3LMwcTAcONUxE8JU+
# uD7kXTN/lv3atNEy4MTFkTeNtKgbYJJuPwWrDRNdbVXPwrEHGWN3+ZYISmuYb+p+
# XL2/7HeP7/qEVMW2d18+7OCriZwKiBRZRKUrtG7mQSBZEMetbhpA+mLcxAZT0FAl
# 18O/mcvEJrrE7x6Bqyv96b8PE0/er5cVg/b/wrkKS8DL4NWU9bJSjJNRrvt9bvvl
# jSzPGo4ngHlfO0OpurLoFOZCVxKWVXgaKkQ3pOz301nsDyhEndNLeCxrITac8G2Q
# C/WQuMaeOoV1x7N2MzaCQmyRzy8yGkG9av0aI/8feobfV/Yg4wPsfhcEn/XQWXKv
# NUJ4/z78FbJlI2JeDP2QSA==
# =xaMv
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 27 Feb 2024 15:33:21 GMT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# gpg:                 aka "Peter Maydell <peter@archaic.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* tag 'pull-target-arm-20240227-1' of https://git.linaro.org/people/pmaydell/qemu-arm: (36 commits)
  docs/system/arm: Add RPi4B to raspi.rst
  hw/misc/bcm2835_property: Add missed BCM2835 properties
  tests/avocado/boot_linux_console.py: Add Rpi4b boot tests
  hw/arm/bcm2838_peripherals: Add clock_isp stub
  hw/arm: Add memory region for BCM2837 RPiVid ASB
  hw/arm/raspi4b: Temporarily disable unimplemented rpi4b devices
  hw/arm: Introduce Raspberry PI 4 machine
  hw/arm: Add GPIO and SD to BCM2838 periph
  hw/gpio: Connect SD controller to BCM2838 GPIO
  hw/gpio: Implement BCM2838 GPIO functionality
  hw/gpio: Add BCM2838 GPIO stub
  hw/arm/bcm2838: Add GIC-400 to BCM2838 SoC
  hw/arm: Introduce BCM2838 SoC
  hw/arm/raspi: Split out raspi machine common part
  hw/arm/bcm2853_peripherals: Split out common part of peripherals
  hw/arm/bcm2836: Split out common part of BCM283X classes
  docs/devel/reset: Update to discuss system reset
  hw/core/machine: Use qemu_register_resettable for sysbus reset
  hw/core/reset: Implement qemu_register_reset via qemu_register_resettable
  hw/core/reset: Add qemu_{register, unregister}_resettable()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/core/reset.c')
-rw-r--r--hw/core/reset.c170
1 files changed, 135 insertions, 35 deletions
diff --git a/hw/core/reset.c b/hw/core/reset.c
index d3263b613e..d50da7e304 100644
--- a/hw/core/reset.c
+++ b/hw/core/reset.c
@@ -24,64 +24,164 @@
  */
 
 #include "qemu/osdep.h"
-#include "qemu/queue.h"
 #include "sysemu/reset.h"
+#include "hw/resettable.h"
+#include "hw/core/resetcontainer.h"
 
-/* reset/shutdown handler */
+/*
+ * Return a pointer to the singleton container that holds all the Resettable
+ * items that will be reset when qemu_devices_reset() is called.
+ */
+static ResettableContainer *get_root_reset_container(void)
+{
+    static ResettableContainer *root_reset_container;
 
-typedef struct QEMUResetEntry {
-    QTAILQ_ENTRY(QEMUResetEntry) entry;
+    if (!root_reset_container) {
+        root_reset_container =
+            RESETTABLE_CONTAINER(object_new(TYPE_RESETTABLE_CONTAINER));
+    }
+    return root_reset_container;
+}
+
+/*
+ * Reason why the currently in-progress qemu_devices_reset() was called.
+ * If we made at least SHUTDOWN_CAUSE_SNAPSHOT_LOAD have a corresponding
+ * ResetType we could perhaps avoid the need for this global.
+ */
+static ShutdownCause device_reset_reason;
+
+/*
+ * This is an Object which implements Resettable simply to call the
+ * callback function in the hold phase.
+ */
+#define TYPE_LEGACY_RESET "legacy-reset"
+OBJECT_DECLARE_SIMPLE_TYPE(LegacyReset, LEGACY_RESET)
+
+struct LegacyReset {
+    Object parent;
+    ResettableState reset_state;
     QEMUResetHandler *func;
     void *opaque;
     bool skip_on_snapshot_load;
-} QEMUResetEntry;
+};
+
+OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(LegacyReset, legacy_reset, LEGACY_RESET, OBJECT, { TYPE_RESETTABLE_INTERFACE }, { })
+
+static ResettableState *legacy_reset_get_state(Object *obj)
+{
+    LegacyReset *lr = LEGACY_RESET(obj);
+    return &lr->reset_state;
+}
+
+static void legacy_reset_hold(Object *obj)
+{
+    LegacyReset *lr = LEGACY_RESET(obj);
+
+    if (device_reset_reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
+        lr->skip_on_snapshot_load) {
+        return;
+    }
+    lr->func(lr->opaque);
+}
+
+static void legacy_reset_init(Object *obj)
+{
+}
+
+static void legacy_reset_finalize(Object *obj)
+{
+}
+
+static void legacy_reset_class_init(ObjectClass *klass, void *data)
+{
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
 
-static QTAILQ_HEAD(, QEMUResetEntry) reset_handlers =
-    QTAILQ_HEAD_INITIALIZER(reset_handlers);
+    rc->get_state = legacy_reset_get_state;
+    rc->phases.hold = legacy_reset_hold;
+}
 
 void qemu_register_reset(QEMUResetHandler *func, void *opaque)
 {
-    QEMUResetEntry *re = g_new0(QEMUResetEntry, 1);
+    Object *obj = object_new(TYPE_LEGACY_RESET);
+    LegacyReset *lr = LEGACY_RESET(obj);
 
-    re->func = func;
-    re->opaque = opaque;
-    QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
+    lr->func = func;
+    lr->opaque = opaque;
+    qemu_register_resettable(obj);
 }
 
 void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque)
 {
-    QEMUResetEntry *re = g_new0(QEMUResetEntry, 1);
+    Object *obj = object_new(TYPE_LEGACY_RESET);
+    LegacyReset *lr = LEGACY_RESET(obj);
 
-    re->func = func;
-    re->opaque = opaque;
-    re->skip_on_snapshot_load = true;
-    QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
+    lr->func = func;
+    lr->opaque = opaque;
+    lr->skip_on_snapshot_load = true;
+    qemu_register_resettable(obj);
 }
 
-void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
+typedef struct FindLegacyInfo {
+    QEMUResetHandler *func;
+    void *opaque;
+    LegacyReset *lr;
+} FindLegacyInfo;
+
+static void find_legacy_reset_cb(Object *obj, void *opaque, ResetType type)
 {
-    QEMUResetEntry *re;
-
-    QTAILQ_FOREACH(re, &reset_handlers, entry) {
-        if (re->func == func && re->opaque == opaque) {
-            QTAILQ_REMOVE(&reset_handlers, re, entry);
-            g_free(re);
-            return;
-        }
+    LegacyReset *lr;
+    FindLegacyInfo *fli = opaque;
+
+    /* Not everything in the ResettableContainer will be a LegacyReset */
+    lr = LEGACY_RESET(object_dynamic_cast(obj, TYPE_LEGACY_RESET));
+    if (lr && lr->func == fli->func && lr->opaque == fli->opaque) {
+        fli->lr = lr;
     }
 }
 
-void qemu_devices_reset(ShutdownCause reason)
+static LegacyReset *find_legacy_reset(QEMUResetHandler *func, void *opaque)
+{
+    /*
+     * Find the LegacyReset with the specified func and opaque,
+     * by getting the ResettableContainer to call our callback for
+     * every item in it.
+     */
+    ResettableContainer *rootcon = get_root_reset_container();
+    ResettableClass *rc = RESETTABLE_GET_CLASS(rootcon);
+    FindLegacyInfo fli;
+
+    fli.func = func;
+    fli.opaque = opaque;
+    fli.lr = NULL;
+    rc->child_foreach(OBJECT(rootcon), find_legacy_reset_cb,
+                      &fli, RESET_TYPE_COLD);
+    return fli.lr;
+}
+
+void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
 {
-    QEMUResetEntry *re, *nre;
-
-    /* reset all devices */
-    QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
-        if (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
-            re->skip_on_snapshot_load) {
-            continue;
-        }
-        re->func(re->opaque);
+    Object *obj = OBJECT(find_legacy_reset(func, opaque));
+
+    if (obj) {
+        qemu_unregister_resettable(obj);
+        object_unref(obj);
     }
 }
 
+void qemu_register_resettable(Object *obj)
+{
+    resettable_container_add(get_root_reset_container(), obj);
+}
+
+void qemu_unregister_resettable(Object *obj)
+{
+    resettable_container_remove(get_root_reset_container(), obj);
+}
+
+void qemu_devices_reset(ShutdownCause reason)
+{
+    device_reset_reason = reason;
+
+    /* Reset the simulation */
+    resettable_reset(OBJECT(get_root_reset_container()), RESET_TYPE_COLD);
+}