unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
int boot_menu;
+uint8_t *boot_splash_filedata;
+int boot_splash_filedata_size;
+uint8_t qemu_extra_params_fw[2];
typedef struct FWBootEntry FWBootEntry;
static NotifierList machine_init_done_notifiers =
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
+static int tcg_allowed = 1;
int kvm_allowed = 0;
+int xen_allowed = 0;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
+static int tcg_tb_size;
static int default_serial = 1;
static int default_parallel = 1;
{ .driver = "isa-serial", .flag = &default_serial },
{ .driver = "isa-parallel", .flag = &default_parallel },
{ .driver = "isa-fdc", .flag = &default_floppy },
+ { .driver = "ide-cd", .flag = &default_cdrom },
+ { .driver = "ide-hd", .flag = &default_cdrom },
{ .driver = "ide-drive", .flag = &default_cdrom },
+ { .driver = "scsi-cd", .flag = &default_cdrom },
{ .driver = "virtio-serial-pci", .flag = &default_virtcon },
{ .driver = "virtio-serial-s390", .flag = &default_virtcon },
{ .driver = "virtio-serial", .flag = &default_virtcon },
{ .driver = "VGA", .flag = &default_vga },
{ .driver = "cirrus-vga", .flag = &default_vga },
{ .driver = "vmware-svga", .flag = &default_vga },
+ { .driver = "isa-vga", .flag = &default_vga },
+ { .driver = "qxl-vga", .flag = &default_vga },
};
+static void res_free(void)
+{
+ if (boot_splash_filedata != NULL) {
+ qemu_free(boot_splash_filedata);
+ boot_splash_filedata = NULL;
+ }
+}
+
static int default_driver_check(QemuOpts *opts, void *opaque)
{
const char *driver = qemu_opt_get(opts, "driver");
/*
* This function returns null terminated string that consist of new line
- * separated device pathes.
+ * separated device paths.
*
* memory pointed by "size" is assigned total length of the array in bytes
*
goto done;
/* the other ones */
+#ifndef CONFIG_LINUX
+ /* only the linux version is qdev-ified, usb-bsd still needs this */
if (strstart(devname, "host:", &p)) {
dev = usb_host_device_open(p);
- } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
+ } else
+#endif
+ if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
dev = usb_bt_init(devname[2] ? hci_init(p) :
bt_new_hci(qemu_find_bt_vlan(0)));
} else {
static int debug_requested;
static int vmstop_requested;
+int qemu_shutdown_requested_get(void)
+{
+ return shutdown_requested;
+}
+
+int qemu_reset_requested_get(void)
+{
+ return reset_requested;
+}
+
int qemu_shutdown_requested(void)
{
int r = shutdown_requested;
*/
fputc('\n', stderr);
} else {
- fprintf(stderr, " from pid %d\n", shutdown_pid);
+ fprintf(stderr, " from pid " FMT_pid "\n", shutdown_pid);
}
shutdown_signal = -1;
}
}
}
-void qemu_system_reset(void)
+void qemu_system_reset(bool report)
{
QEMUResetEntry *re, *nre;
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
re->func(re->opaque);
}
- monitor_protocol_event(QEVENT_RESET, NULL);
+ if (report) {
+ monitor_protocol_event(QEVENT_RESET, NULL);
+ }
cpu_synchronize_all_post_reset();
}
monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
if (no_shutdown) {
vm_stop(VMSTOP_SHUTDOWN);
- no_shutdown = 0;
} else
break;
}
if (qemu_reset_requested()) {
pause_all_vcpus();
cpu_synchronize_all_states();
- qemu_system_reset();
+ qemu_system_reset(VMRESET_REPORT);
resume_all_vcpus();
}
if (qemu_powerdown_requested()) {
/* create empty opts */
opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
}
- qemu_opt_set(opts, "driver", "virtio-balloon-pci");
+ qemu_opt_set(opts, "driver", "virtio-balloon");
return 0;
}
return 0;
}
+static QEMUMachine *machine_parse(const char *name)
+{
+ QEMUMachine *m, *machine = NULL;
+
+ if (name) {
+ machine = find_machine(name);
+ }
+ if (machine) {
+ return machine;
+ }
+ printf("Supported machines are:\n");
+ for (m = first_machine; m != NULL; m = m->next) {
+ if (m->alias) {
+ printf("%-10s %s (alias of %s)\n", m->alias, m->desc, m->name);
+ }
+ printf("%-10s %s%s\n", m->name, m->desc,
+ m->is_default ? " (default)" : "");
+ }
+ exit(!name || *name != '?');
+}
+
+static int tcg_init(void)
+{
+ tcg_exec_init(tcg_tb_size * 1024 * 1024);
+ return 0;
+}
+
+static struct {
+ const char *opt_name;
+ const char *name;
+ int (*available)(void);
+ int (*init)(void);
+ int *allowed;
+} accel_list[] = {
+ { "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
+ { "xen", "Xen", xen_available, xen_init, &xen_allowed },
+ { "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
+};
+
+static int configure_accelerator(void)
+{
+ const char *p = NULL;
+ char buf[10];
+ int i, ret;
+ bool accel_initalised = 0;
+ bool init_failed = 0;
+
+ QemuOptsList *list = qemu_find_opts("machine");
+ if (!QTAILQ_EMPTY(&list->head)) {
+ p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel");
+ }
+
+ if (p == NULL) {
+ /* Use the default "accelerator", tcg */
+ p = "tcg";
+ }
+
+ while (!accel_initalised && *p != '\0') {
+ if (*p == ':') {
+ p++;
+ }
+ p = get_opt_name(buf, sizeof (buf), p, ':');
+ for (i = 0; i < ARRAY_SIZE(accel_list); i++) {
+ if (strcmp(accel_list[i].opt_name, buf) == 0) {
+ *(accel_list[i].allowed) = 1;
+ ret = accel_list[i].init();
+ if (ret < 0) {
+ init_failed = 1;
+ if (!accel_list[i].available()) {
+ printf("%s not supported for this target\n",
+ accel_list[i].name);
+ } else {
+ fprintf(stderr, "failed to initialize %s: %s\n",
+ accel_list[i].name,
+ strerror(-ret));
+ }
+ *(accel_list[i].allowed) = 0;
+ } else {
+ accel_initalised = 1;
+ }
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(accel_list)) {
+ fprintf(stderr, "\"%s\" accelerator does not exist.\n", buf);
+ }
+ }
+
+ if (!accel_initalised) {
+ fprintf(stderr, "No accelerator found!\n");
+ exit(1);
+ }
+
+ if (init_failed) {
+ fprintf(stderr, "Back to %s accelerator.\n", accel_list[i].name);
+ }
+
+ return !accel_initalised;
+}
+
void qemu_add_exit_notifier(Notifier *notify)
{
notifier_list_add(&exit_notifiers, notify);
static void qemu_run_exit_notifiers(void)
{
- notifier_list_notify(&exit_notifiers);
+ notifier_list_notify(&exit_notifiers, NULL);
}
void qemu_add_machine_init_done_notifier(Notifier *notify)
static void qemu_run_machine_init_done_notifiers(void)
{
- notifier_list_notify(&machine_init_done_notifiers);
+ notifier_list_notify(&machine_init_done_notifiers, NULL);
}
static const QEMUOption *lookup_opt(int argc, char **argv,
const char *loadvm = NULL;
QEMUMachine *machine;
const char *cpu_model;
- int tb_size;
const char *pid_file = NULL;
const char *incoming = NULL;
#ifdef CONFIG_VNC
#endif
int defconfig = 1;
const char *trace_file = NULL;
+ const char *log_mask = NULL;
+ const char *log_file = NULL;
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
nb_numa_nodes = 0;
nb_nics = 0;
- tb_size = 0;
autostart= 1;
/* first pass of option parsing */
}
switch(popt->index) {
case QEMU_OPTION_M:
- machine = find_machine(optarg);
- if (!machine) {
- QEMUMachine *m;
- printf("Supported machines are:\n");
- for(m = first_machine; m != NULL; m = m->next) {
- if (m->alias)
- printf("%-10s %s (alias of %s)\n",
- m->alias, m->desc, m->name);
- printf("%-10s %s%s\n",
- m->name, m->desc,
- m->is_default ? " (default)" : "");
- }
- exit(*optarg != '?');
- }
+ machine = machine_parse(optarg);
break;
case QEMU_OPTION_cpu:
/* hw initialization will check this */
HD_OPTS);
break;
case QEMU_OPTION_drive:
- drive_def(optarg);
+ if (drive_def(optarg) == NULL) {
+ exit(1);
+ }
break;
case QEMU_OPTION_set:
if (qemu_set_option(optarg) != 0)
#endif
break;
case QEMU_OPTION_portrait:
- graphic_rotate = 1;
+ graphic_rotate = 90;
+ break;
+ case QEMU_OPTION_rotate:
+ graphic_rotate = strtol(optarg, (char **) &optarg, 10);
+ if (graphic_rotate != 0 && graphic_rotate != 90 &&
+ graphic_rotate != 180 && graphic_rotate != 270) {
+ fprintf(stderr,
+ "qemu: only 90, 180, 270 deg rotation is available\n");
+ exit(1);
+ }
break;
case QEMU_OPTION_kernel:
kernel_filename = optarg;
case QEMU_OPTION_boot:
{
static const char * const params[] = {
- "order", "once", "menu", NULL
+ "order", "once", "menu",
+ "splash", "splash-time", NULL
};
char buf[sizeof(boot_devices)];
char *standard_boot_devices;
exit(1);
}
}
+ qemu_opts_parse(qemu_find_opts("boot-opts"),
+ optarg, 0);
}
}
break;
exit(1);
}
- /* On 32-bit hosts, QEMU is limited by virtual address space */
- if (value > (2047 << 20) && HOST_LONG_BITS == 32) {
- fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
- exit(1);
- }
if (value != (uint64_t)(ram_addr_t)value) {
fprintf(stderr, "qemu: ram size too large\n");
exit(1);
break;
#endif
case QEMU_OPTION_d:
- set_cpu_log(optarg);
+ log_mask = optarg;
+ break;
+ case QEMU_OPTION_D:
+ log_file = optarg;
break;
case QEMU_OPTION_s:
gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
}
break;
case QEMU_OPTION_virtfs: {
- char *arg_fsdev = NULL;
- char *arg_9p = NULL;
- int len = 0;
+ QemuOpts *fsdev;
+ QemuOpts *device;
olist = qemu_find_opts("virtfs");
if (!olist) {
qemu_opt_get(opts, "security_model") == NULL) {
fprintf(stderr, "Usage: -virtfs fstype,path=/share_path/,"
"security_model=[mapped|passthrough|none],"
- "mnt_tag=tag.\n");
+ "mount_tag=tag.\n");
exit(1);
}
- len = strlen(",id=,path=,security_model=");
- len += strlen(qemu_opt_get(opts, "fstype"));
- len += strlen(qemu_opt_get(opts, "mount_tag"));
- len += strlen(qemu_opt_get(opts, "path"));
- len += strlen(qemu_opt_get(opts, "security_model"));
- arg_fsdev = qemu_malloc((len + 1) * sizeof(*arg_fsdev));
-
- snprintf(arg_fsdev, (len + 1) * sizeof(*arg_fsdev),
- "%s,id=%s,path=%s,security_model=%s",
- qemu_opt_get(opts, "fstype"),
- qemu_opt_get(opts, "mount_tag"),
- qemu_opt_get(opts, "path"),
- qemu_opt_get(opts, "security_model"));
-
- len = strlen("virtio-9p-pci,fsdev=,mount_tag=");
- len += 2*strlen(qemu_opt_get(opts, "mount_tag"));
- arg_9p = qemu_malloc((len + 1) * sizeof(*arg_9p));
-
- snprintf(arg_9p, (len + 1) * sizeof(*arg_9p),
- "virtio-9p-pci,fsdev=%s,mount_tag=%s",
- qemu_opt_get(opts, "mount_tag"),
- qemu_opt_get(opts, "mount_tag"));
-
- if (!qemu_opts_parse(qemu_find_opts("fsdev"), arg_fsdev, 1)) {
- fprintf(stderr, "parse error [fsdev]: %s\n", optarg);
+ fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
+ qemu_opt_get(opts, "mount_tag"), 1);
+ if (!fsdev) {
+ fprintf(stderr, "duplicate fsdev id: %s\n",
+ qemu_opt_get(opts, "mount_tag"));
exit(1);
}
-
- if (!qemu_opts_parse(qemu_find_opts("device"), arg_9p, 1)) {
- fprintf(stderr, "parse error [device]: %s\n", optarg);
- exit(1);
- }
-
- qemu_free(arg_fsdev);
- qemu_free(arg_9p);
+ qemu_opt_set(fsdev, "fstype", qemu_opt_get(opts, "fstype"));
+ qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
+ qemu_opt_set(fsdev, "security_model",
+ qemu_opt_get(opts, "security_model"));
+
+ device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+ qemu_opt_set(device, "driver", "virtio-9p-pci");
+ qemu_opt_set(device, "fsdev",
+ qemu_opt_get(opts, "mount_tag"));
+ qemu_opt_set(device, "mount_tag",
+ qemu_opt_get(opts, "mount_tag"));
break;
}
case QEMU_OPTION_serial:
do_smbios_option(optarg);
break;
case QEMU_OPTION_enable_kvm:
- kvm_allowed = 1;
+ olist = qemu_find_opts("machine");
+ qemu_opts_reset(olist);
+ qemu_opts_parse(olist, "accel=kvm", 0);
+ break;
+ case QEMU_OPTION_machine:
+ olist = qemu_find_opts("machine");
+ qemu_opts_reset(olist);
+ opts = qemu_opts_parse(olist, optarg, 1);
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
+ }
+ optarg = qemu_opt_get(opts, "type");
+ if (optarg) {
+ machine = machine_parse(optarg);
+ }
break;
case QEMU_OPTION_usb:
usb_enabled = 1;
configure_rtc(opts);
break;
case QEMU_OPTION_tb_size:
- tb_size = strtol(optarg, NULL, 0);
- if (tb_size < 0)
- tb_size = 0;
+ tcg_tb_size = strtol(optarg, NULL, 0);
+ if (tcg_tb_size < 0) {
+ tcg_tb_size = 0;
+ }
break;
case QEMU_OPTION_icount:
icount_option = optarg;
}
loc_set_none();
+ /* Open the logfile at this point, if necessary. We can't open the logfile
+ * when encountering either of the logging options (-d or -D) because the
+ * other one may be encountered later on the command line, changing the
+ * location or level of logging.
+ */
+ if (log_mask) {
+ if (log_file) {
+ set_cpu_log_filename(log_file);
+ }
+ set_cpu_log(log_mask);
+ }
+
if (!st_init(trace_file)) {
fprintf(stderr, "warning: unable to initialize simple trace backend\n");
}
exit(1);
}
+ /*
+ * Get the default machine options from the machine if it is not already
+ * specified either by the configuration file or by the command line.
+ */
+ if (machine->default_machine_opts) {
+ QemuOptsList *list = qemu_find_opts("machine");
+ const char *p = NULL;
+
+ if (!QTAILQ_EMPTY(&list->head)) {
+ p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel");
+ }
+ if (p == NULL) {
+ qemu_opts_reset(list);
+ opts = qemu_opts_parse(list, machine->default_machine_opts, 0);
+ if (!opts) {
+ fprintf(stderr, "parse error for machine %s: %s\n",
+ machine->name, machine->default_machine_opts);
+ exit(1);
+ }
+ }
+ }
+
qemu_opts_foreach(qemu_find_opts("device"), default_driver_check, NULL, 0);
qemu_opts_foreach(qemu_find_opts("global"), default_driver_check, NULL, 0);
exit(1);
}
- if (kvm_allowed) {
- int ret = kvm_init();
- if (ret < 0) {
- if (!kvm_available()) {
- printf("KVM not supported for this target\n");
- } else {
- fprintf(stderr, "failed to initialize KVM: %s\n", strerror(-ret));
- }
- exit(1);
- }
- }
+ configure_accelerator();
if (qemu_init_main_loop()) {
fprintf(stderr, "qemu_init_main_loop failed\n");
exit(1);
/* init the memory */
- if (ram_size == 0)
+ if (ram_size == 0) {
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
+ }
+
+ if (!xen_enabled()) {
+ /* On 32-bit hosts, QEMU is limited by virtual address space */
+ if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
+ fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
+ exit(1);
+ }
+ }
- /* init the dynamic translator */
- cpu_exec_init_all(tb_size * 1024 * 1024);
+ cpu_exec_init_all();
bdrv_init_with_whitelist();
if (nb_numa_nodes > 0) {
int i;
- if (nb_numa_nodes > smp_cpus) {
- nb_numa_nodes = smp_cpus;
+ if (nb_numa_nodes > MAX_NODES) {
+ nb_numa_nodes = MAX_NODES;
}
/* If no memory size if given for any node, assume the default case
qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
qemu_run_machine_init_done_notifiers();
- qemu_system_reset();
+ qemu_system_reset(VMRESET_SILENT);
if (loadvm) {
if (load_vmstate(loadvm) < 0) {
autostart = 0;
main_loop();
quit_timers();
net_cleanup();
+ res_free();
return 0;
}