[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 32/36] vl: extract softmmu/runstate.c
From: |
Igor Mammedov |
Subject: |
Re: [PATCH 32/36] vl: extract softmmu/runstate.c |
Date: |
Fri, 27 Nov 2020 13:59:36 +0100 |
On Mon, 23 Nov 2020 09:14:31 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Looks like a lot more than just runstate, starting from qemu_init_subsystems()
which pulls in a lot of headers. But I don't have a better idea how to name new
file, maybe latter it could be split further, but for now
Acked-by: Igor Mammedov <imammedo@redhat.com>
> ---
> include/sysemu/sysemu.h | 3 +
> softmmu/meson.build | 1 +
> softmmu/runstate.c | 800 ++++++++++++++++++++++++++++++++++++++++
> softmmu/vl.c | 752 +------------------------------------
> 4 files changed, 805 insertions(+), 751 deletions(-)
> create mode 100644 softmmu/runstate.c
>
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 18cf586cd0..3dac3229ec 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -24,6 +24,8 @@ void qemu_remove_machine_init_done_notifier(Notifier
> *notify);
>
> void configure_rtc(QemuOpts *opts);
>
> +void qemu_init_subsystems(void);
> +
> extern int autostart;
>
> typedef enum {
> @@ -44,6 +46,7 @@ extern int alt_grab;
> extern int ctrl_grab;
> extern int graphic_rotate;
> extern int no_shutdown;
> +extern int no_reboot;
> extern int old_param;
> extern int boot_menu;
> extern bool boot_strict;
> diff --git a/softmmu/meson.build b/softmmu/meson.build
> index d098d89653..2a73ebc223 100644
> --- a/softmmu/meson.build
> +++ b/softmmu/meson.build
> @@ -7,6 +7,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
> 'physmem.c',
> 'ioport.c',
> 'rtc.c',
> + 'runstate.c',
> 'memory.c',
> 'memory_mapping.c',
> 'qtest.c',
> diff --git a/softmmu/runstate.c b/softmmu/runstate.c
> new file mode 100644
> index 0000000000..892f2f679f
> --- /dev/null
> +++ b/softmmu/runstate.c
> @@ -0,0 +1,800 @@
> +/*
> + * QEMU main system emulation loop
> + *
> + * Copyright (c) 2003-2020 QEMU contributors
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> copy
> + * of this software and associated documentation files (the "Software"), to
> deal
> + * in the Software without restriction, including without limitation the
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "audio/audio.h"
> +#include "block/block.h"
> +#include "chardev/char.h"
> +#include "crypto/cipher.h"
> +#include "crypto/init.h"
> +#include "exec/cpu-common.h"
> +#include "exec/exec-all.h"
> +#include "exec/gdbstub.h"
> +#include "hw/boards.h"
> +#include "migration/misc.h"
> +#include "migration/postcopy-ram.h"
> +#include "monitor/monitor.h"
> +#include "net/net.h"
> +#include "net/vhost_net.h"
> +#include "qapi/error.h"
> +#include "qapi/qapi-commands-run-state.h"
> +#include "qapi/qapi-events-run-state.h"
> +#include "qemu-common.h"
> +#include "qemu/error-report.h"
> +#include "qemu/job.h"
> +#include "qemu/module.h"
> +#include "qemu/plugin.h"
> +#include "qemu/sockets.h"
> +#include "qemu/thread.h"
> +#include "qom/object.h"
> +#include "qom/object_interfaces.h"
> +#include "sysemu/cpus.h"
> +#include "sysemu/qtest.h"
> +#include "sysemu/replay.h"
> +#include "sysemu/reset.h"
> +#include "sysemu/runstate.h"
> +#include "sysemu/sysemu.h"
> +#include "sysemu/tpm.h"
> +#include "trace.h"
looks like an awful lot headers just for runstate
> +
> +static NotifierList exit_notifiers =
> + NOTIFIER_LIST_INITIALIZER(exit_notifiers);
> +
> +static RunState current_run_state = RUN_STATE_PRELAUNCH;
> +
> +/* We use RUN_STATE__MAX but any invalid value will do */
> +static RunState vmstop_requested = RUN_STATE__MAX;
> +static QemuMutex vmstop_lock;
> +
> +typedef struct {
> + RunState from;
> + RunState to;
> +} RunStateTransition;
> +
> +static const RunStateTransition runstate_transitions_def[] = {
> + { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
> +
> + { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
> + { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
> +
> + { RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
> + { RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
> + { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
> + { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
> + { RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN },
> + { RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED },
> + { RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG },
> + { RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
> + { RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
> + { RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE },
> + { RUN_STATE_INMIGRATE, RUN_STATE_COLO },
> +
> + { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
> + { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH },
> +
> + { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
> + { RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH },
> +
> + { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
> + { RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
> + { RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
> + { RUN_STATE_PAUSED, RUN_STATE_COLO},
> +
> + { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
> + { RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH },
> +
> + { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
> + { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
> +
> + { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
> + { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
> + { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
> + { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
> + { RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO},
> +
> + { RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
> + { RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
> +
> + { RUN_STATE_COLO, RUN_STATE_RUNNING },
> +
> + { RUN_STATE_RUNNING, RUN_STATE_DEBUG },
> + { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
> + { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
> + { RUN_STATE_RUNNING, RUN_STATE_PAUSED },
> + { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
> + { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
> + { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
> + { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
> + { RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
> + { RUN_STATE_RUNNING, RUN_STATE_COLO},
> +
> + { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
> +
> + { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
> + { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH },
> + { RUN_STATE_SHUTDOWN, RUN_STATE_COLO },
> +
> + { RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
> + { RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
> + { RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
> + { RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
> + { RUN_STATE_SUSPENDED, RUN_STATE_COLO},
> +
> + { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
> + { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH },
> + { RUN_STATE_WATCHDOG, RUN_STATE_COLO},
> +
> + { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
> + { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
> + { RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },
> +
> + { RUN_STATE__MAX, RUN_STATE__MAX },
> +};
> +
> +static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
> +
> +bool runstate_check(RunState state)
> +{
> + return current_run_state == state;
> +}
> +
> +bool runstate_store(char *str, size_t size)
> +{
> + const char *state = RunState_str(current_run_state);
> + size_t len = strlen(state) + 1;
> +
> + if (len > size) {
> + return false;
> + }
> + memcpy(str, state, len);
> + return true;
> +}
> +
> +static void runstate_init(void)
> +{
> + const RunStateTransition *p;
> +
> + memset(&runstate_valid_transitions, 0,
> sizeof(runstate_valid_transitions));
> + for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
> + runstate_valid_transitions[p->from][p->to] = true;
> + }
> +
> + qemu_mutex_init(&vmstop_lock);
> +}
> +
> +/* This function will abort() on invalid state transitions */
> +void runstate_set(RunState new_state)
> +{
> + assert(new_state < RUN_STATE__MAX);
> +
> + trace_runstate_set(current_run_state, RunState_str(current_run_state),
> + new_state, RunState_str(new_state));
> +
> + if (current_run_state == new_state) {
> + return;
> + }
> +
> + if (!runstate_valid_transitions[current_run_state][new_state]) {
> + error_report("invalid runstate transition: '%s' -> '%s'",
> + RunState_str(current_run_state),
> + RunState_str(new_state));
> + abort();
> + }
> +
> + current_run_state = new_state;
> +}
> +
> +int runstate_is_running(void)
> +{
> + return runstate_check(RUN_STATE_RUNNING);
> +}
> +
> +bool runstate_needs_reset(void)
> +{
> + return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
> + runstate_check(RUN_STATE_SHUTDOWN);
> +}
> +
> +StatusInfo *qmp_query_status(Error **errp)
> +{
> + StatusInfo *info = g_malloc0(sizeof(*info));
> +
> + info->running = runstate_is_running();
> + info->singlestep = singlestep;
> + info->status = current_run_state;
> +
> + return info;
> +}
> +
> +bool qemu_vmstop_requested(RunState *r)
> +{
> + qemu_mutex_lock(&vmstop_lock);
> + *r = vmstop_requested;
> + vmstop_requested = RUN_STATE__MAX;
> + qemu_mutex_unlock(&vmstop_lock);
> + return *r < RUN_STATE__MAX;
> +}
> +
> +void qemu_system_vmstop_request_prepare(void)
> +{
> + qemu_mutex_lock(&vmstop_lock);
> +}
> +
> +void qemu_system_vmstop_request(RunState state)
> +{
> + vmstop_requested = state;
> + qemu_mutex_unlock(&vmstop_lock);
> + qemu_notify_event();
> +}
> +struct VMChangeStateEntry {
> + VMChangeStateHandler *cb;
> + void *opaque;
> + QTAILQ_ENTRY(VMChangeStateEntry) entries;
> + int priority;
> +};
> +
> +static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
> + QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
> +
> +/**
> + * qemu_add_vm_change_state_handler_prio:
> + * @cb: the callback to invoke
> + * @opaque: user data passed to the callback
> + * @priority: low priorities execute first when the vm runs and the reverse
> is
> + * true when the vm stops
> + *
> + * Register a callback function that is invoked when the vm starts or stops
> + * running.
> + *
> + * Returns: an entry to be freed using qemu_del_vm_change_state_handler()
> + */
> +VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
> + VMChangeStateHandler *cb, void *opaque, int priority)
> +{
> + VMChangeStateEntry *e;
> + VMChangeStateEntry *other;
> +
> + e = g_malloc0(sizeof(*e));
> + e->cb = cb;
> + e->opaque = opaque;
> + e->priority = priority;
> +
> + /* Keep list sorted in ascending priority order */
> + QTAILQ_FOREACH(other, &vm_change_state_head, entries) {
> + if (priority < other->priority) {
> + QTAILQ_INSERT_BEFORE(other, e, entries);
> + return e;
> + }
> + }
> +
> + QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries);
> + return e;
> +}
> +
> +VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler
> *cb,
> + void *opaque)
> +{
> + return qemu_add_vm_change_state_handler_prio(cb, opaque, 0);
> +}
> +
> +void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
> +{
> + QTAILQ_REMOVE(&vm_change_state_head, e, entries);
> + g_free(e);
> +}
> +
> +void vm_state_notify(int running, RunState state)
> +{
> + VMChangeStateEntry *e, *next;
> +
> + trace_vm_state_notify(running, state, RunState_str(state));
> +
> + if (running) {
> + QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
> + e->cb(e->opaque, running, state);
> + }
> + } else {
> + QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next)
> {
> + e->cb(e->opaque, running, state);
> + }
> + }
> +}
> +
> +static ShutdownCause reset_requested;
> +static ShutdownCause shutdown_requested;
> +static int shutdown_signal;
> +static pid_t shutdown_pid;
> +static int powerdown_requested;
> +static int debug_requested;
> +static int suspend_requested;
> +static WakeupReason wakeup_reason;
> +static NotifierList powerdown_notifiers =
> + NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
> +static NotifierList suspend_notifiers =
> + NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
> +static NotifierList wakeup_notifiers =
> + NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
> +static NotifierList shutdown_notifiers =
> + NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
> +static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
> +
> +ShutdownCause qemu_shutdown_requested_get(void)
> +{
> + return shutdown_requested;
> +}
> +
> +ShutdownCause qemu_reset_requested_get(void)
> +{
> + return reset_requested;
> +}
> +
> +static int qemu_shutdown_requested(void)
> +{
> + return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE);
> +}
> +
> +static void qemu_kill_report(void)
> +{
> + if (!qtest_driver() && shutdown_signal) {
> + if (shutdown_pid == 0) {
> + /* This happens for eg ^C at the terminal, so it's worth
> + * avoiding printing an odd message in that case.
> + */
> + error_report("terminating on signal %d", shutdown_signal);
> + } else {
> + char *shutdown_cmd = qemu_get_pid_name(shutdown_pid);
> +
> + error_report("terminating on signal %d from pid " FMT_pid "
> (%s)",
> + shutdown_signal, shutdown_pid,
> + shutdown_cmd ? shutdown_cmd : "<unknown process>");
> + g_free(shutdown_cmd);
> + }
> + shutdown_signal = 0;
> + }
> +}
> +
> +static ShutdownCause qemu_reset_requested(void)
> +{
> + ShutdownCause r = reset_requested;
> +
> + if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
> + reset_requested = SHUTDOWN_CAUSE_NONE;
> + return r;
> + }
> + return SHUTDOWN_CAUSE_NONE;
> +}
> +
> +static int qemu_suspend_requested(void)
> +{
> + int r = suspend_requested;
> + if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) {
> + suspend_requested = 0;
> + return r;
> + }
> + return false;
> +}
> +
> +static WakeupReason qemu_wakeup_requested(void)
> +{
> + return wakeup_reason;
> +}
> +
> +static int qemu_powerdown_requested(void)
> +{
> + int r = powerdown_requested;
> + powerdown_requested = 0;
> + return r;
> +}
> +
> +static int qemu_debug_requested(void)
> +{
> + int r = debug_requested;
> + debug_requested = 0;
> + return r;
> +}
> +
> +/*
> + * Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
> + */
> +void qemu_system_reset(ShutdownCause reason)
> +{
> + MachineClass *mc;
> +
> + mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
> +
> + cpu_synchronize_all_states();
> +
> + if (mc && mc->reset) {
> + mc->reset(current_machine);
> + } else {
> + qemu_devices_reset();
> + }
> + if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
> + qapi_event_send_reset(shutdown_caused_by_guest(reason), 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);
> + }
> +}
> +
> +void qemu_system_guest_panicked(GuestPanicInformation *info)
> +{
> + qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
> +
> + if (current_cpu) {
> + current_cpu->crash_occurred = true;
> + }
> + qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
> + !!info, info);
> + vm_stop(RUN_STATE_GUEST_PANICKED);
> + if (!no_shutdown) {
> + qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
> + !!info, info);
> + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
> + }
> +
> + if (info) {
> + if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
> + qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64
> + " %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
> + info->u.hyper_v.arg1,
> + info->u.hyper_v.arg2,
> + info->u.hyper_v.arg3,
> + info->u.hyper_v.arg4,
> + info->u.hyper_v.arg5);
> + } else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) {
> + qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n"
> + "PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n",
> + info->u.s390.core,
> + S390CrashReason_str(info->u.s390.reason),
> + info->u.s390.psw_mask,
> + info->u.s390.psw_addr);
> + }
> + qapi_free_GuestPanicInformation(info);
> + }
> +}
> +
> +void qemu_system_guest_crashloaded(GuestPanicInformation *info)
> +{
> + qemu_log_mask(LOG_GUEST_ERROR, "Guest crash loaded");
> +
> + qapi_event_send_guest_crashloaded(GUEST_PANIC_ACTION_RUN,
> + !!info, info);
> +
> + if (info) {
> + qapi_free_GuestPanicInformation(info);
> + }
> +}
> +
> +void qemu_system_reset_request(ShutdownCause reason)
> +{
> + if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
> + shutdown_requested = reason;
> + } else {
> + reset_requested = reason;
> + }
> + cpu_stop_current();
> + qemu_notify_event();
> +}
> +
> +static void qemu_system_suspend(void)
> +{
> + pause_all_vcpus();
> + notifier_list_notify(&suspend_notifiers, NULL);
> + runstate_set(RUN_STATE_SUSPENDED);
> + qapi_event_send_suspend();
> +}
> +
> +void qemu_system_suspend_request(void)
> +{
> + if (runstate_check(RUN_STATE_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, Error **errp)
> +{
> + trace_system_wakeup_request(reason);
> +
> + if (!runstate_check(RUN_STATE_SUSPENDED)) {
> + error_setg(errp,
> + "Unable to wake up: guest is not in suspended state");
> + return;
> + }
> + if (!(wakeup_reason_mask & (1 << reason))) {
> + return;
> + }
> + runstate_set(RUN_STATE_RUNNING);
> + wakeup_reason = reason;
> + qemu_notify_event();
> +}
> +
> +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);
> +}
> +
> +static bool wakeup_suspend_enabled;
> +
> +void qemu_register_wakeup_support(void)
> +{
> + wakeup_suspend_enabled = true;
> +}
> +
> +bool qemu_wakeup_suspend_enabled(void)
> +{
> + return wakeup_suspend_enabled;
> +}
> +
> +void qemu_system_killed(int signal, pid_t pid)
> +{
> + shutdown_signal = signal;
> + shutdown_pid = pid;
> + no_shutdown = 0;
> +
> + /* Cannot call qemu_system_shutdown_request directly because
> + * we are in a signal handler.
> + */
> + shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
> + qemu_notify_event();
> +}
> +
> +void qemu_system_shutdown_request(ShutdownCause reason)
> +{
> + trace_qemu_system_shutdown_request(reason);
> + replay_shutdown_request(reason);
> + shutdown_requested = reason;
> + qemu_notify_event();
> +}
> +
> +static void qemu_system_powerdown(void)
> +{
> + qapi_event_send_powerdown();
> + notifier_list_notify(&powerdown_notifiers, NULL);
> +}
> +
> +static void qemu_system_shutdown(ShutdownCause cause)
> +{
> + qapi_event_send_shutdown(shutdown_caused_by_guest(cause), cause);
> + notifier_list_notify(&shutdown_notifiers, &cause);
> +}
> +
> +void qemu_system_powerdown_request(void)
> +{
> + trace_qemu_system_powerdown_request();
> + powerdown_requested = 1;
> + qemu_notify_event();
> +}
> +
> +void qemu_register_powerdown_notifier(Notifier *notifier)
> +{
> + notifier_list_add(&powerdown_notifiers, notifier);
> +}
> +
> +void qemu_register_shutdown_notifier(Notifier *notifier)
> +{
> + notifier_list_add(&shutdown_notifiers, notifier);
> +}
> +
> +void qemu_system_debug_request(void)
> +{
> + debug_requested = 1;
> + qemu_notify_event();
> +}
> +
> +static bool main_loop_should_exit(void)
> +{
> + RunState r;
> + ShutdownCause request;
> +
> + if (qemu_debug_requested()) {
> + vm_stop(RUN_STATE_DEBUG);
> + }
> + if (qemu_suspend_requested()) {
> + qemu_system_suspend();
> + }
> + request = qemu_shutdown_requested();
> + if (request) {
> + qemu_kill_report();
> + qemu_system_shutdown(request);
> + if (no_shutdown) {
> + vm_stop(RUN_STATE_SHUTDOWN);
> + } else {
> + return true;
> + }
> + }
> + request = qemu_reset_requested();
> + if (request) {
> + pause_all_vcpus();
> + qemu_system_reset(request);
> + resume_all_vcpus();
> + /*
> + * runstate can change in pause_all_vcpus()
> + * as iothread mutex is unlocked
> + */
> + if (!runstate_check(RUN_STATE_RUNNING) &&
> + !runstate_check(RUN_STATE_INMIGRATE) &&
> + !runstate_check(RUN_STATE_FINISH_MIGRATE)) {
> + runstate_set(RUN_STATE_PRELAUNCH);
> + }
> + }
> + if (qemu_wakeup_requested()) {
> + pause_all_vcpus();
> + qemu_system_wakeup();
> + notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
> + wakeup_reason = QEMU_WAKEUP_REASON_NONE;
> + resume_all_vcpus();
> + qapi_event_send_wakeup();
> + }
> + if (qemu_powerdown_requested()) {
> + qemu_system_powerdown();
> + }
> + if (qemu_vmstop_requested(&r)) {
> + vm_stop(r);
> + }
> + return false;
> +}
> +
> +void qemu_main_loop(void)
> +{
> +#ifdef CONFIG_PROFILER
> + int64_t ti;
> +#endif
> + while (!main_loop_should_exit()) {
> +#ifdef CONFIG_PROFILER
> + ti = profile_getclock();
> +#endif
> + main_loop_wait(false);
> +#ifdef CONFIG_PROFILER
> + dev_time += profile_getclock() - ti;
> +#endif
> + }
> +}
> +
> +void qemu_add_exit_notifier(Notifier *notify)
> +{
> + notifier_list_add(&exit_notifiers, notify);
> +}
> +
> +void qemu_remove_exit_notifier(Notifier *notify)
> +{
> + notifier_remove(notify);
> +}
> +
> +static void qemu_run_exit_notifiers(void)
> +{
> + notifier_list_notify(&exit_notifiers, NULL);
> +}
> +
> +void qemu_init_subsystems(void)
> +{
> + Error *err;
> +
> + os_set_line_buffering();
> +
> + module_call_init(MODULE_INIT_TRACE);
> +
> + qemu_init_cpu_list();
> + qemu_init_cpu_loop();
> + qemu_mutex_lock_iothread();
> +
> + atexit(qemu_run_exit_notifiers);
> +
> + module_call_init(MODULE_INIT_QOM);
> + module_call_init(MODULE_INIT_MIGRATION);
> +
> + runstate_init();
> + precopy_infrastructure_init();
> + postcopy_infrastructure_init();
> + monitor_init_globals();
> +
> + if (qcrypto_init(&err) < 0) {
> + error_reportf_err(err, "cannot initialize crypto: ");
> + exit(1);
> + }
> +
> + os_setup_early_signal_handling();
> +
> + bdrv_init_with_whitelist();
> + socket_init();
> +}
> +
> +
> +void qemu_cleanup(void)
> +{
> + gdbserver_cleanup();
> +
> + /*
> + * cleaning up the migration object cancels any existing migration
> + * try to do this early so that it also stops using devices.
> + */
> + migration_shutdown();
> +
> + /*
> + * We must cancel all block jobs while the block layer is drained,
> + * or cancelling will be affected by throttling and thus may block
> + * for an extended period of time.
> + * vm_shutdown() will bdrv_drain_all(), so we may as well include
> + * it in the drained section.
> + * We do not need to end this section, because we do not want any
> + * requests happening from here on anyway.
> + */
> + bdrv_drain_all_begin();
> +
> + /* No more vcpu or device emulation activity beyond this point */
> + vm_shutdown();
> + replay_finish();
> +
> + job_cancel_sync_all();
> + bdrv_close_all();
> +
> + /* vhost-user must be cleaned up before chardevs. */
> + tpm_cleanup();
> + net_cleanup();
> + audio_cleanup();
> + monitor_cleanup();
> + qemu_chr_cleanup();
> + user_creatable_cleanup();
> + /* TODO: unref root container, check all devices are ok */
> +}
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index c9bb205c42..914b86ee86 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -112,7 +112,6 @@
> #include "qapi/qapi-commands-block-core.h"
> #include "qapi/qapi-commands-migration.h"
> #include "qapi/qapi-commands-misc.h"
> -#include "qapi/qapi-commands-run-state.h"
> #include "qapi/qapi-commands-ui.h"
> #include "qapi/qmp/qerror.h"
> #include "sysemu/iothread.h"
> @@ -164,7 +163,7 @@ Chardev *parallel_hds[MAX_PARALLEL_PORTS];
> int win2k_install_hack = 0;
> int singlestep = 0;
> int fd_bootchk = 1;
> -static int no_reboot;
> +int no_reboot;
> int no_shutdown = 0;
> int graphic_rotate = 0;
> static const char *watchdog;
> @@ -191,9 +190,6 @@ static const char *qtest_log;
> QemuUUID qemu_uuid;
> bool qemu_uuid_set;
>
> -static NotifierList exit_notifiers =
> - NOTIFIER_LIST_INITIALIZER(exit_notifiers);
> -
> uint32_t xen_domid;
> enum xen_mode xen_mode = XEN_EMULATE;
> bool xen_domid_restrict;
> @@ -535,12 +531,6 @@ const char *qemu_get_vm_name(void)
> return qemu_name;
> }
>
> -static void res_free(void)
> -{
> - g_free(boot_splash_filedata);
> - boot_splash_filedata = NULL;
> -}
> -
> static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp)
> {
> const char *driver = qemu_opt_get(opts, "driver");
> @@ -556,206 +546,6 @@ static int default_driver_check(void *opaque, QemuOpts
> *opts, Error **errp)
> return 0;
> }
>
> -/***********************************************************/
> -/* QEMU state */
> -
> -static RunState current_run_state = RUN_STATE_PRELAUNCH;
> -
> -/* We use RUN_STATE__MAX but any invalid value will do */
> -static RunState vmstop_requested = RUN_STATE__MAX;
> -static QemuMutex vmstop_lock;
> -
> -typedef struct {
> - RunState from;
> - RunState to;
> -} RunStateTransition;
> -
> -static const RunStateTransition runstate_transitions_def[] = {
> - { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
> -
> - { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
> - { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
> -
> - { RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
> - { RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
> - { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
> - { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
> - { RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN },
> - { RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED },
> - { RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG },
> - { RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
> - { RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
> - { RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE },
> - { RUN_STATE_INMIGRATE, RUN_STATE_COLO },
> -
> - { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
> - { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH },
> -
> - { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
> - { RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH },
> -
> - { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
> - { RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
> - { RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
> - { RUN_STATE_PAUSED, RUN_STATE_COLO},
> -
> - { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
> - { RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH },
> -
> - { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
> - { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
> -
> - { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
> - { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
> - { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
> - { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
> - { RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO},
> -
> - { RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
> - { RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
> -
> - { RUN_STATE_COLO, RUN_STATE_RUNNING },
> -
> - { RUN_STATE_RUNNING, RUN_STATE_DEBUG },
> - { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
> - { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
> - { RUN_STATE_RUNNING, RUN_STATE_PAUSED },
> - { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
> - { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
> - { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
> - { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
> - { RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
> - { RUN_STATE_RUNNING, RUN_STATE_COLO},
> -
> - { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
> -
> - { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
> - { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH },
> - { RUN_STATE_SHUTDOWN, RUN_STATE_COLO },
> -
> - { RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
> - { RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
> - { RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
> - { RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
> - { RUN_STATE_SUSPENDED, RUN_STATE_COLO},
> -
> - { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
> - { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH },
> - { RUN_STATE_WATCHDOG, RUN_STATE_COLO},
> -
> - { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
> - { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
> - { RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },
> -
> - { RUN_STATE__MAX, RUN_STATE__MAX },
> -};
> -
> -static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
> -
> -bool runstate_check(RunState state)
> -{
> - return current_run_state == state;
> -}
> -
> -bool runstate_store(char *str, size_t size)
> -{
> - const char *state = RunState_str(current_run_state);
> - size_t len = strlen(state) + 1;
> -
> - if (len > size) {
> - return false;
> - }
> - memcpy(str, state, len);
> - return true;
> -}
> -
> -static void runstate_init(void)
> -{
> - const RunStateTransition *p;
> -
> - memset(&runstate_valid_transitions, 0,
> sizeof(runstate_valid_transitions));
> - for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
> - runstate_valid_transitions[p->from][p->to] = true;
> - }
> -
> - qemu_mutex_init(&vmstop_lock);
> -}
> -
> -/* This function will abort() on invalid state transitions */
> -void runstate_set(RunState new_state)
> -{
> - assert(new_state < RUN_STATE__MAX);
> -
> - trace_runstate_set(current_run_state, RunState_str(current_run_state),
> - new_state, RunState_str(new_state));
> -
> - if (current_run_state == new_state) {
> - return;
> - }
> -
> - if (!runstate_valid_transitions[current_run_state][new_state]) {
> - error_report("invalid runstate transition: '%s' -> '%s'",
> - RunState_str(current_run_state),
> - RunState_str(new_state));
> - abort();
> - }
> -
> - current_run_state = new_state;
> -}
> -
> -int runstate_is_running(void)
> -{
> - return runstate_check(RUN_STATE_RUNNING);
> -}
> -
> -bool runstate_needs_reset(void)
> -{
> - return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
> - runstate_check(RUN_STATE_SHUTDOWN);
> -}
> -
> -StatusInfo *qmp_query_status(Error **errp)
> -{
> - StatusInfo *info = g_malloc0(sizeof(*info));
> -
> - info->running = runstate_is_running();
> - info->singlestep = singlestep;
> - info->status = current_run_state;
> -
> - return info;
> -}
> -
> -bool qemu_vmstop_requested(RunState *r)
> -{
> - qemu_mutex_lock(&vmstop_lock);
> - *r = vmstop_requested;
> - vmstop_requested = RUN_STATE__MAX;
> - qemu_mutex_unlock(&vmstop_lock);
> - return *r < RUN_STATE__MAX;
> -}
> -
> -void qemu_system_vmstop_request_prepare(void)
> -{
> - qemu_mutex_lock(&vmstop_lock);
> -}
> -
> -void qemu_system_vmstop_request(RunState state)
> -{
> - vmstop_requested = state;
> - qemu_mutex_unlock(&vmstop_lock);
> - qemu_notify_event();
> -}
> static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
> {
> const char *proc_name;
> @@ -1072,458 +862,6 @@ static int machine_help_func(QemuOpts *opts,
> MachineState *machine)
> return 1;
> }
>
> -struct VMChangeStateEntry {
> - VMChangeStateHandler *cb;
> - void *opaque;
> - QTAILQ_ENTRY(VMChangeStateEntry) entries;
> - int priority;
> -};
> -
> -static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
> - QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
> -
> -/**
> - * qemu_add_vm_change_state_handler_prio:
> - * @cb: the callback to invoke
> - * @opaque: user data passed to the callback
> - * @priority: low priorities execute first when the vm runs and the reverse
> is
> - * true when the vm stops
> - *
> - * Register a callback function that is invoked when the vm starts or stops
> - * running.
> - *
> - * Returns: an entry to be freed using qemu_del_vm_change_state_handler()
> - */
> -VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
> - VMChangeStateHandler *cb, void *opaque, int priority)
> -{
> - VMChangeStateEntry *e;
> - VMChangeStateEntry *other;
> -
> - e = g_malloc0(sizeof(*e));
> - e->cb = cb;
> - e->opaque = opaque;
> - e->priority = priority;
> -
> - /* Keep list sorted in ascending priority order */
> - QTAILQ_FOREACH(other, &vm_change_state_head, entries) {
> - if (priority < other->priority) {
> - QTAILQ_INSERT_BEFORE(other, e, entries);
> - return e;
> - }
> - }
> -
> - QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries);
> - return e;
> -}
> -
> -VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler
> *cb,
> - void *opaque)
> -{
> - return qemu_add_vm_change_state_handler_prio(cb, opaque, 0);
> -}
> -
> -void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
> -{
> - QTAILQ_REMOVE(&vm_change_state_head, e, entries);
> - g_free(e);
> -}
> -
> -void vm_state_notify(int running, RunState state)
> -{
> - VMChangeStateEntry *e, *next;
> -
> - trace_vm_state_notify(running, state, RunState_str(state));
> -
> - if (running) {
> - QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
> - e->cb(e->opaque, running, state);
> - }
> - } else {
> - QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next)
> {
> - e->cb(e->opaque, running, state);
> - }
> - }
> -}
> -
> -static ShutdownCause reset_requested;
> -static ShutdownCause shutdown_requested;
> -static int shutdown_signal;
> -static pid_t shutdown_pid;
> -static int powerdown_requested;
> -static int debug_requested;
> -static int suspend_requested;
> -static WakeupReason wakeup_reason;
> -static NotifierList powerdown_notifiers =
> - NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
> -static NotifierList suspend_notifiers =
> - NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
> -static NotifierList wakeup_notifiers =
> - NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
> -static NotifierList shutdown_notifiers =
> - NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
> -static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
> -
> -ShutdownCause qemu_shutdown_requested_get(void)
> -{
> - return shutdown_requested;
> -}
> -
> -ShutdownCause qemu_reset_requested_get(void)
> -{
> - return reset_requested;
> -}
> -
> -static int qemu_shutdown_requested(void)
> -{
> - return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE);
> -}
> -
> -static void qemu_kill_report(void)
> -{
> - if (!qtest_driver() && shutdown_signal) {
> - if (shutdown_pid == 0) {
> - /* This happens for eg ^C at the terminal, so it's worth
> - * avoiding printing an odd message in that case.
> - */
> - error_report("terminating on signal %d", shutdown_signal);
> - } else {
> - char *shutdown_cmd = qemu_get_pid_name(shutdown_pid);
> -
> - error_report("terminating on signal %d from pid " FMT_pid "
> (%s)",
> - shutdown_signal, shutdown_pid,
> - shutdown_cmd ? shutdown_cmd : "<unknown process>");
> - g_free(shutdown_cmd);
> - }
> - shutdown_signal = 0;
> - }
> -}
> -
> -static ShutdownCause qemu_reset_requested(void)
> -{
> - ShutdownCause r = reset_requested;
> -
> - if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
> - reset_requested = SHUTDOWN_CAUSE_NONE;
> - return r;
> - }
> - return SHUTDOWN_CAUSE_NONE;
> -}
> -
> -static int qemu_suspend_requested(void)
> -{
> - int r = suspend_requested;
> - if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) {
> - suspend_requested = 0;
> - return r;
> - }
> - return false;
> -}
> -
> -static WakeupReason qemu_wakeup_requested(void)
> -{
> - return wakeup_reason;
> -}
> -
> -static int qemu_powerdown_requested(void)
> -{
> - int r = powerdown_requested;
> - powerdown_requested = 0;
> - return r;
> -}
> -
> -static int qemu_debug_requested(void)
> -{
> - int r = debug_requested;
> - debug_requested = 0;
> - return r;
> -}
> -
> -/*
> - * Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
> - */
> -void qemu_system_reset(ShutdownCause reason)
> -{
> - MachineClass *mc;
> -
> - mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
> -
> - cpu_synchronize_all_states();
> -
> - if (mc && mc->reset) {
> - mc->reset(current_machine);
> - } else {
> - qemu_devices_reset();
> - }
> - if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
> - qapi_event_send_reset(shutdown_caused_by_guest(reason), 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);
> - }
> -}
> -
> -void qemu_system_guest_panicked(GuestPanicInformation *info)
> -{
> - qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
> -
> - if (current_cpu) {
> - current_cpu->crash_occurred = true;
> - }
> - qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
> - !!info, info);
> - vm_stop(RUN_STATE_GUEST_PANICKED);
> - if (!no_shutdown) {
> - qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
> - !!info, info);
> - qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
> - }
> -
> - if (info) {
> - if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
> - qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64
> - " %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
> - info->u.hyper_v.arg1,
> - info->u.hyper_v.arg2,
> - info->u.hyper_v.arg3,
> - info->u.hyper_v.arg4,
> - info->u.hyper_v.arg5);
> - } else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) {
> - qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n"
> - "PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n",
> - info->u.s390.core,
> - S390CrashReason_str(info->u.s390.reason),
> - info->u.s390.psw_mask,
> - info->u.s390.psw_addr);
> - }
> - qapi_free_GuestPanicInformation(info);
> - }
> -}
> -
> -void qemu_system_guest_crashloaded(GuestPanicInformation *info)
> -{
> - qemu_log_mask(LOG_GUEST_ERROR, "Guest crash loaded");
> -
> - qapi_event_send_guest_crashloaded(GUEST_PANIC_ACTION_RUN,
> - !!info, info);
> -
> - if (info) {
> - qapi_free_GuestPanicInformation(info);
> - }
> -}
> -
> -void qemu_system_reset_request(ShutdownCause reason)
> -{
> - if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
> - shutdown_requested = reason;
> - } else {
> - reset_requested = reason;
> - }
> - cpu_stop_current();
> - qemu_notify_event();
> -}
> -
> -static void qemu_system_suspend(void)
> -{
> - pause_all_vcpus();
> - notifier_list_notify(&suspend_notifiers, NULL);
> - runstate_set(RUN_STATE_SUSPENDED);
> - qapi_event_send_suspend();
> -}
> -
> -void qemu_system_suspend_request(void)
> -{
> - if (runstate_check(RUN_STATE_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, Error **errp)
> -{
> - trace_system_wakeup_request(reason);
> -
> - if (!runstate_check(RUN_STATE_SUSPENDED)) {
> - error_setg(errp,
> - "Unable to wake up: guest is not in suspended state");
> - return;
> - }
> - if (!(wakeup_reason_mask & (1 << reason))) {
> - return;
> - }
> - runstate_set(RUN_STATE_RUNNING);
> - wakeup_reason = reason;
> - qemu_notify_event();
> -}
> -
> -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_register_wakeup_support(void)
> -{
> - wakeup_suspend_enabled = true;
> -}
> -
> -bool qemu_wakeup_suspend_enabled(void)
> -{
> - return wakeup_suspend_enabled;
> -}
> -
> -void qemu_system_killed(int signal, pid_t pid)
> -{
> - shutdown_signal = signal;
> - shutdown_pid = pid;
> - no_shutdown = 0;
> -
> - /* Cannot call qemu_system_shutdown_request directly because
> - * we are in a signal handler.
> - */
> - shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
> - qemu_notify_event();
> -}
> -
> -void qemu_system_shutdown_request(ShutdownCause reason)
> -{
> - trace_qemu_system_shutdown_request(reason);
> - replay_shutdown_request(reason);
> - shutdown_requested = reason;
> - qemu_notify_event();
> -}
> -
> -static void qemu_system_powerdown(void)
> -{
> - qapi_event_send_powerdown();
> - notifier_list_notify(&powerdown_notifiers, NULL);
> -}
> -
> -static void qemu_system_shutdown(ShutdownCause cause)
> -{
> - qapi_event_send_shutdown(shutdown_caused_by_guest(cause), cause);
> - notifier_list_notify(&shutdown_notifiers, &cause);
> -}
> -
> -void qemu_system_powerdown_request(void)
> -{
> - trace_qemu_system_powerdown_request();
> - powerdown_requested = 1;
> - qemu_notify_event();
> -}
> -
> -void qemu_register_powerdown_notifier(Notifier *notifier)
> -{
> - notifier_list_add(&powerdown_notifiers, notifier);
> -}
> -
> -void qemu_register_shutdown_notifier(Notifier *notifier)
> -{
> - notifier_list_add(&shutdown_notifiers, notifier);
> -}
> -
> -void qemu_system_debug_request(void)
> -{
> - debug_requested = 1;
> - qemu_notify_event();
> -}
> -
> -static bool main_loop_should_exit(void)
> -{
> - RunState r;
> - ShutdownCause request;
> -
> - if (qemu_debug_requested()) {
> - vm_stop(RUN_STATE_DEBUG);
> - }
> - if (qemu_suspend_requested()) {
> - qemu_system_suspend();
> - }
> - request = qemu_shutdown_requested();
> - if (request) {
> - qemu_kill_report();
> - qemu_system_shutdown(request);
> - if (no_shutdown) {
> - vm_stop(RUN_STATE_SHUTDOWN);
> - } else {
> - return true;
> - }
> - }
> - request = qemu_reset_requested();
> - if (request) {
> - pause_all_vcpus();
> - qemu_system_reset(request);
> - resume_all_vcpus();
> - /*
> - * runstate can change in pause_all_vcpus()
> - * as iothread mutex is unlocked
> - */
> - if (!runstate_check(RUN_STATE_RUNNING) &&
> - !runstate_check(RUN_STATE_INMIGRATE) &&
> - !runstate_check(RUN_STATE_FINISH_MIGRATE)) {
> - runstate_set(RUN_STATE_PRELAUNCH);
> - }
> - }
> - if (qemu_wakeup_requested()) {
> - pause_all_vcpus();
> - qemu_system_wakeup();
> - notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
> - wakeup_reason = QEMU_WAKEUP_REASON_NONE;
> - resume_all_vcpus();
> - qapi_event_send_wakeup();
> - }
> - if (qemu_powerdown_requested()) {
> - qemu_system_powerdown();
> - }
> - if (qemu_vmstop_requested(&r)) {
> - vm_stop(r);
> - }
> - return false;
> -}
> -
> -void qemu_main_loop(void)
> -{
> -#ifdef CONFIG_PROFILER
> - int64_t ti;
> -#endif
> - while (!main_loop_should_exit()) {
> -#ifdef CONFIG_PROFILER
> - ti = profile_getclock();
> -#endif
> - main_loop_wait(false);
> -#ifdef CONFIG_PROFILER
> - dev_time += profile_getclock() - ti;
> -#endif
> - }
> -}
> -
> static void version(void)
> {
> printf("QEMU emulator version " QEMU_FULL_VERSION "\n"
> @@ -2248,21 +1586,6 @@ static MachineClass *machine_parse(const char *name,
> GSList *machines)
> return mc;
> }
>
> -void qemu_add_exit_notifier(Notifier *notify)
> -{
> - notifier_list_add(&exit_notifiers, notify);
> -}
> -
> -void qemu_remove_exit_notifier(Notifier *notify)
> -{
> - notifier_remove(notify);
> -}
> -
> -static void qemu_run_exit_notifiers(void)
> -{
> - notifier_list_notify(&exit_notifiers, NULL);
> -}
> -
> static const char *pid_file;
> static Notifier qemu_unlink_pidfile_notifier;
>
> @@ -3061,39 +2384,6 @@ static void qemu_maybe_daemonize(const char *pid_file)
> qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
> }
>
> -static void qemu_init_subsystems(void)
> -{
> - Error *err;
> -
> - os_set_line_buffering();
> -
> - module_call_init(MODULE_INIT_TRACE);
> -
> - qemu_init_cpu_list();
> - qemu_init_cpu_loop();
> - qemu_mutex_lock_iothread();
> -
> - atexit(qemu_run_exit_notifiers);
> -
> - module_call_init(MODULE_INIT_QOM);
> - module_call_init(MODULE_INIT_MIGRATION);
> -
> - runstate_init();
> - precopy_infrastructure_init();
> - postcopy_infrastructure_init();
> - monitor_init_globals();
> -
> - if (qcrypto_init(&err) < 0) {
> - error_reportf_err(err, "cannot initialize crypto: ");
> - exit(1);
> - }
> -
> - os_setup_early_signal_handling();
> -
> - bdrv_init_with_whitelist();
> - socket_init();
> -}
> -
> static void qemu_init_displays(void)
> {
> DisplayState *ds;
> @@ -4275,43 +3565,3 @@ void qemu_init(int argc, char **argv, char **envp)
> accel_setup_post(current_machine);
> os_setup_post();
> }
> -
> -void qemu_cleanup(void)
> -{
> - gdbserver_cleanup();
> -
> - /*
> - * cleaning up the migration object cancels any existing migration
> - * try to do this early so that it also stops using devices.
> - */
> - migration_shutdown();
> -
> - /*
> - * We must cancel all block jobs while the block layer is drained,
> - * or cancelling will be affected by throttling and thus may block
> - * for an extended period of time.
> - * vm_shutdown() will bdrv_drain_all(), so we may as well include
> - * it in the drained section.
> - * We do not need to end this section, because we do not want any
> - * requests happening from here on anyway.
> - */
> - bdrv_drain_all_begin();
> -
> - /* No more vcpu or device emulation activity beyond this point */
> - vm_shutdown();
> - replay_finish();
> -
> - job_cancel_sync_all();
> - bdrv_close_all();
> -
> - res_free();
> -
> - /* vhost-user must be cleaned up before chardevs. */
> - tpm_cleanup();
> - net_cleanup();
> - audio_cleanup();
> - monitor_cleanup();
> - qemu_chr_cleanup();
> - user_creatable_cleanup();
> - /* TODO: unref root container, check all devices are ok */
> -}
- Re: [PATCH 31/36] vl: extract softmmu/rtc.c, (continued)
- [PATCH 19/36] vl: separate qemu_apply_machine_options, Paolo Bonzini, 2020/11/23
- [PATCH 29/36] vl: extract softmmu/datadir.c, Paolo Bonzini, 2020/11/23
- [PATCH 24/36] vl: start VM via qmp_cont, Paolo Bonzini, 2020/11/23
- [PATCH 36/36] vl: move all generic initialization out of vl.c, Paolo Bonzini, 2020/11/23
- [PATCH 27/36] vl: remove separate preconfig main_loop, Paolo Bonzini, 2020/11/23
- [PATCH 32/36] vl: extract softmmu/runstate.c, Paolo Bonzini, 2020/11/23
- Re: [PATCH 32/36] vl: extract softmmu/runstate.c,
Igor Mammedov <=
- [PATCH 33/36] vl: extract softmmu/globals.c, Paolo Bonzini, 2020/11/23
- [PATCH 35/36] vl: clean up -boot variables, Paolo Bonzini, 2020/11/23
- [PATCH 34/36] vl: remove serial_max_hds, Paolo Bonzini, 2020/11/23
- [PATCH 37/36] machine: introduce MachineInitPhase, Paolo Bonzini, 2020/11/27
- Re: [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing, Igor Mammedov, 2020/11/30