From 164dafd1744c69d268b89015977e19d8a9617fdf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 04:44:18 -0400 Subject: [PATCH 01/45] remove preconfig state The preconfig state is only used if -incoming is not specified, which makes the RunState state machine more tricky than it need be. However there is already an equivalent condition which works even with -incoming, namely qdev_hotplug. Use it instead of a separate runstate. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/core/machine-qmp-cmds.c | 5 ++--- include/qapi/qmp/dispatch.h | 1 + monitor/hmp.c | 7 ++++--- monitor/qmp-cmds.c | 5 ++--- qapi/qmp-dispatch.c | 5 +---- qapi/run-state.json | 5 +---- softmmu/qdev-monitor.c | 12 ++++++++++++ softmmu/vl.c | 13 ++----------- stubs/meson.build | 1 + stubs/qmp-command-available.c | 7 +++++++ tests/qtest/qmp-test.c | 2 +- 11 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 stubs/qmp-command-available.c diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c index 5362c80a18..cb9387c5f5 100644 --- a/hw/core/machine-qmp-cmds.c +++ b/hw/core/machine-qmp-cmds.c @@ -286,9 +286,8 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) void qmp_set_numa_node(NumaOptions *cmd, Error **errp) { - if (!runstate_check(RUN_STATE_PRECONFIG)) { - error_setg(errp, "The command is permitted only in '%s' state", - RunState_str(RUN_STATE_PRECONFIG)); + if (qdev_hotplug) { + error_setg(errp, "The command is permitted only before the machine has been created"); return; } diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index af8d96c570..1486cac3ef 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -48,6 +48,7 @@ void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); bool qmp_command_is_enabled(const QmpCommand *cmd); +bool qmp_command_available(const QmpCommand *cmd, Error **errp); const char *qmp_command_name(const QmpCommand *cmd); bool qmp_has_success_response(const QmpCommand *cmd); QDict *qmp_error_response(Error *err); diff --git a/monitor/hmp.c b/monitor/hmp.c index d40f4f4391..f2fe192d69 100644 --- a/monitor/hmp.c +++ b/monitor/hmp.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include +#include "hw/qdev-core.h" #include "monitor-internal.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" @@ -215,7 +216,7 @@ static bool cmd_can_preconfig(const HMPCommand *cmd) static bool cmd_available(const HMPCommand *cmd) { - return !runstate_check(RUN_STATE_PRECONFIG) || cmd_can_preconfig(cmd); + return qdev_hotplug || cmd_can_preconfig(cmd); } static void help_cmd_dump_one(Monitor *mon, @@ -658,8 +659,8 @@ static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon, return NULL; } if (!cmd_available(cmd)) { - monitor_printf(mon, "Command '%.*s' not available with -preconfig " - "until after exit_preconfig.\n", + monitor_printf(mon, "Command '%.*s' not available " + "until machine initialization has completed.\n", (int)(p - cmdp_start), cmdp_start); return NULL; } diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 6223a28e8b..639a219294 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -104,9 +104,8 @@ void qmp_system_powerdown(Error **errp) void qmp_x_exit_preconfig(Error **errp) { - if (!runstate_check(RUN_STATE_PRECONFIG)) { - error_setg(errp, "The command is permitted only in '%s' state", - RunState_str(RUN_STATE_PRECONFIG)); + if (qdev_hotplug) { + error_setg(errp, "The command is permitted only before machine initialization"); return; } qemu_exit_preconfig_request(); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 9a2d7dd29a..0a2b20a4e4 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -167,10 +167,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, goto out; } - if (runstate_check(RUN_STATE_PRECONFIG) && - !(cmd->options & QCO_ALLOW_PRECONFIG)) { - error_setg(&err, "The command '%s' isn't permitted in '%s' state", - cmd->name, RunState_str(RUN_STATE_PRECONFIG)); + if (!qmp_command_available(cmd, &err)) { goto out; } diff --git a/qapi/run-state.json b/qapi/run-state.json index b2f77cbf3f..a47c500f83 100644 --- a/qapi/run-state.json +++ b/qapi/run-state.json @@ -50,15 +50,12 @@ # @colo: guest is paused to save/restore VM state under colo checkpoint, # VM can not get into this state unless colo capability is enabled # for migration. (since 2.8) -# @preconfig: QEMU is paused before board specific init callback is executed. -# The state is reachable only if the --preconfig CLI option is used. -# (Since 3.0) ## { 'enum': 'RunState', 'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused', 'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm', 'running', 'save-vm', 'shutdown', 'suspended', 'watchdog', - 'guest-panicked', 'colo', 'preconfig' ] } + 'guest-panicked', 'colo' ] } ## # @ShutdownCause: diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 8c072e3efc..3f1e67267d 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -25,6 +25,7 @@ #include "sysemu/arch_init.h" #include "qapi/error.h" #include "qapi/qapi-commands-qdev.h" +#include "qapi/qmp/dispatch.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qemu/config-file.h" @@ -983,3 +984,14 @@ int qemu_global_option(const char *str) return 0; } + +bool qmp_command_available(const QmpCommand *cmd, Error **errp) +{ + if (!qdev_hotplug && + !(cmd->options & QCO_ALLOW_PRECONFIG)) { + error_setg(errp, "The command '%s' is permitted only after machine initialization has completed", + cmd->name); + return false; + } + return true; +} diff --git a/softmmu/vl.c b/softmmu/vl.c index 7146fbe219..ab2210bc79 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -557,7 +557,7 @@ static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp) /***********************************************************/ /* QEMU state */ -static RunState current_run_state = RUN_STATE_PRECONFIG; +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; @@ -569,13 +569,7 @@ typedef struct { } RunStateTransition; static const RunStateTransition runstate_transitions_def[] = { - /* from -> to */ - { RUN_STATE_PRECONFIG, RUN_STATE_PRELAUNCH }, - /* Early switch to inmigrate state to allow -incoming CLI option work - * as it used to. TODO: delay actual switching to inmigrate state to - * the point after machine is built and remove this hack. - */ - { RUN_STATE_PRECONFIG, RUN_STATE_INMIGRATE }, + { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE }, { RUN_STATE_DEBUG, RUN_STATE_RUNNING }, { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE }, @@ -1471,9 +1465,6 @@ static bool main_loop_should_exit(void) ShutdownCause request; if (preconfig_exit_requested) { - if (runstate_check(RUN_STATE_PRECONFIG)) { - runstate_set(RUN_STATE_PRELAUNCH); - } preconfig_exit_requested = false; return true; } diff --git a/stubs/meson.build b/stubs/meson.build index 82b7ba60ab..cc56c83063 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -29,6 +29,7 @@ stub_ss.add(files('pci-bus.c')) stub_ss.add(files('pci-host-piix.c')) stub_ss.add(files('qemu-timer-notify-cb.c')) stub_ss.add(files('qmp_memory_device.c')) +stub_ss.add(files('qmp-command-available.c')) stub_ss.add(files('qtest.c')) stub_ss.add(files('ram-block.c')) stub_ss.add(files('ramfb.c')) diff --git a/stubs/qmp-command-available.c b/stubs/qmp-command-available.c new file mode 100644 index 0000000000..46540af7bf --- /dev/null +++ b/stubs/qmp-command-available.c @@ -0,0 +1,7 @@ +#include "qemu/osdep.h" +#include "qapi/qmp/dispatch.h" + +bool qmp_command_available(const QmpCommand *cmd, Error **errp) +{ + return true; +} diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c index eb1cd8abb8..11614bf63f 100644 --- a/tests/qtest/qmp-test.c +++ b/tests/qtest/qmp-test.c @@ -295,7 +295,7 @@ static void test_qmp_preconfig(void) rsp = qtest_qmp(qs, "{ 'execute': 'query-status' }"); ret = qdict_get_qdict(rsp, "return"); g_assert(ret); - g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "preconfig"); + g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "prelaunch"); qobject_unref(rsp); /* exit preconfig state */ From b4e1a342112e50e05b609e857f38c1f2b7aafdc4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 08:44:23 -0400 Subject: [PATCH 02/45] vl: remove separate preconfig main_loop Move post-preconfig initialization to the x-exit-preconfig. If preconfig is not requested, just exit preconfig mode immediately with the QMP command. As a result, the preconfig loop will run with accel_setup_post and os_setup_post restrictions (xen_restrict, chroot, etc.) already done. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- include/sysemu/runstate.h | 1 - monitor/qmp-cmds.c | 9 ---- softmmu/vl.c | 95 +++++++++++++++++---------------------- 3 files changed, 41 insertions(+), 64 deletions(-) diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h index f760094858..e557f470d4 100644 --- a/include/sysemu/runstate.h +++ b/include/sysemu/runstate.h @@ -41,7 +41,6 @@ typedef enum WakeupReason { QEMU_WAKEUP_REASON_OTHER, } WakeupReason; -void qemu_exit_preconfig_request(void); void qemu_system_reset_request(ShutdownCause reason); void qemu_system_suspend_request(void); void qemu_register_suspend_notifier(Notifier *notifier); diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 639a219294..d141aaa132 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -102,15 +102,6 @@ void qmp_system_powerdown(Error **errp) qemu_system_powerdown_request(); } -void qmp_x_exit_preconfig(Error **errp) -{ - if (qdev_hotplug) { - error_setg(errp, "The command is permitted only before machine initialization"); - return; - } - qemu_exit_preconfig_request(); -} - void qmp_cont(Error **errp) { BlockBackend *blk; diff --git a/softmmu/vl.c b/softmmu/vl.c index ab2210bc79..abbbb83e1a 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1151,7 +1151,6 @@ static pid_t shutdown_pid; static int powerdown_requested; static int debug_requested; static int suspend_requested; -static bool preconfig_exit_requested = true; static WakeupReason wakeup_reason; static NotifierList powerdown_notifiers = NOTIFIER_LIST_INITIALIZER(powerdown_notifiers); @@ -1238,11 +1237,6 @@ static int qemu_debug_requested(void) return r; } -void qemu_exit_preconfig_request(void) -{ - preconfig_exit_requested = true; -} - /* * Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE. */ @@ -1464,10 +1458,6 @@ static bool main_loop_should_exit(void) RunState r; ShutdownCause request; - if (preconfig_exit_requested) { - preconfig_exit_requested = false; - return true; - } if (qemu_debug_requested()) { vm_stop(RUN_STATE_DEBUG); } @@ -3283,6 +3273,43 @@ static void qemu_machine_creation_done(void) register_global_state(); } +void qmp_x_exit_preconfig(Error **errp) +{ + if (qdev_hotplug) { + error_setg(errp, "The command is permitted only before machine initialization"); + return; + } + + qemu_init_board(); + qemu_create_cli_devices(); + qemu_machine_creation_done(); + + if (loadvm) { + Error *local_err = NULL; + if (load_snapshot(loadvm, &local_err) < 0) { + error_report_err(local_err); + autostart = 0; + exit(1); + } + } + if (replay_mode != REPLAY_MODE_NONE) { + replay_vmstate_init(); + } + + if (incoming) { + Error *local_err = NULL; + if (strcmp(incoming, "defer") != 0) { + qmp_migrate_incoming(incoming, &local_err); + if (local_err) { + error_reportf_err(local_err, "-incoming %s: ", incoming); + exit(1); + } + } + } else if (autostart) { + qmp_cont(NULL); + } +} + void qemu_init(int argc, char **argv, char **envp) { QemuOpts *opts; @@ -3847,7 +3874,6 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_preconfig: - preconfig_exit_requested = false; preconfig_requested = true; break; case QEMU_OPTION_enable_kvm: @@ -4272,57 +4298,18 @@ void qemu_init(int argc, char **argv, char **envp) qemu_resolve_machine_memdev(); parse_numa_opts(current_machine); - if (preconfig_requested) { - qemu_init_displays(); - } - - /* do monitor/qmp handling at preconfig state if requested */ - qemu_main_loop(); - - qemu_init_board(); - - qemu_create_cli_devices(); - - /* initialize displays after all errors have been reported */ - if (!preconfig_requested) { - qemu_init_displays(); - } - qemu_machine_creation_done(); - - if (loadvm) { - Error *local_err = NULL; - if (load_snapshot(loadvm, &local_err) < 0) { - error_report_err(local_err); - autostart = 0; - exit(1); - } - } - if (replay_mode != REPLAY_MODE_NONE) { - replay_vmstate_init(); - } - if (vmstate_dump_file) { /* dump and exit */ dump_vmstate_json_to_file(vmstate_dump_file); exit(0); } - if (incoming) { - Error *local_err = NULL; - if (strcmp(incoming, "defer") != 0) { - qmp_migrate_incoming(incoming, &local_err); - if (local_err) { - error_reportf_err(local_err, "-incoming %s: ", incoming); - exit(1); - } - } - } else if (autostart) { - qmp_cont(NULL); - } + qemu_init_displays(); + if (!preconfig_requested) { + qmp_x_exit_preconfig(&error_fatal); + } accel_setup_post(current_machine); os_setup_post(); - - return; } void qemu_cleanup(void) From 8fafaa04c30d4d67d3d13fc4027cb57da5a2f162 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 09:15:53 -0400 Subject: [PATCH 03/45] vl: allow -incoming defer with -preconfig Now that there is no RUN_STATE_PRECONFIG anymore that can conflict with RUN_STATE_INMIGRATE, we can allow -incoming defer with -preconfig. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index abbbb83e1a..3dfac8299b 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2986,9 +2986,8 @@ static void qemu_validate_options(void) "mutually exclusive"); exit(EXIT_FAILURE); } - if (incoming && preconfig_requested) { - error_report("'preconfig' and 'incoming' options are " - "mutually exclusive"); + if (incoming && preconfig_requested && strcmp(incoming, "defer") != 0) { + error_report("'preconfig' supports '-incoming defer' only"); exit(EXIT_FAILURE); } From ba87e43481f2c9a7780f21aa22682573169f041d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 13 Nov 2020 03:25:19 -0500 Subject: [PATCH 04/45] vl: extract softmmu/runstate.c Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- 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 29c32f9851..0e7b405d22 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" + +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 : ""); + 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 3dfac8299b..6282ae2101 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" @@ -162,7 +161,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; @@ -189,9 +188,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; @@ -533,12 +529,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"); @@ -554,206 +544,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; @@ -1070,458 +860,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 : ""); - 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" @@ -2241,21 +1579,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; @@ -3101,39 +2424,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; @@ -4310,43 +3600,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 */ -} From c5e3c9182d0cc312196aa5e1de305e9ab5a7cda3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 08:04:08 -0400 Subject: [PATCH 05/45] vl: extract softmmu/globals.c Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 2 ++ include/exec/cpu-common.h | 3 ++ include/exec/exec-all.h | 3 -- softmmu/globals.c | 74 +++++++++++++++++++++++++++++++++++++++ softmmu/meson.build | 1 + softmmu/vl.c | 45 ++---------------------- 6 files changed, 83 insertions(+), 45 deletions(-) create mode 100644 softmmu/globals.c diff --git a/hw/core/machine.c b/hw/core/machine.c index d7f8fdee45..26cfd87b5c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -216,6 +216,8 @@ GlobalProperty hw_compat_2_1[] = { }; const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1); +MachineState *current_machine; + static char *machine_get_kernel(Object *obj, Error **errp) { MachineState *ms = MACHINE(obj); diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index bd5e15dd7d..5a0a2d93e0 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -105,4 +105,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length); #endif +/* vl.c */ +extern int singlestep; + #endif /* CPU_COMMON_H */ diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 94fe05daaa..fab573da06 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -676,7 +676,4 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu, MemoryRegionSection *section); #endif -/* vl.c */ -extern int singlestep; - #endif diff --git a/softmmu/globals.c b/softmmu/globals.c new file mode 100644 index 0000000000..e62d9cd8da --- /dev/null +++ b/softmmu/globals.c @@ -0,0 +1,74 @@ +/* + * Global variables that (mostly) should not exist + * + * 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 "exec/cpu-common.h" +#include "hw/display/vga.h" +#include "hw/i386/pc.h" +#include "hw/i386/x86.h" +#include "hw/loader.h" +#include "hw/xen/xen.h" +#include "net/net.h" +#include "sysemu/cpus.h" +#include "sysemu/sysemu.h" + +enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; +int display_opengl; +const char* keyboard_layout; +bool enable_mlock; +bool enable_cpu_pm; +int nb_nics; +NICInfo nd_table[MAX_NICS]; +int autostart = 1; +int vga_interface_type = VGA_NONE; +Chardev *parallel_hds[MAX_PARALLEL_PORTS]; +int win2k_install_hack; +int singlestep; +int fd_bootchk = 1; +int no_reboot; +int no_shutdown; +int graphic_rotate; +QEMUOptionRom option_rom[MAX_OPTION_ROMS]; +int nb_option_roms; +int old_param; +const char *qemu_name; +int alt_grab; +int ctrl_grab; +unsigned int nb_prom_envs; +const char *prom_envs[MAX_PROM_ENVS]; +int boot_menu; +bool boot_strict; +uint8_t *boot_splash_filedata; +int only_migratable; /* turn it off unless user states otherwise */ +int icount_align_option; + +/* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the + * little-endian "wire format" described in the SMBIOS 2.6 specification. + */ +QemuUUID qemu_uuid; +bool qemu_uuid_set; + +uint32_t xen_domid; +enum xen_mode xen_mode = XEN_EMULATE; +bool xen_domid_restrict; diff --git a/softmmu/meson.build b/softmmu/meson.build index 2a73ebc223..e5865b97cb 100644 --- a/softmmu/meson.build +++ b/softmmu/meson.build @@ -4,6 +4,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( 'cpus.c', 'cpu-throttle.c', 'datadir.c', + 'globals.c', 'physmem.c', 'ioport.c', 'rtc.c', diff --git a/softmmu/vl.c b/softmmu/vl.c index 6282ae2101..685d92df5d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -26,6 +26,7 @@ #include "qemu-common.h" #include "qemu/datadir.h" #include "qemu/units.h" +#include "exec/cpu-common.h" #include "hw/boards.h" #include "hw/qdev-properties.h" #include "qapi/error.h" @@ -67,6 +68,8 @@ #include "qemu/log.h" #include "sysemu/blockdev.h" #include "hw/block/block.h" +#include "hw/i386/x86.h" +#include "hw/i386/pc.h" #include "migration/misc.h" #include "migration/snapshot.h" #include "migration/global_state.h" @@ -139,17 +142,8 @@ static bool preconfig_requested; static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); static BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); static bool nographic = false; -enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; static int mem_prealloc; /* force preallocation of physical target memory */ -int display_opengl; -const char* keyboard_layout = NULL; static ram_addr_t ram_size; -bool enable_mlock = false; -bool enable_cpu_pm = false; -int nb_nics; -NICInfo nd_table[MAX_NICS]; -int autostart = 1; -int vga_interface_type = VGA_NONE; static const char *vga_model = NULL; static DisplayOptions dpy; static int num_serial_hds; @@ -157,41 +151,10 @@ static Chardev **serial_hds; static const char *log_mask; static const char *log_file; static bool list_data_dirs; -Chardev *parallel_hds[MAX_PARALLEL_PORTS]; -int win2k_install_hack = 0; -int singlestep = 0; -int fd_bootchk = 1; -int no_reboot; -int no_shutdown = 0; -int graphic_rotate = 0; static const char *watchdog; -QEMUOptionRom option_rom[MAX_OPTION_ROMS]; -int nb_option_roms; -int old_param = 0; -const char *qemu_name; -int alt_grab = 0; -int ctrl_grab = 0; -unsigned int nb_prom_envs = 0; -const char *prom_envs[MAX_PROM_ENVS]; -int boot_menu; -bool boot_strict; -uint8_t *boot_splash_filedata; -int only_migratable; /* turn it off unless user states otherwise */ -bool wakeup_suspend_enabled; -int icount_align_option; static const char *qtest_chrdev; static const char *qtest_log; -/* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the - * little-endian "wire format" described in the SMBIOS 2.6 specification. - */ -QemuUUID qemu_uuid; -bool qemu_uuid_set; - -uint32_t xen_domid; -enum xen_mode xen_mode = XEN_EMULATE; -bool xen_domid_restrict; - static int has_defaults = 1; static int default_serial = 1; static int default_parallel = 1; @@ -799,8 +762,6 @@ static int usb_parse(const char *cmdline) /***********************************************************/ /* machine registration */ -MachineState *current_machine; - static MachineClass *find_machine(const char *name, GSList *machines) { GSList *el; From f66dc8737c94a0ab57a252a280e5e83d6d630c67 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 13 Nov 2020 02:43:56 -0500 Subject: [PATCH 06/45] vl: move all generic initialization out of vl.c qdev_machine_creation_done is only setting a flag now. Extend it to move more code out of vl.c. Leave only consistency checks and gdbserver processing in qemu_machine_creation_done. gdbserver_start can be moved after qdev_machine_creation_done because it only does listen on the socket and creates some internal data structures; it does not send any data (e.g. guest state) over the socket. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 47 +++++++++++++++++++++++++++++++++++++++++- hw/core/qdev.c | 12 +++-------- include/hw/qdev-core.h | 1 + softmmu/vl.c | 37 +-------------------------------- 4 files changed, 51 insertions(+), 46 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 26cfd87b5c..036609d9f3 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -16,16 +16,21 @@ #include "sysemu/replay.h" #include "qemu/units.h" #include "hw/boards.h" +#include "hw/loader.h" #include "qapi/error.h" #include "qapi/qapi-visit-common.h" #include "qapi/visitor.h" #include "hw/sysbus.h" +#include "sysemu/cpus.h" #include "sysemu/sysemu.h" +#include "sysemu/reset.h" +#include "sysemu/runstate.h" #include "sysemu/numa.h" #include "qemu/error-report.h" #include "sysemu/qtest.h" #include "hw/pci/pci.h" #include "hw/mem/nvdimm.h" +#include "migration/global_state.h" #include "migration/vmstate.h" GlobalProperty hw_compat_5_2[] = {}; @@ -1189,10 +1194,50 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify) notifier_remove(notify); } -void qemu_run_machine_init_done_notifiers(void) +void qdev_machine_creation_done(void) { + cpu_synchronize_all_post_init(); + + if (current_machine->boot_once) { + qemu_boot_set(current_machine->boot_once, &error_fatal); + qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order)); + } + + /* + * ok, initial machine setup is done, starting from now we can + * only create hotpluggable devices + */ + qdev_hotplug = true; + qdev_assert_realized_properly(); + + /* TODO: once all bus devices are qdevified, this should be done + * when bus is created by qdev.c */ + /* + * TODO: If we had a main 'reset container' that the whole system + * lived in, we could reset that using the multi-phase reset + * APIs. For the moment, we just reset the sysbus, which will cause + * all devices hanging off it (and all their child buses, recursively) + * to be reset. Note that this will *not* reset any Device objects + * which are not attached to some part of the qbus tree! + */ + qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default()); + machine_init_done = true; notifier_list_notify(&machine_init_done_notifiers, NULL); + + if (rom_check_and_register_reset() != 0) { + error_report("rom check and register reset failed"); + exit(1); + } + + replay_start(); + + /* This checkpoint is required by replay to separate prior clock + reading from the other reads, because timer polling functions query + clock values from the log. */ + replay_checkpoint(CHECKPOINT_RESET); + qemu_system_reset(SHUTDOWN_CAUSE_NONE); + register_global_state(); } static const TypeInfo machine_info = { diff --git a/hw/core/qdev.c b/hw/core/qdev.c index d3611e7c03..dddb0b2d69 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -404,7 +404,7 @@ void qdev_unrealize(DeviceState *dev) object_property_set_bool(OBJECT(dev), "realized", false, &error_abort); } -static int qdev_assert_realized_properly(Object *obj, void *opaque) +static int qdev_assert_realized_properly_cb(Object *obj, void *opaque) { DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE)); DeviceClass *dc; @@ -417,16 +417,10 @@ static int qdev_assert_realized_properly(Object *obj, void *opaque) return 0; } -void qdev_machine_creation_done(void) +void qdev_assert_realized_properly(void) { - /* - * ok, initial machine setup is done, starting from now we can - * only create hotpluggable devices - */ - qdev_hotplug = true; - object_child_foreach_recursive(object_get_root(), - qdev_assert_realized_properly, NULL); + qdev_assert_realized_properly_cb, NULL); } bool qdev_machine_modified(void) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 8f91faebc3..3dab50cd87 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -780,6 +780,7 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev); const char *qdev_fw_name(DeviceState *dev); +void qdev_assert_realized_properly(void); Object *qdev_get_machine(void); /* FIXME: make this a link<> */ diff --git a/softmmu/vl.c b/softmmu/vl.c index 685d92df5d..d8af26c281 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -72,7 +72,6 @@ #include "hw/i386/pc.h" #include "migration/misc.h" #include "migration/snapshot.h" -#include "migration/global_state.h" #include "sysemu/tpm.h" #include "sysemu/dma.h" #include "hw/audio/soundhw.h" @@ -2465,8 +2464,6 @@ static void qemu_create_cli_devices(void) static void qemu_machine_creation_done(void) { - cpu_synchronize_all_post_init(); - /* Did we create any drives that we failed to create a device for? */ drive_check_orphaned(); @@ -2484,43 +2481,11 @@ static void qemu_machine_creation_done(void) qdev_prop_check_globals(); - if (current_machine->boot_once) { - qemu_boot_set(current_machine->boot_once, &error_fatal); - qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order)); - } + qdev_machine_creation_done(); if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { exit(1); } - - qdev_machine_creation_done(); - - /* TODO: once all bus devices are qdevified, this should be done - * when bus is created by qdev.c */ - /* - * TODO: If we had a main 'reset container' that the whole system - * lived in, we could reset that using the multi-phase reset - * APIs. For the moment, we just reset the sysbus, which will cause - * all devices hanging off it (and all their child buses, recursively) - * to be reset. Note that this will *not* reset any Device objects - * which are not attached to some part of the qbus tree! - */ - qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default()); - qemu_run_machine_init_done_notifiers(); - - if (rom_check_and_register_reset() != 0) { - error_report("rom check and register reset failed"); - exit(1); - } - - replay_start(); - - /* This checkpoint is required by replay to separate prior clock - reading from the other reads, because timer polling functions query - clock values from the log. */ - replay_checkpoint(CHECKPOINT_RESET); - qemu_system_reset(SHUTDOWN_CAUSE_NONE); - register_global_state(); } void qmp_x_exit_preconfig(Error **errp) From 5a1ee6077b89ee9a803aaf8d1c98004701f63684 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 30 Nov 2020 13:44:49 -0500 Subject: [PATCH 07/45] chardev: do not use machine_init_done machine_init_done is not the right flag to check when preconfig is taken into account; for example "./qemu-system-x86_64 -serial mon:stdio -preconfig" does not print the QEMU monitor header until after exit_preconfig. Add back a custom bool for mux character devices. This partially undoes commit c7278b4355 ("chardev: introduce chr_machine_done hook", 2018-03-12), but it keeps the cleaner logic using a function pointer in ChardevClass. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- chardev/char-mux.c | 38 ++++++++++++++++++--- chardev/chardev-sysemu.c | 69 --------------------------------------- chardev/meson.build | 2 +- hw/core/machine.c | 2 +- include/chardev/char.h | 6 ++-- include/sysemu/sysemu.h | 2 -- softmmu/vl.c | 3 ++ stubs/machine-init-done.c | 8 ----- stubs/meson.build | 1 - 9 files changed, 43 insertions(+), 88 deletions(-) delete mode 100644 chardev/chardev-sysemu.c delete mode 100644 stubs/machine-init-done.c diff --git a/chardev/char-mux.c b/chardev/char-mux.c index 6f980bb836..72beef29d2 100644 --- a/chardev/char-mux.c +++ b/chardev/char-mux.c @@ -33,6 +33,13 @@ /* MUX driver for serial I/O splitting */ +/* + * Set to false by suspend_mux_open. Open events are delayed until + * resume_mux_open. Usually suspend_mux_open is called before + * command line processing and resume_mux_open afterwards. + */ +static bool muxes_opened = true; + /* Called with chr_write_lock held. */ static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len) { @@ -237,7 +244,7 @@ void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) MuxChardev *d = MUX_CHARDEV(chr); int i; - if (!machine_init_done) { + if (!muxes_opened) { return; } @@ -328,7 +335,7 @@ static void qemu_chr_open_mux(Chardev *chr, /* only default to opened state if we've realized the initial * set of muxes */ - *be_opened = machine_init_done; + *be_opened = muxes_opened; qemu_chr_fe_init(&d->chr, drv, errp); } @@ -360,19 +367,42 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, * mux will receive CHR_EVENT_OPENED notifications for the BE * immediately. */ -static int open_muxes(Chardev *chr) +static void open_muxes(Chardev *chr) { /* send OPENED to all already-attached FEs */ mux_chr_send_all_event(chr, CHR_EVENT_OPENED); + /* * mark mux as OPENED so any new FEs will immediately receive * OPENED event */ chr->be_open = 1; +} + +void suspend_mux_open(void) +{ + muxes_opened = false; +} + +static int chardev_options_parsed_cb(Object *child, void *opaque) +{ + Chardev *chr = (Chardev *)child; + ChardevClass *class = CHARDEV_GET_CLASS(chr); + + if (!chr->be_open && class->chr_options_parsed) { + class->chr_options_parsed(chr); + } return 0; } +void resume_mux_open(void) +{ + muxes_opened = true; + object_child_foreach(get_chardevs_root(), + chardev_options_parsed_cb, NULL); +} + static void char_mux_class_init(ObjectClass *oc, void *data) { ChardevClass *cc = CHARDEV_CLASS(oc); @@ -383,7 +413,7 @@ static void char_mux_class_init(ObjectClass *oc, void *data) cc->chr_accept_input = mux_chr_accept_input; cc->chr_add_watch = mux_chr_add_watch; cc->chr_be_event = mux_chr_be_event; - cc->chr_machine_done = open_muxes; + cc->chr_options_parsed = open_muxes; cc->chr_update_read_handler = mux_chr_update_read_handlers; } diff --git a/chardev/chardev-sysemu.c b/chardev/chardev-sysemu.c deleted file mode 100644 index eecdc615ee..0000000000 --- a/chardev/chardev-sysemu.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * 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 "sysemu/sysemu.h" -#include "chardev/char.h" -#include "qemu/error-report.h" -#include "chardev-internal.h" - -static int chardev_machine_done_notify_one(Object *child, void *opaque) -{ - Chardev *chr = (Chardev *)child; - ChardevClass *class = CHARDEV_GET_CLASS(chr); - - if (class->chr_machine_done) { - return class->chr_machine_done(chr); - } - - return 0; -} - -static void chardev_machine_done_hook(Notifier *notifier, void *unused) -{ - int ret = object_child_foreach(get_chardevs_root(), - chardev_machine_done_notify_one, NULL); - - if (ret) { - error_report("Failed to call chardev machine_done hooks"); - exit(1); - } -} - - -static Notifier chardev_machine_done_notify = { - .notify = chardev_machine_done_hook, -}; - -static void register_types(void) -{ - /* - * This must be done after machine init, since we register FEs with muxes - * as part of realize functions like serial_isa_realizefn when -nographic - * is specified. - */ - qemu_add_machine_init_done_notifier(&chardev_machine_done_notify); -} - -type_init(register_types); diff --git a/chardev/meson.build b/chardev/meson.build index 859d8b04d4..4e19722c5e 100644 --- a/chardev/meson.build +++ b/chardev/meson.build @@ -25,7 +25,7 @@ chardev_ss.add(when: 'CONFIG_WIN32', if_true: files( chardev_ss = chardev_ss.apply(config_host, strict: false) -softmmu_ss.add(files('chardev-sysemu.c', 'msmouse.c', 'wctablet.c', 'testdev.c')) +softmmu_ss.add(files('msmouse.c', 'wctablet.c', 'testdev.c')) chardev_modules = {} diff --git a/hw/core/machine.c b/hw/core/machine.c index 036609d9f3..07268afe52 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1179,7 +1179,7 @@ void machine_run_board_init(MachineState *machine) static NotifierList machine_init_done_notifiers = NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); -bool machine_init_done; +static bool machine_init_done; void qemu_add_machine_init_done_notifier(Notifier *notify) { diff --git a/include/chardev/char.h b/include/chardev/char.h index db42f0a8c6..4181a2784a 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -270,8 +270,7 @@ struct ChardevClass { void (*chr_set_echo)(Chardev *chr, bool echo); void (*chr_set_fe_open)(Chardev *chr, int fe_open); void (*chr_be_event)(Chardev *s, QEMUChrEvent event); - /* Return 0 if succeeded, 1 if failed */ - int (*chr_machine_done)(Chardev *chr); + void (*chr_options_parsed)(Chardev *chr); }; Chardev *qemu_chardev_new(const char *id, const char *typename, @@ -283,6 +282,9 @@ extern int term_escape_char; GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms, GSourceFunc func, void *private); +void suspend_mux_open(void); +void resume_mux_open(void); + /* console.c */ void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 0e7b405d22..9b47cdca55 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -16,8 +16,6 @@ extern bool qemu_uuid_set; void qemu_add_exit_notifier(Notifier *notify); void qemu_remove_exit_notifier(Notifier *notify); -extern bool machine_init_done; - void qemu_run_machine_init_done_notifiers(void); void qemu_add_machine_init_done_notifier(Notifier *notify); void qemu_remove_machine_init_done_notifier(Notifier *notify); diff --git a/softmmu/vl.c b/softmmu/vl.c index d8af26c281..8e18c52f6e 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3462,6 +3462,8 @@ void qemu_init(int argc, char **argv, char **envp) qemu_create_machine(select_machine()); + suspend_mux_open(); + qemu_disable_default_devices(); qemu_create_default_devices(); qemu_create_early_backends(); @@ -3525,4 +3527,5 @@ void qemu_init(int argc, char **argv, char **envp) } accel_setup_post(current_machine); os_setup_post(); + resume_mux_open(); } diff --git a/stubs/machine-init-done.c b/stubs/machine-init-done.c deleted file mode 100644 index cd8e81392d..0000000000 --- a/stubs/machine-init-done.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "qemu/osdep.h" -#include "sysemu/sysemu.h" - -bool machine_init_done = true; - -void qemu_add_machine_init_done_notifier(Notifier *notify) -{ -} diff --git a/stubs/meson.build b/stubs/meson.build index cc56c83063..80b1d81a31 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -21,7 +21,6 @@ stub_ss.add(files('iothread-lock.c')) stub_ss.add(files('isa-bus.c')) stub_ss.add(files('is-daemonized.c')) stub_ss.add(when: 'CONFIG_LINUX_AIO', if_true: files('linux-aio.c')) -stub_ss.add(files('machine-init-done.c')) stub_ss.add(files('migr-blocker.c')) stub_ss.add(files('monitor.c')) stub_ss.add(files('monitor-core.c')) From 2f181fbd5a9d456d1da291bea61d7e3ad10ec7d1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 12 Nov 2020 09:38:36 -0500 Subject: [PATCH 08/45] machine: introduce MachineInitPhase Generalize the qdev_hotplug variable to the different phases of machine initialization. We would like to allow different monitor commands depending on the phase. Signed-off-by: Paolo Bonzini --- hw/core/machine-qmp-cmds.c | 6 +++--- hw/core/machine.c | 8 +++----- hw/core/qdev.c | 16 ++++++++++++++-- hw/pci/pci.c | 2 +- hw/usb/core.c | 2 +- hw/virtio/virtio-iommu.c | 2 +- include/hw/qdev-core.h | 32 +++++++++++++++++++++++++++++++- monitor/hmp.c | 2 +- softmmu/qdev-monitor.c | 24 +++++++++++++----------- softmmu/vl.c | 9 ++++----- ui/console.c | 2 +- 11 files changed, 73 insertions(+), 32 deletions(-) diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c index cb9387c5f5..87f14140a3 100644 --- a/hw/core/machine-qmp-cmds.c +++ b/hw/core/machine-qmp-cmds.c @@ -286,9 +286,9 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) void qmp_set_numa_node(NumaOptions *cmd, Error **errp) { - if (qdev_hotplug) { - error_setg(errp, "The command is permitted only before the machine has been created"); - return; + if (phase_check(PHASE_MACHINE_INITIALIZED)) { + error_setg(errp, "The command is permitted only before the machine has been created"); + return; } set_numa_options(MACHINE(qdev_get_machine()), cmd, errp); diff --git a/hw/core/machine.c b/hw/core/machine.c index 07268afe52..607eb88291 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1174,17 +1174,16 @@ void machine_run_board_init(MachineState *machine) } machine_class->init(machine); + phase_advance(PHASE_MACHINE_INITIALIZED); } static NotifierList machine_init_done_notifiers = NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); -static bool machine_init_done; - void qemu_add_machine_init_done_notifier(Notifier *notify) { notifier_list_add(&machine_init_done_notifiers, notify); - if (machine_init_done) { + if (phase_check(PHASE_MACHINE_READY)) { notify->notify(notify, NULL); } } @@ -1207,7 +1206,7 @@ void qdev_machine_creation_done(void) * ok, initial machine setup is done, starting from now we can * only create hotpluggable devices */ - qdev_hotplug = true; + phase_advance(PHASE_MACHINE_READY); qdev_assert_realized_properly(); /* TODO: once all bus devices are qdevified, this should be done @@ -1222,7 +1221,6 @@ void qdev_machine_creation_done(void) */ qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default()); - machine_init_done = true; notifier_list_notify(&machine_init_done_notifiers, NULL); if (rom_check_and_register_reset() != 0) { diff --git a/hw/core/qdev.c b/hw/core/qdev.c index dddb0b2d69..cefc5eaa0a 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -41,7 +41,6 @@ #include "migration/vmstate.h" #include "trace.h" -bool qdev_hotplug = false; static bool qdev_hot_added = false; bool qdev_hot_removed = false; @@ -905,7 +904,7 @@ static void device_initfn(Object *obj) { DeviceState *dev = DEVICE(obj); - if (qdev_hotplug) { + if (phase_check(PHASE_MACHINE_READY)) { dev->hotplugged = 1; qdev_hot_added = true; } @@ -1138,6 +1137,19 @@ Object *qdev_get_machine(void) return dev; } +static MachineInitPhase machine_phase; + +bool phase_check(MachineInitPhase phase) +{ + return machine_phase >= phase; +} + +void phase_advance(MachineInitPhase phase) +{ + assert(machine_phase == phase - 1); + machine_phase = phase; +} + static const TypeInfo device_type_info = { .name = TYPE_DEVICE, .parent = TYPE_OBJECT, diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 9424231542..d4349ea577 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1062,7 +1062,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_container_region, pci_dev->name); - if (qdev_hotplug) { + if (phase_check(PHASE_MACHINE_READY)) { pci_init_bus_master(pci_dev); } pci_dev->irq_state = 0; diff --git a/hw/usb/core.c b/hw/usb/core.c index 5234dcc73f..e960036f4d 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -97,7 +97,7 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream) USBDevice *dev = ep->dev; USBBus *bus = usb_bus_from_device(dev); - if (!qdev_hotplug) { + if (!phase_check(PHASE_MACHINE_READY)) { /* * This is machine init cold plug. No need to wakeup anyone, * all devices will be reset anyway. And trying to wakeup can diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index cea8811295..6b9ef7f6b2 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -930,7 +930,7 @@ static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr, * accept it. Having a different masks is possible but the guest will use * sub-optimal block sizes, so warn about it. */ - if (qdev_hotplug) { + if (phase_check(PHASE_MACHINE_READY)) { int new_granule = ctz64(new_mask); int cur_granule = ctz64(cur_mask); diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 3dab50cd87..bafc311bfa 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -786,7 +786,6 @@ Object *qdev_get_machine(void); /* FIXME: make this a link<> */ bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp); -extern bool qdev_hotplug; extern bool qdev_hot_removed; char *qdev_get_dev_path(DeviceState *dev); @@ -812,4 +811,35 @@ void device_listener_unregister(DeviceListener *listener); */ bool qdev_should_hide_device(QemuOpts *opts); +typedef enum MachineInitPhase { + /* current_machine is NULL. */ + PHASE_NO_MACHINE, + + /* current_machine is not NULL, but current_machine->accel is NULL. */ + PHASE_MACHINE_CREATED, + + /* + * current_machine->accel is not NULL, but the machine properties have + * not been validated and machine_class->init has not yet been called. + */ + PHASE_ACCEL_CREATED, + + /* + * machine_class->init has been called, thus creating any embedded + * devices and validating machine properties. Devices created at + * this time are considered to be cold-plugged. + */ + PHASE_MACHINE_INITIALIZED, + + /* + * QEMU is ready to start CPUs and devices created at this time + * are considered to be hot-plugged. The monitor is not restricted + * to "preconfig" commands. + */ + PHASE_MACHINE_READY, +} MachineInitPhase; + +extern bool phase_check(MachineInitPhase phase); +extern void phase_advance(MachineInitPhase phase); + #endif diff --git a/monitor/hmp.c b/monitor/hmp.c index f2fe192d69..6c0b33a0b1 100644 --- a/monitor/hmp.c +++ b/monitor/hmp.c @@ -216,7 +216,7 @@ static bool cmd_can_preconfig(const HMPCommand *cmd) static bool cmd_available(const HMPCommand *cmd) { - return qdev_hotplug || cmd_can_preconfig(cmd); + return phase_check(PHASE_MACHINE_READY) || cmd_can_preconfig(cmd); } static void help_cmd_dump_one(Monitor *mon, diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 3f1e67267d..2c57e36c9a 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -245,7 +245,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp) dc = DEVICE_CLASS(oc); if (!dc->user_creatable || - (qdev_hotplug && !dc->hotpluggable)) { + (phase_check(PHASE_MACHINE_READY) && !dc->hotpluggable)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver", "a pluggable device type"); return NULL; @@ -627,7 +627,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) } } - if (qdev_hotplug && bus && !qbus_is_hotpluggable(bus)) { + if (phase_check(PHASE_MACHINE_READY) && bus && !qbus_is_hotpluggable(bus)) { error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name); return NULL; } @@ -641,15 +641,17 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) dev = qdev_new(driver); /* Check whether the hotplug is allowed by the machine */ - if (qdev_hotplug && !qdev_hotplug_allowed(dev, errp)) { - goto err_del_dev; - } + if (phase_check(PHASE_MACHINE_READY)) { + if (!qdev_hotplug_allowed(dev, errp)) { + goto err_del_dev; + } - if (!bus && qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) { - /* No bus, no machine hotplug handler --> device is not hotpluggable */ - error_setg(errp, "Device '%s' can not be hotplugged on this machine", - driver); - goto err_del_dev; + if (!bus && !qdev_get_machine_hotplug_handler(dev)) { + /* No bus, no machine hotplug handler --> device is not hotpluggable */ + error_setg(errp, "Device '%s' can not be hotplugged on this machine", + driver); + goto err_del_dev; + } } qdev_set_id(dev, qemu_opts_id(opts)); @@ -987,7 +989,7 @@ int qemu_global_option(const char *str) bool qmp_command_available(const QmpCommand *cmd, Error **errp) { - if (!qdev_hotplug && + if (!phase_check(PHASE_MACHINE_READY) && !(cmd->options & QCO_ALLOW_PRECONFIG)) { error_setg(errp, "The command '%s' is permitted only after machine initialization has completed", cmd->name); diff --git a/softmmu/vl.c b/softmmu/vl.c index 8e18c52f6e..4fece1b9db 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2406,10 +2406,6 @@ static void qemu_init_displays(void) } } -/* - * Called after leaving preconfig state. From here on runstate is - * RUN_STATE_PRELAUNCH or RUN_STATE_INMIGRATE. - */ static void qemu_init_board(void) { MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); @@ -2424,6 +2420,7 @@ static void qemu_init_board(void) exit(1); } + /* From here on we enter MACHINE_PHASE_INITIALIZED. */ machine_run_board_init(current_machine); /* @@ -2490,7 +2487,7 @@ static void qemu_machine_creation_done(void) void qmp_x_exit_preconfig(Error **errp) { - if (qdev_hotplug) { + if (phase_check(PHASE_MACHINE_INITIALIZED)) { error_setg(errp, "The command is permitted only before machine initialization"); return; } @@ -3469,12 +3466,14 @@ void qemu_init(int argc, char **argv, char **envp) qemu_create_early_backends(); qemu_apply_machine_options(); + phase_advance(PHASE_MACHINE_CREATED); /* * Note: uses machine properties such as kernel-irqchip, must run * after machine_set_property(). */ configure_accelerators(argv[0]); + phase_advance(PHASE_ACCEL_CREATED); /* * Beware, QOM objects created before this point miss global and diff --git a/ui/console.c b/ui/console.c index 30e70be555..4db5b04cc2 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1345,7 +1345,7 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, if (QTAILQ_EMPTY(&consoles)) { s->index = 0; QTAILQ_INSERT_TAIL(&consoles, s, next); - } else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) { + } else if (console_type != GRAPHIC_CONSOLE || phase_check(PHASE_MACHINE_READY)) { QemuConsole *last = QTAILQ_LAST(&consoles); s->index = last->index + 1; QTAILQ_INSERT_TAIL(&consoles, s, next); From 55810e90cc9a5ca18289c25aa5c1e0e2dc77eadb Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 8 Dec 2020 11:46:06 -0500 Subject: [PATCH 09/45] ppc/spapr: cleanup -machine pseries,nvdimm=X handling Since NVDIMM support was introduced on pseries machine, it ignored machine's nvdimm=on|off option and effectively was always enabled on machines that support NVDIMM. Later on commit (28f5a716212 ppc/spapr_nvdimm: do not enable support with 'nvdimm=off') makes QEMU error out in case user explicitly set 'nvdimm=off' on CLI by peeking at machine_opts. However that's a workaround and leaves 'nvdimms_state->is_enabled' in inconsistent state (false) when it should be set true by default. Instead of using on machine_opts, set default to true for pseries machine in initfn time. If user sets manually 'nvdimm=off' it will overwrite default value to false and QEMU will error as expected without need to peek into machine_opts. That way pseries will have, nvdimm enabled by default and will honor user provided 'nvdimm=on|off'. Signed-off-by: Igor Mammedov Message-Id: <20201208164606.4109134-1-imammedo@redhat.com> Signed-off-by: Paolo Bonzini --- hw/ppc/spapr.c | 13 +++++++++++++ hw/ppc/spapr_nvdimm.c | 14 +------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index dee48a0043..489cefcb81 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3275,6 +3275,19 @@ static void spapr_instance_init(Object *obj) { SpaprMachineState *spapr = SPAPR_MACHINE(obj); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); + MachineState *ms = MACHINE(spapr); + MachineClass *mc = MACHINE_GET_CLASS(ms); + + /* + * NVDIMM support went live in 5.1 without considering that, in + * other archs, the user needs to enable NVDIMM support with the + * 'nvdimm' machine option and the default behavior is NVDIMM + * support disabled. It is too late to roll back to the standard + * behavior without breaking 5.1 guests. + */ + if (mc->nvdimm_supported) { + ms->nvdimms_state->is_enabled = true; + } spapr->htab_fd = -1; spapr->use_hotplug_event_source = true; diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c index 73ee006541..b46c36917c 100644 --- a/hw/ppc/spapr_nvdimm.c +++ b/hw/ppc/spapr_nvdimm.c @@ -27,10 +27,8 @@ #include "hw/ppc/spapr_nvdimm.h" #include "hw/mem/nvdimm.h" #include "qemu/nvdimm-utils.h" -#include "qemu/option.h" #include "hw/ppc/fdt.h" #include "qemu/range.h" -#include "sysemu/sysemu.h" #include "hw/ppc/spapr_numa.h" bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm, @@ -38,7 +36,6 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm, { const MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); const MachineState *ms = MACHINE(hotplug_dev); - const char *nvdimm_opt = qemu_opt_get(qemu_get_machine_opts(), "nvdimm"); g_autofree char *uuidstr = NULL; QemuUUID uuid; int ret; @@ -48,16 +45,7 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm, return false; } - /* - * NVDIMM support went live in 5.1 without considering that, in - * other archs, the user needs to enable NVDIMM support with the - * 'nvdimm' machine option and the default behavior is NVDIMM - * support disabled. It is too late to roll back to the standard - * behavior without breaking 5.1 guests. What we can do is to - * ensure that, if the user sets nvdimm=off, we error out - * regardless of being 5.1 or newer. - */ - if (!ms->nvdimms_state->is_enabled && nvdimm_opt) { + if (!ms->nvdimms_state->is_enabled) { error_setg(errp, "nvdimm device found but 'nvdimm=off' was set"); return false; } From f2ce39b4f067fe8b8de6104a2d8ac558d35c330b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 2 Nov 2020 09:44:36 -0500 Subject: [PATCH 10/45] vl: make qemu_get_machine_opts static Machine options can be retrieved as properties of the machine object. Encourage that by removing the "easy" accessor to machine options. Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 11 ++++------- hw/arm/boot.c | 2 +- hw/microblaze/boot.c | 9 ++++----- hw/nios2/boot.c | 9 ++++----- hw/ppc/e500.c | 5 ++--- hw/ppc/virtex_ml507.c | 2 +- hw/riscv/sifive_u.c | 6 ++---- hw/riscv/virt.c | 6 ++---- hw/xtensa/xtfpga.c | 9 ++++----- include/sysemu/sysemu.h | 2 -- softmmu/device_tree.c | 2 +- softmmu/vl.c | 2 +- 12 files changed, 26 insertions(+), 39 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index baaa54249d..666b9ab96c 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2013,7 +2013,6 @@ static int kvm_init(MachineState *ms) const KVMCapabilityInfo *missing_cap; int ret; int type = 0; - const char *kvm_type; uint64_t dirty_log_manual_caps; s = KVM_STATE(ms->accelerator); @@ -2069,13 +2068,11 @@ static int kvm_init(MachineState *ms) } s->as = g_new0(struct KVMAs, s->nr_as); - kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type"); - if (mc->kvm_type) { + if (object_property_find(OBJECT(current_machine), "kvm-type")) { + g_autofree char *kvm_type = object_property_get_str(OBJECT(current_machine), + "kvm-type", + &error_abort); type = mc->kvm_type(ms, kvm_type); - } else if (kvm_type) { - ret = -EINVAL; - fprintf(stderr, "Invalid argument kvm-type=%s\n", kvm_type); - goto err; } do { diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 4d9d47ba1c..e56c42ac22 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -1299,7 +1299,7 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info) info->kernel_filename = ms->kernel_filename; info->kernel_cmdline = ms->kernel_cmdline; info->initrd_filename = ms->initrd_filename; - info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); + info->dtb_filename = ms->dtb; info->dtb_limit = 0; /* Load the kernel. */ diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index 6715ba2ff9..caaba1aa4c 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -34,6 +34,7 @@ #include "sysemu/device_tree.h" #include "sysemu/reset.h" #include "sysemu/sysemu.h" +#include "hw/boards.h" #include "hw/loader.h" #include "elf.h" #include "qemu/cutils.h" @@ -116,16 +117,14 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, const char *dtb_filename, void (*machine_cpu_reset)(MicroBlazeCPU *)) { - QemuOpts *machine_opts; const char *kernel_filename; const char *kernel_cmdline; const char *dtb_arg; char *filename = NULL; - machine_opts = qemu_get_machine_opts(); - kernel_filename = qemu_opt_get(machine_opts, "kernel"); - kernel_cmdline = qemu_opt_get(machine_opts, "append"); - dtb_arg = qemu_opt_get(machine_opts, "dtb"); + kernel_filename = current_machine->kernel_filename; + kernel_cmdline = current_machine->kernel_cmdline; + dtb_arg = current_machine->dtb; /* default to pcbios dtb as passed by machine_init */ if (!dtb_arg && dtb_filename) { filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename); diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c index 95a8697906..d9969ac148 100644 --- a/hw/nios2/boot.c +++ b/hw/nios2/boot.c @@ -39,6 +39,7 @@ #include "sysemu/device_tree.h" #include "sysemu/reset.h" #include "sysemu/sysemu.h" +#include "hw/boards.h" #include "hw/loader.h" #include "elf.h" @@ -120,16 +121,14 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, const char *dtb_filename, void (*machine_cpu_reset)(Nios2CPU *)) { - QemuOpts *machine_opts; const char *kernel_filename; const char *kernel_cmdline; const char *dtb_arg; char *filename = NULL; - machine_opts = qemu_get_machine_opts(); - kernel_filename = qemu_opt_get(machine_opts, "kernel"); - kernel_cmdline = qemu_opt_get(machine_opts, "append"); - dtb_arg = qemu_opt_get(machine_opts, "dtb"); + kernel_filename = current_machine->kernel_filename; + kernel_cmdline = current_machine->kernel_cmdline; + dtb_arg = current_machine->dtb; /* default to pcbios dtb as passed by machine_init */ if (!dtb_arg) { filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename); diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 072e558c2d..c64b5d08bd 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -343,9 +343,8 @@ static int ppce500_load_device_tree(PPCE500MachineState *pms, pmc->pci_pio_base >> 32, pmc->pci_pio_base, 0x0, 0x10000, }; - QemuOpts *machine_opts = qemu_get_machine_opts(); - const char *dtb_file = qemu_opt_get(machine_opts, "dtb"); - const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); + const char *dtb_file = machine->dtb; + const char *toplevel_compat = machine->dt_compatible; if (dtb_file) { char *filename; diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 7f1bca928c..07fe49da0d 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -152,7 +152,7 @@ static int xilinx_load_device_tree(hwaddr addr, int r; const char *dtb_filename; - dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); + dtb_filename = current_machine->dtb; if (dtb_filename) { fdt = load_device_tree(dtb_filename, &fdt_size); if (!fdt) { diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 2f19a9cda2..e7f6dc5fb3 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -100,14 +100,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, int cpu; uint32_t *cells; char *nodename; - const char *dtb_filename; char ethclk_names[] = "pclk\0hclk"; uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1; uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle; - dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); - if (dtb_filename) { - fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size); + if (ms->dtb) { + fdt = s->fdt = load_device_tree(ms->dtb, &s->fdt_size); if (!fdt) { error_report("load_device_tree() failed"); exit(1); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 25cea7aa67..3cc18a76e7 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -181,7 +181,6 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, { void *fdt; int i, cpu, socket; - const char *dtb_filename; MachineState *mc = MACHINE(s); uint64_t addr, size; uint32_t *clint_cells, *plic_cells; @@ -195,9 +194,8 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2; hwaddr flashbase = virt_memmap[VIRT_FLASH].base; - dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); - if (dtb_filename) { - fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size); + if (mc->dtb) { + fdt = s->fdt = load_device_tree(mc->dtb, &s->fdt_size); if (!fdt) { error_report("load_device_tree() failed"); exit(1); diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index b1470b88e6..7be53f1895 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -233,11 +233,10 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine) qemu_irq *extints; DriveInfo *dinfo; PFlashCFI01 *flash = NULL; - QemuOpts *machine_opts = qemu_get_machine_opts(); - const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); - const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); - const char *dtb_filename = qemu_opt_get(machine_opts, "dtb"); - const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); + const char *kernel_filename = machine->kernel_filename; + const char *kernel_cmdline = machine->kernel_cmdline; + const char *dtb_filename = machine->dtb; + const char *initrd_filename = machine->initrd_filename; const unsigned system_io_size = 224 * MiB; uint32_t freq = 10000000; int n; diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 9b47cdca55..e8f463ff30 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -104,8 +104,6 @@ typedef void QEMUBootSetHandler(void *opaque, const char *boot_order, void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque); void qemu_boot_set(const char *boot_order, Error **errp); -QemuOpts *qemu_get_machine_opts(void); - bool defaults_enabled(void); void qemu_init(int argc, char **argv, char **envp); diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c index b335dae707..b9a3ddc518 100644 --- a/softmmu/device_tree.c +++ b/softmmu/device_tree.c @@ -526,7 +526,7 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) void qemu_fdt_dumpdtb(void *fdt, int size) { - const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb"); + const char *dumpdtb = current_machine->dumpdtb; if (dumpdtb) { /* Dump the dtb to a file and quit */ diff --git a/softmmu/vl.c b/softmmu/vl.c index 4fece1b9db..0f7222af31 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -481,7 +481,7 @@ static QemuOptsList qemu_fw_cfg_opts = { * * Returns: machine options (never null). */ -QemuOpts *qemu_get_machine_opts(void) +static QemuOpts *qemu_get_machine_opts(void) { return qemu_find_opts_singleton("machine"); } From 0572f558cbc45acdd13ae3548c06ce650641f292 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 04:58:26 -0400 Subject: [PATCH 11/45] plugin: propagate errors qemu_finish_machine_init currently can only exit QEMU if it fails. Prepare for giving it proper error propagation, and possibly for adding a plugin_add monitor command that calls an accelerator method. While at it, make all errors from plugin_load look the same. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- include/qemu/plugin.h | 4 ++-- linux-user/main.c | 4 +--- plugins/loader.c | 34 +++++++++++++++++----------------- softmmu/vl.c | 4 +--- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index ab790ad105..841deed79c 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -45,7 +45,7 @@ static inline void qemu_plugin_add_opts(void) } void qemu_plugin_opt_parse(const char *optarg, QemuPluginList *head); -int qemu_plugin_load_list(QemuPluginList *head); +int qemu_plugin_load_list(QemuPluginList *head, Error **errp); union qemu_plugin_cb_sig { qemu_plugin_simple_cb_t simple; @@ -199,7 +199,7 @@ static inline void qemu_plugin_opt_parse(const char *optarg, exit(1); } -static inline int qemu_plugin_load_list(QemuPluginList *head) +static inline int qemu_plugin_load_list(QemuPluginList *head, Error **errp) { return 0; } diff --git a/linux-user/main.c b/linux-user/main.c index 24d1eb73ad..750a01118f 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -671,9 +671,7 @@ int main(int argc, char **argv, char **envp) exit(1); } trace_init_file(); - if (qemu_plugin_load_list(&plugins)) { - exit(1); - } + qemu_plugin_load_list(&plugins, &error_fatal); /* Zero out regs */ memset(regs, 0, sizeof(struct target_pt_regs)); diff --git a/plugins/loader.c b/plugins/loader.c index 8ac5dbc20f..5cb9794fda 100644 --- a/plugins/loader.c +++ b/plugins/loader.c @@ -150,7 +150,7 @@ static uint64_t xorshift64star(uint64_t x) return x * UINT64_C(2685821657736338717); } -static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info) +static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info, Error **errp) { qemu_plugin_install_func_t install; struct qemu_plugin_ctx *ctx; @@ -163,37 +163,37 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info) ctx->handle = g_module_open(desc->path, G_MODULE_BIND_LOCAL); if (ctx->handle == NULL) { - error_report("%s: %s", __func__, g_module_error()); + error_setg(errp, "Could not load plugin %s: %s", desc->path, g_module_error()); goto err_dlopen; } if (!g_module_symbol(ctx->handle, "qemu_plugin_install", &sym)) { - error_report("%s: %s", __func__, g_module_error()); + error_setg(errp, "Could not load plugin %s: %s", desc->path, g_module_error()); goto err_symbol; } install = (qemu_plugin_install_func_t) sym; /* symbol was found; it could be NULL though */ if (install == NULL) { - error_report("%s: %s: qemu_plugin_install is NULL", - __func__, desc->path); + error_setg(errp, "Could not load plugin %s: qemu_plugin_install is NULL", + desc->path); goto err_symbol; } if (!g_module_symbol(ctx->handle, "qemu_plugin_version", &sym)) { - error_report("TCG plugin %s does not declare API version %s", - desc->path, g_module_error()); + error_setg(errp, "Could not load plugin %s: plugin does not declare API version %s", + desc->path, g_module_error()); goto err_symbol; } else { int version = *(int *)sym; if (version < QEMU_PLUGIN_MIN_VERSION) { - error_report("TCG plugin %s requires API version %d, but " - "this QEMU supports only a minimum version of %d", - desc->path, version, QEMU_PLUGIN_MIN_VERSION); + error_setg(errp, "Could not load plugin %s: plugin requires API version %d, but " + "this QEMU supports only a minimum version of %d", + desc->path, version, QEMU_PLUGIN_MIN_VERSION); goto err_symbol; } else if (version > QEMU_PLUGIN_VERSION) { - error_report("TCG plugin %s requires API version %d, but " - "this QEMU supports only up to version %d", - desc->path, version, QEMU_PLUGIN_VERSION); + error_setg(errp, "Could not load plugin %s: plugin requires API version %d, but " + "this QEMU supports only up to version %d", + desc->path, version, QEMU_PLUGIN_VERSION); goto err_symbol; } } @@ -220,8 +220,8 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info) rc = install(ctx->id, info, desc->argc, desc->argv); ctx->installing = false; if (rc) { - error_report("%s: qemu_plugin_install returned error code %d", - __func__, rc); + error_setg(errp, "Could not load plugin %s: qemu_plugin_install returned error code %d", + desc->path, rc); /* * we cannot rely on the plugin doing its own cleanup, so * call a full uninstall if the plugin did not yet call it. @@ -263,7 +263,7 @@ static void plugin_desc_free(struct qemu_plugin_desc *desc) * Note: the descriptor of each successfully installed plugin is removed * from the list given by @head. */ -int qemu_plugin_load_list(QemuPluginList *head) +int qemu_plugin_load_list(QemuPluginList *head, Error **errp) { struct qemu_plugin_desc *desc, *next; g_autofree qemu_info_t *info = g_new0(qemu_info_t, 1); @@ -283,7 +283,7 @@ int qemu_plugin_load_list(QemuPluginList *head) QTAILQ_FOREACH_SAFE(desc, head, entry, next) { int err; - err = plugin_load(desc, info); + err = plugin_load(desc, info, errp); if (err) { return err; } diff --git a/softmmu/vl.c b/softmmu/vl.c index 0f7222af31..553482ec02 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2416,9 +2416,7 @@ static void qemu_init_board(void) } /* process plugin before CPUs are created, but once -smp has been parsed */ - if (qemu_plugin_load_list(&plugin_list)) { - exit(1); - } + qemu_plugin_load_list(&plugin_list, &error_fatal); /* From here on we enter MACHINE_PHASE_INITIALIZED. */ machine_run_board_init(current_machine); From 0a2949e0be1d7320e4714b26ef60ac4d874dd64f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 03:52:01 -0400 Subject: [PATCH 12/45] memory: allow creating MemoryRegions before accelerators Compute the DIRTY_MEMORY_CODE bit in memory_region_get_dirty_log_mask instead of memory_region_init_*. This makes it possible to allocate memory backend objects at any time. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/memory.c | 12 ++++++------ softmmu/vl.c | 6 +----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index 22bacbbc78..333e1ed7b0 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1548,7 +1548,6 @@ void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr, mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->ram_block = qemu_ram_alloc(size, share, mr, &err); - mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; if (err) { mr->size = int128_zero(); object_unparent(OBJECT(mr)); @@ -1573,7 +1572,6 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr, mr->destructor = memory_region_destructor_ram; mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, mr, &err); - mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; if (err) { mr->size = int128_zero(); object_unparent(OBJECT(mr)); @@ -1598,7 +1596,6 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, mr->destructor = memory_region_destructor_ram; mr->align = align; mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, &err); - mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; if (err) { mr->size = int128_zero(); object_unparent(OBJECT(mr)); @@ -1622,7 +1619,6 @@ void memory_region_init_ram_from_fd(MemoryRegion *mr, mr->ram_block = qemu_ram_alloc_from_fd(size, mr, share ? RAM_SHARED : 0, fd, &err); - mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; if (err) { mr->size = int128_zero(); object_unparent(OBJECT(mr)); @@ -1641,7 +1637,6 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ assert(ptr != NULL); @@ -1661,7 +1656,7 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, mr->ops = &ram_device_mem_ops; mr->opaque = mr; mr->destructor = memory_region_destructor_ram; - mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ assert(ptr != NULL); mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); @@ -1819,6 +1814,11 @@ uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr) memory_region_is_iommu(mr))) { mask |= (1 << DIRTY_MEMORY_MIGRATION); } + + if (tcg_enabled() && rb) { + /* TCG only cares about dirty memory logging for RAM, not IOMMU. */ + mask |= (1 << DIRTY_MEMORY_CODE); + } return mask; } diff --git a/softmmu/vl.c b/softmmu/vl.c index 553482ec02..20db39b556 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1714,11 +1714,7 @@ static bool object_create_early(const char *type, QemuOpts *opts) return false; } - /* Memory allocation by backends needs to be done - * after configure_accelerator() (due to the tcg_enabled() - * checks at memory_region_init_*()). - * - * Also, allocation of large amounts of memory may delay + /* Allocation of large amounts of memory may delay * chardev initialization for too long, and trigger timeouts * on software that waits for a monitor socket to be created * (e.g. libvirt). From ebe3444468a4913e0208db1f74ea9336c7580202 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 06:56:32 -0400 Subject: [PATCH 13/45] monitor: allow quitting while in preconfig state Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hmp-commands.hx | 1 + qapi/control.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index dd460eb908..470a420c2d 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -45,6 +45,7 @@ ERST .params = "", .help = "quit the emulator", .cmd = hmp_quit, + .flags = "p", }, SRST diff --git a/qapi/control.json b/qapi/control.json index 9c8a51352d..2615d5170b 100644 --- a/qapi/control.json +++ b/qapi/control.json @@ -219,7 +219,8 @@ # -> { "execute": "quit" } # <- { "return": {} } ## -{ 'command': 'quit' } +{ 'command': 'quit', + 'allow-preconfig': true } ## # @MonitorMode: From e6dba0481363ad343c5f984dd4de3dd06d79ee68 Mon Sep 17 00:00:00 2001 From: Alejandro Jimenez Date: Fri, 11 Dec 2020 11:52:43 -0500 Subject: [PATCH 14/45] qmp: generalize watchdog-set-action to -no-reboot/-no-shutdown Add a QMP command to allow for the behaviors specified by the -no-reboot and -no-shutdown command line option to be set at runtime. The new command is named set-action and takes optional arguments, named after an event, that provide a corresponding action to take. Example: -> { "execute": "set-action", "arguments": { "reboot": "none", "shutdown": "poweroff", "watchdog": "debug" } } <- { "return": {} } Suggested-by: Paolo Bonzini Signed-off-by: Alejandro Jimenez Message-Id: <1607705564-26264-4-git-send-email-alejandro.j.jimenez@oracle.com> [Split the series differently, with -action based on the QMP command. - Paolo] Signed-off-by: Paolo Bonzini --- MAINTAINERS | 2 ++ include/sysemu/runstate-action.h | 18 ++++++++++ include/sysemu/sysemu.h | 2 -- monitor/qmp-cmds.c | 3 +- qapi/run-state.json | 58 ++++++++++++++++++++++++++++++++ softmmu/globals.c | 2 -- softmmu/meson.build | 1 + softmmu/runstate-action.c | 41 ++++++++++++++++++++++ softmmu/runstate.c | 10 +++--- softmmu/vl.c | 5 +-- ui/sdl2.c | 5 +-- 11 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 include/sysemu/runstate-action.h create mode 100644 softmmu/runstate-action.c diff --git a/MAINTAINERS b/MAINTAINERS index 138b4ed461..1d6ea877be 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2357,6 +2357,7 @@ M: Paolo Bonzini S: Maintained F: include/qemu/main-loop.h F: include/sysemu/runstate.h +F: include/sysemu/runstate-action.h F: util/main-loop.c F: util/qemu-timer.c F: softmmu/vl.c @@ -2365,6 +2366,7 @@ F: softmmu/cpus.c F: softmmu/cpu-throttle.c F: softmmu/cpu-timers.c F: softmmu/icount.c +F: softmmu/runstate-action.c F: qapi/run-state.json Read, Copy, Update (RCU) diff --git a/include/sysemu/runstate-action.h b/include/sysemu/runstate-action.h new file mode 100644 index 0000000000..51a461c4ac --- /dev/null +++ b/include/sysemu/runstate-action.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef RUNSTATE_ACTION_H +#define RUNSTATE_ACTION_H + +#include "qapi/qapi-commands-run-state.h" + +/* in softmmu/runstate-action.c */ +extern RebootAction reboot_action; +extern ShutdownAction shutdown_action; + +#endif /* RUNSTATE_ACTION_H */ diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index e8f463ff30..8fae667172 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -43,8 +43,6 @@ extern int win2k_install_hack; 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/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index d141aaa132..34f7e75b7b 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -26,6 +26,7 @@ #include "ui/vnc.h" #include "sysemu/kvm.h" #include "sysemu/runstate.h" +#include "sysemu/runstate-action.h" #include "sysemu/arch_init.h" #include "sysemu/blockdev.h" #include "sysemu/block-backend.h" @@ -72,7 +73,7 @@ UuidInfo *qmp_query_uuid(Error **errp) void qmp_quit(Error **errp) { - no_shutdown = 0; + shutdown_action = SHUTDOWN_ACTION_POWEROFF; qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT); } diff --git a/qapi/run-state.json b/qapi/run-state.json index a47c500f83..25e82d1be1 100644 --- a/qapi/run-state.json +++ b/qapi/run-state.json @@ -325,6 +325,34 @@ 'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none', 'inject-nmi' ] } +## +# @RebootAction: +# +# Possible QEMU actions upon guest reboot +# +# @none: Reset the VM +# +# @shutdown: Shutdown the VM and exit +# +# Since: 6.0 +## +{ 'enum': 'RebootAction', + 'data': [ 'none', 'shutdown' ] } + +## +# @ShutdownAction: +# +# Possible QEMU actions upon guest shutdown +# +# @poweroff: Shutdown the VM and exit +# +# @pause: pause the VM# +# +# Since: 6.0 +## +{ 'enum': 'ShutdownAction', + 'data': [ 'poweroff', 'pause' ] } + ## # @watchdog-set-action: # @@ -334,6 +362,36 @@ ## { 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} } +## +# @set-action: +# +# Set the actions that will be taken by the emulator in response to guest +# events. +# +# @reboot: @RebootAction action taken on guest reboot. +# +# @shutdown: @ShutdownAction action taken on guest shutdown. +# +# @watchdog: @WatchdogAction action taken when watchdog timer expires . +# +# Returns: Nothing on success. +# +# Since: 6.0 +# +# Example: +# +# -> { "execute": "set-action", +# "arguments": { "reboot": "shutdown", +# "shutdown" : "pause", +# "watchdog": "inject-nmi" } } +# <- { "return": {} } +## +{ 'command': 'set-action', + 'data': { '*reboot': 'RebootAction', + '*shutdown': 'ShutdownAction', + '*watchdog': 'WatchdogAction' }, + 'allow-preconfig': true } + ## # @GUEST_PANICKED: # diff --git a/softmmu/globals.c b/softmmu/globals.c index e62d9cd8da..7d0fc81183 100644 --- a/softmmu/globals.c +++ b/softmmu/globals.c @@ -46,8 +46,6 @@ Chardev *parallel_hds[MAX_PARALLEL_PORTS]; int win2k_install_hack; int singlestep; int fd_bootchk = 1; -int no_reboot; -int no_shutdown; int graphic_rotate; QEMUOptionRom option_rom[MAX_OPTION_ROMS]; int nb_option_roms; diff --git a/softmmu/meson.build b/softmmu/meson.build index e5865b97cb..2dab6c7eb6 100644 --- a/softmmu/meson.build +++ b/softmmu/meson.build @@ -14,6 +14,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( 'qtest.c', 'vl.c', 'cpu-timers.c', + 'runstate-action.c', )]) specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: [files( diff --git a/softmmu/runstate-action.c b/softmmu/runstate-action.c new file mode 100644 index 0000000000..44de01adaf --- /dev/null +++ b/softmmu/runstate-action.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "sysemu/runstate-action.h" +#include "sysemu/watchdog.h" +#include "qemu/config-file.h" +#include "qapi/error.h" +#include "qemu/option_int.h" + +RebootAction reboot_action = REBOOT_ACTION_NONE; +ShutdownAction shutdown_action = SHUTDOWN_ACTION_POWEROFF; + +/* + * Receives actions to be applied for specific guest events + * and sets the internal state as requested. + */ +void qmp_set_action(bool has_reboot, RebootAction reboot, + bool has_shutdown, ShutdownAction shutdown, + bool has_panic, PanicAction panic, + bool has_watchdog, WatchdogAction watchdog, + Error **errp) +{ + if (has_reboot) { + reboot_action = reboot; + } + + if (has_watchdog) { + qmp_watchdog_set_action(watchdog, errp); + } + + /* Process shutdown last, in case the panic action needs to be altered */ + if (has_shutdown) { + shutdown_action = shutdown; + } +} diff --git a/softmmu/runstate.c b/softmmu/runstate.c index 892f2f679f..bd0522ed9e 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -54,6 +54,7 @@ #include "sysemu/replay.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" +#include "sysemu/runstate-action.h" #include "sysemu/sysemu.h" #include "sysemu/tpm.h" #include "trace.h" @@ -471,7 +472,7 @@ void qemu_system_guest_panicked(GuestPanicInformation *info) qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, !!info, info); vm_stop(RUN_STATE_GUEST_PANICKED); - if (!no_shutdown) { + if (shutdown_action == SHUTDOWN_ACTION_POWEROFF) { qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF, !!info, info); qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC); @@ -512,7 +513,8 @@ void qemu_system_guest_crashloaded(GuestPanicInformation *info) void qemu_system_reset_request(ShutdownCause reason) { - if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) { + if (reboot_action == REBOOT_ACTION_SHUTDOWN && + reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) { shutdown_requested = reason; } else { reset_requested = reason; @@ -591,7 +593,7 @@ void qemu_system_killed(int signal, pid_t pid) { shutdown_signal = signal; shutdown_pid = pid; - no_shutdown = 0; + shutdown_action = SHUTDOWN_ACTION_POWEROFF; /* Cannot call qemu_system_shutdown_request directly because * we are in a signal handler. @@ -658,7 +660,7 @@ static bool main_loop_should_exit(void) if (request) { qemu_kill_report(); qemu_system_shutdown(request); - if (no_shutdown) { + if (shutdown_action == SHUTDOWN_ACTION_PAUSE) { vm_stop(RUN_STATE_SHUTDOWN); } else { return true; diff --git a/softmmu/vl.c b/softmmu/vl.c index 20db39b556..04d94da843 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -36,6 +36,7 @@ #include "qemu/uuid.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" +#include "sysemu/runstate-action.h" #include "sysemu/seccomp.h" #include "sysemu/tcg.h" #include "sysemu/xen.h" @@ -3154,10 +3155,10 @@ void qemu_init(int argc, char **argv, char **envp) qemu_opts_parse_noisily(olist, "hpet=off", false); break; case QEMU_OPTION_no_reboot: - no_reboot = 1; + reboot_action = REBOOT_ACTION_SHUTDOWN; break; case QEMU_OPTION_no_shutdown: - no_shutdown = 1; + shutdown_action = SHUTDOWN_ACTION_PAUSE; break; case QEMU_OPTION_show_cursor: warn_report("The -show-cursor option is deprecated. Please " diff --git a/ui/sdl2.c b/ui/sdl2.c index a578017268..5e49709283 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -30,6 +30,7 @@ #include "ui/input.h" #include "ui/sdl2.h" #include "sysemu/runstate.h" +#include "sysemu/runstate-action.h" #include "sysemu/sysemu.h" #include "ui/win32-kbd-hook.h" @@ -606,7 +607,7 @@ static void handle_windowevent(SDL_Event *ev) allow_close = false; } if (allow_close) { - no_shutdown = 0; + shutdown_action = SHUTDOWN_ACTION_POWEROFF; qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI); } } else { @@ -653,7 +654,7 @@ void sdl2_poll_events(struct sdl2_console *scon) allow_close = false; } if (allow_close) { - no_shutdown = 0; + shutdown_action = SHUTDOWN_ACTION_POWEROFF; qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI); } break; From 2a5ad60b5406daca3658f2a6735318615ee6a116 Mon Sep 17 00:00:00 2001 From: Alejandro Jimenez Date: Fri, 11 Dec 2020 11:52:41 -0500 Subject: [PATCH 15/45] vl: Add an -action option specifying response to guest events Several command line options currently in use are meant to modify the behavior of QEMU in response to certain guest events like: -no-reboot, -no-shutdown, -watchdog-action. These can be grouped into a single option of the form: -action event=action Which can be used to specify the existing options above in the following format: -action reboot=none|shutdown -action shutdown=poweroff|pause -action watchdog=reset|shutdown|poweroff|pause|debug|none|inject-nmi This is done in preparation for adding yet another option of this type, which modifies the QEMU behavior when a guest panic occurs. Suggested-by: Paolo Bonzini Signed-off-by: Alejandro Jimenez Message-Id: <1607705564-26264-2-git-send-email-alejandro.j.jimenez@oracle.com> [Use QemuOpts help support, invoke QMP command. - Paolo] Signed-off-by: Paolo Bonzini --- qemu-options.hx | 22 +++++++++++++++++++ softmmu/vl.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index ae8872d1d6..eb55cd0eea 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3894,6 +3894,28 @@ SRST changes to the disk image. ERST +DEF("action", HAS_ARG, QEMU_OPTION_action, + "-action reboot=none|shutdown\n" + " action when guest reboots [default=none]\n" + "-action shutdown=poweroff|pause\n" + " action when guest shuts down [default=poweroff]\n" + "-action watchdog=reset|shutdown|poweroff|inject-nmi|pause|debug|none\n" + " action when watchdog fires [default=reset]\n", + QEMU_ARCH_ALL) +SRST +``-action event=action`` + The action parameter serves to modify QEMU's default behavior when + certain guest events occur. It provides a generic method for specifying the + same behaviors that are modified by the ``-no-reboot`` and ``-no-shutdown`` + parameters. + + Examples: + + ``-action reboot=shutdown,shutdown=pause`` + ``-watchdog i6300esb -action watchdog=pause`` + +ERST + DEF("loadvm", HAS_ARG, QEMU_OPTION_loadvm, \ "-loadvm [tag|id]\n" \ " start right away with a saved state (loadvm in monitor)\n", diff --git a/softmmu/vl.c b/softmmu/vl.c index 04d94da843..6d1a7ebb08 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -30,6 +30,7 @@ #include "hw/boards.h" #include "hw/qdev-properties.h" #include "qapi/error.h" +#include "qapi/qmp/qdict.h" #include "qemu-version.h" #include "qemu/cutils.h" #include "qemu/help_option.h" @@ -477,6 +478,25 @@ static QemuOptsList qemu_fw_cfg_opts = { }, }; +static QemuOptsList qemu_action_opts = { + .name = "action", + .merge_lists = true, + .head = QTAILQ_HEAD_INITIALIZER(qemu_action_opts.head), + .desc = { + { + .name = "shutdown", + .type = QEMU_OPT_STRING, + },{ + .name = "reboot", + .type = QEMU_OPT_STRING, + },{ + .name = "watchdog", + .type = QEMU_OPT_STRING, + }, + { /* end of list */ } + }, +}; + /** * Get machine options * @@ -2298,6 +2318,26 @@ static void qemu_process_sugar_options(void) } } +/* -action processing */ + +/* + * Process all the -action parameters parsed from cmdline. + */ +static int process_runstate_actions(void *opaque, QemuOpts *opts, Error **errp) +{ + Error *local_err = NULL; + QDict *qdict = qemu_opts_to_qdict(opts, NULL); + QObject *ret = NULL; + qmp_marshal_set_action(qdict, &ret, &local_err); + qobject_unref(ret); + qobject_unref(qdict); + if (local_err) { + error_propagate(errp, local_err); + return 1; + } + return 0; +} + static void qemu_process_early_options(void) { #ifdef CONFIG_SECCOMP @@ -2310,6 +2350,11 @@ static void qemu_process_early_options(void) qemu_opts_foreach(qemu_find_opts("name"), parse_name, NULL, &error_fatal); + if (qemu_opts_foreach(qemu_find_opts("action"), + process_runstate_actions, NULL, &error_fatal)) { + exit(1); + } + #ifndef _WIN32 qemu_opts_foreach(qemu_find_opts("add-fd"), parse_add_fd, NULL, &error_fatal); @@ -2560,6 +2605,7 @@ void qemu_init(int argc, char **argv, char **envp) qemu_add_opts(&qemu_icount_opts); qemu_add_opts(&qemu_semihosting_config_opts); qemu_add_opts(&qemu_fw_cfg_opts); + qemu_add_opts(&qemu_action_opts); module_call_init(MODULE_INIT_OPTS); error_init(argv[0]); @@ -3010,6 +3056,12 @@ void qemu_init(int argc, char **argv, char **envp) } watchdog = optarg; break; + case QEMU_OPTION_action: + olist = qemu_find_opts("action"); + if (!qemu_opts_parse_noisily(olist, optarg, false)) { + exit(1); + } + break; case QEMU_OPTION_watchdog_action: if (select_watchdog_action(optarg) == -1) { error_report("unknown -watchdog-action parameter"); @@ -3155,10 +3207,12 @@ void qemu_init(int argc, char **argv, char **envp) qemu_opts_parse_noisily(olist, "hpet=off", false); break; case QEMU_OPTION_no_reboot: - reboot_action = REBOOT_ACTION_SHUTDOWN; + olist = qemu_find_opts("action"); + qemu_opts_parse_noisily(olist, "reboot=shutdown", false); break; case QEMU_OPTION_no_shutdown: - shutdown_action = SHUTDOWN_ACTION_PAUSE; + olist = qemu_find_opts("action"); + qemu_opts_parse_noisily(olist, "shutdown=pause", false); break; case QEMU_OPTION_show_cursor: warn_report("The -show-cursor option is deprecated. Please " From c753e8e72548493d2a110c0482c4a987a733b033 Mon Sep 17 00:00:00 2001 From: Alejandro Jimenez Date: Fri, 11 Dec 2020 17:31:52 -0500 Subject: [PATCH 16/45] vl: Add option to avoid stopping VM upon guest panic The current default action of pausing a guest after a panic event is received leaves the responsibility to resume guest execution to the management layer. The reasons for this behavior are discussed here: https://lore.kernel.org/qemu-devel/52148F88.5000509@redhat.com/ However, in instances like the case of older guests (Linux and Windows) using a pvpanic device but missing support for the PVPANIC_CRASHLOADED event, and Windows guests using the hv-crash enlightenment, it is desirable to allow the guests to continue running after sending a PVPANIC_PANICKED event. This allows such guests to proceed to capture a crash dump and automatically reboot without intervention of a management layer. Add an option to avoid stopping a VM after a panic event is received, by passing: -action panic=none in the command line arguments, or during runtime by using an upcoming QMP command. Suggested-by: Paolo Bonzini Signed-off-by: Alejandro Jimenez Message-Id: <1607705564-26264-3-git-send-email-alejandro.j.jimenez@oracle.com> [Do not fix panic action in the variable, instead modify -no-shutdown. - Paolo] Signed-off-by: Paolo Bonzini --- include/sysemu/runstate-action.h | 1 + qapi/run-state.json | 16 ++++++++++++++++ qemu-options.hx | 3 +++ softmmu/runstate-action.c | 5 +++++ softmmu/runstate.c | 18 ++++++++++++++---- softmmu/vl.c | 5 ++++- 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/include/sysemu/runstate-action.h b/include/sysemu/runstate-action.h index 51a461c4ac..cff45a047b 100644 --- a/include/sysemu/runstate-action.h +++ b/include/sysemu/runstate-action.h @@ -14,5 +14,6 @@ /* in softmmu/runstate-action.c */ extern RebootAction reboot_action; extern ShutdownAction shutdown_action; +extern PanicAction panic_action; #endif /* RUNSTATE_ACTION_H */ diff --git a/qapi/run-state.json b/qapi/run-state.json index 25e82d1be1..1f3b329f05 100644 --- a/qapi/run-state.json +++ b/qapi/run-state.json @@ -353,6 +353,18 @@ { 'enum': 'ShutdownAction', 'data': [ 'poweroff', 'pause' ] } +## +# @PanicAction: +# +# @none: Continue VM execution +# +# @pause: Pause the VM +# +# Since: 6.0 +## +{ 'enum': 'PanicAction', + 'data': [ 'poweroff', 'pause', 'none' ] } + ## # @watchdog-set-action: # @@ -372,6 +384,8 @@ # # @shutdown: @ShutdownAction action taken on guest shutdown. # +# @panic: @PanicAction action taken on guest panic. +# # @watchdog: @WatchdogAction action taken when watchdog timer expires . # # Returns: Nothing on success. @@ -383,12 +397,14 @@ # -> { "execute": "set-action", # "arguments": { "reboot": "shutdown", # "shutdown" : "pause", +# "panic": "pause", # "watchdog": "inject-nmi" } } # <- { "return": {} } ## { 'command': 'set-action', 'data': { '*reboot': 'RebootAction', '*shutdown': 'ShutdownAction', + '*panic': 'PanicAction', '*watchdog': 'WatchdogAction' }, 'allow-preconfig': true } diff --git a/qemu-options.hx b/qemu-options.hx index eb55cd0eea..94cdfcf32e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3899,6 +3899,8 @@ DEF("action", HAS_ARG, QEMU_OPTION_action, " action when guest reboots [default=none]\n" "-action shutdown=poweroff|pause\n" " action when guest shuts down [default=poweroff]\n" + "-action panic=poweroff|pause|none\n" + " action when guest panics [default=poweroff]\n" "-action watchdog=reset|shutdown|poweroff|inject-nmi|pause|debug|none\n" " action when watchdog fires [default=reset]\n", QEMU_ARCH_ALL) @@ -3911,6 +3913,7 @@ SRST Examples: + ``-action panic=none`` ``-action reboot=shutdown,shutdown=pause`` ``-watchdog i6300esb -action watchdog=pause`` diff --git a/softmmu/runstate-action.c b/softmmu/runstate-action.c index 44de01adaf..99ce880886 100644 --- a/softmmu/runstate-action.c +++ b/softmmu/runstate-action.c @@ -15,6 +15,7 @@ RebootAction reboot_action = REBOOT_ACTION_NONE; ShutdownAction shutdown_action = SHUTDOWN_ACTION_POWEROFF; +PanicAction panic_action = PANIC_ACTION_POWEROFF; /* * Receives actions to be applied for specific guest events @@ -30,6 +31,10 @@ void qmp_set_action(bool has_reboot, RebootAction reboot, reboot_action = reboot; } + if (has_panic) { + panic_action = panic; + } + if (has_watchdog) { qmp_watchdog_set_action(watchdog, errp); } diff --git a/softmmu/runstate.c b/softmmu/runstate.c index bd0522ed9e..636aab0add 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -469,13 +469,23 @@ void qemu_system_guest_panicked(GuestPanicInformation *info) 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 (shutdown_action == SHUTDOWN_ACTION_POWEROFF) { + /* + * TODO: Currently the available panic actions are: none, pause, and + * poweroff, but in principle debug and reset could be supported as well. + * Investigate any potential use cases for the unimplemented actions. + */ + if (panic_action == PANIC_ACTION_PAUSE) { + qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, + !!info, info); + vm_stop(RUN_STATE_GUEST_PANICKED); + } else if (panic_action == PANIC_ACTION_POWEROFF) { qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF, !!info, info); + vm_stop(RUN_STATE_GUEST_PANICKED); qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC); + } else { + qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_RUN, + !!info, info); } if (info) { diff --git a/softmmu/vl.c b/softmmu/vl.c index 6d1a7ebb08..3921a04f77 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -489,6 +489,9 @@ static QemuOptsList qemu_action_opts = { },{ .name = "reboot", .type = QEMU_OPT_STRING, + },{ + .name = "panic", + .type = QEMU_OPT_STRING, },{ .name = "watchdog", .type = QEMU_OPT_STRING, @@ -3212,7 +3215,7 @@ void qemu_init(int argc, char **argv, char **envp) break; case QEMU_OPTION_no_shutdown: olist = qemu_find_opts("action"); - qemu_opts_parse_noisily(olist, "shutdown=pause", false); + qemu_opts_parse_noisily(olist, "panic=pause,shutdown=pause", false); break; case QEMU_OPTION_show_cursor: warn_report("The -show-cursor option is deprecated. Please " From c9ca89a9079688b3832b0ad3d7baf6418320dc64 Mon Sep 17 00:00:00 2001 From: Alejandro Jimenez Date: Fri, 11 Dec 2020 11:52:44 -0500 Subject: [PATCH 17/45] qtest/pvpanic: Test panic option that allows VM to continue Test the scenario where the -action panic=none parameter is used to signal that the VM must continue executing after a guest panic occurs. Suggested-by: Paolo Bonzini Signed-off-by: Alejandro Jimenez Message-Id: <1607705564-26264-5-git-send-email-alejandro.j.jimenez@oracle.com> Signed-off-by: Paolo Bonzini --- tests/qtest/pvpanic-test.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/qtest/pvpanic-test.c b/tests/qtest/pvpanic-test.c index 016b32ebee..6dcad2db49 100644 --- a/tests/qtest/pvpanic-test.c +++ b/tests/qtest/pvpanic-test.c @@ -11,13 +11,36 @@ #include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" +static void test_panic_nopause(void) +{ + uint8_t val; + QDict *response, *data; + QTestState *qts; + + qts = qtest_init("-device pvpanic -action panic=none"); + + val = qtest_inb(qts, 0x505); + g_assert_cmpuint(val, ==, 3); + + qtest_outb(qts, 0x505, 0x1); + + response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED"); + g_assert(qdict_haskey(response, "data")); + data = qdict_get_qdict(response, "data"); + g_assert(qdict_haskey(data, "action")); + g_assert_cmpstr(qdict_get_str(data, "action"), ==, "run"); + qobject_unref(response); + + qtest_quit(qts); +} + static void test_panic(void) { uint8_t val; QDict *response, *data; QTestState *qts; - qts = qtest_init("-device pvpanic"); + qts = qtest_init("-device pvpanic -action panic=pause"); val = qtest_inb(qts, 0x505); g_assert_cmpuint(val, ==, 3); @@ -40,6 +63,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); qtest_add_func("/pvpanic/panic", test_panic); + qtest_add_func("/pvpanic/panic-nopause", test_panic_nopause); ret = g_test_run(); From 58cf0f86d4ab6b78d11850557c5335ecfd2d2696 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 1 Dec 2020 09:42:23 -0500 Subject: [PATCH 18/45] msix: assert that accesses are within bounds This makes the testcase from the next patch fail. Signed-off-by: Paolo Bonzini --- hw/pci/msix.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 67e34f34d6..36491ee52b 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -179,6 +179,7 @@ static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr, { PCIDevice *dev = opaque; + assert(addr + size <= dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE); return pci_get_long(dev->msix_table + addr); } @@ -189,6 +190,8 @@ static void msix_table_mmio_write(void *opaque, hwaddr addr, int vector = addr / PCI_MSIX_ENTRY_SIZE; bool was_masked; + assert(addr + size <= dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE); + was_masked = msix_is_masked(dev, vector); pci_set_long(dev->msix_table + addr, val); msix_handle_mask_update(dev, vector, was_masked); From 4bfb024bc76973d40a359476dc0291f46e435442 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 1 Dec 2020 09:29:56 -0500 Subject: [PATCH 19/45] memory: clamp cached translation in case it points to an MMIO region In using the address_space_translate_internal API, address_space_cache_init forgot one piece of advice that can be found in the code for address_space_translate_internal: /* MMIO registers can be expected to perform full-width accesses based only * on their address, without considering adjacent registers that could * decode to completely different MemoryRegions. When such registers * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO * regions overlap wildly. For this reason we cannot clamp the accesses * here. * * If the length is small (as is the case for address_space_ldl/stl), * everything works fine. If the incoming length is large, however, * the caller really has to do the clamping through memory_access_size. */ address_space_cache_init is exactly one such case where "the incoming length is large", therefore we need to clamp the resulting length---not to memory_access_size though, since we are not doing an access yet, but to the size of the resulting section. This ensures that subsequent accesses to the cached MemoryRegionSection will be in range. With this patch, the enclosed testcase notices that the used ring does not fit into the MSI-X table and prints a "qemu-system-x86_64: Cannot map used" error. Signed-off-by: Paolo Bonzini --- softmmu/physmem.c | 10 ++++++++ tests/qtest/fuzz-test.c | 51 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 3027747c03..2cd1de4a2c 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -3255,6 +3255,7 @@ int64_t address_space_cache_init(MemoryRegionCache *cache, AddressSpaceDispatch *d; hwaddr l; MemoryRegion *mr; + Int128 diff; assert(len > 0); @@ -3263,6 +3264,15 @@ int64_t address_space_cache_init(MemoryRegionCache *cache, d = flatview_to_dispatch(cache->fv); cache->mrs = *address_space_translate_internal(d, addr, &cache->xlat, &l, true); + /* + * cache->xlat is now relative to cache->mrs.mr, not to the section itself. + * Take that into account to compute how many bytes are there between + * cache->xlat and the end of the section. + */ + diff = int128_sub(cache->mrs.size, + int128_make64(cache->xlat - cache->mrs.offset_within_region)); + l = int128_get64(int128_min(diff, int128_make64(l))); + mr = cache->mrs.mr; memory_region_ref(mr); if (memory_access_is_direct(mr, is_write)) { diff --git a/tests/qtest/fuzz-test.c b/tests/qtest/fuzz-test.c index 87b72307a5..cdb1100a0b 100644 --- a/tests/qtest/fuzz-test.c +++ b/tests/qtest/fuzz-test.c @@ -48,6 +48,55 @@ static void test_lp1878642_pci_bus_get_irq_level_assert(void) qtest_quit(s); } +/* + * Here a MemoryRegionCache pointed to an MMIO region but had a + * larger size than the underlying region. + */ +static void test_mmio_oob_from_memory_region_cache(void) +{ + QTestState *s; + + s = qtest_init("-M pc-q35-5.2 -display none -m 512M " + "-device virtio-scsi,num_queues=8,addr=03.0 "); + + qtest_outl(s, 0xcf8, 0x80001811); + qtest_outb(s, 0xcfc, 0x6e); + qtest_outl(s, 0xcf8, 0x80001824); + qtest_outl(s, 0xcf8, 0x80001813); + qtest_outl(s, 0xcfc, 0xa080000); + qtest_outl(s, 0xcf8, 0x80001802); + qtest_outl(s, 0xcfc, 0x5a175a63); + qtest_outb(s, 0x6e08, 0x9e); + qtest_writeb(s, 0x9f003, 0xff); + qtest_writeb(s, 0x9f004, 0x01); + qtest_writeb(s, 0x9e012, 0x0e); + qtest_writeb(s, 0x9e01b, 0x0e); + qtest_writeb(s, 0x9f006, 0x01); + qtest_writeb(s, 0x9f008, 0x01); + qtest_writeb(s, 0x9f00a, 0x01); + qtest_writeb(s, 0x9f00c, 0x01); + qtest_writeb(s, 0x9f00e, 0x01); + qtest_writeb(s, 0x9f010, 0x01); + qtest_writeb(s, 0x9f012, 0x01); + qtest_writeb(s, 0x9f014, 0x01); + qtest_writeb(s, 0x9f016, 0x01); + qtest_writeb(s, 0x9f018, 0x01); + qtest_writeb(s, 0x9f01a, 0x01); + qtest_writeb(s, 0x9f01c, 0x01); + qtest_writeb(s, 0x9f01e, 0x01); + qtest_writeb(s, 0x9f020, 0x01); + qtest_writeb(s, 0x9f022, 0x01); + qtest_writeb(s, 0x9f024, 0x01); + qtest_writeb(s, 0x9f026, 0x01); + qtest_writeb(s, 0x9f028, 0x01); + qtest_writeb(s, 0x9f02a, 0x01); + qtest_writeb(s, 0x9f02c, 0x01); + qtest_writeb(s, 0x9f02e, 0x01); + qtest_writeb(s, 0x9f030, 0x01); + qtest_outb(s, 0x6e10, 0x00); + qtest_quit(s); +} + int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -59,6 +108,8 @@ int main(int argc, char **argv) test_lp1878263_megasas_zero_iov_cnt); qtest_add_func("fuzz/test_lp1878642_pci_bus_get_irq_level_assert", test_lp1878642_pci_bus_get_irq_level_assert); + qtest_add_func("fuzz/test_mmio_oob_from_memory_region_cache", + test_mmio_oob_from_memory_region_cache); } return g_test_run(); From e76f68d3cc931a6db6dcc8a4aa240d08656bc3f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 10 Dec 2020 16:58:05 +0100 Subject: [PATCH 20/45] accel/tcg: Remove deprecated '-tb-size' option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The '-tb-size' option (replaced by '-accel tcg,tb-size') is deprecated since 5.0 (commit fe174132478). Remove it. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201202112714.1223783-1-philmd@redhat.com> Reviewed-by: Ján Tomko Signed-off-by: Thomas Huth Message-Id: <20201210155808.233895-2-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- accel/tcg/translate-all.c | 2 +- docs/system/deprecated.rst | 12 +++++------- qemu-options.hx | 8 -------- softmmu/vl.c | 8 -------- 4 files changed, 6 insertions(+), 24 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 4572b4901f..b7d50a73d4 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2379,7 +2379,7 @@ void dump_exec_info(void) qemu_printf("Translation buffer state:\n"); /* * Report total code size including the padding and TB structs; - * otherwise users might think "-tb-size" is not honoured. + * otherwise users might think "-accel tcg,tb-size" is not honoured. * For avg host size we use the precise numbers from tb_tree_stats though. */ qemu_printf("gen code size %zu/%zu\n", diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index 09c8f380bc..0b22812434 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -100,13 +100,6 @@ QEMU 5.1 has three options: to the user to load all the images they need. 3. ``-bios `` - Tells QEMU to load the specified file as the firmwrae. -``-tb-size`` option (since 5.0) -''''''''''''''''''''''''''''''' - -QEMU 5.0 introduced an alternative syntax to specify the size of the translation -block cache, ``-accel tcg,tb-size=``. The new syntax deprecates the -previously available ``-tb-size`` option. - ``-show-cursor`` option (since 5.0) ''''''''''''''''''''''''''''''''''' @@ -516,6 +509,11 @@ for the ``id`` parameter, which should now be used instead. The ``-no-kvm`` argument was a synonym for setting ``-machine accel=tcg``. +``-tb-size`` option (removed in 6.0) +'''''''''''''''''''''''''''''''''''' + +QEMU 5.0 introduced an alternative syntax to specify the size of the translation +block cache, ``-accel tcg,tb-size=``. QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/qemu-options.hx b/qemu-options.hx index 94cdfcf32e..6f0098717d 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4111,14 +4111,6 @@ SRST Show cursor. ERST -DEF("tb-size", HAS_ARG, QEMU_OPTION_tb_size, \ - "-tb-size n set TB size\n", QEMU_ARCH_ALL) -SRST -``-tb-size n`` - Set TCG translation block cache size. Deprecated, use - '\ ``-accel tcg,tb-size=n``\ ' instead. -ERST - DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \ "-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]\n" \ "-incoming rdma:host:port[,ipv4][,ipv6]\n" \ diff --git a/softmmu/vl.c b/softmmu/vl.c index 3921a04f77..da9a0bdb94 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3286,14 +3286,6 @@ void qemu_init(int argc, char **argv, char **envp) exit(1); } break; - case QEMU_OPTION_tb_size: -#ifndef CONFIG_TCG - error_report("TCG is disabled"); - exit(1); -#endif - warn_report("The -tb-size option is deprecated, use -accel tcg,tb-size instead"); - object_register_sugar_prop(ACCEL_CLASS_NAME("tcg"), "tb-size", optarg); - break; case QEMU_OPTION_icount: icount_opts = qemu_opts_parse_noisily(qemu_find_opts("icount"), optarg, true); From 2c5060cd32bf8ec120de7579b39d14d773e5b4ea Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 10 Dec 2020 16:58:06 +0100 Subject: [PATCH 21/45] docs/system: Move the list of removed features to a separate file Otherwise there is a chance that new deprecated features get added to the list of removed features at the end of the file by accident. It's way less confusing if the removed features reside in a separate file. Signed-off-by: Thomas Huth Message-Id: <20201210155808.233895-3-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- docs/system/deprecated.rst | 232 ------------------------------- docs/system/index.rst | 1 + docs/system/removed-features.rst | 231 ++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+), 232 deletions(-) create mode 100644 docs/system/removed-features.rst diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index 0b22812434..b0d44a06cb 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -486,235 +486,3 @@ nanoMIPS ISA The ``nanoMIPS`` ISA has never been upstreamed to any compiler toolchain. As it is hard to generate binaries for it, declare it deprecated. - - -Recently removed features -========================= - -What follows is a record of recently removed, formerly deprecated -features that serves as a record for users who have encountered -trouble after a recent upgrade. - -System emulator command line arguments --------------------------------------- - -``-net ...,name=``\ *name* (removed in 5.1) -''''''''''''''''''''''''''''''''''''''''''' - -The ``name`` parameter of the ``-net`` option was a synonym -for the ``id`` parameter, which should now be used instead. - -``-no-kvm`` (removed in 5.2) -'''''''''''''''''''''''''''' - -The ``-no-kvm`` argument was a synonym for setting ``-machine accel=tcg``. - -``-tb-size`` option (removed in 6.0) -'''''''''''''''''''''''''''''''''''' - -QEMU 5.0 introduced an alternative syntax to specify the size of the translation -block cache, ``-accel tcg,tb-size=``. - -QEMU Machine Protocol (QMP) commands ------------------------------------- - -``block-dirty-bitmap-add`` "autoload" parameter (since 4.2.0) -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The "autoload" parameter has been ignored since 2.12.0. All bitmaps -are automatically loaded from qcow2 images. - -``cpu-add`` (removed in 5.2) -'''''''''''''''''''''''''''' - -Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See -documentation of ``query-hotpluggable-cpus`` for additional details. - -Human Monitor Protocol (HMP) commands -------------------------------------- - -The ``hub_id`` parameter of ``hostfwd_add`` / ``hostfwd_remove`` (removed in 5.0) -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The ``[hub_id name]`` parameter tuple of the 'hostfwd_add' and -'hostfwd_remove' HMP commands has been replaced by ``netdev_id``. - -``cpu-add`` (removed in 5.2) -'''''''''''''''''''''''''''' - -Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See -documentation of ``query-hotpluggable-cpus`` for additional details. - -Guest Emulator ISAs -------------------- - -RISC-V ISA privilege specification version 1.09.1 (removed in 5.1) -'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The RISC-V ISA privilege specification version 1.09.1 has been removed. -QEMU supports both the newer version 1.10.0 and the ratified version 1.11.0, these -should be used instead of the 1.09.1 version. - -System emulator CPUS --------------------- - -KVM guest support on 32-bit Arm hosts (removed in 5.2) -'''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The Linux kernel has dropped support for allowing 32-bit Arm systems -to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating -its support for this configuration and will remove it in a future version. -Running 32-bit guests on a 64-bit Arm host remains supported. - -RISC-V ISA Specific CPUs (removed in 5.1) -''''''''''''''''''''''''''''''''''''''''' - -The RISC-V cpus with the ISA version in the CPU name have been removed. The -four CPUs are: ``rv32gcsu-v1.9.1``, ``rv32gcsu-v1.10.0``, ``rv64gcsu-v1.9.1`` and -``rv64gcsu-v1.10.0``. Instead the version can be specified via the CPU ``priv_spec`` -option when using the ``rv32`` or ``rv64`` CPUs. - -RISC-V no MMU CPUs (removed in 5.1) -''''''''''''''''''''''''''''''''''' - -The RISC-V no MMU cpus have been removed. The two CPUs: ``rv32imacu-nommu`` and -``rv64imacu-nommu`` can no longer be used. Instead the MMU status can be specified -via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs. - -System emulator machines ------------------------- - -``spike_v1.9.1`` and ``spike_v1.10`` (removed in 5.1) -''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The version specific Spike machines have been removed in favour of the -generic ``spike`` machine. If you need to specify an older version of the RISC-V -spec you can use the ``-cpu rv64gcsu,priv_spec=v1.10.0`` command line argument. - -mips ``r4k`` platform (removed in 5.2) -'''''''''''''''''''''''''''''''''''''' - -This machine type was very old and unmaintained. Users should use the ``malta`` -machine type instead. - -Related binaries ----------------- - -``qemu-nbd --partition`` (removed in 5.0) -''''''''''''''''''''''''''''''''''''''''' - -The ``qemu-nbd --partition $digit`` code (also spelled ``-P``) -could only handle MBR partitions, and never correctly handled logical -partitions beyond partition 5. Exporting a partition can still be -done by utilizing the ``--image-opts`` option with a raw blockdev -using the ``offset`` and ``size`` parameters layered on top of -any other existing blockdev. For example, if partition 1 is 100MiB -long starting at 1MiB, the old command:: - - qemu-nbd -t -P 1 -f qcow2 file.qcow2 - -can be rewritten as:: - - qemu-nbd -t --image-opts driver=raw,offset=1M,size=100M,file.driver=qcow2,file.file.driver=file,file.file.filename=file.qcow2 - -``qemu-img convert -n -o`` (removed in 5.1) -''''''''''''''''''''''''''''''''''''''''''' - -All options specified in ``-o`` are image creation options, so -they are now rejected when used with ``-n`` to skip image creation. - - -``qemu-img create -b bad file $size`` (removed in 5.1) -'''''''''''''''''''''''''''''''''''''''''''''''''''''' - -When creating an image with a backing file that could not be opened, -``qemu-img create`` used to issue a warning about the failure but -proceed with the image creation if an explicit size was provided. -However, as the ``-u`` option exists for this purpose, it is safer to -enforce that any failure to open the backing image (including if the -backing file is missing or an incorrect format was specified) is an -error when ``-u`` is not used. - -Command line options --------------------- - -``-smp`` (invalid topologies) (removed 5.2) -''''''''''''''''''''''''''''''''''''''''''' - -CPU topology properties should describe whole machine topology including -possible CPUs. - -However, historically it was possible to start QEMU with an incorrect topology -where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, -which could lead to an incorrect topology enumeration by the guest. -Support for invalid topologies is removed, the user must ensure -topologies described with -smp include all possible cpus, i.e. -*sockets* * *cores* * *threads* = *maxcpus*. - -``-numa`` node (without memory specified) (removed 5.2) -''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -Splitting RAM by default between NUMA nodes had the same issues as ``mem`` -parameter with the difference that the role of the user plays QEMU using -implicit generic or board specific splitting rule. -Use ``memdev`` with *memory-backend-ram* backend or ``mem`` (if -it's supported by used machine type) to define mapping explicitly instead. -Users of existing VMs, wishing to preserve the same RAM distribution, should -configure it explicitly using ``-numa node,memdev`` options. Current RAM -distribution can be retrieved using HMP command ``info numa`` and if separate -memory devices (pc|nv-dimm) are present use ``info memory-device`` and subtract -device memory from output of ``info numa``. - -``-numa node,mem=``\ *size* (removed in 5.1) -'''''''''''''''''''''''''''''''''''''''''''' - -The parameter ``mem`` of ``-numa node`` was used to assign a part of -guest RAM to a NUMA node. But when using it, it's impossible to manage a specified -RAM chunk on the host side (like bind it to a host node, setting bind policy, ...), -so the guest ends up with the fake NUMA configuration with suboptiomal performance. -However since 2014 there is an alternative way to assign RAM to a NUMA node -using parameter ``memdev``, which does the same as ``mem`` and adds -means to actually manage node RAM on the host side. Use parameter ``memdev`` -with *memory-backend-ram* backend as replacement for parameter ``mem`` -to achieve the same fake NUMA effect or a properly configured -*memory-backend-file* backend to actually benefit from NUMA configuration. -New machine versions (since 5.1) will not accept the option but it will still -work with old machine types. User can check the QAPI schema to see if the legacy -option is supported by looking at MachineInfo::numa-mem-supported property. - -``-mem-path`` fallback to RAM (removed in 5.0) -'''''''''''''''''''''''''''''''''''''''''''''' - -If guest RAM allocation from file pointed by ``mem-path`` failed, -QEMU was falling back to allocating from RAM, which might have resulted -in unpredictable behavior since the backing file specified by the user -as ignored. Currently, users are responsible for making sure the backing storage -specified with ``-mem-path`` can actually provide the guest RAM configured with -``-m`` and QEMU fails to start up if RAM allocation is unsuccessful. - -``-smp`` (invalid topologies) (removed 5.2) -''''''''''''''''''''''''''''''''''''''''''' - -CPU topology properties should describe whole machine topology including -possible CPUs. - -However, historically it was possible to start QEMU with an incorrect topology -where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, -which could lead to an incorrect topology enumeration by the guest. -Support for invalid topologies is removed, the user must ensure -topologies described with -smp include all possible cpus, i.e. -*sockets* * *cores* * *threads* = *maxcpus*. - -``-machine enforce-config-section=on|off`` (removed 5.2) -'''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The ``enforce-config-section`` property was replaced by the -``-global migration.send-configuration={on|off}`` option. - -Block devices -------------- - -VXHS backend (removed in 5.1) -''''''''''''''''''''''''''''' - -The VXHS code does not compile since v2.12.0. It was removed in 5.1. diff --git a/docs/system/index.rst b/docs/system/index.rst index e5a35817a2..d40f72c92b 100644 --- a/docs/system/index.rst +++ b/docs/system/index.rst @@ -35,5 +35,6 @@ Contents: targets security deprecated + removed-features build-platforms license diff --git a/docs/system/removed-features.rst b/docs/system/removed-features.rst new file mode 100644 index 0000000000..8a974f7acd --- /dev/null +++ b/docs/system/removed-features.rst @@ -0,0 +1,231 @@ + +Removed features +================ + +What follows is a record of recently removed, formerly deprecated +features that serves as a record for users who have encountered +trouble after a recent upgrade. + +System emulator command line arguments +-------------------------------------- + +``-net ...,name=``\ *name* (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''''' + +The ``name`` parameter of the ``-net`` option was a synonym +for the ``id`` parameter, which should now be used instead. + +``-no-kvm`` (removed in 5.2) +'''''''''''''''''''''''''''' + +The ``-no-kvm`` argument was a synonym for setting ``-machine accel=tcg``. + +``-tb-size`` option (removed in 6.0) +'''''''''''''''''''''''''''''''''''' + +QEMU 5.0 introduced an alternative syntax to specify the size of the translation +block cache, ``-accel tcg,tb-size=``. + +QEMU Machine Protocol (QMP) commands +------------------------------------ + +``block-dirty-bitmap-add`` "autoload" parameter (removed in 4.2.0) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The "autoload" parameter has been ignored since 2.12.0. All bitmaps +are automatically loaded from qcow2 images. + +``cpu-add`` (removed in 5.2) +'''''''''''''''''''''''''''' + +Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See +documentation of ``query-hotpluggable-cpus`` for additional details. + +Human Monitor Protocol (HMP) commands +------------------------------------- + +The ``hub_id`` parameter of ``hostfwd_add`` / ``hostfwd_remove`` (removed in 5.0) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The ``[hub_id name]`` parameter tuple of the 'hostfwd_add' and +'hostfwd_remove' HMP commands has been replaced by ``netdev_id``. + +``cpu-add`` (removed in 5.2) +'''''''''''''''''''''''''''' + +Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See +documentation of ``query-hotpluggable-cpus`` for additional details. + +Guest Emulator ISAs +------------------- + +RISC-V ISA privilege specification version 1.09.1 (removed in 5.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The RISC-V ISA privilege specification version 1.09.1 has been removed. +QEMU supports both the newer version 1.10.0 and the ratified version 1.11.0, these +should be used instead of the 1.09.1 version. + +System emulator CPUS +-------------------- + +KVM guest support on 32-bit Arm hosts (removed in 5.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The Linux kernel has dropped support for allowing 32-bit Arm systems +to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating +its support for this configuration and will remove it in a future version. +Running 32-bit guests on a 64-bit Arm host remains supported. + +RISC-V ISA Specific CPUs (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''' + +The RISC-V cpus with the ISA version in the CPU name have been removed. The +four CPUs are: ``rv32gcsu-v1.9.1``, ``rv32gcsu-v1.10.0``, ``rv64gcsu-v1.9.1`` and +``rv64gcsu-v1.10.0``. Instead the version can be specified via the CPU ``priv_spec`` +option when using the ``rv32`` or ``rv64`` CPUs. + +RISC-V no MMU CPUs (removed in 5.1) +''''''''''''''''''''''''''''''''''' + +The RISC-V no MMU cpus have been removed. The two CPUs: ``rv32imacu-nommu`` and +``rv64imacu-nommu`` can no longer be used. Instead the MMU status can be specified +via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs. + +System emulator machines +------------------------ + +``spike_v1.9.1`` and ``spike_v1.10`` (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The version specific Spike machines have been removed in favour of the +generic ``spike`` machine. If you need to specify an older version of the RISC-V +spec you can use the ``-cpu rv64gcsu,priv_spec=v1.10.0`` command line argument. + +mips ``r4k`` platform (removed in 5.2) +'''''''''''''''''''''''''''''''''''''' + +This machine type was very old and unmaintained. Users should use the ``malta`` +machine type instead. + +Related binaries +---------------- + +``qemu-nbd --partition`` (removed in 5.0) +''''''''''''''''''''''''''''''''''''''''' + +The ``qemu-nbd --partition $digit`` code (also spelled ``-P``) +could only handle MBR partitions, and never correctly handled logical +partitions beyond partition 5. Exporting a partition can still be +done by utilizing the ``--image-opts`` option with a raw blockdev +using the ``offset`` and ``size`` parameters layered on top of +any other existing blockdev. For example, if partition 1 is 100MiB +long starting at 1MiB, the old command:: + + qemu-nbd -t -P 1 -f qcow2 file.qcow2 + +can be rewritten as:: + + qemu-nbd -t --image-opts driver=raw,offset=1M,size=100M,file.driver=qcow2,file.file.driver=file,file.file.filename=file.qcow2 + +``qemu-img convert -n -o`` (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''''' + +All options specified in ``-o`` are image creation options, so +they are now rejected when used with ``-n`` to skip image creation. + + +``qemu-img create -b bad file $size`` (removed in 5.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''' + +When creating an image with a backing file that could not be opened, +``qemu-img create`` used to issue a warning about the failure but +proceed with the image creation if an explicit size was provided. +However, as the ``-u`` option exists for this purpose, it is safer to +enforce that any failure to open the backing image (including if the +backing file is missing or an incorrect format was specified) is an +error when ``-u`` is not used. + +Command line options +-------------------- + +``-smp`` (invalid topologies) (removed 5.2) +''''''''''''''''''''''''''''''''''''''''''' + +CPU topology properties should describe whole machine topology including +possible CPUs. + +However, historically it was possible to start QEMU with an incorrect topology +where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, +which could lead to an incorrect topology enumeration by the guest. +Support for invalid topologies is removed, the user must ensure +topologies described with -smp include all possible cpus, i.e. +*sockets* * *cores* * *threads* = *maxcpus*. + +``-numa`` node (without memory specified) (removed 5.2) +''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Splitting RAM by default between NUMA nodes had the same issues as ``mem`` +parameter with the difference that the role of the user plays QEMU using +implicit generic or board specific splitting rule. +Use ``memdev`` with *memory-backend-ram* backend or ``mem`` (if +it's supported by used machine type) to define mapping explicitly instead. +Users of existing VMs, wishing to preserve the same RAM distribution, should +configure it explicitly using ``-numa node,memdev`` options. Current RAM +distribution can be retrieved using HMP command ``info numa`` and if separate +memory devices (pc|nv-dimm) are present use ``info memory-device`` and subtract +device memory from output of ``info numa``. + +``-numa node,mem=``\ *size* (removed in 5.1) +'''''''''''''''''''''''''''''''''''''''''''' + +The parameter ``mem`` of ``-numa node`` was used to assign a part of +guest RAM to a NUMA node. But when using it, it's impossible to manage a specified +RAM chunk on the host side (like bind it to a host node, setting bind policy, ...), +so the guest ends up with the fake NUMA configuration with suboptiomal performance. +However since 2014 there is an alternative way to assign RAM to a NUMA node +using parameter ``memdev``, which does the same as ``mem`` and adds +means to actually manage node RAM on the host side. Use parameter ``memdev`` +with *memory-backend-ram* backend as replacement for parameter ``mem`` +to achieve the same fake NUMA effect or a properly configured +*memory-backend-file* backend to actually benefit from NUMA configuration. +New machine versions (since 5.1) will not accept the option but it will still +work with old machine types. User can check the QAPI schema to see if the legacy +option is supported by looking at MachineInfo::numa-mem-supported property. + +``-mem-path`` fallback to RAM (removed in 5.0) +'''''''''''''''''''''''''''''''''''''''''''''' + +If guest RAM allocation from file pointed by ``mem-path`` failed, +QEMU was falling back to allocating from RAM, which might have resulted +in unpredictable behavior since the backing file specified by the user +as ignored. Currently, users are responsible for making sure the backing storage +specified with ``-mem-path`` can actually provide the guest RAM configured with +``-m`` and QEMU fails to start up if RAM allocation is unsuccessful. + +``-smp`` (invalid topologies) (removed 5.2) +''''''''''''''''''''''''''''''''''''''''''' + +CPU topology properties should describe whole machine topology including +possible CPUs. + +However, historically it was possible to start QEMU with an incorrect topology +where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, +which could lead to an incorrect topology enumeration by the guest. +Support for invalid topologies is removed, the user must ensure +topologies described with -smp include all possible cpus, i.e. +*sockets* * *cores* * *threads* = *maxcpus*. + +``-machine enforce-config-section=on|off`` (removed 5.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The ``enforce-config-section`` property was replaced by the +``-global migration.send-configuration={on|off}`` option. + +Block devices +------------- + +VXHS backend (removed in 5.1) +''''''''''''''''''''''''''''' + +The VXHS code did not compile since v2.12.0. It was removed in 5.1. From c8c9dc42b7ca84b6892b51e3daeb693a9efec7a4 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 10 Dec 2020 16:58:07 +0100 Subject: [PATCH 22/45] Remove the deprecated -realtime option It has been marked as deprecated since QEMU v4.2, replaced by the -overcommit option. Time to remove it now. Signed-off-by: Thomas Huth Message-Id: <20201210155808.233895-4-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- docs/system/deprecated.rst | 6 ------ docs/system/removed-features.rst | 6 ++++++ qemu-options.hx | 14 +------------- softmmu/vl.c | 29 +---------------------------- tests/migration/guestperf/engine.py | 2 +- 5 files changed, 9 insertions(+), 48 deletions(-) diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index b0d44a06cb..16810d1b85 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -75,12 +75,6 @@ The ``pretty=on|off`` switch has no effect for HMP monitors, but is silently ignored. Using the switch with HMP monitors will become an error in the future. -``-realtime`` (since 4.1) -''''''''''''''''''''''''' - -The ``-realtime mlock=on|off`` argument has been replaced by the -``-overcommit mem-lock=on|off`` argument. - RISC-V ``-bios`` (since 5.1) '''''''''''''''''''''''''''' diff --git a/docs/system/removed-features.rst b/docs/system/removed-features.rst index 8a974f7acd..58d4e3874c 100644 --- a/docs/system/removed-features.rst +++ b/docs/system/removed-features.rst @@ -20,6 +20,12 @@ for the ``id`` parameter, which should now be used instead. The ``-no-kvm`` argument was a synonym for setting ``-machine accel=tcg``. +``-realtime`` (removed in 6.0) +'''''''''''''''''''''''''''''' + +The ``-realtime mlock=on|off`` argument has been replaced by the +``-overcommit mem-lock=on|off`` argument. + ``-tb-size`` option (removed in 6.0) '''''''''''''''''''''''''''''''''''' diff --git a/qemu-options.hx b/qemu-options.hx index 6f0098717d..c85f73e300 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3713,17 +3713,6 @@ SRST Do not start CPU at startup (you must type 'c' in the monitor). ERST -DEF("realtime", HAS_ARG, QEMU_OPTION_realtime, - "-realtime [mlock=on|off]\n" - " run qemu with realtime features\n" - " mlock=on|off controls mlock support (default: on)\n", - QEMU_ARCH_ALL) -SRST -``-realtime mlock=on|off`` - Run qemu with realtime features. mlocking qemu and guest memory can - be enabled via ``mlock=on`` (enabled by default). -ERST - DEF("overcommit", HAS_ARG, QEMU_OPTION_overcommit, "-overcommit [mem-lock=on|off][cpu-pm=on|off]\n" " run qemu with overcommit hints\n" @@ -3739,8 +3728,7 @@ SRST Locking qemu and guest memory can be enabled via ``mem-lock=on`` (disabled by default). This works when host memory is not - overcommitted and reduces the worst-case latency for guest. This is - equivalent to ``realtime``. + overcommitted and reduces the worst-case latency for guest. Guest ability to manage power state of host cpus (increasing latency for other processes on the same host cpu, but decreasing latency for diff --git a/softmmu/vl.c b/softmmu/vl.c index da9a0bdb94..b3918d6a68 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -326,18 +326,6 @@ static QemuOptsList qemu_tpmdev_opts = { }, }; -static QemuOptsList qemu_realtime_opts = { - .name = "realtime", - .head = QTAILQ_HEAD_INITIALIZER(qemu_realtime_opts.head), - .desc = { - { - .name = "mlock", - .type = QEMU_OPT_BOOL, - }, - { /* end of list */ } - }, -}; - static QemuOptsList qemu_overcommit_opts = { .name = "overcommit", .head = QTAILQ_HEAD_INITIALIZER(qemu_overcommit_opts.head), @@ -2600,7 +2588,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_add_opts(&qemu_add_fd_opts); qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_tpmdev_opts); - qemu_add_opts(&qemu_realtime_opts); qemu_add_opts(&qemu_overcommit_opts); qemu_add_opts(&qemu_msg_opts); qemu_add_opts(&qemu_name_opts); @@ -3418,27 +3405,13 @@ void qemu_init(int argc, char **argv, char **envp) exit(1); } break; - case QEMU_OPTION_realtime: - warn_report("'-realtime mlock=...' is deprecated, please use " - "'-overcommit mem-lock=...' instead"); - opts = qemu_opts_parse_noisily(qemu_find_opts("realtime"), - optarg, false); - if (!opts) { - exit(1); - } - /* Don't override the -overcommit option if set */ - enable_mlock = enable_mlock || - qemu_opt_get_bool(opts, "mlock", true); - break; case QEMU_OPTION_overcommit: opts = qemu_opts_parse_noisily(qemu_find_opts("overcommit"), optarg, false); if (!opts) { exit(1); } - /* Don't override the -realtime option if set */ - enable_mlock = enable_mlock || - qemu_opt_get_bool(opts, "mem-lock", false); + enable_mlock = qemu_opt_get_bool(opts, "mem-lock", false); enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", false); break; case QEMU_OPTION_msg: diff --git a/tests/migration/guestperf/engine.py b/tests/migration/guestperf/engine.py index e2a214bdab..83bfc3b6bb 100644 --- a/tests/migration/guestperf/engine.py +++ b/tests/migration/guestperf/engine.py @@ -304,7 +304,7 @@ class Engine(object): argv_source += ["-mem-path", "/dev/shm", "-mem-prealloc"] if hardware._locked_pages: - argv_source += ["-realtime", "mlock=on"] + argv_source += ["-overcommit", "mem-lock=on"] if hardware._huge_pages: pass From 90d6a086bb220bcd8b2ba3c881ac53862caa4987 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 10 Dec 2020 16:58:08 +0100 Subject: [PATCH 23/45] Remove the deprecated -show-cursor option It has been marked as deprecated since QEMU v5.0, replaced by the corresponding parameter of the -display option. Signed-off-by: Thomas Huth Message-Id: <20201210155808.233895-5-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- docs/system/deprecated.rst | 6 ------ docs/system/removed-features.rst | 6 ++++++ qemu-options.hx | 7 ------- softmmu/vl.c | 8 -------- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index 16810d1b85..bacd76d7a5 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -94,12 +94,6 @@ QEMU 5.1 has three options: to the user to load all the images they need. 3. ``-bios `` - Tells QEMU to load the specified file as the firmwrae. -``-show-cursor`` option (since 5.0) -''''''''''''''''''''''''''''''''''' - -Use ``-display sdl,show-cursor=on`` or - ``-display gtk,show-cursor=on`` instead. - ``Configuring floppies with ``-global`` ''''''''''''''''''''''''''''''''''''''' diff --git a/docs/system/removed-features.rst b/docs/system/removed-features.rst index 58d4e3874c..8b20d78a4d 100644 --- a/docs/system/removed-features.rst +++ b/docs/system/removed-features.rst @@ -26,6 +26,12 @@ The ``-no-kvm`` argument was a synonym for setting ``-machine accel=tcg``. The ``-realtime mlock=on|off`` argument has been replaced by the ``-overcommit mem-lock=on|off`` argument. +``-show-cursor`` option (since 5.0) +''''''''''''''''''''''''''''''''''' + +Use ``-display sdl,show-cursor=on``, ``-display gtk,show-cursor=on`` +or ``-display default,show-cursor=on`` instead. + ``-tb-size`` option (removed in 6.0) '''''''''''''''''''''''''''''''''''' diff --git a/qemu-options.hx b/qemu-options.hx index c85f73e300..459c916d3d 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4092,13 +4092,6 @@ SRST ERST -DEF("show-cursor", 0, QEMU_OPTION_show_cursor, \ - "-show-cursor show cursor\n", QEMU_ARCH_ALL) -SRST -``-show-cursor`` - Show cursor. -ERST - DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \ "-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]\n" \ "-incoming rdma:host:port[,ipv4][,ipv6]\n" \ diff --git a/softmmu/vl.c b/softmmu/vl.c index b3918d6a68..c56e6dc0b3 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3204,14 +3204,6 @@ void qemu_init(int argc, char **argv, char **envp) olist = qemu_find_opts("action"); qemu_opts_parse_noisily(olist, "panic=pause,shutdown=pause", false); break; - case QEMU_OPTION_show_cursor: - warn_report("The -show-cursor option is deprecated. Please " - "add show-cursor=on to your -display options."); - warn_report("When using the default display you can use " - "-display default,show-cursor=on"); - dpy.has_show_cursor = true; - dpy.show_cursor = true; - break; case QEMU_OPTION_uuid: if (qemu_uuid_parse(optarg, &qemu_uuid) < 0) { error_report("failed to parse UUID string: wrong format"); From 835cbd8d44b62217b8774b39e1bfd314750c2c51 Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Tue, 8 Dec 2020 12:10:58 +0300 Subject: [PATCH 24/45] icount: improve exec nocache usage cpu-exec tries to execute TB without caching when current icount budget is over. But sometimes refilled budget is big enough to try executing cached blocks. This patch checks that instruction budget is big enough for next block execution instead of just running cpu_exec_nocache. It halves the number of calls of cpu_exec_nocache function during tested OS boot scenario. Signed-off-by: Pavel Dovgalyuk Message-Id: <160741865825.348476.7169239332367828943.stgit@pasha-ThinkPad-X280> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- accel/tcg/cpu-exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 58aea605d8..251b340fb9 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -685,7 +685,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, insns_left = MIN(0xffff, cpu->icount_budget); cpu_neg(cpu)->icount_decr.u16.low = insns_left; cpu->icount_extra = cpu->icount_budget - insns_left; - if (!cpu->icount_extra) { + if (!cpu->icount_extra && insns_left < tb->icount) { /* Execute any remaining instructions, then let the main loop * handle the next event. */ From cfd4e36352d4426221aa94da44a172da1aaa741b Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Thu, 10 Dec 2020 14:59:29 +0200 Subject: [PATCH 25/45] scsi: fix device removal race vs IO restart callback on resume There is (mostly theoretical) race between removal of a scsi device and scsi_dma_restart_bh. It used to be easier to hit this race prior to my / Paulo's patch series that added rcu to scsi bus device handling code, but IMHO this race should still be possible to hit, at least in theory. Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1854811 Fix it anyway with a patch that was proposed by Paulo in the above bugzilla. Suggested-by: Paolo Bonzini Signed-off-by: Maxim Levitsky Message-Id: <20201210125929.1136390-2-mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-bus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index b901e701f0..edb5c3492a 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -170,6 +170,8 @@ static void scsi_dma_restart_bh(void *opaque) scsi_req_unref(req); } aio_context_release(blk_get_aio_context(s->conf.blk)); + /* Drop the reference that was acquired in scsi_dma_restart_cb */ + object_unref(OBJECT(s)); } void scsi_req_retry(SCSIRequest *req) @@ -188,6 +190,8 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state) } if (!s->bh) { AioContext *ctx = blk_get_aio_context(s->conf.blk); + /* The reference is dropped in scsi_dma_restart_bh.*/ + object_ref(OBJECT(s)); s->bh = aio_bh_new(ctx, scsi_dma_restart_bh, s); qemu_bh_schedule(s->bh); } From 4054adbdd2f66d78f73cdce0092eb5513b3b3521 Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Tue, 8 Dec 2020 19:40:13 +0800 Subject: [PATCH 26/45] kvm: Take into account the unaligned section size when preparing bitmap The kernel KVM_CLEAR_DIRTY_LOG interface has align requirement on both the start and the size of the given range of pages. We have been careful to handle the unaligned cases when performing CLEAR on one slot. But it seems that we forget to take the unaligned *size* case into account when preparing bitmap for the interface, and we may end up clearing dirty status for pages outside of [start, start + size). If the size is unaligned, let's go through the slow path to manipulate a temp bitmap for the interface so that we won't bother with those unaligned bits at the end of bitmap. I don't think this can happen in practice since the upper layer would provide us with the alignment guarantee. I'm not sure if kvm-all could rely on it. And this patch is mainly intended to address correctness of the specific algorithm used inside kvm_log_clear_one_slot(). Signed-off-by: Zenghui Yu Message-Id: <20201208114013.875-1-yuzenghui@huawei.com> Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 666b9ab96c..389eaace72 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -745,7 +745,7 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start, assert(bmap_start % BITS_PER_LONG == 0); /* We should never do log_clear before log_sync */ assert(mem->dirty_bmap); - if (start_delta) { + if (start_delta || bmap_npages - size / psize) { /* Slow path - we need to manipulate a temp bitmap */ bmap_clear = bitmap_new(bmap_npages); bitmap_copy_with_src_offset(bmap_clear, mem->dirty_bmap, @@ -758,7 +758,10 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start, bitmap_clear(bmap_clear, 0, start_delta); d.dirty_bitmap = bmap_clear; } else { - /* Fast path - start address aligns well with BITS_PER_LONG */ + /* + * Fast path - both start and size align well with BITS_PER_LONG + * (or the end of memory slot) + */ d.dirty_bitmap = mem->dirty_bmap + BIT_WORD(bmap_start); } From 924e9b0da90ca1fa0de7c5076768a8a9f3795f8d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 8 Nov 2020 10:21:21 -0500 Subject: [PATCH 27/45] qemu-option: simplify search for end of key Use strcspn to find an equal or comma value, and pass the result directly to get_opt_name to avoid another strchr. Reviewed-by: Markus Armbruster Signed-off-by: Paolo Bonzini --- util/qemu-option.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/util/qemu-option.c b/util/qemu-option.c index 25792159ba..6bd654a473 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -38,27 +38,19 @@ #include "qemu/help_option.h" /* - * Extracts the name of an option from the parameter string (p points at the + * Extracts the name of an option from the parameter string (@p points at the * first byte of the option name) * - * The option name is delimited by delim (usually , or =) or the string end - * and is copied into option. The caller is responsible for free'ing option - * when no longer required. + * The option name is @len characters long and is copied into @option. The + * caller is responsible for free'ing @option when no longer required. * * The return value is the position of the delimiter/zero byte after the option - * name in p. + * name in @p. */ -static const char *get_opt_name(const char *p, char **option, char delim) +static const char *get_opt_name(const char *p, char **option, size_t len) { - char *offset = strchr(p, delim); - - if (offset) { - *option = g_strndup(p, offset - p); - return offset; - } else { - *option = g_strdup(p); - return p + strlen(p); - } + *option = g_strndup(p, len); + return p + len; } /* @@ -766,12 +758,11 @@ static const char *get_opt_name_value(const char *params, const char *firstname, char **name, char **value) { - const char *p, *pe, *pc; + const char *p; + size_t len; - pe = strchr(params, '='); - pc = strchr(params, ','); - - if (!pe || (pc && pc < pe)) { + len = strcspn(params, "=,"); + if (params[len] != '=') { /* found "foo,more" */ if (firstname) { /* implicitly named first option */ @@ -779,7 +770,7 @@ static const char *get_opt_name_value(const char *params, p = get_opt_value(params, value); } else { /* option without value, must be a flag */ - p = get_opt_name(params, name, ','); + p = get_opt_name(params, name, len); if (strncmp(*name, "no", 2) == 0) { memmove(*name, *name + 2, strlen(*name + 2) + 1); *value = g_strdup("off"); @@ -789,7 +780,7 @@ static const char *get_opt_name_value(const char *params, } } else { /* found "foo=bar,more" */ - p = get_opt_name(params, name, '='); + p = get_opt_name(params, name, len); assert(*p == '='); p++; p = get_opt_value(p, value); From 45c53fe64c28239b7504d00d76fe37ef31c0eefa Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 9 Nov 2020 03:50:46 -0500 Subject: [PATCH 28/45] qemu-option: pass QemuOptsList to opts_accepts_any A QemuOptsList can be of one of two kinds: either it is pre-validated, or it accepts any key and validation happens somewhere else (typically in a Visitor or against a list of QOM properties). opts_accepts_any returns true if a QemuOpts instance was created from a QemuOptsList of the latter kind, but there is no function to do the check on a QemuOptsList. Since this property comes from the QemuOptsList and almost all callers of opts_accepts_any use opts->list anyway, modify the function to accept QemuOptsList. Reviewed-by: Markus Armbruster Signed-off-by: Paolo Bonzini --- util/qemu-option.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/util/qemu-option.c b/util/qemu-option.c index 6bd654a473..c88e159f18 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -460,16 +460,16 @@ static bool qemu_opt_parse(QemuOpt *opt, Error **errp) } } -static bool opts_accepts_any(const QemuOpts *opts) +static bool opts_accepts_any(const QemuOptsList *list) { - return opts->list->desc[0].name == NULL; + return list->desc[0].name == NULL; } int qemu_opt_unset(QemuOpts *opts, const char *name) { QemuOpt *opt = qemu_opt_find(opts, name); - assert(opts_accepts_any(opts)); + assert(opts_accepts_any(opts->list)); if (opt == NULL) { return -1; @@ -500,9 +500,10 @@ static bool opt_validate(QemuOpt *opt, bool *help_wanted, Error **errp) { const QemuOptDesc *desc; + const QemuOptsList *list = opt->opts->list; - desc = find_desc_by_name(opt->opts->list->desc, opt->name); - if (!desc && !opts_accepts_any(opt->opts)) { + desc = find_desc_by_name(list->desc, opt->name); + if (!desc && !opts_accepts_any(list)) { error_setg(errp, QERR_INVALID_PARAMETER, opt->name); if (help_wanted && is_help_option(opt->name)) { *help_wanted = true; @@ -535,9 +536,10 @@ bool qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val, { QemuOpt *opt; const QemuOptDesc *desc; + const QemuOptsList *list = opts->list; - desc = find_desc_by_name(opts->list->desc, name); - if (!desc && !opts_accepts_any(opts)) { + desc = find_desc_by_name(list->desc, name); + if (!desc && !opts_accepts_any(list)) { error_setg(errp, QERR_INVALID_PARAMETER, name); return false; } @@ -557,9 +559,10 @@ bool qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val, { QemuOpt *opt; const QemuOptDesc *desc; + const QemuOptsList *list = opts->list; - desc = find_desc_by_name(opts->list->desc, name); - if (!desc && !opts_accepts_any(opts)) { + desc = find_desc_by_name(list->desc, name); + if (!desc && !opts_accepts_any(list)) { error_setg(errp, QERR_INVALID_PARAMETER, name); return false; } @@ -1107,7 +1110,7 @@ bool qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp) { QemuOpt *opt; - assert(opts_accepts_any(opts)); + assert(opts_accepts_any(opts->list)); QTAILQ_FOREACH(opt, &opts->head, next) { opt->desc = find_desc_by_name(desc, opt->name); From 7245ca7411d88e1b7c9205836c2852b20e3900a7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 2 Nov 2020 10:46:52 -0500 Subject: [PATCH 29/45] vl: rename local variable in configure_accelerators Silly patch extracted from the next one, which is already big enough. Because there are already local variables named "accel", we will name the global vl.c variable for "-M accel" accelerators instead. Rename it already in configure_accelerators to be ready. Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index c56e6dc0b3..0ed5c5ba93 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2159,17 +2159,17 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp) static void configure_accelerators(const char *progname) { - const char *accel; + const char *accelerators; bool init_failed = false; qemu_opts_foreach(qemu_find_opts("icount"), do_configure_icount, NULL, &error_fatal); - accel = qemu_opt_get(qemu_get_machine_opts(), "accel"); + accelerators = qemu_opt_get(qemu_get_machine_opts(), "accel"); if (QTAILQ_EMPTY(&qemu_accel_opts.head)) { char **accel_list, **tmp; - if (accel == NULL) { + if (accelerators == NULL) { /* Select the default accelerator */ bool have_tcg = accel_find("tcg"); bool have_kvm = accel_find("kvm"); @@ -2177,21 +2177,21 @@ static void configure_accelerators(const char *progname) if (have_tcg && have_kvm) { if (g_str_has_suffix(progname, "kvm")) { /* If the program name ends with "kvm", we prefer KVM */ - accel = "kvm:tcg"; + accelerators = "kvm:tcg"; } else { - accel = "tcg:kvm"; + accelerators = "tcg:kvm"; } } else if (have_kvm) { - accel = "kvm"; + accelerators = "kvm"; } else if (have_tcg) { - accel = "tcg"; + accelerators = "tcg"; } else { error_report("No accelerator selected and" " no default accelerator available"); exit(1); } } - accel_list = g_strsplit(accel, ":", 0); + accel_list = g_strsplit(accelerators, ":", 0); for (tmp = accel_list; *tmp; tmp++) { /* @@ -2207,7 +2207,7 @@ static void configure_accelerators(const char *progname) } g_strfreev(accel_list); } else { - if (accel != NULL) { + if (accelerators != NULL) { error_report("The -accel and \"-machine accel=\" options are incompatible"); exit(1); } From daf07a6714b111340fe2d0234d1a5287d6ebe0ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 1 Dec 2020 22:37:04 +0400 Subject: [PATCH 30/45] docs: set CONFDIR when running sphinx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default configuration path /etc/qemu can be overriden with configure options, and the generated documentation used to reflect it. Fixes regression introduced in commit f8aa24ea9a82da38370470c6bc0eaa393999edfe ("meson: sphinx-build"). Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1902537 Signed-off-by: Marc-André Lureau Message-Id: <20201201183704.299697-1-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- docs/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/meson.build b/docs/meson.build index ebd85d59f9..bb8fe4c9e4 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -9,7 +9,7 @@ endif # Check if tools are available to build documentation. build_docs = false if sphinx_build.found() - SPHINX_ARGS = [sphinx_build] + SPHINX_ARGS = ['env', 'CONFDIR=' + qemu_confdir, sphinx_build] # If we're making warnings fatal, apply this to Sphinx runs as well if get_option('werror') SPHINX_ARGS += [ '-W' ] From 98199a654c5425d37293b63ae329d3256bfbcc00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 7 Dec 2020 23:07:09 +0100 Subject: [PATCH 31/45] hw/core: Restrict 'fw-path-provider.c' to system mode emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fw-path-provider.c is only consumed by qdev-fw.c, which itself is in softmmu_ss[], so we can restrict fw-path-provider.c to softmmu too. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201207220709.4017938-1-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- hw/core/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/core/meson.build b/hw/core/meson.build index 4a744f3b5e..032576f571 100644 --- a/hw/core/meson.build +++ b/hw/core/meson.build @@ -1,7 +1,6 @@ # core qdev-related obj files, also used by *-user and unit tests hwcore_files = files( 'bus.c', - 'fw-path-provider.c', 'hotplug.c', 'qdev-properties.c', 'qdev.c', @@ -25,6 +24,7 @@ common_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c')) common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c')) softmmu_ss.add(files( + 'fw-path-provider.c', 'loader.c', 'machine-hmp-cmds.c', 'machine.c', From 6a4757fe51a1c5ea31f33d8a83c03387302ac2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 10 Dec 2020 17:47:40 +0400 Subject: [PATCH 32/45] qemu/atomic: Drop special case for unsupported compiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit efc6c070aca ("configure: Add a test for the minimum compiler version") the minimum compiler version required for GCC is 4.8, which has the GCC BZ#36793 bug fixed. We can safely remove the special case introduced in commit a281ebc11a6 ("virtio: add missing mb() on notification"). With clang 3.4, __ATOMIC_RELAXED is defined, so the chunk to remove (which is x86-specific), isn't reached either. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Marc-André Lureau Message-Id: <20201210134752.780923-2-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/atomic.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index c1d211a351..8f4b3a80fb 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -241,23 +241,6 @@ #else /* __ATOMIC_RELAXED */ -/* - * We use GCC builtin if it's available, as that can use mfence on - * 32-bit as well, e.g. if built with -march=pentium-m. However, on - * i386 the spec is buggy, and the implementation followed it until - * 4.3 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36793). - */ -#if defined(__i386__) || defined(__x86_64__) -#if !QEMU_GNUC_PREREQ(4, 4) -#if defined __x86_64__ -#define smp_mb() ({ asm volatile("mfence" ::: "memory"); (void)0; }) -#else -#define smp_mb() ({ asm volatile("lock; addl $0,0(%%esp) " ::: "memory"); (void)0; }) -#endif -#endif -#endif - - #ifdef __alpha__ #define smp_read_barrier_depends() asm volatile("mb":::"memory") #endif From 19a84318c674c157f1b04c5c99595379f8ac8bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 10 Dec 2020 17:47:41 +0400 Subject: [PATCH 33/45] accel/tcg: Remove special case for GCC < 4.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit efc6c070aca ("configure: Add a test for the minimum compiler version") the minimum compiler version required for GCC is 4.8. We can safely remove the special case for GCC 4.6 introduced in commit 0448f5f8b81 ("cpu-exec: Fix compiler warning (-Werror=clobbered)"). No change for Clang as we don't know. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Reviewed-by: Marc-André Lureau Message-Id: <20201210134752.780923-3-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- accel/tcg/cpu-exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 251b340fb9..c2c26489c7 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -724,7 +724,7 @@ int cpu_exec(CPUState *cpu) /* prepare setjmp context for exception handling */ if (sigsetjmp(cpu->jmp_env, 0) != 0) { -#if defined(__clang__) || !QEMU_GNUC_PREREQ(4, 6) +#if defined(__clang__) /* Some compilers wrongly smash all local variables after * siglongjmp. There were bug reports for gcc 4.5.0 and clang. * Reload essential local variables here for those compilers. From 44cb2c9fe5dd2aa8b44eb42f34ec786ba21a2731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:42 +0400 Subject: [PATCH 34/45] compiler.h: remove GCC < 3 __builtin_expect fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit efc6c07 ("configure: Add a test for the minimum compiler version"), QEMU explicitely depends on GCC >= 4.8. (clang >= 3.4 advertizes itself as GCC >= 4.2 compatible and supports __builtin_expect too) Signed-off-by: Marc-André Lureau Message-Id: <20201210134752.780923-4-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/compiler.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index c76281f354..226ead6c90 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -44,10 +44,6 @@ #endif #ifndef likely -#if __GNUC__ < 3 -#define __builtin_expect(x, n) (x) -#endif - #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #endif From 53b5d954f21ba3e0472f6cd3fde4de0eba89b243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:43 +0400 Subject: [PATCH 35/45] qemu-plugin.h: remove GCC < 4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit efc6c07 ("configure: Add a test for the minimum compiler version"), QEMU explicitely depends on GCC >= 4.8. (clang >= 3.4 advertizes itself as GCC >= 4.2 compatible) Signed-off-by: Marc-André Lureau Acked-by: Alex Bennée Message-Id: <20201210134752.780923-5-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/qemu-plugin.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index bab8b0d4b3..5775e82c4e 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -28,13 +28,8 @@ #endif #define QEMU_PLUGIN_LOCAL #else - #if __GNUC__ >= 4 - #define QEMU_PLUGIN_EXPORT __attribute__((visibility("default"))) - #define QEMU_PLUGIN_LOCAL __attribute__((visibility("hidden"))) - #else - #define QEMU_PLUGIN_EXPORT - #define QEMU_PLUGIN_LOCAL - #endif + #define QEMU_PLUGIN_EXPORT __attribute__((visibility("default"))) + #define QEMU_PLUGIN_LOCAL __attribute__((visibility("hidden"))) #endif typedef uint64_t qemu_plugin_id_t; From 77d35c83d3bcabdc64e2e8a58d6ff0d546e65120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:44 +0400 Subject: [PATCH 36/45] tests: remove GCC < 4 fallbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit efc6c07 ("configure: Add a test for the minimum compiler version"), QEMU explicitely depends on GCC >= 4.8. (clang >= 3.4 advertizes itself as GCC >= 4.2 compatible) Signed-off-by: Marc-André Lureau Reviewed-by: Peter Maydell Acked-by: Alex Bennée Message-Id: <20201210134752.780923-6-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- tests/tcg/arm/fcvt.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/tcg/arm/fcvt.c b/tests/tcg/arm/fcvt.c index 617626bc63..7ac47b564e 100644 --- a/tests/tcg/arm/fcvt.c +++ b/tests/tcg/arm/fcvt.c @@ -73,11 +73,9 @@ static void print_int64(int i, int64_t num) #ifndef SNANF /* Signaling NaN macros, if supported. */ -# if __GNUC_PREREQ(3, 3) -# define SNANF (__builtin_nansf ("")) -# define SNAN (__builtin_nans ("")) -# define SNANL (__builtin_nansl ("")) -# endif +# define SNANF (__builtin_nansf ("")) +# define SNAN (__builtin_nans ("")) +# define SNANL (__builtin_nansl ("")) #endif float single_numbers[] = { -SNANF, From db5deef996e78f02e2fec0c2453de8d0db749832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:45 +0400 Subject: [PATCH 37/45] virtiofsd: replace _Static_assert with QEMU_BUILD_BUG_ON MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to get rid of a check for older GCC version (which was a bit bogus too since it was falling back on c++ version..) Signed-off-by: Marc-André Lureau Reviewed-by: Dr. David Alan Gilbert Message-Id: <20201210134752.780923-7-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- tools/virtiofsd/fuse_common.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h index 30b18b4966..a090040bb2 100644 --- a/tools/virtiofsd/fuse_common.h +++ b/tools/virtiofsd/fuse_common.h @@ -807,15 +807,6 @@ void fuse_remove_signal_handlers(struct fuse_session *se); * * On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags! */ - -#if defined(__GNUC__) && \ - (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && \ - !defined __cplusplus -_Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit"); -#else -struct _fuse_off_t_must_be_64bit_dummy_struct { - unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1); -}; -#endif +QEMU_BUILD_BUG_ON(sizeof(off_t) != 8); #endif /* FUSE_COMMON_H_ */ From 28f86163a4395fd67203f9482cbca508c216de74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:46 +0400 Subject: [PATCH 38/45] compiler.h: explicit case for Clang printf attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit efc6c07 ("configure: Add a test for the minimum compiler version"), QEMU explicitely depends on GCC >= 4.8, we could thus drop earlier version checks. Except clang advertizes itself as GCC 4.2.1. Since clang doesn't support gnu_printf, make that case explicitely and drop GCC version check. Signed-off-by: Marc-André Lureau Reviewed-by: Peter Maydell Message-Id: <20201210134752.780923-8-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/compiler.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 226ead6c90..6212295e52 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -99,18 +99,18 @@ #define QEMU_BUILD_BUG_ON_ZERO(x) (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - \ sizeof(QEMU_BUILD_BUG_ON_STRUCT(x))) -#if defined __GNUC__ -# if !QEMU_GNUC_PREREQ(4, 4) - /* gcc versions before 4.4.x don't support gnu_printf, so use printf. */ -# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m))) -# else - /* Use gnu_printf when supported (qemu uses standard format strings). */ -# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) -# if defined(_WIN32) - /* Map __printf__ to __gnu_printf__ because we want standard format strings - * even when MinGW or GLib include files use __printf__. */ -# define __printf__ __gnu_printf__ -# endif +#if defined(__clang__) +/* clang doesn't support gnu_printf, so use printf. */ +# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m))) +#elif defined(__GNUC__) +/* Use gnu_printf (qemu uses standard format strings). */ +# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) +# if defined(_WIN32) +/* + * Map __printf__ to __gnu_printf__ because we want standard format strings even + * when MinGW or GLib include files use __printf__. + */ +# define __printf__ __gnu_printf__ # endif #else #define GCC_FMT_ATTR(n, m) From b8f02d1616ac02acbf74171af4119897a2d7e31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:48 +0400 Subject: [PATCH 39/45] poison: remove GNUC check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU requires Clang or GCC, that define and support __GNUC__ extensions Signed-off-by: Marc-André Lureau Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201210134752.780923-10-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/exec/poison.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/exec/poison.h b/include/exec/poison.h index 7b9ac361dc..d7ae1f23e7 100644 --- a/include/exec/poison.h +++ b/include/exec/poison.h @@ -3,7 +3,6 @@ #ifndef HW_POISON_H #define HW_POISON_H -#ifdef __GNUC__ #pragma GCC poison TARGET_I386 #pragma GCC poison TARGET_X86_64 @@ -93,4 +92,3 @@ #pragma GCC poison CONFIG_SOFTMMU #endif -#endif From d55e5bd15aa8c235ac96501e587c7d38d38ec0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:49 +0400 Subject: [PATCH 40/45] xen: remove GNUC check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU requires Clang or GCC, that define and support __GNUC__ extensions Signed-off-by: Marc-André Lureau Acked-by: Stefano Stabellini Message-Id: <20201210134752.780923-11-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/hw/xen/interface/io/ring.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/hw/xen/interface/io/ring.h b/include/hw/xen/interface/io/ring.h index 5d048b335c..115705f3f4 100644 --- a/include/hw/xen/interface/io/ring.h +++ b/include/hw/xen/interface/io/ring.h @@ -206,21 +206,12 @@ typedef struct __name##_back_ring __name##_back_ring_t #define RING_HAS_UNCONSUMED_RESPONSES(_r) \ ((_r)->sring->rsp_prod - (_r)->rsp_cons) -#ifdef __GNUC__ #define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \ unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \ unsigned int rsp = RING_SIZE(_r) - \ ((_r)->req_cons - (_r)->rsp_prod_pvt); \ req < rsp ? req : rsp; \ }) -#else -/* Same as above, but without the nice GCC ({ ... }) syntax. */ -#define RING_HAS_UNCONSUMED_REQUESTS(_r) \ - ((((_r)->sring->req_prod - (_r)->req_cons) < \ - (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \ - ((_r)->sring->req_prod - (_r)->req_cons) : \ - (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) -#endif /* Direct access to individual ring elements, by index. */ #define RING_GET_REQUEST(_r, _idx) \ From 4e063f7b29468412bbb067496db36e6982cb6922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:50 +0400 Subject: [PATCH 41/45] compiler: remove GNUC check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU requires Clang or GCC, that define and support __GNUC__ extensions. Signed-off-by: Marc-André Lureau Reviewed-by: Peter Maydell Message-Id: <20201210134752.780923-12-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/compiler.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 6212295e52..5e6cf2c8e8 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -64,14 +64,10 @@ (offsetof(container, field) + sizeof_field(container, field)) /* Convert from a base type to a parent type, with compile time checking. */ -#ifdef __GNUC__ #define DO_UPCAST(type, field, dev) ( __extension__ ( { \ char __attribute__((unused)) offset_must_be_zero[ \ -offsetof(type, field)]; \ container_of(dev, type, field);})) -#else -#define DO_UPCAST(type, field, dev) container_of(dev, type, field) -#endif #define typeof_field(type, field) typeof(((type *)0)->field) #define type_check(t1,t2) ((t1*)0 - (t2*)0) @@ -102,7 +98,7 @@ #if defined(__clang__) /* clang doesn't support gnu_printf, so use printf. */ # define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m))) -#elif defined(__GNUC__) +#else /* Use gnu_printf (qemu uses standard format strings). */ # define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) # if defined(_WIN32) @@ -112,8 +108,6 @@ */ # define __printf__ __gnu_printf__ # endif -#else -#define GCC_FMT_ATTR(n, m) #endif #ifndef __has_warning From 36c5e0b8efb7a54b1cecca05de55a49ab91ac6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:51 +0400 Subject: [PATCH 42/45] linux-user: remove GNUC check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU requires Clang or GCC, that define and support __GNUC__ extensions. Signed-off-by: Marc-André Lureau Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201210134752.780923-13-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- linux-user/strace.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 11fea14fba..e00275fcb5 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -24,7 +24,6 @@ struct syscallname { abi_long, abi_long, abi_long); }; -#ifdef __GNUC__ /* * It is possible that target doesn't have syscall that uses * following flags but we don't want the compiler to warn @@ -32,9 +31,6 @@ struct syscallname { * functions. It is ok to keep them while not used. */ #define UNUSED __attribute__ ((unused)) -#else -#define UNUSED -#endif /* * Structure used to translate flag values into strings. This is From 07b35a23c3ccecde85e80fd9981abf2e15c1384b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 10 Dec 2020 17:47:52 +0400 Subject: [PATCH 43/45] compiler.h: remove QEMU_GNUC_PREREQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When needed, the G_GNUC_CHECK_VERSION() glib macro can be used instead. Signed-off-by: Marc-André Lureau Message-Id: <20201210134752.780923-14-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/compiler.h | 11 ----------- scripts/cocci-macro-file.h | 1 - 2 files changed, 12 deletions(-) diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 5e6cf2c8e8..1b9e58e82b 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -11,17 +11,6 @@ #define QEMU_STATIC_ANALYSIS 1 #endif -/*---------------------------------------------------------------------------- -| The macro QEMU_GNUC_PREREQ tests for minimum version of the GNU C compiler. -| The code is a copy of SOFTFLOAT_GNUC_PREREQ, see softfloat-macros.h. -*----------------------------------------------------------------------------*/ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) -# define QEMU_GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else -# define QEMU_GNUC_PREREQ(maj, min) 0 -#endif - #define QEMU_NORETURN __attribute__ ((__noreturn__)) #define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h index c6bbc05ba3..20eea6b708 100644 --- a/scripts/cocci-macro-file.h +++ b/scripts/cocci-macro-file.h @@ -19,7 +19,6 @@ */ /* From qemu/compiler.h */ -#define QEMU_GNUC_PREREQ(maj, min) 1 #define QEMU_NORETURN __attribute__ ((__noreturn__)) #define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #define QEMU_SENTINEL __attribute__((sentinel)) From a1bcbb485c91c0869832b0bda62ff564ddfc52f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 13 Dec 2020 21:51:32 +0100 Subject: [PATCH 44/45] scripts/git.orderfile: Keep files with .inc extension sorted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sort .inc files along with the extension including them. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201213205132.243628-1-f4bug@amsat.org> Signed-off-by: Paolo Bonzini --- scripts/git.orderfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/git.orderfile b/scripts/git.orderfile index 3736c1d6af..b32203b710 100644 --- a/scripts/git.orderfile +++ b/scripts/git.orderfile @@ -12,6 +12,7 @@ # Documentation docs/* *.rst +*.rst.inc # build system configure @@ -28,9 +29,11 @@ qga/*.json # headers *.h +*.h.inc # decoding tree specification *.decode # code *.c +*.c.inc From bbd2d5a8120771ec59b86a80a1f51884e0a26e53 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Mon, 14 Dec 2020 16:09:38 +0100 Subject: [PATCH 45/45] build: -no-pie is no functional linker flag Recent binutils changes dropping unsupported options [1] caused a build issue in regard to the optionroms. ld -m elf_i386 -T /<>/pc-bios/optionrom//flat.lds -no-pie \ -s -o multiboot.img multiboot.o ld.bfd: Error: unable to disambiguate: -no-pie (did you mean --no-pie ?) This isn't really a regression in ld.bfd, filing the bug upstream revealed that this never worked as a ld flag [2] - in fact it seems we were by accident setting --nmagic). Since it never had the wanted effect this usage of LDFLAGS_NOPIE, should be droppable without any effect. This also is the only use-case of LDFLAGS_NOPIE in .mak, therefore we can also remove it from being added there. [1]: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=983d925d [2]: https://sourceware.org/bugzilla/show_bug.cgi?id=27050#c5 Signed-off-by: Christian Ehrhardt Message-Id: <20201214150938.1297512-1-christian.ehrhardt@canonical.com> Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini --- configure | 3 --- pc-bios/optionrom/Makefile | 1 - 2 files changed, 4 deletions(-) diff --git a/configure b/configure index cb21108d34..c228f7c21e 100755 --- a/configure +++ b/configure @@ -2137,7 +2137,6 @@ EOF # Check we support --no-pie first; we will need this for building ROMs. if compile_prog "-Werror -fno-pie" "-no-pie"; then CFLAGS_NOPIE="-fno-pie" - LDFLAGS_NOPIE="-no-pie" fi if test "$static" = "yes"; then @@ -2153,7 +2152,6 @@ if test "$static" = "yes"; then fi elif test "$pie" = "no"; then CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS" - CONFIGURE_LDFLAGS="$LDFLAGS_NOPIE $CONFIGURE_LDFLAGS" elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS" CONFIGURE_LDFLAGS="-pie $CONFIGURE_LDFLAGS" @@ -6714,7 +6712,6 @@ echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak echo "GLIB_LIBS=$glib_libs" >> $config_host_mak echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak -echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak echo "EXESUF=$EXESUF" >> $config_host_mak echo "HOST_DSOSUF=$HOST_DSOSUF" >> $config_host_mak diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index 084fc10f05..30771f8d17 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -41,7 +41,6 @@ override CFLAGS += $(call cc-option, $(Wa)-32) LD_I386_EMULATION ?= elf_i386 override LDFLAGS = -m $(LD_I386_EMULATION) -T $(SRC_DIR)/flat.lds -override LDFLAGS += $(LDFLAGS_NOPIE) all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin