#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"
#include "sysemu/iothread.h"
#define MAX_VIRTIO_CONSOLES 1
-#define MAX_SCLP_CONSOLES 1
static const char *data_dir[16];
static int data_dir_idx;
static Chardev **serial_hds = NULL;
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
Chardev *virtcon_hds[MAX_VIRTIO_CONSOLES];
-Chardev *sclp_hds[MAX_SCLP_CONSOLES];
int win2k_install_hack = 0;
int singlestep = 0;
int smp_cpus;
static int default_serial = 1;
static int default_parallel = 1;
static int default_virtcon = 1;
-static int default_sclp = 1;
static int default_monitor = 1;
static int default_floppy = 1;
static int default_cdrom = 1;
/***********************************************************/
/* 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);
}
}
return 0;
}
-static int sclp_parse(const char *devname)
-{
- QemuOptsList *device = qemu_find_opts("device");
- static int index = 0;
- char label[32];
- QemuOpts *dev_opts;
-
- if (strcmp(devname, "none") == 0) {
- return 0;
- }
- if (index == MAX_SCLP_CONSOLES) {
- error_report("too many sclp consoles");
- exit(1);
- }
-
- assert(arch_type == QEMU_ARCH_S390X);
-
- dev_opts = qemu_opts_create(device, NULL, 0, NULL);
- qemu_opt_set(dev_opts, "driver", "sclpconsole", &error_abort);
-
- snprintf(label, sizeof(label), "sclpcon%d", index);
- sclp_hds[index] = qemu_chr_new(label, devname);
- if (!sclp_hds[index]) {
- error_report("could not connect sclp console"
- " to character backend '%s'", devname);
- return -1;
- }
- qemu_opt_set(dev_opts, "chardev", label, &error_abort);
-
- index++;
- return 0;
-}
-
static int debugcon_parse(const char *devname)
{
QemuOpts *opts;
{
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);
if (!has_defaults || !machine_class->use_virtcon) {
default_virtcon = 0;
}
- if (!has_defaults || !machine_class->use_sclp) {
- default_sclp = 0;
- }
if (!has_defaults || machine_class->no_floppy) {
default_floppy = 0;
}
add_device_config(DEV_SERIAL, "mon:stdio");
} else if (default_virtcon && default_monitor) {
add_device_config(DEV_VIRTCON, "mon:stdio");
- } else if (default_sclp && default_monitor) {
- add_device_config(DEV_SCLP, "mon:stdio");
} else {
if (default_serial)
add_device_config(DEV_SERIAL, "stdio");
if (default_virtcon)
add_device_config(DEV_VIRTCON, "stdio");
- if (default_sclp) {
- add_device_config(DEV_SCLP, "stdio");
- }
if (default_monitor)
monitor_parse("stdio", "readline", false);
}
monitor_parse("vc:80Cx24C", "readline", false);
if (default_virtcon)
add_device_config(DEV_VIRTCON, "vc:80Cx24C");
- if (default_sclp) {
- add_device_config(DEV_SCLP, "vc:80Cx24C");
- }
}
#if defined(CONFIG_VNC)
exit(1);
if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
exit(1);
- if (foreach_device_config(DEV_SCLP, sclp_parse) < 0) {
- exit(1);
- }
if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
exit(1);
}
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();