X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/4cab946a4adc3094a846dd3c7ea104abe7bdc5f1..689a1921aef42ef2a3da1ca4a406c473a0531aed:/vl.c diff --git a/vl.c b/vl.c index 0d20d26180..5f1a17704b 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; @@ -228,6 +228,9 @@ int ctrl_grab = 0; 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; @@ -257,9 +260,12 @@ 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; +static int tcg_tb_size; static int default_serial = 1; static int default_parallel = 1; @@ -277,15 +283,28 @@ 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 void res_free(void) +{ + if (boot_splash_filedata != NULL) { + g_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"); @@ -447,7 +466,7 @@ static struct bt_scatternet_s *qemu_find_bt_vlan(int id) if (vlan->id == id) return &vlan->net; } - vlan = qemu_mallocz(sizeof(struct bt_vlan_s)); + vlan = g_malloc0(sizeof(struct bt_vlan_s)); vlan->id = id; pvlan = &first_bt_vlan; while (*pvlan != NULL) @@ -621,23 +640,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 +662,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; @@ -704,7 +741,7 @@ static void restore_boot_devices(void *opaque) qemu_boot_set(standard_boot_devices); qemu_unregister_reset(restore_boot_devices, standard_boot_devices); - qemu_free(standard_boot_devices); + g_free(standard_boot_devices); } void add_boot_device_path(int32_t bootindex, DeviceState *dev, @@ -718,9 +755,9 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, assert(dev != NULL || suffix != NULL); - node = qemu_mallocz(sizeof(FWBootEntry)); + node = g_malloc0(sizeof(FWBootEntry)); node->bootindex = bootindex; - node->suffix = strdup(suffix); + node->suffix = suffix ? g_strdup(suffix) : NULL; node->dev = dev; QTAILQ_FOREACH(i, &fw_boot_order, link) { @@ -736,6 +773,56 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, QTAILQ_INSERT_TAIL(&fw_boot_order, node, link); } +/* + * This function returns null terminated string that consist of new line + * separated device paths. + * + * memory pointed by "size" is assigned total length of the array in bytes + * + */ +char *get_boot_devices_list(uint32_t *size) +{ + FWBootEntry *i; + uint32_t total = 0; + char *list = NULL; + + QTAILQ_FOREACH(i, &fw_boot_order, link) { + char *devpath = NULL, *bootpath; + int len; + + if (i->dev) { + devpath = qdev_get_fw_dev_path(i->dev); + assert(devpath); + } + + if (i->suffix && devpath) { + size_t bootpathlen = strlen(devpath) + strlen(i->suffix) + 1; + + bootpath = g_malloc(bootpathlen); + snprintf(bootpath, bootpathlen, "%s%s", devpath, i->suffix); + g_free(devpath); + } else if (devpath) { + bootpath = devpath; + } else { + bootpath = g_strdup(i->suffix); + assert(bootpath); + } + + if (total) { + list[total-1] = '\n'; + } + len = strlen(bootpath) + 1; + list = g_realloc(list, total + len); + memcpy(&list[total], bootpath, len); + total += len; + g_free(bootpath); + } + + *size = total; + + return list; +} + static void numa_add(const char *optarg) { char option[128]; @@ -754,7 +841,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); @@ -850,9 +937,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 { @@ -923,7 +1014,7 @@ void pcmcia_socket_register(PCMCIASocket *socket) { struct pcmcia_socket_entry_s *entry; - entry = qemu_malloc(sizeof(struct pcmcia_socket_entry_s)); + entry = g_malloc(sizeof(struct pcmcia_socket_entry_s)); entry->socket = socket; entry->next = pcmcia_sockets; pcmcia_sockets = entry; @@ -937,7 +1028,7 @@ void pcmcia_socket_unregister(PCMCIASocket *socket) for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr) if (entry->socket == socket) { *ptr = entry->next; - qemu_free(entry); + g_free(entry); } } @@ -954,68 +1045,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 */ @@ -1076,7 +1105,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) @@ -1084,7 +1113,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 { @@ -1100,7 +1129,7 @@ VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, { VMChangeStateEntry *e; - e = qemu_mallocz(sizeof (*e)); + e = g_malloc0(sizeof (*e)); e->cb = cb; e->opaque = opaque; @@ -1111,7 +1140,7 @@ VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, void qemu_del_vm_change_state_handler(VMChangeStateEntry *e) { QLIST_REMOVE (e, entries); - qemu_free (e); + g_free (e); } void vm_state_notify(int running, int reason) @@ -1147,10 +1176,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) { @@ -1159,6 +1199,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; @@ -1189,7 +1245,7 @@ static int qemu_vmstop_requested(void) void qemu_register_reset(QEMUResetHandler *func, void *opaque) { - QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry)); + QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry)); re->func = func; re->opaque = opaque; @@ -1203,13 +1259,13 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) QTAILQ_FOREACH(re, &reset_handlers, entry) { if (re->func == func && re->opaque == opaque) { QTAILQ_REMOVE(&reset_handlers, re, entry); - qemu_free(re); + g_free(re); return; } } } -void qemu_system_reset(void) +void qemu_system_reset(bool report) { QEMUResetEntry *re, *nre; @@ -1217,7 +1273,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(); } @@ -1228,9 +1286,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; @@ -1243,9 +1309,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; @@ -1260,56 +1337,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(); @@ -1320,59 +1364,59 @@ 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); - no_shutdown = 0; + vm_stop(VMSTOP_SHUTDOWN); } 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()) { @@ -1454,6 +1498,8 @@ static void select_vgahw (const char *p) vga_interface_type = VGA_VMWARE; } else if (strstart(p, "xenfb", &opts)) { vga_interface_type = VGA_XENFB; + } else if (strstart(p, "qxl", &opts)) { + vga_interface_type = VGA_QXL; } else if (!strstart(p, "none", &opts)) { invalid_vga: fprintf(stderr, "Unknown vga type: %s\n", p); @@ -1474,6 +1520,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; @@ -1492,7 +1632,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; } @@ -1508,7 +1648,7 @@ char *qemu_find_file(int type, const char *name) /* If name contains path separators then try it as a straight path. */ if ((strchr(name, '/') || strchr(name, '\\')) && access(name, R_OK) == 0) { - return qemu_strdup(name); + return g_strdup(name); } switch (type) { case QEMU_FILE_TYPE_BIOS: @@ -1521,10 +1661,10 @@ char *qemu_find_file(int type, const char *name) abort(); } len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2; - buf = qemu_mallocz(len); + buf = g_malloc0(len); snprintf(buf, len, "%s/%s%s", data_dir, subdir, name); if (access(buf, R_OK)) { - qemu_free(buf); + g_free(buf); return NULL; } return buf; @@ -1549,7 +1689,7 @@ static int chardev_init_func(QemuOpts *opts, void *opaque) { CharDriverState *chr; - chr = qemu_chr_open_opts(opts, NULL); + chr = qemu_chr_new_from_opts(opts, NULL); if (!chr) return -1; return 0; @@ -1655,7 +1795,7 @@ static void add_device_config(int type, const char *cmdline) { struct device_config *conf; - conf = qemu_mallocz(sizeof(*conf)); + conf = g_malloc0(sizeof(*conf)); conf->type = type; conf->cmdline = cmdline; QTAILQ_INSERT_TAIL(&device_configs, conf, next); @@ -1688,7 +1828,7 @@ static int serial_parse(const char *devname) exit(1); } snprintf(label, sizeof(label), "serial%d", index); - serial_hds[index] = qemu_chr_open(label, devname, NULL); + serial_hds[index] = qemu_chr_new(label, devname, NULL); if (!serial_hds[index]) { fprintf(stderr, "qemu: could not open serial device '%s': %s\n", devname, strerror(errno)); @@ -1710,7 +1850,7 @@ static int parallel_parse(const char *devname) exit(1); } snprintf(label, sizeof(label), "parallel%d", index); - parallel_hds[index] = qemu_chr_open(label, devname, NULL); + parallel_hds[index] = qemu_chr_new(label, devname, NULL); if (!parallel_hds[index]) { fprintf(stderr, "qemu: could not open parallel device '%s': %s\n", devname, strerror(errno)); @@ -1741,7 +1881,7 @@ static int virtcon_parse(const char *devname) qemu_opt_set(dev_opts, "driver", "virtconsole"); snprintf(label, sizeof(label), "virtcon%d", index); - virtcon_hds[index] = qemu_chr_open(label, devname, NULL); + virtcon_hds[index] = qemu_chr_new(label, devname, NULL); if (!virtcon_hds[index]) { fprintf(stderr, "qemu: could not open virtio console '%s': %s\n", devname, strerror(errno)); @@ -1757,7 +1897,7 @@ static int debugcon_parse(const char *devname) { QemuOpts *opts; - if (!qemu_chr_open("debugcon", devname, NULL)) { + if (!qemu_chr_new("debugcon", devname, NULL)) { exit(1); } opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1); @@ -1770,6 +1910,106 @@ 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) +{ + 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); @@ -1782,7 +2022,7 @@ void qemu_remove_exit_notifier(Notifier *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) @@ -1792,7 +2032,7 @@ 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, @@ -1835,6 +2075,26 @@ static const QEMUOption *lookup_opt(int argc, char **argv, return popt; } +static gpointer malloc_and_trace(gsize n_bytes) +{ + void *ptr = malloc(n_bytes); + trace_qemu_malloc(n_bytes, ptr); + return ptr; +} + +static gpointer realloc_and_trace(gpointer mem, gsize n_bytes) +{ + void *ptr = realloc(mem, n_bytes); + trace_qemu_realloc(mem, n_bytes, ptr); + return ptr; +} + +static void free_and_trace(gpointer mem) +{ + trace_qemu_free(mem); + free(mem); +} + int main(int argc, char **argv, char **envp) { const char *gdbstub_dev = NULL; @@ -1854,18 +2114,26 @@ int main(int argc, char **argv, char **envp) 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 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; + GMemVTable mem_trace = { + .malloc = malloc_and_trace, + .realloc = realloc_and_trace, + .free = free_and_trace, + }; + atexit(qemu_run_exit_notifiers); error_set_progname(argv[0]); + g_mem_set_vtable(&mem_trace); + init_clocks(); qemu_cache_utils_init(envp); @@ -1892,7 +2160,6 @@ int main(int argc, char **argv, char **envp) nb_numa_nodes = 0; nb_nics = 0; - tb_size = 0; autostart= 1; /* first pass of option parsing */ @@ -1935,7 +2202,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; @@ -1946,20 +2213,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 */ @@ -1974,24 +2228,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) @@ -2002,13 +2263,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; @@ -2069,16 +2330,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; @@ -2087,12 +2363,13 @@ 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: { 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; @@ -2117,7 +2394,7 @@ int main(int argc, char **argv, char **envp) if (get_param_value(buf, sizeof(buf), "once", optarg)) { validate_bootdevices(buf); - standard_boot_devices = qemu_strdup(boot_devices); + standard_boot_devices = g_strdup(boot_devices); pstrcpy(boot_devices, sizeof(boot_devices), buf); qemu_register_reset(restore_boot_devices, standard_boot_devices); @@ -2135,12 +2412,15 @@ int main(int argc, char **argv, char **envp) exit(1); } } + qemu_opts_parse(qemu_find_opts("boot-opts"), + optarg, 0); } } 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; @@ -2193,7 +2473,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) { @@ -2201,11 +2481,6 @@ int main(int argc, char **argv, char **envp) 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); @@ -2222,7 +2497,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; @@ -2327,9 +2605,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) { @@ -2348,45 +2625,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"); - 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); + "mount_tag=tag.\n"); exit(1); } - if (!qemu_opts_parse(qemu_find_opts("device"), arg_9p, 1)) { - fprintf(stderr, "parse error [device]: %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); } - - 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: @@ -2449,6 +2709,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; @@ -2466,7 +2734,22 @@ 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); + } + optarg = qemu_opt_get(opts, "type"); + if (optarg) { + machine = machine_parse(optarg); + } break; case QEMU_OPTION_usb: usb_enabled = 1; @@ -2497,9 +2780,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; @@ -2547,13 +2835,13 @@ int main(int argc, char **argv, char **envp) semihosting_enabled = 1; break; case QEMU_OPTION_name: - qemu_name = qemu_strdup(optarg); + qemu_name = g_strdup(optarg); { char *p = strchr(qemu_name, ','); if (p != NULL) { *p++ = 0; if (strncmp(p, "process=", 8)) { - fprintf(stderr, "Unknown subargument %s to -name", p); + fprintf(stderr, "Unknown subargument %s to -name\n", p); exit(1); } p += 8; @@ -2586,9 +2874,10 @@ int main(int argc, char **argv, char **envp) 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; @@ -2682,6 +2971,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) { @@ -2692,12 +2997,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. @@ -2713,6 +3012,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); @@ -2783,18 +3104,13 @@ int main(int argc, char **argv, char **envp) exit(1); } - if (kvm_allowed) { - int ret = kvm_init(smp_cpus); - 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); - } + /* init the memory */ + if (ram_size == 0) { + ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; } + configure_accelerator(); + if (qemu_init_main_loop()) { fprintf(stderr, "qemu_init_main_loop failed\n"); exit(1); @@ -2827,46 +3143,41 @@ int main(int argc, char **argv, char **envp) if (foreach_device_config(DEV_BT, bt_parse)) exit(1); - /* init the memory */ - 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(); 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); 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 @@ -2938,9 +3249,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; @@ -2965,12 +3273,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) { @@ -2994,6 +3304,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); @@ -3004,8 +3318,9 @@ 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) { + if (using_spice && !qxl_enabled) { qemu_spice_display_init(ds); } #endif @@ -3015,15 +3330,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); @@ -3040,10 +3355,12 @@ int main(int argc, char **argv, char **envp) exit(1); } - qemu_register_reset((void *)qbus_reset_all, sysbus_get_default()); + /* TODO: once all bus devices are qdevified, this should be done + * when bus is created by qdev.c */ + 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; @@ -3066,6 +3383,7 @@ int main(int argc, char **argv, char **envp) main_loop(); quit_timers(); net_cleanup(); + res_free(); return 0; }