void vm_stop(RunState state);
void vm_stop_force_state(RunState state);
+typedef enum WakeupReason {
+ QEMU_WAKEUP_REASON_OTHER = 0,
+} WakeupReason;
+
void qemu_system_reset_request(void);
+void qemu_system_suspend_request(void);
+void qemu_register_suspend_notifier(Notifier *notifier);
+void qemu_system_wakeup_request(WakeupReason reason);
+void qemu_system_wakeup_enable(WakeupReason reason, bool enabled);
+void qemu_register_wakeup_notifier(Notifier *notifier);
void qemu_system_shutdown_request(void);
void qemu_system_powerdown_request(void);
void qemu_system_debug_request(void);
static pid_t shutdown_pid;
static int powerdown_requested;
static int debug_requested;
+static int suspend_requested;
+static bool is_suspended;
+static NotifierList suspend_notifiers =
+ NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
+static NotifierList wakeup_notifiers =
+ NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
+static uint32_t wakeup_reason_mask = ~0;
static RunState vmstop_requested = RUN_STATE_MAX;
int qemu_shutdown_requested_get(void)
return r;
}
+static int qemu_suspend_requested(void)
+{
+ int r = suspend_requested;
+ suspend_requested = 0;
+ return r;
+}
+
int qemu_powerdown_requested(void)
{
int r = powerdown_requested;
qemu_notify_event();
}
+static void qemu_system_suspend(void)
+{
+ pause_all_vcpus();
+ notifier_list_notify(&suspend_notifiers, NULL);
+ is_suspended = true;
+}
+
+void qemu_system_suspend_request(void)
+{
+ if (is_suspended) {
+ return;
+ }
+ suspend_requested = 1;
+ cpu_stop_current();
+ qemu_notify_event();
+}
+
+void qemu_register_suspend_notifier(Notifier *notifier)
+{
+ notifier_list_add(&suspend_notifiers, notifier);
+}
+
+void qemu_system_wakeup_request(WakeupReason reason)
+{
+ if (!is_suspended) {
+ return;
+ }
+ if (!(wakeup_reason_mask & (1 << reason))) {
+ return;
+ }
+ notifier_list_notify(&wakeup_notifiers, &reason);
+ reset_requested = 1;
+ qemu_notify_event();
+ is_suspended = false;
+}
+
+void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
+{
+ if (enabled) {
+ wakeup_reason_mask |= (1 << reason);
+ } else {
+ wakeup_reason_mask &= ~(1 << reason);
+ }
+}
+
+void qemu_register_wakeup_notifier(Notifier *notifier)
+{
+ notifier_list_add(&wakeup_notifiers, notifier);
+}
+
void qemu_system_killed(int signal, pid_t pid)
{
shutdown_signal = signal;
if (qemu_debug_requested()) {
vm_stop(RUN_STATE_DEBUG);
}
+ if (qemu_suspend_requested()) {
+ qemu_system_suspend();
+ }
if (qemu_shutdown_requested()) {
qemu_kill_report();
monitor_protocol_event(QEVENT_SHUTDOWN, NULL);