diff mbox series

[2/3] machine: Add wakeup method to MachineClass

Message ID 20190718103951.10027-3-npiggin@gmail.com
State New
Headers show
Series Series to implement suspend for ppc/spapr | expand

Commit Message

Nicholas Piggin July 18, 2019, 10:39 a.m. UTC
Waking from suspend is not logically a machine reset on all machines,
particularly in the paravirtualized case rather than hardware
emulated. The ppc spapr machine for example just invokes hypervisor
to suspend, and expects that call to return with the machine in the
same state (modulo some possible migration and reconfiguration
details).

Implement a machine ->wakeup method and use that if it exists.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 include/hw/boards.h |  1 +
 vl.c                | 29 ++++++++++++++++++++++++++++-
 2 files changed, 29 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/include/hw/boards.h b/include/hw/boards.h
index a71d1a53a5..915ac3352b 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -180,6 +180,7 @@  struct MachineClass {
 
     void (*init)(MachineState *state);
     void (*reset)(MachineState *state);
+    void (*wakeup)(MachineState *state);
     void (*hot_add_cpu)(MachineState *state, const int64_t id, Error **errp);
     int (*kvm_type)(MachineState *machine, const char *arg);
     void (*smp_parse)(MachineState *ms, QemuOpts *opts);
diff --git a/vl.c b/vl.c
index ef3c7ab8b8..b9e9943458 100644
--- a/vl.c
+++ b/vl.c
@@ -1556,6 +1556,33 @@  void qemu_system_reset(ShutdownCause reason)
     cpu_synchronize_all_post_reset();
 }
 
+/*
+ * Wake the VM after suspend.
+ */
+static void qemu_system_wakeup(void)
+{
+    MachineClass *mc;
+
+    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
+
+    if (mc && mc->wakeup) {
+        mc->wakeup(current_machine);
+    } else {
+        /*
+         * Fall back to old reset wakeup method. Platforms supporting
+         * wakeup should be converted over to use ->wakeup and this
+         * fallback code removed.
+         */
+        cpu_synchronize_all_states();
+        if (mc && mc->reset) {
+            mc->reset(current_machine);
+        } else {
+            qemu_devices_reset();
+        }
+        cpu_synchronize_all_post_reset();
+    }
+}
+
 void qemu_system_guest_panicked(GuestPanicInformation *info)
 {
     qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
@@ -1764,7 +1791,7 @@  static bool main_loop_should_exit(void)
     }
     if (qemu_wakeup_requested()) {
         pause_all_vcpus();
-        qemu_system_reset(SHUTDOWN_CAUSE_NONE);
+        qemu_system_wakeup();
         notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
         wakeup_reason = QEMU_WAKEUP_REASON_NONE;
         resume_all_vcpus();