[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH V9 02/12] cpus: stop vm in suspended runstate
From: |
Steve Sistare |
Subject: |
[PATCH V9 02/12] cpus: stop vm in suspended runstate |
Date: |
Wed, 3 Jan 2024 12:05:31 -0800 |
Currently, a vm in the suspended state is not completely stopped. The VCPUs
have been paused, but the cpu clock still runs, and runstate notifiers for
the transition to stopped have not been called. This causes problems for
live migration. Stale cpu timers_state is saved to the migration stream,
causing time errors in the guest when it wakes from suspend, and state that
would have been modified by runstate notifiers is wrong.
Modify vm_stop to completely stop the vm if the current state is suspended,
transition to RUN_STATE_PAUSED, and remember that the machine was suspended.
Modify vm_start to restore the suspended state.
This affects all callers of vm_stop and vm_start, notably, the qapi stop and
cont commands:
old behavior:
RUN_STATE_SUSPENDED --> stop --> RUN_STATE_SUSPENDED
new behavior:
RUN_STATE_SUSPENDED --> stop --> RUN_STATE_PAUSED
RUN_STATE_PAUSED --> cont --> RUN_STATE_SUSPENDED
For example:
(qemu) info status
VM status: paused (suspended)
(qemu) stop
(qemu) info status
VM status: paused
(qemu) system_wakeup
Error: Unable to wake up: guest is not in suspended state
(qemu) cont
(qemu) info status
VM status: paused (suspended)
(qemu) system_wakeup
(qemu) info status
VM status: running
Suggested-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
---
include/sysemu/runstate.h | 9 +++++++++
qapi/misc.json | 11 +++++++++--
qapi/run-state.json | 6 +++---
system/cpus.c | 23 +++++++++++++++--------
system/runstate.c | 3 +++
5 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h
index 88a67e2..618eb49 100644
--- a/include/sysemu/runstate.h
+++ b/include/sysemu/runstate.h
@@ -40,6 +40,15 @@ static inline bool shutdown_caused_by_guest(ShutdownCause
cause)
return cause >= SHUTDOWN_CAUSE_GUEST_SHUTDOWN;
}
+/*
+ * In a "live" state, the vcpu clock is ticking, and the runstate notifiers
+ * think we are running.
+ */
+static inline bool runstate_is_live(RunState state)
+{
+ return state == RUN_STATE_RUNNING || state == RUN_STATE_SUSPENDED;
+}
+
void vm_start(void);
/**
diff --git a/qapi/misc.json b/qapi/misc.json
index cda2eff..3622d98 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -134,7 +134,7 @@
##
# @stop:
#
-# Stop all guest VCPU execution.
+# Stop guest VM execution.
#
# Since: 0.14
#
@@ -143,6 +143,9 @@
# the guest remains paused once migration finishes, as if the -S
# option was passed on the command line.
#
+# In the "suspended" state, it will completely stop the VM and
+# cause a transition to the "paused" state. (Since 9.0)
+#
# Example:
#
# -> { "execute": "stop" }
@@ -153,7 +156,7 @@
##
# @cont:
#
-# Resume guest VCPU execution.
+# Resume guest VM execution.
#
# Since: 0.14
#
@@ -165,6 +168,10 @@
# guest starts once migration finishes, removing the effect of the
# -S command line option if it was passed.
#
+# If the VM was previously suspended, and not been reset or woken,
+# this command will transition back to the "suspended" state.
+# (Since 9.0)
+#
# Example:
#
# -> { "execute": "cont" }
diff --git a/qapi/run-state.json b/qapi/run-state.json
index f216ba5..ca05502 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -102,7 +102,7 @@
##
# @StatusInfo:
#
-# Information about VCPU run state
+# Information about VM run state
#
# @running: true if all VCPUs are runnable, false if not runnable
#
@@ -130,9 +130,9 @@
##
# @query-status:
#
-# Query the run status of all VCPUs
+# Query the run status of the VM
#
-# Returns: @StatusInfo reflecting all VCPUs
+# Returns: @StatusInfo reflecting the VM
#
# Since: 0.14
#
diff --git a/system/cpus.c b/system/cpus.c
index 9f631ab..f162435 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -277,11 +277,15 @@ bool vm_get_suspended(void)
static int do_vm_stop(RunState state, bool send_stop)
{
int ret = 0;
+ RunState oldstate = runstate_get();
- if (runstate_is_running()) {
+ if (runstate_is_live(oldstate)) {
+ vm_was_suspended = (oldstate == RUN_STATE_SUSPENDED);
runstate_set(state);
cpu_disable_ticks();
- pause_all_vcpus();
+ if (oldstate == RUN_STATE_RUNNING) {
+ pause_all_vcpus();
+ }
vm_state_notify(0, state);
if (send_stop) {
qapi_event_send_stop();
@@ -694,11 +698,13 @@ int vm_stop(RunState state)
/**
* Prepare for (re)starting the VM.
- * Returns -1 if the vCPUs are not to be restarted (e.g. if they are already
- * running or in case of an error condition), 0 otherwise.
+ * Returns 0 if the vCPUs should be restarted, -1 on an error condition,
+ * and 1 otherwise.
*/
int vm_prepare_start(bool step_pending)
{
+ int ret = vm_was_suspended ? 1 : 0;
+ RunState state = vm_was_suspended ? RUN_STATE_SUSPENDED :
RUN_STATE_RUNNING;
RunState requested;
qemu_vmstop_requested(&requested);
@@ -729,9 +735,10 @@ int vm_prepare_start(bool step_pending)
qapi_event_send_resume();
cpu_enable_ticks();
- runstate_set(RUN_STATE_RUNNING);
- vm_state_notify(1, RUN_STATE_RUNNING);
- return 0;
+ runstate_set(state);
+ vm_state_notify(1, state);
+ vm_was_suspended = false;
+ return ret;
}
void vm_start(void)
@@ -745,7 +752,7 @@ void vm_start(void)
current state is forgotten forever */
int vm_stop_force_state(RunState state)
{
- if (runstate_is_running()) {
+ if (runstate_is_live(runstate_get())) {
return vm_stop(state);
} else {
int ret;
diff --git a/system/runstate.c b/system/runstate.c
index ea9d6c2..e2fa204 100644
--- a/system/runstate.c
+++ b/system/runstate.c
@@ -108,6 +108,7 @@ static const RunStateTransition runstate_transitions_def[]
= {
{ RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
{ RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
{ RUN_STATE_PAUSED, RUN_STATE_COLO},
+ { RUN_STATE_PAUSED, RUN_STATE_SUSPENDED},
{ RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
{ RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
@@ -161,6 +162,7 @@ static const RunStateTransition runstate_transitions_def[]
= {
{ RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
{ RUN_STATE_SUSPENDED, RUN_STATE_COLO},
+ { RUN_STATE_SUSPENDED, RUN_STATE_PAUSED},
{ RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
{ RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
@@ -502,6 +504,7 @@ void qemu_system_reset(ShutdownCause reason)
qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
}
cpu_synchronize_all_post_reset();
+ vm_set_suspended(false);
}
/*
--
1.8.3.1
- [PATCH V9 04/12] cpus: vm_resume, (continued)
- [PATCH V9 04/12] cpus: vm_resume, Steve Sistare, 2024/01/03
- [PATCH V9 12/12] tests/qtest: postcopy migration with suspend, Steve Sistare, 2024/01/03
- [PATCH V9 03/12] cpus: check running not RUN_STATE_RUNNING, Steve Sistare, 2024/01/03
- [PATCH V9 01/12] cpus: vm_was_suspended, Steve Sistare, 2024/01/03
- [PATCH V9 06/12] migration: preserve suspended runstate, Steve Sistare, 2024/01/03
- [PATCH V9 10/12] tests/qtest: option to suspend during migration, Steve Sistare, 2024/01/03
- [PATCH V9 08/12] migration: preserve suspended for bg_migration, Steve Sistare, 2024/01/03
- [PATCH V9 07/12] migration: preserve suspended for snapshot, Steve Sistare, 2024/01/03
- [PATCH V9 09/12] tests/qtest: migration events, Steve Sistare, 2024/01/03
- [PATCH V9 05/12] migration: propagate suspended runstate, Steve Sistare, 2024/01/03
- [PATCH V9 02/12] cpus: stop vm in suspended runstate,
Steve Sistare <=
- [PATCH V9 11/12] tests/qtest: precopy migration with suspend, Steve Sistare, 2024/01/03
- Re: [PATCH V9 00/12] fix migration of suspended runstate, Peter Xu, 2024/01/03