X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=vl.c;h=acfff858a19d63a06c713049c70a40bdd05b70e8;hb=e6d43cfb1f937898dc031c7b38a23e5ccad8bd9a;hp=33f844fdbcf783fdf601852b1517505ed49c121e;hpb=cad1e2827b616487e3574300f2eaeea13a355197;p=mirror_qemu.git diff --git a/vl.c b/vl.c index 33f844fdbc..acfff858a1 100644 --- a/vl.c +++ b/vl.c @@ -47,9 +47,6 @@ #include #include #include -#ifdef CONFIG_SIMPLE_TRACE -#include "trace.h" -#endif #ifdef CONFIG_BSD #include @@ -159,6 +156,7 @@ int main(int argc, char **argv) #include "slirp/libslirp.h" #include "trace.h" +#include "simpletrace.h" #include "qemu-queue.h" #include "cpus.h" #include "arch_init.h" @@ -208,7 +206,9 @@ int smp_cpus = 1; int max_cpus = 0; int smp_cores = 1; int smp_threads = 1; +#ifdef CONFIG_VNC const char *vnc_display; +#endif int acpi_enabled = 1; int no_hpet = 0; int fd_bootchk = 1; @@ -257,7 +257,9 @@ static NotifierList exit_notifiers = 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; @@ -277,13 +279,18 @@ static struct { { .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 int default_driver_check(QemuOpts *opts, void *opaque) @@ -621,23 +628,18 @@ static int bt_parse(const char *opt) /***********************************************************/ /* QEMU Block devices */ -#define HD_ALIAS "index=%d,media=disk" -#define CDROM_ALIAS "index=2,media=cdrom" -#define FD_ALIAS "index=%d,if=floppy" -#define PFLASH_ALIAS "if=pflash" -#define MTD_ALIAS "if=mtd" -#define SD_ALIAS "index=0,if=sd" +#define HD_OPTS "media=disk" +#define CDROM_OPTS "media=cdrom" +#define FD_OPTS "" +#define PFLASH_OPTS "" +#define MTD_OPTS "" +#define SD_OPTS "" static int drive_init_func(QemuOpts *opts, void *opaque) { int *use_scsi = opaque; - int fatal_error = 0; - if (drive_init(opts, *use_scsi, &fatal_error) == NULL) { - if (fatal_error) - return 1; - } - return 0; + return drive_init(opts, *use_scsi) == NULL; } static int drive_enable_snapshot(QemuOpts *opts, void *opaque) @@ -648,6 +650,29 @@ static int drive_enable_snapshot(QemuOpts *opts, void *opaque) return 0; } +static void default_drive(int enable, int snapshot, int use_scsi, + BlockInterfaceType type, int index, + const char *optstr) +{ + QemuOpts *opts; + + if (type == IF_DEFAULT) { + type = use_scsi ? IF_SCSI : IF_IDE; + } + + if (!enable || drive_get_by_index(type, index)) { + return; + } + + opts = drive_add(type, index, NULL, optstr); + if (snapshot) { + drive_enable_snapshot(opts, NULL); + } + if (!drive_init(opts, use_scsi)) { + exit(1); + } +} + void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque) { boot_set_handler = func; @@ -720,7 +745,7 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, node = qemu_mallocz(sizeof(FWBootEntry)); node->bootindex = bootindex; - node->suffix = strdup(suffix); + node->suffix = suffix ? qemu_strdup(suffix) : NULL; node->dev = dev; QTAILQ_FOREACH(i, &fw_boot_order, link) { @@ -738,7 +763,7 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, /* * 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 * @@ -767,7 +792,7 @@ char *get_boot_devices_list(uint32_t *size) } else if (devpath) { bootpath = devpath; } else { - bootpath = strdup(i->suffix); + bootpath = qemu_strdup(i->suffix); assert(bootpath); } @@ -804,7 +829,7 @@ static void numa_add(const char *optarg) if (get_param_value(option, 128, "mem", optarg) == 0) { node_mem[nodenr] = 0; } else { - ssize_t sval; + int64_t sval; sval = strtosz(option, NULL); if (sval < 0) { fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg); @@ -900,9 +925,13 @@ static int usb_device_add(const char *devname) 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 { @@ -1004,68 +1033,6 @@ void pcmcia_info(Monitor *mon) "Empty"); } -/***********************************************************/ -/* I/O handling */ - -typedef struct IOHandlerRecord { - int fd; - IOCanReadHandler *fd_read_poll; - IOHandler *fd_read; - IOHandler *fd_write; - int deleted; - void *opaque; - /* temporary data */ - struct pollfd *ufd; - QLIST_ENTRY(IOHandlerRecord) next; -} IOHandlerRecord; - -static QLIST_HEAD(, IOHandlerRecord) io_handlers = - QLIST_HEAD_INITIALIZER(io_handlers); - - -/* XXX: fd_read_poll should be suppressed, but an API change is - necessary in the character devices to suppress fd_can_read(). */ -int qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) -{ - IOHandlerRecord *ioh; - - if (!fd_read && !fd_write) { - QLIST_FOREACH(ioh, &io_handlers, next) { - if (ioh->fd == fd) { - ioh->deleted = 1; - break; - } - } - } else { - QLIST_FOREACH(ioh, &io_handlers, next) { - if (ioh->fd == fd) - goto found; - } - ioh = qemu_mallocz(sizeof(IOHandlerRecord)); - QLIST_INSERT_HEAD(&io_handlers, ioh, next); - found: - ioh->fd = fd; - ioh->fd_read_poll = fd_read_poll; - ioh->fd_read = fd_read; - ioh->fd_write = fd_write; - ioh->opaque = opaque; - ioh->deleted = 0; - } - return 0; -} - -int qemu_set_fd_handler(int fd, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) -{ - return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); -} - /***********************************************************/ /* machine registration */ @@ -1126,7 +1093,7 @@ static void gui_update(void *opaque) interval = dcl->gui_timer_interval; dcl = dcl->next; } - qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock)); + qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock)); } static void nographic_update(void *opaque) @@ -1134,7 +1101,7 @@ static void nographic_update(void *opaque) uint64_t interval = GUI_REFRESH_INTERVAL; qemu_flush_coalesced_mmio_buffer(); - qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock)); + qemu_mod_timer(nographic_timer, interval + qemu_get_clock_ms(rt_clock)); } struct vm_change_state_entry { @@ -1197,10 +1164,21 @@ typedef struct QEMUResetEntry { static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers = QTAILQ_HEAD_INITIALIZER(reset_handlers); static int reset_requested; -static int shutdown_requested; +static int shutdown_requested, shutdown_signal = -1; +static pid_t shutdown_pid; static int powerdown_requested; -int debug_requested; -int vmstop_requested; +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) { @@ -1209,6 +1187,22 @@ int qemu_shutdown_requested(void) return r; } +void qemu_kill_report(void) +{ + if (shutdown_signal != -1) { + fprintf(stderr, "qemu: terminating on signal %d", shutdown_signal); + if (shutdown_pid == 0) { + /* This happens for eg ^C at the terminal, so it's worth + * avoiding printing an odd message in that case. + */ + fputc('\n', stderr); + } else { + fprintf(stderr, " from pid " FMT_pid "\n", shutdown_pid); + } + shutdown_signal = -1; + } +} + int qemu_reset_requested(void) { int r = reset_requested; @@ -1259,7 +1253,7 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) } } -void qemu_system_reset(void) +void qemu_system_reset(bool report) { QEMUResetEntry *re, *nre; @@ -1267,7 +1261,9 @@ void qemu_system_reset(void) 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(); } @@ -1278,9 +1274,17 @@ void qemu_system_reset_request(void) } else { reset_requested = 1; } + cpu_stop_current(); qemu_notify_event(); } +void qemu_system_killed(int signal, pid_t pid) +{ + shutdown_signal = signal; + shutdown_pid = pid; + qemu_system_shutdown_request(); +} + void qemu_system_shutdown_request(void) { shutdown_requested = 1; @@ -1293,9 +1297,20 @@ void qemu_system_powerdown_request(void) qemu_notify_event(); } +void qemu_system_debug_request(void) +{ + debug_requested = 1; + qemu_notify_event(); +} + +void qemu_system_vmstop_request(int reason) +{ + vmstop_requested = reason; + qemu_notify_event(); +} + void main_loop_wait(int nonblocking) { - IOHandlerRecord *ioh; fd_set rfds, wfds, xfds; int ret, nfds; struct timeval tv; @@ -1310,56 +1325,23 @@ void main_loop_wait(int nonblocking) os_host_main_loop_wait(&timeout); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + /* poll any events */ /* XXX: separate device handlers from system ones */ nfds = -1; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&xfds); - QLIST_FOREACH(ioh, &io_handlers, next) { - if (ioh->deleted) - continue; - if (ioh->fd_read && - (!ioh->fd_read_poll || - ioh->fd_read_poll(ioh->opaque) != 0)) { - FD_SET(ioh->fd, &rfds); - if (ioh->fd > nfds) - nfds = ioh->fd; - } - if (ioh->fd_write) { - FD_SET(ioh->fd, &wfds); - if (ioh->fd > nfds) - nfds = ioh->fd; - } - } - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - + qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds); slirp_select_fill(&nfds, &rfds, &wfds, &xfds); qemu_mutex_unlock_iothread(); ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); qemu_mutex_lock_iothread(); - if (ret > 0) { - IOHandlerRecord *pioh; - - QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { - if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { - ioh->fd_read(ioh->opaque); - } - if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { - ioh->fd_write(ioh->opaque); - } - - /* Do this last in case read/write handlers marked it for deletion */ - if (ioh->deleted) { - QLIST_REMOVE(ioh, next); - qemu_free(ioh); - } - } - } + qemu_iohandler_poll(&rfds, &wfds, &xfds, ret); slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0)); qemu_run_all_timers(); @@ -1370,59 +1352,60 @@ void main_loop_wait(int nonblocking) } -static int vm_can_run(void) +#ifndef CONFIG_IOTHREAD +static int vm_request_pending(void) { - if (powerdown_requested) - return 0; - if (reset_requested) - return 0; - if (shutdown_requested) - return 0; - if (debug_requested) - return 0; - return 1; + return powerdown_requested || + reset_requested || + shutdown_requested || + debug_requested || + vmstop_requested; } +#endif qemu_irq qemu_system_powerdown; static void main_loop(void) { + bool nonblocking = false; +#ifdef CONFIG_PROFILER + int64_t ti; +#endif int r; qemu_main_loop_start(); for (;;) { - do { - bool nonblocking = false; -#ifdef CONFIG_PROFILER - int64_t ti; -#endif #ifndef CONFIG_IOTHREAD - nonblocking = cpu_exec_all(); + nonblocking = cpu_exec_all(); + if (vm_request_pending()) { + nonblocking = true; + } #endif #ifdef CONFIG_PROFILER - ti = profile_getclock(); + ti = profile_getclock(); #endif - main_loop_wait(nonblocking); + main_loop_wait(nonblocking); #ifdef CONFIG_PROFILER - dev_time += profile_getclock() - ti; + dev_time += profile_getclock() - ti; #endif - } while (vm_can_run()); - if ((r = qemu_debug_requested())) { - vm_stop(r); + if (qemu_debug_requested()) { + vm_stop(VMSTOP_DEBUG); } if (qemu_shutdown_requested()) { + qemu_kill_report(); monitor_protocol_event(QEVENT_SHUTDOWN, NULL); if (no_shutdown) { - vm_stop(0); + vm_stop(VMSTOP_SHUTDOWN); no_shutdown = 0; } else break; } if (qemu_reset_requested()) { pause_all_vcpus(); - qemu_system_reset(); + cpu_synchronize_all_states(); + qemu_system_reset(VMRESET_REPORT); resume_all_vcpus(); } if (qemu_powerdown_requested()) { @@ -1526,6 +1509,100 @@ static void select_vgahw (const char *p) } } +static DisplayType select_display(const char *p) +{ + const char *opts; + DisplayType display = DT_DEFAULT; + + if (strstart(p, "sdl", &opts)) { +#ifdef CONFIG_SDL + display = DT_SDL; + while (*opts) { + const char *nextopt; + + if (strstart(opts, ",frame=", &nextopt)) { + opts = nextopt; + if (strstart(opts, "on", &nextopt)) { + no_frame = 0; + } else if (strstart(opts, "off", &nextopt)) { + no_frame = 1; + } else { + goto invalid_sdl_args; + } + } else if (strstart(opts, ",alt_grab=", &nextopt)) { + opts = nextopt; + if (strstart(opts, "on", &nextopt)) { + alt_grab = 1; + } else if (strstart(opts, "off", &nextopt)) { + alt_grab = 0; + } else { + goto invalid_sdl_args; + } + } else if (strstart(opts, ",ctrl_grab=", &nextopt)) { + opts = nextopt; + if (strstart(opts, "on", &nextopt)) { + ctrl_grab = 1; + } else if (strstart(opts, "off", &nextopt)) { + ctrl_grab = 0; + } else { + goto invalid_sdl_args; + } + } else if (strstart(opts, ",window_close=", &nextopt)) { + opts = nextopt; + if (strstart(opts, "on", &nextopt)) { + no_quit = 0; + } else if (strstart(opts, "off", &nextopt)) { + no_quit = 1; + } else { + goto invalid_sdl_args; + } + } else { + invalid_sdl_args: + fprintf(stderr, "Invalid SDL option string: %s\n", p); + exit(1); + } + opts = nextopt; + } +#else + fprintf(stderr, "SDL support is disabled\n"); + exit(1); +#endif + } else if (strstart(p, "vnc", &opts)) { +#ifdef CONFIG_VNC + display_remote++; + + if (*opts) { + const char *nextopt; + + if (strstart(opts, "=", &nextopt)) { + vnc_display = nextopt; + } + } + if (!vnc_display) { + fprintf(stderr, "VNC requires a display argument vnc=\n"); + exit(1); + } +#else + fprintf(stderr, "VNC support is disabled\n"); + exit(1); +#endif + } else if (strstart(p, "curses", &opts)) { +#ifdef CONFIG_CURSES + display = DT_CURSES; +#else + fprintf(stderr, "Curses support is disabled\n"); + exit(1); +#endif + } else if (strstart(p, "none", &opts)) { + display = DT_NONE; + } else { + fprintf(stderr, "Unknown display type: %s\n", p); + exit(1); + } + + return display; +} + static int balloon_parse(const char *arg) { QemuOpts *opts; @@ -1544,7 +1621,7 @@ static int balloon_parse(const char *arg) /* 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; } @@ -1822,6 +1899,105 @@ static int debugcon_parse(const char *devname) 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) +{ + 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); @@ -1909,12 +2085,14 @@ int main(int argc, char **argv, char **envp) int tb_size; const char *pid_file = NULL; const char *incoming = NULL; +#ifdef CONFIG_VNC int show_vnc_port = 0; +#endif int defconfig = 1; - -#ifdef CONFIG_SIMPLE_TRACE const char *trace_file = NULL; -#endif + const char *log_mask = NULL; + const char *log_file = NULL; + atexit(qemu_run_exit_notifiers); error_set_progname(argv[0]); @@ -1987,7 +2165,7 @@ int main(int argc, char **argv, char **envp) if (optind >= argc) break; if (argv[optind][0] != '-') { - hda_opts = drive_add(argv[optind++], HD_ALIAS, 0); + hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS); } else { const QEMUOption *popt; @@ -1998,20 +2176,7 @@ int main(int argc, char **argv, char **envp) } 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 */ @@ -2026,24 +2191,31 @@ int main(int argc, char **argv, char **envp) initrd_filename = optarg; break; case QEMU_OPTION_hda: - if (cyls == 0) - hda_opts = drive_add(optarg, HD_ALIAS, 0); - else - hda_opts = drive_add(optarg, HD_ALIAS - ",cyls=%d,heads=%d,secs=%d%s", - 0, cyls, heads, secs, - translation == BIOS_ATA_TRANSLATION_LBA ? + { + char buf[256]; + if (cyls == 0) + snprintf(buf, sizeof(buf), "%s", HD_OPTS); + else + snprintf(buf, sizeof(buf), + "%s,cyls=%d,heads=%d,secs=%d%s", + HD_OPTS , cyls, heads, secs, + translation == BIOS_ATA_TRANSLATION_LBA ? ",trans=lba" : - translation == BIOS_ATA_TRANSLATION_NONE ? + translation == BIOS_ATA_TRANSLATION_NONE ? ",trans=none" : ""); - break; + drive_add(IF_DEFAULT, 0, optarg, buf); + break; + } case QEMU_OPTION_hdb: case QEMU_OPTION_hdc: case QEMU_OPTION_hdd: - drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda); + drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optarg, + HD_OPTS); break; case QEMU_OPTION_drive: - drive_add(NULL, "%s", optarg); + if (drive_def(optarg) == NULL) { + exit(1); + } break; case QEMU_OPTION_set: if (qemu_set_option(optarg) != 0) @@ -2054,13 +2226,13 @@ int main(int argc, char **argv, char **envp) exit(1); break; case QEMU_OPTION_mtdblock: - drive_add(optarg, MTD_ALIAS); + drive_add(IF_MTD, -1, optarg, MTD_OPTS); break; case QEMU_OPTION_sd: - drive_add(optarg, SD_ALIAS); + drive_add(IF_SD, 0, optarg, SD_OPTS); break; case QEMU_OPTION_pflash: - drive_add(optarg, PFLASH_ALIAS); + drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS); break; case QEMU_OPTION_snapshot: snapshot = 1; @@ -2121,16 +2293,31 @@ int main(int argc, char **argv, char **envp) } numa_add(optarg); break; + case QEMU_OPTION_display: + display_type = select_display(optarg); + break; case QEMU_OPTION_nographic: display_type = DT_NOGRAPHIC; break; -#ifdef CONFIG_CURSES case QEMU_OPTION_curses: +#ifdef CONFIG_CURSES display_type = DT_CURSES; - break; +#else + fprintf(stderr, "Curses support is disabled\n"); + exit(1); #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; @@ -2139,7 +2326,7 @@ int main(int argc, char **argv, char **envp) kernel_cmdline = optarg; break; case QEMU_OPTION_cdrom: - drive_add(optarg, CDROM_ALIAS); + drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS); break; case QEMU_OPTION_boot: { @@ -2192,7 +2379,8 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_fda: case QEMU_OPTION_fdb: - drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda); + drive_add(IF_FLOPPY, popt->index - QEMU_OPTION_fda, + optarg, FD_OPTS); break; case QEMU_OPTION_no_fd_bootchk: fd_bootchk = 0; @@ -2245,7 +2433,7 @@ int main(int argc, char **argv, char **envp) exit(0); break; case QEMU_OPTION_m: { - ssize_t value; + int64_t value; value = strtosz(optarg, NULL); if (value < 0) { @@ -2274,7 +2462,10 @@ int main(int argc, char **argv, char **envp) 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; @@ -2379,9 +2570,8 @@ int main(int argc, char **argv, char **envp) } 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) { @@ -2400,45 +2590,28 @@ int main(int argc, char **argv, char **envp) 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: @@ -2501,6 +2674,14 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_sdl: display_type = DT_SDL; break; +#else + case QEMU_OPTION_no_frame: + case QEMU_OPTION_alt_grab: + case QEMU_OPTION_ctrl_grab: + case QEMU_OPTION_no_quit: + case QEMU_OPTION_sdl: + fprintf(stderr, "SDL support is disabled\n"); + exit(1); #endif case QEMU_OPTION_pidfile: pid_file = optarg; @@ -2518,7 +2699,19 @@ int main(int argc, char **argv, char **envp) 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); + } + machine = machine_parse(qemu_opt_get(opts, "type")); break; case QEMU_OPTION_usb: usb_enabled = 1; @@ -2549,9 +2742,14 @@ int main(int argc, char **argv, char **envp) } break; case QEMU_OPTION_vnc: +#ifdef CONFIG_VNC display_remote++; - vnc_display = optarg; - break; + vnc_display = optarg; +#else + fprintf(stderr, "VNC support is disabled\n"); + exit(1); +#endif + break; case QEMU_OPTION_no_acpi: acpi_enabled = 0; break; @@ -2734,6 +2932,22 @@ int main(int argc, char **argv, char **envp) } 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"); + } + /* If no data_dir is specified then try to find it relative to the executable path. */ if (!data_dir) { @@ -2744,12 +2958,6 @@ int main(int argc, char **argv, char **envp) data_dir = CONFIG_QEMU_DATADIR; } -#ifdef CONFIG_SIMPLE_TRACE - /* - * Set the trace file name, if specified. - */ - st_set_trace_file(trace_file); -#endif /* * Default to max_cpus = smp_cpus, in case the user doesn't * specify a max_cpus value. @@ -2765,6 +2973,28 @@ int main(int argc, char **argv, char **envp) 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); @@ -2835,17 +3065,7 @@ int main(int argc, char **argv, char **envp) 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"); @@ -2890,27 +3110,19 @@ int main(int argc, char **argv, char **envp) blk_mig_init(); - if (default_cdrom) { - /* we always create the cdrom drive, even if no disk is there */ - drive_add(NULL, CDROM_ALIAS); - } - - if (default_floppy) { - /* we always create at least one floppy */ - drive_add(NULL, FD_ALIAS, 0); - } - - if (default_sdcard) { - /* 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) qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0); if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0) exit(1); + default_drive(default_cdrom, snapshot, machine->use_scsi, + IF_DEFAULT, 2, CDROM_OPTS); + default_drive(default_floppy, snapshot, machine->use_scsi, + IF_FLOPPY, 0, FD_OPTS); + default_drive(default_sdcard, snapshot, machine->use_scsi, + IF_SD, 0, SD_OPTS); + register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL, ram_load, NULL); @@ -2990,9 +3202,6 @@ int main(int argc, char **argv, char **envp) cpu_synchronize_all_post_init(); - /* must be after terminal init, SDL library changes signal handlers */ - os_setup_signal_handling(); - set_numa_modes(); current_machine = machine; @@ -3017,12 +3226,14 @@ int main(int argc, char **argv, char **envp) if (display_type == DT_DEFAULT && !display_remote) { #if defined(CONFIG_SDL) || defined(CONFIG_COCOA) display_type = DT_SDL; -#else +#elif defined(CONFIG_VNC) vnc_display = "localhost:0,to=99"; show_vnc_port = 1; +#else + display_type = DT_NONE; #endif } - + /* init local displays */ switch (display_type) { @@ -3046,6 +3257,10 @@ int main(int argc, char **argv, char **envp) break; } + /* must be after terminal init, SDL library changes signal handlers */ + os_setup_signal_handling(); + +#ifdef CONFIG_VNC /* init remote displays */ if (vnc_display) { vnc_display_init(ds); @@ -3056,6 +3271,7 @@ int main(int argc, char **argv, char **envp) printf("VNC server running on `%s'\n", vnc_display_local_addr(ds)); } } +#endif #ifdef CONFIG_SPICE if (using_spice && !qxl_enabled) { qemu_spice_display_init(ds); @@ -3067,15 +3283,15 @@ int main(int argc, char **argv, char **envp) dcl = ds->listeners; while (dcl != NULL) { if (dcl->dpy_refresh != NULL) { - ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds); - qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock)); + ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds); + qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock)); break; } dcl = dcl->next; } if (ds->gui_timer == NULL) { - nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL); - qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock)); + nographic_timer = qemu_new_timer_ms(rt_clock, nographic_update, NULL); + qemu_mod_timer(nographic_timer, qemu_get_clock_ms(rt_clock)); } text_consoles_set_display(ds); @@ -3097,7 +3313,7 @@ int main(int argc, char **argv, char **envp) 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;