#include "ui/qemu-spice.h"
#include "qapi/string-input-visitor.h"
#include "qapi/opts-visitor.h"
+#include "qapi/clone-visitor.h"
#include "qom/object_interfaces.h"
#include "exec/semihost.h"
#include "crypto/init.h"
#include "sysemu/replay.h"
#include "qapi/qapi-events-run-state.h"
#include "qapi/qapi-visit-block-core.h"
+#include "qapi/qapi-visit-ui.h"
#include "qapi/qapi-commands-block-core.h"
#include "qapi/qapi-commands-misc.h"
#include "qapi/qapi-commands-run-state.h"
/***********************************************************/
/* QEMU state */
-static RunState current_run_state = RUN_STATE_PRELAUNCH;
+static RunState current_run_state = RUN_STATE_PRECONFIG;
/* We use RUN_STATE__MAX but any invalid value will do */
static RunState vmstop_requested = RUN_STATE__MAX;
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_DEBUG, RUN_STATE_RUNNING },
{ RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
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);
return r;
}
+void qemu_exit_preconfig_request(void)
+{
+ preconfig_exit_requested = true;
+}
+
/*
* Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
*/
RunState r;
ShutdownCause request;
+ if (preconfig_exit_requested) {
+ if (runstate_check(RUN_STATE_PRECONFIG)) {
+ runstate_set(RUN_STATE_PRELAUNCH);
+ }
+ preconfig_exit_requested = false;
+ return true;
+ }
if (qemu_debug_requested()) {
vm_stop(RUN_STATE_DEBUG);
}
}
}
+static void parse_display_qapi(const char *optarg)
+{
+ Error *err = NULL;
+ DisplayOptions *opts;
+ Visitor *v;
+
+ v = qobject_input_visitor_new_str(optarg, "type", &err);
+ if (!v) {
+ error_report_err(err);
+ exit(1);
+ }
+
+ visit_type_DisplayOptions(v, NULL, &opts, &error_fatal);
+ QAPI_CLONE_MEMBERS(DisplayOptions, &dpy, opts);
+
+ qapi_free_DisplayOptions(opts);
+ visit_free(v);
+}
+
static void parse_display(const char *p)
{
const char *opts;
if (strstart(p, "sdl", &opts)) {
+ /*
+ * sdl DisplayType needs hand-crafted parser instead of
+ * parse_display_qapi() due to some options not in
+ * DisplayOptions, specifically:
+ * - frame
+ * Already deprecated.
+ * - ctrl_grab + alt_grab
+ * Not clear yet what happens to them long-term. Should
+ * replaced by something better or deprecated and dropped.
+ */
dpy.type = DISPLAY_TYPE_SDL;
while (*opts) {
const char *nextopt;
opts = nextopt;
}
} else if (strstart(p, "vnc", &opts)) {
+ /*
+ * vnc isn't a (local) DisplayType but a protocol for remote
+ * display access.
+ */
if (*opts == '=') {
vnc_parse(opts + 1, &error_fatal);
} else {
error_report("VNC requires a display argument vnc=<display>");
exit(1);
}
- } else if (strstart(p, "egl-headless", &opts)) {
- dpy.type = DISPLAY_TYPE_EGL_HEADLESS;
- } else if (strstart(p, "curses", &opts)) {
- dpy.type = DISPLAY_TYPE_CURSES;
- } else if (strstart(p, "gtk", &opts)) {
- dpy.type = DISPLAY_TYPE_GTK;
- while (*opts) {
- const char *nextopt;
-
- if (strstart(opts, ",grab_on_hover=", &nextopt)) {
- opts = nextopt;
- dpy.u.gtk.has_grab_on_hover = true;
- if (strstart(opts, "on", &nextopt)) {
- dpy.u.gtk.grab_on_hover = true;
- } else if (strstart(opts, "off", &nextopt)) {
- dpy.u.gtk.grab_on_hover = false;
- } else {
- goto invalid_gtk_args;
- }
- } else if (strstart(opts, ",gl=", &nextopt)) {
- opts = nextopt;
- dpy.has_gl = true;
- if (strstart(opts, "on", &nextopt)) {
- dpy.gl = DISPLAYGL_MODE_ON;
- } else if (strstart(opts, "off", &nextopt)) {
- dpy.gl = DISPLAYGL_MODE_OFF;
- } else {
- goto invalid_gtk_args;
- }
- } else {
- invalid_gtk_args:
- error_report("invalid GTK option string");
- exit(1);
- }
- opts = nextopt;
- }
- } else if (strstart(p, "none", &opts)) {
- dpy.type = DISPLAY_TYPE_NONE;
} else {
- error_report("unknown display type");
- exit(1);
+ parse_display_qapi(p);
}
}
{
uint64_t sz;
const char *mem_str;
- const char *maxmem_str, *slots_str;
const ram_addr_t default_ram_size = mc->default_ram_size;
QemuOpts *opts = qemu_find_opts_singleton("memory");
Location loc;
qemu_opt_set_number(opts, "size", ram_size, &error_abort);
*maxram_size = ram_size;
- maxmem_str = qemu_opt_get(opts, "maxmem");
- slots_str = qemu_opt_get(opts, "slots");
- if (maxmem_str && slots_str) {
+ if (qemu_opt_get(opts, "maxmem")) {
uint64_t slots;
sz = qemu_opt_get_size(opts, "maxmem", 0);
"the initial memory size (0x" RAM_ADDR_FMT ")",
sz, ram_size);
exit(EXIT_FAILURE);
- } else if (sz > ram_size) {
- if (!slots) {
- error_report("invalid value of -m option: maxmem was "
- "specified, but no hotplug slots were specified");
- exit(EXIT_FAILURE);
- }
- } else if (slots) {
+ } else if (slots && sz == ram_size) {
error_report("invalid value of -m option maxmem: "
"memory slots were specified but maximum memory size "
"(0x%" PRIx64 ") is equal to the initial memory size "
*maxram_size = sz;
*ram_slots = slots;
- } else if ((!maxmem_str && slots_str) ||
- (maxmem_str && !slots_str)) {
- error_report("invalid -m option value: missing "
- "'%s' option", slots_str ? "maxmem" : "slots");
+ } else if (qemu_opt_get(opts, "slots")) {
+ error_report("invalid -m option value: missing 'maxmem' option");
exit(EXIT_FAILURE);
}
exit(1);
}
switch(popt->index) {
- case QEMU_OPTION_no_kvm_irqchip: {
- olist = qemu_find_opts("machine");
- qemu_opts_parse_noisily(olist, "kernel_irqchip=off", false);
- break;
- }
case QEMU_OPTION_cpu:
/* hw initialization will check this */
cpu_model = optarg;
}
break;
case QEMU_OPTION_virtiocon:
+ warn_report("This option is deprecated, "
+ "use '-device virtconsole' instead");
add_device_config(DEV_VIRTCON, optarg);
default_virtcon = 0;
if (strncmp(optarg, "mon:", 4) == 0) {
exit(1);
}
break;
+ case QEMU_OPTION_preconfig:
+ preconfig_exit_requested = false;
+ break;
case QEMU_OPTION_enable_kvm:
olist = qemu_find_opts("machine");
qemu_opts_parse_noisily(olist, "accel=kvm", false);
olist = qemu_find_opts("machine");
qemu_opts_parse_noisily(olist, "accel=tcg", false);
break;
- case QEMU_OPTION_no_kvm_pit_reinjection: {
- static GlobalProperty kvm_pit_lost_tick_policy = {
- .driver = "kvm-pit",
- .property = "lost_tick_policy",
- .value = "discard",
- };
-
- warn_report("deprecated, replaced by "
- "-global kvm-pit.lost_tick_policy=discard");
- qdev_prop_register_global(&kvm_pit_lost_tick_policy);
- break;
- }
case QEMU_OPTION_accel:
accel_opts = qemu_opts_parse_noisily(qemu_find_opts("accel"),
optarg, true);
exit(1);
}
break;
+ case QEMU_OPTION_nodefconfig:
+ case QEMU_OPTION_nouserconfig:
+ /* Nothing to be parsed here. Especially, do not error out below. */
+ break;
default:
- os_parse_cmd_args(popt->index, optarg);
+ if (os_parse_cmd_args(popt->index, optarg)) {
+ error_report("Option not supported in this build");
+ exit(1);
+ }
}
}
}
replay_configure(icount_opts);
+ if (incoming && !preconfig_exit_requested) {
+ error_report("'preconfig' and 'incoming' options are "
+ "mutually exclusive");
+ exit(EXIT_FAILURE);
+ }
+
machine_class = select_machine();
set_memory_options(&ram_slots, &maxram_size, machine_class);
}
parse_numa_opts(current_machine);
+ /* do monitor/qmp handling at preconfig state if requested */
+ main_loop();
+
+ /* from here on runstate is RUN_STATE_PRELAUNCH */
machine_run_board_init(current_machine);
realtime_init();
/* No more vcpu or device emulation activity beyond this point */
vm_shutdown();
+ job_cancel_sync_all();
bdrv_close_all();
res_free();