mirror of https://github.com/xqemu/xqemu.git
suspend: add infrastructure
This patch adds some infrastructure to handle suspend and resume to qemu. First there are two functions to switch state and second there is a suspend notifier: * qemu_system_suspend_request is supposed to be called when the guest asks for being be suspended, for example via ACPI. * qemu_system_wakeup_request is supposed to be called on events which should wake up the guest. * qemu_register_suspend_notifier can be used to register a notifier which will be called when the guest is suspended. Machine types and device models can hook in there to modify state if needed. * qemu_register_wakeup_notifier can be used to register a notifier which will be called when the guest is woken up. Machine types and device models can hook in there to modify state if needed. * qemu_system_wakeup_enable can be used to enable/disable wakeup events. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
8283c4f565
commit
95b363b5c6
9
sysemu.h
9
sysemu.h
|
@ -38,7 +38,16 @@ void vm_start(void);
|
|||
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);
|
||||
|
|
67
vl.c
67
vl.c
|
@ -1283,6 +1283,13 @@ static int shutdown_requested, shutdown_signal = -1;
|
|||
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)
|
||||
|
@ -1325,6 +1332,13 @@ int qemu_reset_requested(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;
|
||||
|
@ -1398,6 +1412,56 @@ void qemu_system_reset_request(void)
|
|||
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;
|
||||
|
@ -1438,6 +1502,9 @@ static bool main_loop_should_exit(void)
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue