system: Move runstate-related code from cpus.c to runstate.c

Keep cpus.c focused on vCPUs handling, move code related to
VM state to runstate.c where similar code lives.

Fix few checkpatch.pl warnings:

  WARNING: Block comments use a leading /* on a separate line
  WARNING: Block comments use * on subsequent lines
  #327: FILE: system/runstate.c:541:
  +/* does a state transition even if the VM is already stopped,
  +   current state is forgotten forever */

Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260812211708.92824-17-philmd@oss.qualcomm.com>
This commit is contained in:
Philippe Mathieu-Daudé 2026-08-12 10:41:57 +02:00
parent 259c2aae8d
commit f036b28896
2 changed files with 154 additions and 147 deletions

View file

@ -25,7 +25,6 @@
#include "qemu/osdep.h"
#include "qemu/coroutine-tls.h"
#include "qapi/error.h"
#include "qapi/qapi-events-run-state.h"
#include "exec/gdbstub.h"
#include "accel/accel-cpu-ops.h"
#include "system/hw_accel.h"
@ -272,58 +271,6 @@ void cpu_interrupt(CPUState *cpu, int mask)
cpus_accel->handle_interrupt(cpu, mask);
}
/*
* True if the vm was previously suspended, and has not been woken or reset.
*/
static int vm_was_suspended;
void vm_set_suspended(bool suspended)
{
vm_was_suspended = suspended;
}
bool vm_get_suspended(void)
{
return vm_was_suspended;
}
static int do_vm_stop(RunState state, bool send_stop)
{
int ret = 0;
RunState oldstate = runstate_get();
if (runstate_is_live(oldstate)) {
vm_was_suspended = (oldstate == RUN_STATE_SUSPENDED);
runstate_set(state);
cpu_disable_ticks();
if (oldstate == RUN_STATE_RUNNING) {
pause_all_vcpus();
}
ret = vm_state_notify(0, state);
if (send_stop) {
qapi_event_send_stop();
}
}
bdrv_drain_all();
/*
* Even if vm_state_notify() return failure,
* it would be better to flush as before.
*/
ret |= bdrv_flush_all();
trace_vm_stop_flush_all(ret);
return ret;
}
/* Special vm_stop() variant for terminating the process. Historically clients
* did not expect a QMP STOP event and so we need to retain compatibility.
*/
int vm_shutdown(void)
{
return do_vm_stop(RUN_STATE_SHUTDOWN, false);
}
bool cpu_can_run(CPUState *cpu)
{
if (cpu->stop) {
@ -734,97 +681,3 @@ void cpu_stop_current(void)
cpu_exit(current_cpu);
}
}
int vm_stop(RunState state)
{
if (qemu_in_vcpu_thread()) {
qemu_system_vmstop_request_prepare();
qemu_system_vmstop_request(state);
/*
* FIXME: should not return to device code in case
* vm_stop() has been requested.
*/
cpu_stop_current();
return 0;
}
return do_vm_stop(state, true);
}
/**
* Prepare for (re)starting the VM.
* 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);
if (runstate_is_running() && requested == RUN_STATE__MAX) {
return -1;
}
/* Ensure that a STOP/RESUME pair of events is emitted if a
* vmstop request was pending. The BLOCK_IO_ERROR event, for
* example, according to documentation is always followed by
* the STOP event.
*/
if (runstate_is_running()) {
qapi_event_send_stop();
qapi_event_send_resume();
return -1;
}
/*
* WHPX accelerator needs to know whether we are going to step
* any CPUs, before starting the first one.
*/
accel_pre_resume(MACHINE(qdev_get_machine()), step_pending);
/* We are sending this now, but the CPUs will be resumed shortly later */
qapi_event_send_resume();
cpu_enable_ticks();
runstate_set(state);
vm_state_notify(1, state);
vm_was_suspended = false;
return ret;
}
void vm_start(void)
{
if (!vm_prepare_start(false)) {
resume_all_vcpus();
}
}
void vm_resume(RunState state)
{
if (runstate_is_live(state)) {
vm_start();
} else {
runstate_set(state);
}
}
/* does a state transition even if the VM is already stopped,
current state is forgotten forever */
int vm_stop_force_state(RunState state)
{
if (runstate_is_live(runstate_get())) {
return vm_stop(state);
} else {
int ret;
runstate_set(state);
bdrv_drain_all();
/* Make sure to return an error if the flush in a previous vm_stop()
* failed. */
ret = bdrv_flush_all();
trace_vm_stop_flush_all(ret);
return ret;
}
}

View file

@ -52,6 +52,7 @@
#include "qemu/thread.h"
#include "qom/object.h"
#include "qom/object_interfaces.h"
#include "system/cpu-timers.h"
#include "system/cpus.h"
#include "system/qtest.h"
#include "system/replay.h"
@ -408,6 +409,159 @@ int vm_state_notify(bool running, RunState state)
return ret;
}
/*
* True if the vm was previously suspended, and has not been woken or reset.
*/
static int vm_was_suspended;
void vm_set_suspended(bool suspended)
{
vm_was_suspended = suspended;
}
bool vm_get_suspended(void)
{
return vm_was_suspended;
}
static int do_vm_stop(RunState state, bool send_stop)
{
int ret = 0;
RunState oldstate = runstate_get();
if (runstate_is_live(oldstate)) {
vm_was_suspended = (oldstate == RUN_STATE_SUSPENDED);
runstate_set(state);
cpu_disable_ticks();
if (oldstate == RUN_STATE_RUNNING) {
pause_all_vcpus();
}
ret = vm_state_notify(0, state);
if (send_stop) {
qapi_event_send_stop();
}
}
bdrv_drain_all();
/*
* Even if vm_state_notify() return failure,
* it would be better to flush as before.
*/
ret |= bdrv_flush_all();
trace_vm_stop_flush_all(ret);
return ret;
}
/*
* Special vm_stop() variant for terminating the process. Historically clients
* did not expect a QMP STOP event and so we need to retain compatibility.
*/
int vm_shutdown(void)
{
return do_vm_stop(RUN_STATE_SHUTDOWN, false);
}
int vm_stop(RunState state)
{
if (qemu_in_vcpu_thread()) {
qemu_system_vmstop_request_prepare();
qemu_system_vmstop_request(state);
/*
* FIXME: should not return to device code in case
* vm_stop() has been requested.
*/
cpu_stop_current();
return 0;
}
return do_vm_stop(state, true);
}
/**
* Prepare for (re)starting the VM.
* 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);
if (runstate_is_running() && requested == RUN_STATE__MAX) {
return -1;
}
/*
* Ensure that a STOP/RESUME pair of events is emitted if a
* vmstop request was pending. The BLOCK_IO_ERROR event, for
* example, according to documentation is always followed by
* the STOP event.
*/
if (runstate_is_running()) {
qapi_event_send_stop();
qapi_event_send_resume();
return -1;
}
/*
* WHPX accelerator needs to know whether we are going to step
* any CPUs, before starting the first one.
*/
accel_pre_resume(MACHINE(qdev_get_machine()), step_pending);
/* We are sending this now, but the CPUs will be resumed shortly later */
qapi_event_send_resume();
cpu_enable_ticks();
runstate_set(state);
vm_state_notify(1, state);
vm_was_suspended = false;
return ret;
}
void vm_start(void)
{
if (!vm_prepare_start(false)) {
resume_all_vcpus();
}
}
void vm_resume(RunState state)
{
if (runstate_is_live(state)) {
vm_start();
} else {
runstate_set(state);
}
}
/*
* does a state transition even if the VM is already stopped,
* current state is forgotten forever
*/
int vm_stop_force_state(RunState state)
{
if (runstate_is_live(runstate_get())) {
return vm_stop(state);
} else {
int ret;
runstate_set(state);
bdrv_drain_all();
/*
* Make sure to return an error if the flush in a previous vm_stop()
* failed.
*/
ret = bdrv_flush_all();
trace_vm_stop_flush_all(ret);
return ret;
}
}
static ShutdownCause reset_requested;
static ShutdownCause shutdown_requested;
static int shutdown_exit_code = EXIT_SUCCESS;