#include "hw/usb.h"
#include "hw/i386/pc.h"
#include "hw/isa/isa.h"
+#include "hw/scsi/scsi.h"
#include "hw/bt.h"
#include "sysemu/watchdog.h"
#include "hw/smbios/smbios.h"
+#include "hw/acpi/acpi.h"
#include "hw/xen/xen.h"
#include "hw/qdev.h"
#include "hw/loader.h"
#include "sysemu/cpus.h"
#include "migration/colo.h"
#include "sysemu/kvm.h"
+#include "sysemu/hax.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi-visit.h"
#include "qapi/qmp/qjson.h"
#include "qemu/option.h"
#include "qemu/config-file.h"
#include "slirp/libslirp.h"
-#include "trace.h"
+#include "trace-root.h"
#include "trace/control.h"
#include "qemu/queue.h"
#include "sysemu/arch_init.h"
static int no_frame = 0;
int no_quit = 0;
static bool grab_on_hover;
-CharDriverState *serial_hds[MAX_SERIAL_PORTS];
-CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
-CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
-CharDriverState *sclp_hds[MAX_SCLP_CONSOLES];
+Chardev *serial_hds[MAX_SERIAL_PORTS];
+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 = 1;
uint8_t *boot_splash_filedata;
size_t boot_splash_filedata_size;
uint8_t qemu_extra_params_fw[2];
+int only_migratable; /* turn it off unless user states otherwise */
int icount_align_option;
{ .driver = "ide-hd", .flag = &default_cdrom },
{ .driver = "ide-drive", .flag = &default_cdrom },
{ .driver = "scsi-cd", .flag = &default_cdrom },
+ { .driver = "scsi-hd", .flag = &default_cdrom },
{ .driver = "virtio-serial-pci", .flag = &default_virtcon },
{ .driver = "virtio-serial", .flag = &default_virtcon },
{ .driver = "VGA", .flag = &default_vga },
},
};
+static QemuOptsList qemu_accel_opts = {
+ .name = "accel",
+ .implied_opt_name = "accel",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_accel_opts.head),
+ .merge_lists = true,
+ .desc = {
+ {
+ .name = "accel",
+ .type = QEMU_OPT_STRING,
+ .help = "Select the type of accelerator",
+ },
+ {
+ .name = "thread",
+ .type = QEMU_OPT_STRING,
+ .help = "Enable/disable multi-threaded TCG",
+ },
+ { /* end of list */ }
+ },
+};
+
static QemuOptsList qemu_boot_opts = {
.name = "boot-opts",
.implied_opt_name = "order",
}, {
.name = "rrfile",
.type = QEMU_OPT_STRING,
+ }, {
+ .name = "rrsnapshot",
+ .type = QEMU_OPT_STRING,
},
{ /* end of list */ }
},
},
};
-#ifdef CONFIG_LIBISCSI
-static QemuOptsList qemu_iscsi_opts = {
- .name = "iscsi",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
- .desc = {
- {
- .name = "user",
- .type = QEMU_OPT_STRING,
- .help = "username for CHAP authentication to target",
- },{
- .name = "password",
- .type = QEMU_OPT_STRING,
- .help = "password for CHAP authentication to target",
- },{
- .name = "password-secret",
- .type = QEMU_OPT_STRING,
- .help = "ID of the secret providing password for CHAP "
- "authentication to target",
- },{
- .name = "header-digest",
- .type = QEMU_OPT_STRING,
- .help = "HeaderDigest setting. "
- "{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
- },{
- .name = "initiator-name",
- .type = QEMU_OPT_STRING,
- .help = "Initiator iqn name to use when connecting",
- },{
- .name = "timeout",
- .type = QEMU_OPT_NUMBER,
- .help = "Request timeout in seconds (default 0 = no timeout)",
- },
- { /* end of list */ }
- },
-};
-#endif
-
/**
* Get machine options
*
return info;
}
-static bool qemu_vmstop_requested(RunState *r)
+bool qemu_vmstop_requested(RunState *r)
{
qemu_mutex_lock(&vmstop_lock);
*r = vmstop_requested;
qemu_notify_event();
}
-void vm_start(void)
-{
- RunState requested;
-
- qemu_vmstop_requested(&requested);
- if (runstate_is_running() && requested == RUN_STATE__MAX) {
- return;
- }
-
- /* Ensure that a STOP/RESUME pair of events is emitted if a
- * vmstop request was pending. The BLOCK_IO_ERROR event, for
- * example, according to documentation is always followed by
- * the STOP event.
- */
- if (runstate_is_running()) {
- qapi_event_send_stop(&error_abort);
- } else {
- replay_enable_events();
- cpu_enable_ticks();
- runstate_set(RUN_STATE_RUNNING);
- vm_state_notify(1, RUN_STATE_RUNNING);
- resume_all_vcpus();
- }
-
- qapi_event_send_resume(&error_abort);
-}
-
-
/***********************************************************/
/* real time host monotonic timer */
info->name = g_strdup(mc->name);
info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus;
- info->hotpluggable_cpus = !!mc->query_hotpluggable_cpus;
+ info->hotpluggable_cpus = mc->has_hotpluggable_cpus;
entry = g_malloc0(sizeof(*entry));
entry->value = info;
}
}
-/* reset/shutdown handler */
-
-typedef struct QEMUResetEntry {
- QTAILQ_ENTRY(QEMUResetEntry) entry;
- QEMUResetHandler *func;
- void *opaque;
-} QEMUResetEntry;
-
-static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
- QTAILQ_HEAD_INITIALIZER(reset_handlers);
static int reset_requested;
static int shutdown_requested, shutdown_signal = -1;
static pid_t shutdown_pid;
return r;
}
-void qemu_register_reset(QEMUResetHandler *func, void *opaque)
-{
- QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry));
-
- re->func = func;
- re->opaque = opaque;
- QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
-}
-
-void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
-{
- QEMUResetEntry *re;
-
- QTAILQ_FOREACH(re, &reset_handlers, entry) {
- if (re->func == func && re->opaque == opaque) {
- QTAILQ_REMOVE(&reset_handlers, re, entry);
- g_free(re);
- return;
- }
- }
-}
-
-void qemu_devices_reset(void)
-{
- QEMUResetEntry *re, *nre;
-
- /* reset all devices */
- QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
- re->func(re->opaque);
- }
-}
-
void qemu_system_reset(bool report)
{
MachineClass *mc;
cpu_synchronize_all_post_reset();
}
-void qemu_system_guest_panicked(void)
+void qemu_system_guest_panicked(GuestPanicInformation *info)
{
+ qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed\n");
+
if (current_cpu) {
current_cpu->crash_occurred = true;
}
- qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
+ qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
+ !!info, info, &error_abort);
vm_stop(RUN_STATE_GUEST_PANICKED);
if (!no_shutdown) {
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
- &error_abort);
+ !!info, info, &error_abort);
qemu_system_shutdown_request();
}
+
+ if (info) {
+ if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
+ qemu_log_mask(LOG_GUEST_ERROR, "HV 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);
+ }
+ qapi_free_GuestPanicInformation(info);
+ }
}
void qemu_system_reset_request(void)
static void main_loop(void)
{
- bool nonblocking;
- int last_io = 0;
#ifdef CONFIG_PROFILER
int64_t ti;
#endif
do {
- nonblocking = !kvm_enabled() && !xen_enabled() && last_io > 0;
#ifdef CONFIG_PROFILER
ti = profile_getclock();
#endif
- last_io = main_loop_wait(nonblocking);
+ main_loop_wait(false);
#ifdef CONFIG_PROFILER
dev_time += profile_getclock() - ti;
#endif
static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
{
- CharDriverState *chr;
+ Chardev *chr;
const char *chardev;
const char *mode;
int flags;
return 0;
}
+static int qemu_read_default_config_file(void)
+{
+ int ret;
+
+ ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf");
+ if (ret < 0 && ret != -ENOENT) {
+ return ret;
+ }
+
+ return 0;
+}
+
int main(int argc, char **argv, char **envp)
{
int i;
const char *boot_once = NULL;
DisplayState *ds;
int cyls, heads, secs, translation;
- QemuOpts *hda_opts = NULL, *opts, *machine_opts, *icount_opts = NULL;
+ QemuOpts *opts, *machine_opts;
+ QemuOpts *hda_opts = NULL, *icount_opts = NULL, *accel_opts = NULL;
QemuOptsList *olist;
int optind;
const char *optarg;
Error *main_loop_err = NULL;
Error *err = NULL;
bool list_data_dirs = false;
+ typedef struct BlockdevOptions_queue {
+ BlockdevOptions *bdo;
+ Location loc;
+ QSIMPLEQ_ENTRY(BlockdevOptions_queue) entry;
+ } BlockdevOptions_queue;
+ QSIMPLEQ_HEAD(, BlockdevOptions_queue) bdo_queue
+ = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
module_call_init(MODULE_INIT_TRACE);
qemu_init_exec_dir(argv[0]);
module_call_init(MODULE_INIT_QOM);
- module_call_init(MODULE_INIT_QAPI);
+ monitor_init_qmp_commands();
qemu_add_opts(&qemu_drive_opts);
qemu_add_drive_opts(&qemu_legacy_drive_opts);
qemu_add_opts(&qemu_trace_opts);
qemu_add_opts(&qemu_option_rom_opts);
qemu_add_opts(&qemu_machine_opts);
+ qemu_add_opts(&qemu_accel_opts);
qemu_add_opts(&qemu_mem_opts);
qemu_add_opts(&qemu_smp_opts);
qemu_add_opts(&qemu_boot_opts);
qemu_add_opts(&qemu_icount_opts);
qemu_add_opts(&qemu_semihosting_config_opts);
qemu_add_opts(&qemu_fw_cfg_opts);
-#ifdef CONFIG_LIBISCSI
- qemu_add_opts(&qemu_iscsi_opts);
-#endif
module_call_init(MODULE_INIT_OPTS);
runstate_init();
}
}
- if (defconfig) {
- int ret;
- ret = qemu_read_default_config_files(userconfig);
- if (ret < 0) {
+ if (defconfig && userconfig) {
+ if (qemu_read_default_config_file() < 0) {
exit(1);
}
}
drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optarg,
HD_OPTS);
break;
+ case QEMU_OPTION_blockdev:
+ {
+ Visitor *v;
+ BlockdevOptions_queue *bdo;
+
+ v = qobject_input_visitor_new_str(optarg, "driver", &err);
+ if (!v) {
+ error_report_err(err);
+ exit(1);
+ }
+
+ bdo = g_new(BlockdevOptions_queue, 1);
+ visit_type_BlockdevOptions(v, NULL, &bdo->bdo,
+ &error_fatal);
+ visit_free(v);
+ loc_save(&bdo->loc);
+ QSIMPLEQ_INSERT_TAIL(&bdo_queue, bdo, entry);
+ break;
+ }
case QEMU_OPTION_drive:
if (drive_def(optarg) == NULL) {
exit(1);
if (!opts) {
exit(1);
}
- do_acpitable_option(opts);
+ acpi_table_add(opts, &error_fatal);
break;
case QEMU_OPTION_smbios:
opts = qemu_opts_parse_noisily(qemu_find_opts("smbios"),
if (!opts) {
exit(1);
}
- do_smbios_option(opts);
+ smbios_entry_add(opts, &error_fatal);
break;
case QEMU_OPTION_fwcfg:
opts = qemu_opts_parse_noisily(qemu_find_opts("fw_cfg"),
olist = qemu_find_opts("machine");
qemu_opts_parse_noisily(olist, "accel=kvm", false);
break;
+ case QEMU_OPTION_enable_hax:
+ olist = qemu_find_opts("machine");
+ qemu_opts_parse_noisily(olist, "accel=hax", false);
+ break;
case QEMU_OPTION_M:
case QEMU_OPTION_machine:
olist = qemu_find_opts("machine");
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);
+ optarg = qemu_opt_get(accel_opts, "accel");
+
+ olist = qemu_find_opts("machine");
+ if (strcmp("kvm", optarg) == 0) {
+ qemu_opts_parse_noisily(olist, "accel=kvm", false);
+ } else if (strcmp("xen", optarg) == 0) {
+ qemu_opts_parse_noisily(olist, "accel=xen", false);
+ } else if (strcmp("tcg", optarg) == 0) {
+ qemu_opts_parse_noisily(olist, "accel=tcg", false);
+ } else {
+ if (!is_help_option(optarg)) {
+ error_printf("Unknown accelerator: %s", optarg);
+ }
+ error_printf("Supported accelerators: kvm, xen, tcg\n");
+ exit(1);
+ }
+ break;
case QEMU_OPTION_usb:
olist = qemu_find_opts("machine");
qemu_opts_parse_noisily(olist, "usb=on", false);
}
incoming = optarg;
break;
+ case QEMU_OPTION_only_migratable:
+ only_migratable = 1;
+ break;
case QEMU_OPTION_nodefaults:
has_defaults = 0;
break;
sdl_display_early_init(request_opengl);
}
+ qemu_console_early_init();
+
if (request_opengl == 1 && display_opengl == 0) {
#if defined(CONFIG_OPENGL)
error_report("OpenGL is not supported by the display");
cpu_ticks_init();
if (icount_opts) {
- if (kvm_enabled() || xen_enabled()) {
- error_report("-icount is not allowed with kvm or xen");
+ if (!tcg_enabled()) {
+ error_report("-icount is not allowed with hardware virtualization");
exit(1);
}
configure_icount(icount_opts, &error_abort);
qemu_opts_del(icount_opts);
}
+ qemu_tcg_configure(accel_opts, &error_fatal);
+
if (default_net) {
QemuOptsList *net = qemu_find_opts("net");
qemu_opts_set(net, NULL, "type", "nic", &error_abort);
}
/* open the virtual block devices */
+ while (!QSIMPLEQ_EMPTY(&bdo_queue)) {
+ BlockdevOptions_queue *bdo = QSIMPLEQ_FIRST(&bdo_queue);
+
+ QSIMPLEQ_REMOVE_HEAD(&bdo_queue, entry);
+ loc_push_restore(&bdo->loc);
+ qmp_blockdev_add(bdo->bdo, &error_fatal);
+ loc_pop(&bdo->loc);
+ qapi_free_BlockdevOptions(bdo->bdo);
+ g_free(bdo);
+ }
if (snapshot || replay_mode != REPLAY_MODE_NONE) {
qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot,
NULL, NULL);
audio_init();
- cpu_synchronize_all_post_init();
-
- numa_post_machine_init();
+ if (hax_enabled()) {
+ hax_sync_vcpus();
+ }
if (qemu_opts_foreach(qemu_find_opts("fw_cfg"),
parse_fw_cfg, fw_cfg_find(), NULL) != 0) {
device_init_func, NULL, NULL)) {
exit(1);
}
+
+ cpu_synchronize_all_post_init();
+
+ numa_post_machine_init();
+
rom_reset_order_override();
+ /*
+ * Create frontends for -drive if=scsi leftovers.
+ * Normally, frontends for -drive get created by machine
+ * initialization for onboard SCSI HBAs. However, we create a few
+ * more ever since SCSI qdevification, but this is pretty much an
+ * implementation accident, and deprecated.
+ */
+ scsi_legacy_handle_cmdline();
+
/* Did we create any drives that we failed to create a device for? */
drive_check_orphaned();
replay_checkpoint(CHECKPOINT_RESET);
qemu_system_reset(VMRESET_SILENT);
register_global_state();
- if (loadvm) {
+ if (replay_mode != REPLAY_MODE_NONE) {
+ replay_vmstate_init();
+ } else if (loadvm) {
if (load_vmstate(loadvm) < 0) {
autostart = 0;
}