diff options
Diffstat (limited to 'vl.c')
-rw-r--r-- | vl.c | 552 |
1 files changed, 336 insertions, 216 deletions
@@ -156,6 +156,7 @@ int main(int argc, char **argv) #include "balloon.h" #include "qemu-option.h" #include "qemu-config.h" +#include "qemu-objects.h" #include "qemu-kvm.h" #include "hw/device-assignment.h" @@ -174,9 +175,6 @@ int main(int argc, char **argv) #define DEFAULT_RAM_SIZE 128 -/* Maximum number of monitor devices */ -#define MAX_MONITOR_DEVICES 10 - static const char *data_dir; const char *bios_name = NULL; /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available @@ -196,7 +194,7 @@ int autostart; static int rtc_utc = 1; static int rtc_date_offset = -1; /* -1 means no change */ QEMUClock *rtc_clock; -int vga_interface_type = VGA_CIRRUS; +int vga_interface_type = VGA_NONE; #ifdef TARGET_SPARC int graphic_width = 1024; int graphic_height = 768; @@ -285,6 +283,41 @@ uint8_t qemu_uuid[16]; static QEMUBootSetHandler *boot_set_handler; static void *boot_set_opaque; +static int default_serial = 1; +static int default_parallel = 1; +static int default_virtcon = 1; +static int default_monitor = 1; +static int default_vga = 1; +static int default_drive = 1; + +static struct { + const char *driver; + int *flag; +} default_list[] = { + { .driver = "isa-serial", .flag = &default_serial }, + { .driver = "isa-parallel", .flag = &default_parallel }, + { .driver = "virtio-console-pci", .flag = &default_virtcon }, + { .driver = "virtio-console-s390", .flag = &default_virtcon }, + { .driver = "VGA", .flag = &default_vga }, + { .driver = "Cirrus VGA", .flag = &default_vga }, + { .driver = "QEMUware SVGA", .flag = &default_vga }, +}; + +static int default_driver_check(QemuOpts *opts, void *opaque) +{ + const char *driver = qemu_opt_get(opts, "driver"); + int i; + + if (!driver) + return 0; + for (i = 0; i < ARRAY_SIZE(default_list); i++) { + if (strcmp(default_list[i].driver, driver) != 0) + continue; + *(default_list[i].flag) = 0; + } + return 0; +} + /***********************************************************/ /* x86 ISA bus support */ @@ -472,25 +505,72 @@ int kbd_mouse_is_absolute(void) return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute; } -void do_info_mice(Monitor *mon) +static void info_mice_iter(QObject *data, void *opaque) +{ + QDict *mouse; + Monitor *mon = opaque; + + mouse = qobject_to_qdict(data); + monitor_printf(mon, "%c Mouse #%" PRId64 ": %s\n", + (qdict_get_bool(mouse, "current") ? '*' : ' '), + qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name")); +} + +void do_info_mice_print(Monitor *mon, const QObject *data) +{ + QList *mice_list; + + mice_list = qobject_to_qlist(data); + if (qlist_empty(mice_list)) { + monitor_printf(mon, "No mouse devices connected\n"); + return; + } + + qlist_iter(mice_list, info_mice_iter, mon); +} + +/** + * do_info_mice(): Show VM mice information + * + * Each mouse is represented by a QDict, the returned QObject is a QList of + * all mice. + * + * The mouse QDict contains the following: + * + * - "name": mouse's name + * - "index": mouse's index + * - "current": true if this mouse is receiving events, false otherwise + * + * Example: + * + * [ { "name": "QEMU Microsoft Mouse", "index": 0, "current": false }, + * { "name": "QEMU PS/2 Mouse", "index": 1, "current": true } ] + */ +void do_info_mice(Monitor *mon, QObject **ret_data) { QEMUPutMouseEntry *cursor; + QList *mice_list; int index = 0; + mice_list = qlist_new(); + if (!qemu_put_mouse_event_head) { - monitor_printf(mon, "No mouse devices connected\n"); - return; + goto out; } - monitor_printf(mon, "Mouse devices available:\n"); cursor = qemu_put_mouse_event_head; while (cursor != NULL) { - monitor_printf(mon, "%c Mouse #%d: %s\n", - (cursor == qemu_put_mouse_event_current ? '*' : ' '), - index, cursor->qemu_put_mouse_event_name); + QObject *obj; + obj = qobject_from_jsonf("{ 'name': %s, 'index': %d, 'current': %i }", + cursor->qemu_put_mouse_event_name, + index, cursor == qemu_put_mouse_event_current); + qlist_append_obj(mice_list, obj); index++; cursor = cursor->next; } + +out: + *ret_data = QOBJECT(mice_list); } void do_mouse_set(Monitor *mon, const QDict *qdict) @@ -4403,6 +4483,7 @@ static void select_vgahw (const char *p) { const char *opts; + default_vga = 0; vga_interface_type = VGA_NONE; if (strstart(p, "std", &opts)) { vga_interface_type = VGA_STD; @@ -4644,10 +4725,94 @@ static int device_init_func(QemuOpts *opts, void *opaque) return 0; } +static int chardev_init_func(QemuOpts *opts, void *opaque) +{ + CharDriverState *chr; + + chr = qemu_chr_open_opts(opts, NULL); + if (!chr) + return -1; + return 0; +} + +static int mon_init_func(QemuOpts *opts, void *opaque) +{ + CharDriverState *chr; + const char *chardev; + const char *mode; + int flags; + + mode = qemu_opt_get(opts, "mode"); + if (mode == NULL) { + mode = "readline"; + } + if (strcmp(mode, "readline") == 0) { + flags = MONITOR_USE_READLINE; + } else if (strcmp(mode, "control") == 0) { + flags = MONITOR_USE_CONTROL; + } else { + fprintf(stderr, "unknown monitor mode \"%s\"\n", mode); + exit(1); + } + + if (qemu_opt_get_bool(opts, "default", 0)) + flags |= MONITOR_IS_DEFAULT; + + chardev = qemu_opt_get(opts, "chardev"); + chr = qemu_chr_find(chardev); + if (chr == NULL) { + fprintf(stderr, "chardev \"%s\" not found\n", chardev); + exit(1); + } + + monitor_init(chr, flags); + return 0; +} + +static void monitor_parse(const char *optarg, const char *mode) +{ + static int monitor_device_index = 0; + QemuOpts *opts; + const char *p; + char label[32]; + int def = 0; + + if (strstart(optarg, "chardev:", &p)) { + snprintf(label, sizeof(label), "%s", p); + } else { + if (monitor_device_index) { + snprintf(label, sizeof(label), "monitor%d", + monitor_device_index); + } else { + snprintf(label, sizeof(label), "monitor"); + def = 1; + } + opts = qemu_chr_parse_compat(label, optarg); + if (!opts) { + fprintf(stderr, "parse error: %s\n", optarg); + exit(1); + } + } + + opts = qemu_opts_create(&qemu_mon_opts, label, 1); + if (!opts) { + fprintf(stderr, "duplicate chardev: %s\n", label); + exit(1); + } + qemu_opt_set(opts, "mode", mode); + qemu_opt_set(opts, "chardev", label); + if (def) + qemu_opt_set(opts, "default", "on"); + monitor_device_index++; +} + struct device_config { enum { - DEV_USB, /* -usbdevice */ - DEV_BT, /* -bt */ + DEV_USB, /* -usbdevice */ + DEV_BT, /* -bt */ + DEV_SERIAL, /* -serial */ + DEV_PARALLEL, /* -parallel */ + DEV_VIRTCON, /* -virtioconsole */ } type; const char *cmdline; QTAILQ_ENTRY(device_config) next; @@ -4679,6 +4844,72 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline)) return 0; } +static int serial_parse(const char *devname) +{ + static int index = 0; + char label[32]; + + if (strcmp(devname, "none") == 0) + return 0; + if (index == MAX_SERIAL_PORTS) { + fprintf(stderr, "qemu: too many serial ports\n"); + exit(1); + } + snprintf(label, sizeof(label), "serial%d", index); + serial_hds[index] = qemu_chr_open(label, devname, NULL); + if (!serial_hds[index]) { + fprintf(stderr, "qemu: could not open serial device '%s': %s\n", + devname, strerror(errno)); + return -1; + } + index++; + return 0; +} + +static int parallel_parse(const char *devname) +{ + static int index = 0; + char label[32]; + + if (strcmp(devname, "none") == 0) + return 0; + if (index == MAX_PARALLEL_PORTS) { + fprintf(stderr, "qemu: too many parallel ports\n"); + exit(1); + } + snprintf(label, sizeof(label), "parallel%d", index); + parallel_hds[index] = qemu_chr_open(label, devname, NULL); + if (!parallel_hds[index]) { + fprintf(stderr, "qemu: could not open parallel device '%s': %s\n", + devname, strerror(errno)); + return -1; + } + index++; + return 0; +} + +static int virtcon_parse(const char *devname) +{ + static int index = 0; + char label[32]; + + if (strcmp(devname, "none") == 0) + return 0; + if (index == MAX_VIRTIO_CONSOLES) { + fprintf(stderr, "qemu: too many virtio consoles\n"); + exit(1); + } + snprintf(label, sizeof(label), "virtcon%d", index); + virtcon_hds[index] = qemu_chr_open(label, devname, NULL); + if (!virtcon_hds[index]) { + fprintf(stderr, "qemu: could not open virtio console '%s': %s\n", + devname, strerror(errno)); + return -1; + } + index++; + return 0; +} + int main(int argc, char **argv, char **envp) { const char *gdbstub_dev = NULL; @@ -4694,16 +4925,6 @@ int main(int argc, char **argv, char **envp) QemuOpts *hda_opts = NULL, *opts; int optind; const char *r, *optarg; - CharDriverState *monitor_hds[MAX_MONITOR_DEVICES]; - const char *monitor_devices[MAX_MONITOR_DEVICES]; - int monitor_flags[MAX_MONITOR_DEVICES]; - int monitor_device_index; - const char *serial_devices[MAX_SERIAL_PORTS]; - int serial_device_index; - const char *parallel_devices[MAX_PARALLEL_PORTS]; - int parallel_device_index; - const char *virtio_consoles[MAX_VIRTIO_CONSOLES]; - int virtio_console_index; const char *loadvm = NULL; QEMUMachine *machine; const char *cpu_model; @@ -4769,43 +4990,6 @@ int main(int argc, char **argv, char **envp) cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; -#ifdef TARGET_S390X - for(i = 0; i < MAX_SERIAL_PORTS; i++) - serial_devices[i] = NULL; - serial_device_index = 0; - - for(i = 0; i < MAX_PARALLEL_PORTS; i++) - parallel_devices[i] = NULL; - parallel_device_index = 0; - - virtio_consoles[0] = "mon:stdio"; - for(i = 1; i < MAX_VIRTIO_CONSOLES; i++) - virtio_consoles[i] = NULL; - virtio_console_index = 0; -#else - serial_devices[0] = "vc:80Cx24C"; - for(i = 1; i < MAX_SERIAL_PORTS; i++) - serial_devices[i] = NULL; - serial_device_index = 0; - - parallel_devices[0] = "vc:80Cx24C"; - for(i = 1; i < MAX_PARALLEL_PORTS; i++) - parallel_devices[i] = NULL; - parallel_device_index = 0; - - for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) - virtio_consoles[i] = NULL; - virtio_console_index = 0; -#endif - - monitor_devices[0] = "vc:80Cx24C"; - monitor_flags[0] = MONITOR_IS_DEFAULT | MONITOR_USE_READLINE; - for (i = 1; i < MAX_MONITOR_DEVICES; i++) { - monitor_devices[i] = NULL; - monitor_flags[i] = MONITOR_USE_READLINE; - } - monitor_device_index = 0; - for (i = 0; i < MAX_NODES; i++) { node_mem[i] = 0; node_cpumask[i] = 0; @@ -4911,6 +5095,10 @@ int main(int argc, char **argv, char **envp) if (qemu_set_option(optarg) != 0) exit(1); break; + case QEMU_OPTION_global: + if (qemu_global_option(optarg) != 0) + exit(1); + break; case QEMU_OPTION_mtdblock: drive_add(optarg, MTD_ALIAS); break; @@ -5221,14 +5409,20 @@ int main(int argc, char **argv, char **envp) break; } case QEMU_OPTION_monitor: - if (monitor_device_index >= MAX_MONITOR_DEVICES) { - fprintf(stderr, "qemu: too many monitor devices\n"); + monitor_parse(optarg, "readline"); + default_monitor = 0; + break; + case QEMU_OPTION_qmp: + monitor_parse(optarg, "control"); + default_monitor = 0; + break; + case QEMU_OPTION_mon: + opts = qemu_opts_parse(&qemu_mon_opts, optarg, "chardev"); + if (!opts) { + fprintf(stderr, "parse error: %s\n", optarg); exit(1); } - monitor_devices[monitor_device_index] = - monitor_cmdline_parse(optarg, - &monitor_flags[monitor_device_index]); - monitor_device_index++; + default_monitor = 0; break; case QEMU_OPTION_chardev: opts = qemu_opts_parse(&qemu_chardev_opts, optarg, "backend"); @@ -5236,17 +5430,10 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "parse error: %s\n", optarg); exit(1); } - if (qemu_chr_open_opts(opts, NULL) == NULL) { - exit(1); - } break; case QEMU_OPTION_serial: - if (serial_device_index >= MAX_SERIAL_PORTS) { - fprintf(stderr, "qemu: too many serial ports\n"); - exit(1); - } - serial_devices[serial_device_index] = optarg; - serial_device_index++; + add_device_config(DEV_SERIAL, optarg); + default_serial = 0; break; case QEMU_OPTION_watchdog: if (watchdog) { @@ -5263,20 +5450,12 @@ int main(int argc, char **argv, char **envp) } break; case QEMU_OPTION_virtiocon: - if (virtio_console_index >= MAX_VIRTIO_CONSOLES) { - fprintf(stderr, "qemu: too many virtio consoles\n"); - exit(1); - } - virtio_consoles[virtio_console_index] = optarg; - virtio_console_index++; + add_device_config(DEV_VIRTCON, optarg); + default_virtcon = 0; break; case QEMU_OPTION_parallel: - if (parallel_device_index >= MAX_PARALLEL_PORTS) { - fprintf(stderr, "qemu: too many parallel ports\n"); - exit(1); - } - parallel_devices[parallel_device_index] = optarg; - parallel_device_index++; + add_device_config(DEV_PARALLEL, optarg); + default_parallel = 0; break; case QEMU_OPTION_loadvm: loadvm = optarg; @@ -5515,6 +5694,15 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_incoming: incoming = optarg; break; + case QEMU_OPTION_nodefaults: + default_serial = 0; + default_parallel = 0; + default_virtcon = 0; + default_monitor = 0; + default_vga = 0; + default_net = 0; + default_drive = 0; + break; #ifndef _WIN32 case QEMU_OPTION_chroot: chroot_dir = optarg; @@ -5596,16 +5784,50 @@ int main(int argc, char **argv, char **envp) exit(1); } - if (display_type == DT_NOGRAPHIC) { - if (serial_device_index == 0) - serial_devices[0] = "stdio"; - if (parallel_device_index == 0) - parallel_devices[0] = "null"; - if (strncmp(monitor_devices[0], "vc", 2) == 0) { - monitor_devices[0] = "stdio"; - } + qemu_opts_foreach(&qemu_device_opts, default_driver_check, NULL, 0); + + if (machine->no_serial) { + default_serial = 0; + } + if (machine->no_parallel) { + default_parallel = 0; + } + if (!machine->use_virtcon) { + default_virtcon = 0; + } + if (machine->no_vga) { + default_vga = 0; } + if (display_type == DT_NOGRAPHIC) { + if (default_parallel) + add_device_config(DEV_PARALLEL, "null"); + if (default_serial && default_monitor) { + add_device_config(DEV_SERIAL, "mon:stdio"); + } else if (default_virtcon && default_monitor) { + add_device_config(DEV_VIRTCON, "mon:stdio"); + } else { + if (default_serial) + add_device_config(DEV_SERIAL, "stdio"); + if (default_virtcon) + add_device_config(DEV_VIRTCON, "stdio"); + if (default_monitor) + monitor_parse("stdio", "readline"); + } + } else { + if (default_serial) + add_device_config(DEV_SERIAL, "vc:80Cx24C"); + if (default_parallel) + add_device_config(DEV_PARALLEL, "vc:80Cx24C"); + if (default_monitor) + monitor_parse("vc:80Cx24C", "readline"); + } + if (default_vga) + vga_interface_type = VGA_CIRRUS; + + if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0) + exit(1); + #ifndef _WIN32 if (daemonize) { pid_t pid; @@ -5736,14 +5958,16 @@ int main(int argc, char **argv, char **envp) blk_mig_init(); - /* we always create the cdrom drive, even if no disk is there */ - drive_add(NULL, CDROM_ALIAS); + if (default_drive) { + /* we always create the cdrom drive, even if no disk is there */ + drive_add(NULL, CDROM_ALIAS); - /* we always create at least one floppy */ - drive_add(NULL, FD_ALIAS, 0); + /* we always create at least one floppy */ + drive_add(NULL, FD_ALIAS, 0); - /* we always create one sd slot, even if no card is in it */ - drive_add(NULL, SD_ALIAS); + /* we always create one sd slot, even if no card is in it */ + drive_add(NULL, SD_ALIAS); + } /* open the virtual block devices */ if (snapshot) @@ -5755,32 +5979,6 @@ int main(int argc, char **argv, char **envp) register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL, ram_load, NULL); - /* Maintain compatibility with multiple stdio monitors */ - if (!strcmp(monitor_devices[0],"stdio")) { - for (i = 0; i < MAX_SERIAL_PORTS; i++) { - const char *devname = serial_devices[i]; - if (devname && !strcmp(devname,"mon:stdio")) { - monitor_devices[0] = NULL; - break; - } else if (devname && !strcmp(devname,"stdio")) { - monitor_devices[0] = NULL; - serial_devices[i] = "mon:stdio"; - break; - } - } - for (i = 0; i < MAX_VIRTIO_CONSOLES; i++) { - const char *devname = virtio_consoles[i]; - if (devname && !strcmp(devname,"mon:stdio")) { - monitor_devices[0] = NULL; - break; - } else if (devname && !strcmp(devname,"stdio")) { - monitor_devices[0] = NULL; - virtio_consoles[i] = "mon:stdio"; - break; - } - } - } - if (nb_numa_nodes > 0) { int i; @@ -5823,65 +6021,12 @@ int main(int argc, char **argv, char **envp) } } - for (i = 0; i < MAX_MONITOR_DEVICES; i++) { - const char *devname = monitor_devices[i]; - if (devname && strcmp(devname, "none")) { - char label[32]; - if (i == 0) { - snprintf(label, sizeof(label), "monitor"); - } else { - snprintf(label, sizeof(label), "monitor%d", i); - } - monitor_hds[i] = qemu_chr_open(label, devname, NULL); - if (!monitor_hds[i]) { - fprintf(stderr, "qemu: could not open monitor device '%s'\n", - devname); - exit(1); - } - } - } - - for(i = 0; i < MAX_SERIAL_PORTS; i++) { - const char *devname = serial_devices[i]; - if (devname && strcmp(devname, "none")) { - char label[32]; - snprintf(label, sizeof(label), "serial%d", i); - serial_hds[i] = qemu_chr_open(label, devname, NULL); - if (!serial_hds[i]) { - fprintf(stderr, "qemu: could not open serial device '%s': %s\n", - devname, strerror(errno)); - exit(1); - } - } - } - - for(i = 0; i < MAX_PARALLEL_PORTS; i++) { - const char *devname = parallel_devices[i]; - if (devname && strcmp(devname, "none")) { - char label[32]; - snprintf(label, sizeof(label), "parallel%d", i); - parallel_hds[i] = qemu_chr_open(label, devname, NULL); - if (!parallel_hds[i]) { - fprintf(stderr, "qemu: could not open parallel device '%s': %s\n", - devname, strerror(errno)); - exit(1); - } - } - } - - for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { - const char *devname = virtio_consoles[i]; - if (devname && strcmp(devname, "none")) { - char label[32]; - snprintf(label, sizeof(label), "virtcon%d", i); - virtcon_hds[i] = qemu_chr_open(label, devname, NULL); - if (!virtcon_hds[i]) { - fprintf(stderr, "qemu: could not open virtio console '%s': %s\n", - devname, strerror(errno)); - exit(1); - } - } - } + if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) + exit(1); + if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) + exit(1); + if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0) + exit(1); module_call_init(MODULE_INIT_DEVICE); @@ -5892,8 +6037,10 @@ int main(int argc, char **argv, char **envp) } if (machine->compat_props) { - qdev_prop_register_compat(machine->compat_props); + qdev_prop_register_global_list(machine->compat_props); } + qemu_add_globals(); + machine->init(ram_size, boot_devices, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); @@ -5986,35 +6133,8 @@ int main(int argc, char **argv, char **envp) text_consoles_set_display(display_state); - for (i = 0; i < MAX_MONITOR_DEVICES; i++) { - if (monitor_devices[i] && monitor_hds[i]) { - monitor_init(monitor_hds[i], monitor_flags[i]); - } - } - - for(i = 0; i < MAX_SERIAL_PORTS; i++) { - const char *devname = serial_devices[i]; - if (devname && strcmp(devname, "none")) { - if (strstart(devname, "vc", 0)) - qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i); - } - } - - for(i = 0; i < MAX_PARALLEL_PORTS; i++) { - const char *devname = parallel_devices[i]; - if (devname && strcmp(devname, "none")) { - if (strstart(devname, "vc", 0)) - qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i); - } - } - - for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { - const char *devname = virtio_consoles[i]; - if (virtcon_hds[i] && devname) { - if (strstart(devname, "vc", 0)) - qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i); - } - } + if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0) + exit(1); if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) { fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n", |