CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
int win2k_install_hack = 0;
-int usb_enabled = 0;
int singlestep = 0;
int smp_cpus = 1;
int max_cpus = 0;
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING },
{ RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
- { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
+ { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
return 1;
}
+static int parse_sandbox(QemuOpts *opts, void *opaque)
+{
+ /* FIXME: change this to true for 1.3 */
+ if (qemu_opt_get_bool(opts, "enable", false)) {
+#ifdef CONFIG_SECCOMP
+ if (seccomp_start() < 0) {
+ qerror_report(ERROR_CLASS_GENERIC_ERROR,
+ "failed to install seccomp syscall filter in the kernel");
+ return -1;
+ }
+#else
+ qerror_report(ERROR_CLASS_GENERIC_ERROR,
+ "sandboxing request but seccomp is not compiled into this build");
+ return -1;
+#endif
+ }
+
+ return 0;
+}
+
+/*********QEMU USB setting******/
+bool usb_enabled(bool default_usb)
+{
+ QemuOpts *mach_opts;
+ mach_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+ if (mach_opts) {
+ return qemu_opt_get_bool(mach_opts, "usb", default_usb);
+ }
+ return default_usb;
+}
+
+#ifndef _WIN32
+static int parse_add_fd(QemuOpts *opts, void *opaque)
+{
+ int fd, dupfd, flags;
+ int64_t fdset_id;
+ const char *fd_opaque = NULL;
+
+ fd = qemu_opt_get_number(opts, "fd", -1);
+ fdset_id = qemu_opt_get_number(opts, "set", -1);
+ fd_opaque = qemu_opt_get(opts, "opaque");
+
+ if (fd < 0) {
+ qerror_report(ERROR_CLASS_GENERIC_ERROR,
+ "fd option is required and must be non-negative");
+ return -1;
+ }
+
+ if (fd <= STDERR_FILENO) {
+ qerror_report(ERROR_CLASS_GENERIC_ERROR,
+ "fd cannot be a standard I/O stream");
+ return -1;
+ }
+
+ /*
+ * All fds inherited across exec() necessarily have FD_CLOEXEC
+ * clear, while qemu sets FD_CLOEXEC on all other fds used internally.
+ */
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1 || (flags & FD_CLOEXEC)) {
+ qerror_report(ERROR_CLASS_GENERIC_ERROR,
+ "fd is not valid or already in use");
+ return -1;
+ }
+
+ if (fdset_id < 0) {
+ qerror_report(ERROR_CLASS_GENERIC_ERROR,
+ "set option is required and must be non-negative");
+ return -1;
+ }
+
+#ifdef F_DUPFD_CLOEXEC
+ dupfd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+#else
+ dupfd = dup(fd);
+ if (dupfd != -1) {
+ qemu_set_cloexec(dupfd);
+ }
+#endif
+ if (dupfd == -1) {
+ qerror_report(ERROR_CLASS_GENERIC_ERROR,
+ "Error duplicating fd: %s", strerror(errno));
+ return -1;
+ }
+
+ /* add the duplicate fd, and optionally the opaque string, to the fd set */
+ monitor_fdset_add_fd(dupfd, true, fdset_id, fd_opaque ? true : false,
+ fd_opaque, NULL);
+
+ return 0;
+}
+
+static int cleanup_add_fd(QemuOpts *opts, void *opaque)
+{
+ int fd;
+
+ fd = qemu_opt_get_number(opts, "fd", -1);
+ close(fd);
+
+ return 0;
+}
+#endif
+
/***********************************************************/
/* QEMU Block devices */
}
nb_numa_nodes++;
}
- return;
}
static void smp_parse(const char *optarg)
const char *p;
USBDevice *dev = NULL;
- if (!usb_enabled)
+ if (!usb_enabled(false)) {
return -1;
+ }
/* drivers with .usbdevice_name entry in USBDeviceInfo */
dev = usbdevice_create(devname);
if (strstart(devname, "host:", &p))
return usb_host_device_close(p);
- if (!usb_enabled)
+ if (!usb_enabled(false)) {
return -1;
+ }
p = strchr(devname, '.');
if (!p)
static int debug_requested;
static int suspend_requested;
static int wakeup_requested;
+static NotifierList powerdown_notifiers =
+ NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
static NotifierList suspend_notifiers =
NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
static NotifierList wakeup_notifiers =
}
}
-void qemu_system_reset(bool report)
+void qemu_devices_reset(void)
{
QEMUResetEntry *re, *nre;
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
re->func(re->opaque);
}
+}
+
+void qemu_system_reset(bool report)
+{
+ if (current_machine && current_machine->reset) {
+ current_machine->reset();
+ } else {
+ qemu_devices_reset();
+ }
if (report) {
monitor_protocol_event(QEVENT_RESET, NULL);
}
qemu_notify_event();
}
+static void qemu_system_powerdown(void)
+{
+ monitor_protocol_event(QEVENT_POWERDOWN, NULL);
+ notifier_list_notify(&powerdown_notifiers, NULL);
+}
+
void qemu_system_powerdown_request(void)
{
powerdown_requested = 1;
qemu_notify_event();
}
+void qemu_register_powerdown_notifier(Notifier *notifier)
+{
+ notifier_list_add(&powerdown_notifiers, notifier);
+}
+
void qemu_system_debug_request(void)
{
debug_requested = 1;
qemu_notify_event();
}
-qemu_irq qemu_system_powerdown;
-
static bool main_loop_should_exit(void)
{
RunState r;
monitor_protocol_event(QEVENT_WAKEUP, NULL);
}
if (qemu_powerdown_requested()) {
- monitor_protocol_event(QEVENT_POWERDOWN, NULL);
- qemu_irq_raise(qemu_system_powerdown);
+ qemu_system_powerdown();
}
if (qemu_vmstop_requested(&r)) {
vm_stop(r);
static bool vga_available(void)
{
- return qdev_exists("VGA") || qdev_exists("isa-vga");
+ return object_class_by_name("VGA") || object_class_by_name("isa-vga");
}
static bool cirrus_vga_available(void)
{
- return qdev_exists("cirrus-vga") || qdev_exists("isa-cirrus-vga");
+ return object_class_by_name("cirrus-vga")
+ || object_class_by_name("isa-cirrus-vga");
}
static bool vmware_vga_available(void)
{
- return qdev_exists("vmware-svga");
+ return object_class_by_name("vmware-svga");
+}
+
+static bool qxl_vga_available(void)
+{
+ return object_class_by_name("qxl-vga");
}
static void select_vgahw (const char *p)
} else if (strstart(p, "xenfb", &opts)) {
vga_interface_type = VGA_XENFB;
} else if (strstart(p, "qxl", &opts)) {
- vga_interface_type = VGA_QXL;
+ if (qxl_vga_available()) {
+ vga_interface_type = VGA_QXL;
+ } else {
+ fprintf(stderr, "Error: QXL VGA not available\n");
+ exit(0);
+ }
} else if (!strstart(p, "none", &opts)) {
invalid_vga:
fprintf(stderr, "Unknown vga type: %s\n", p);
const char *trace_events = NULL;
const char *trace_file = NULL;
-#ifdef CONFIG_SECCOMP
- if (seccomp_start() < 0) {
- fprintf(stderr,
- "seccomp: failed to install syscall filter in the kernel\n");
- exit(1);
- }
-#endif
-
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
{
static const char * const params[] = {
"order", "once", "menu",
- "splash", "splash-time", NULL
+ "splash", "splash-time",
+ "reboot-timeout", NULL
};
char buf[sizeof(boot_devices)];
char *standard_boot_devices;
break;
case QEMU_OPTION_m: {
int64_t value;
+ uint64_t sz;
char *end;
value = strtosz(optarg, &end);
fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
exit(1);
}
-
- if (value != (uint64_t)(ram_addr_t)value) {
+ sz = QEMU_ALIGN_UP((uint64_t)value, 8192);
+ ram_size = sz;
+ if (ram_size != sz) {
fprintf(stderr, "qemu: ram size too large\n");
exit(1);
}
- ram_size = value;
break;
}
case QEMU_OPTION_mempath:
}
break;
case QEMU_OPTION_usb:
- usb_enabled = 1;
+ machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+ if (machine_opts) {
+ qemu_opt_set_bool(machine_opts, "usb", true);
+ }
break;
case QEMU_OPTION_usbdevice:
- usb_enabled = 1;
+ machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+ if (machine_opts) {
+ qemu_opt_set_bool(machine_opts, "usb", true);
+ }
add_device_config(DEV_USB, optarg);
break;
case QEMU_OPTION_device:
case QEMU_OPTION_qtest_log:
qtest_log = optarg;
break;
+ case QEMU_OPTION_sandbox:
+ opts = qemu_opts_parse(qemu_find_opts("sandbox"), optarg, 1);
+ if (!opts) {
+ exit(0);
+ }
+ break;
+ case QEMU_OPTION_add_fd:
+#ifndef _WIN32
+ opts = qemu_opts_parse(qemu_find_opts("add-fd"), optarg, 0);
+ if (!opts) {
+ exit(0);
+ }
+#else
+ error_report("File descriptor passing is disabled on this "
+ "platform");
+ exit(1);
+#endif
+ break;
default:
os_parse_cmd_args(popt->index, optarg);
}
}
loc_set_none();
+ if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) {
+ exit(1);
+ }
+
+#ifndef _WIN32
+ if (qemu_opts_foreach(qemu_find_opts("add-fd"), parse_add_fd, NULL, 1)) {
+ exit(1);
+ }
+
+ if (qemu_opts_foreach(qemu_find_opts("add-fd"), cleanup_add_fd, NULL, 1)) {
+ exit(1);
+ }
+#endif
+
if (machine == NULL) {
fprintf(stderr, "No machine found.\n");
exit(1);
exit(1);
/* If no default VGA is requested, the default is "none". */
- if (default_vga && cirrus_vga_available()) {
- vga_model = "cirrus";
+ if (default_vga) {
+ if (cirrus_vga_available()) {
+ vga_model = "cirrus";
+ } else if (vga_available()) {
+ vga_model = "std";
+ }
}
select_vgahw(vga_model);
qdev_machine_init();
- machine->init(ram_size, boot_devices,
- kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
+ QEMUMachineInitArgs args = { .ram_size = ram_size,
+ .boot_device = boot_devices,
+ .kernel_filename = kernel_filename,
+ .kernel_cmdline = kernel_cmdline,
+ .initrd_filename = initrd_filename,
+ .cpu_model = cpu_model };
+ machine->init(&args);
cpu_synchronize_all_post_init();
current_machine = machine;
/* init USB devices */
- if (usb_enabled) {
+ if (usb_enabled(false)) {
if (foreach_device_config(DEV_USB, usb_parse) < 0)
exit(1);
}
break;
#if defined(CONFIG_CURSES)
case DT_CURSES:
- curses_display_init(ds, full_screen);
+ if (!is_daemonized()) {
+ curses_display_init(ds, full_screen);
+ }
break;
#endif
#if defined(CONFIG_SDL)
#ifdef CONFIG_VNC
/* init remote displays */
if (vnc_display) {
+ Error *local_err = NULL;
vnc_display_init(ds);
- if (vnc_display_open(ds, vnc_display) < 0) {
- fprintf(stderr, "Failed to start VNC server on `%s'\n",
- vnc_display);
+ vnc_display_open(ds, vnc_display, &local_err);
+ if (local_err != NULL) {
+ fprintf(stderr, "Failed to start VNC server on `%s': %s\n",
+ vnc_display, error_get_pretty(local_err));
+ error_free(local_err);
exit(1);
}
}
if (incoming) {
- Error *errp = NULL;
- int ret = qemu_start_incoming_migration(incoming, &errp);
- if (ret < 0) {
- if (error_is_set(&errp)) {
- fprintf(stderr, "Migrate: %s\n", error_get_pretty(errp));
- error_free(errp);
- }
- fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
- incoming, ret);
- exit(ret);
+ Error *local_err = NULL;
+ qemu_start_incoming_migration(incoming, &local_err);
+ if (local_err) {
+ fprintf(stderr, "-incoming %s: %s\n", incoming, error_get_pretty(local_err));
+ error_free(local_err);
+ exit(1);
}
} else if (autostart) {
vm_start();