#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);
}
}
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;
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);
exit(1);
}
break;
+ case QEMU_OPTION_nodefconfig:
+ case QEMU_OPTION_nouserconfig:
+ /* Nothing to be parsed here. Especially, do not error out below. */
+ break;
default:
if (os_parse_cmd_args(popt->index, optarg)) {
error_report("Option not supported in this build");
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();