X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=vl.c;h=a89428573bc0fcaf33f54def45e45373855faea6;hb=2191dffcf6ba7df884ac902e829415d55a0b2b68;hp=06e2fe574a3af5475c3a98a952abc4bf88bdd0e3;hpb=ef3adf68f802da54b2096da8aa3ce97bde54be2e;p=qemu diff --git a/vl.c b/vl.c index 06e2fe5..a894285 100644 --- a/vl.c +++ b/vl.c @@ -29,8 +29,10 @@ #include #include -/* Needed early for HOST_BSD etc. */ +/* Needed early for CONFIG_BSD etc. */ #include "config-host.h" +/* Needed early to override system queue definitions on BSD */ +#include "sys-queue.h" #ifndef _WIN32 #include @@ -54,7 +56,7 @@ #include #include #include -#ifdef HOST_BSD +#ifdef CONFIG_BSD #include #if defined(__FreeBSD__) || defined(__DragonFly__) #include @@ -106,11 +108,7 @@ #ifdef _WIN32 #include -#include -#include #include -#define getopt_long_only getopt_long -#define memalign(align, size) malloc(size) #endif #ifdef CONFIG_SDL @@ -143,6 +141,7 @@ int main(int argc, char **argv) #include "hw/watchdog.h" #include "hw/smbios.h" #include "hw/xen.h" +#include "hw/qdev.h" #include "bt-host.h" #include "net.h" #include "monitor.h" @@ -159,6 +158,7 @@ int main(int argc, char **argv) #include "kvm.h" #include "balloon.h" #include "qemu-option.h" +#include "qemu-config.h" #include "disas.h" @@ -173,18 +173,12 @@ int main(int argc, char **argv) #define DEFAULT_RAM_SIZE 128 -/* Max number of USB devices that can be specified on the commandline. */ -#define MAX_USB_CMDLINE 8 - -/* Max number of bluetooth switches on the commandline. */ -#define MAX_BT_CMDLINE 10 - static const char *data_dir; const char *bios_name = NULL; /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available to store the VM snapshots */ -DriveInfo drives_table[MAX_DRIVES+1]; -int nb_drives; +struct drivelist drives = TAILQ_HEAD_INITIALIZER(drives); +struct driveoptlist driveopts = TAILQ_HEAD_INITIALIZER(driveopts); enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; static DisplayState *display_state; DisplayType display_type = DT_DEFAULT; @@ -194,13 +188,10 @@ ram_addr_t ram_size; int nb_nics; NICInfo nd_table[MAX_NICS]; int vm_running; -static int autostart; +int autostart; static int rtc_utc = 1; static int rtc_date_offset = -1; /* -1 means no change */ -int cirrus_vga_enabled = 1; -int std_vga_enabled = 0; -int vmsvga_enabled = 0; -int xenfb_enabled = 0; +int vga_interface_type = VGA_CIRRUS; #ifdef TARGET_SPARC int graphic_width = 1024; int graphic_height = 768; @@ -225,21 +216,22 @@ int rtc_td_hack = 0; int usb_enabled = 0; int singlestep = 0; int smp_cpus = 1; +int max_cpus = 0; +int smp_cores = 1; +int smp_threads = 1; const char *vnc_display; int acpi_enabled = 1; int no_hpet = 0; -int virtio_balloon = 1; -const char *virtio_balloon_devaddr; int fd_bootchk = 1; int no_reboot = 0; int no_shutdown = 0; int cursor_hide = 1; int graphic_rotate = 0; +uint8_t irq0override = 1; #ifndef _WIN32 int daemonize = 0; #endif -WatchdogTimerModel *watchdog = NULL; -int watchdog_action = WDT_RESET; +const char *watchdog; const char *option_rom[MAX_OPTION_ROMS]; int nb_option_roms; int semihosting_enabled = 0; @@ -252,8 +244,7 @@ int alt_grab = 0; unsigned int nb_prom_envs = 0; const char *prom_envs[MAX_PROM_ENVS]; #endif -int nb_drives_opt; -struct drive_opt drives_opt[MAX_DRIVES]; +int boot_menu; int nb_numa_nodes; uint64_t node_mem[MAX_NODES]; @@ -274,6 +265,9 @@ static QEMUTimer *nographic_timer; uint8_t qemu_uuid[16]; +static QEMUBootSetHandler *boot_set_handler; +static void *boot_set_opaque; + /***********************************************************/ /* x86 ISA bus support */ @@ -304,7 +298,7 @@ void hw_error(const char *fmt, ...) static void set_proc_name(const char *s) { -#ifdef __linux__ +#if defined(__linux__) && defined(PR_SET_NAME) char name[16]; if (!s) return; @@ -510,7 +504,7 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) union { uint64_t ll; struct { -#ifdef WORDS_BIGENDIAN +#ifdef HOST_WORDS_BIGENDIAN uint32_t high, low; #else uint32_t low, high; @@ -995,7 +989,7 @@ int qemu_timer_pending(QEMUTimer *ts) return 0; } -static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) +int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) { if (!timer_head) return 0; @@ -1144,11 +1138,6 @@ static void host_alarm_handler(int host_signum) if (next_cpu) { /* stop the currently executing cpu because a timer occured */ cpu_exit(next_cpu); -#ifdef CONFIG_KQEMU - if (next_cpu->kqemu_enabled) { - kqemu_cpu_interrupt(next_cpu); - } -#endif } #endif timer_alarm_pending = 1; @@ -1600,70 +1589,6 @@ static int socket_init(void) } #endif -int get_next_param_value(char *buf, int buf_size, - const char *tag, const char **pstr) -{ - const char *p; - char option[128]; - - p = *pstr; - for(;;) { - p = get_opt_name(option, sizeof(option), p, '='); - if (*p != '=') - break; - p++; - if (!strcmp(tag, option)) { - *pstr = get_opt_value(buf, buf_size, p); - if (**pstr == ',') { - (*pstr)++; - } - return strlen(buf); - } else { - p = get_opt_value(NULL, 0, p); - } - if (*p != ',') - break; - p++; - } - return 0; -} - -int get_param_value(char *buf, int buf_size, - const char *tag, const char *str) -{ - return get_next_param_value(buf, buf_size, tag, &str); -} - -int check_params(char *buf, int buf_size, - const char * const *params, const char *str) -{ - const char *p; - int i; - - p = str; - while (*p != '\0') { - p = get_opt_name(buf, buf_size, p, '='); - if (*p != '=') { - return -1; - } - p++; - for (i = 0; params[i] != NULL; i++) { - if (!strcmp(params[i], buf)) { - break; - } - } - if (params[i] == NULL) { - return -1; - } - p = get_opt_value(NULL, 0, p); - if (*p != ',') { - break; - } - p++; - } - return 0; -} - /***********************************************************/ /* Bluetooth support */ static int nb_hcis; @@ -1865,106 +1790,89 @@ static int bt_parse(const char *opt) #define MTD_ALIAS "if=mtd" #define SD_ALIAS "index=0,if=sd" -static int drive_opt_get_free_idx(void) +QemuOpts *drive_add(const char *file, const char *fmt, ...) { - int index; + va_list ap; + char optstr[1024]; + QemuOpts *opts; - for (index = 0; index < MAX_DRIVES; index++) - if (!drives_opt[index].used) { - drives_opt[index].used = 1; - return index; - } + va_start(ap, fmt); + vsnprintf(optstr, sizeof(optstr), fmt, ap); + va_end(ap); - return -1; + opts = qemu_opts_parse(&qemu_drive_opts, optstr, NULL); + if (!opts) { + fprintf(stderr, "%s: huh? duplicate? (%s)\n", + __FUNCTION__, optstr); + return NULL; + } + if (file) + qemu_opt_set(opts, "file", file); + return opts; } -static int drive_get_free_idx(void) +DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) { - int index; - - for (index = 0; index < MAX_DRIVES; index++) - if (!drives_table[index].used) { - drives_table[index].used = 1; - return index; - } + DriveInfo *dinfo; - return -1; -} - -int drive_add(const char *file, const char *fmt, ...) -{ - va_list ap; - int index = drive_opt_get_free_idx(); + /* seek interface, bus and unit */ - if (nb_drives_opt >= MAX_DRIVES || index == -1) { - fprintf(stderr, "qemu: too many drives\n"); - return -1; + TAILQ_FOREACH(dinfo, &drives, next) { + if (dinfo->type == type && + dinfo->bus == bus && + dinfo->unit == unit) + return dinfo; } - drives_opt[index].file = file; - va_start(ap, fmt); - vsnprintf(drives_opt[index].opt, - sizeof(drives_opt[0].opt), fmt, ap); - va_end(ap); - - nb_drives_opt++; - return index; -} - -void drive_remove(int index) -{ - drives_opt[index].used = 0; - nb_drives_opt--; + return NULL; } -int drive_get_index(BlockInterfaceType type, int bus, int unit) +DriveInfo *drive_get_by_id(const char *id) { - int index; - - /* seek interface, bus and unit */ - - for (index = 0; index < MAX_DRIVES; index++) - if (drives_table[index].type == type && - drives_table[index].bus == bus && - drives_table[index].unit == unit && - drives_table[index].used) - return index; + DriveInfo *dinfo; - return -1; + TAILQ_FOREACH(dinfo, &drives, next) { + if (strcmp(id, dinfo->id)) + continue; + return dinfo; + } + return NULL; } int drive_get_max_bus(BlockInterfaceType type) { int max_bus; - int index; + DriveInfo *dinfo; max_bus = -1; - for (index = 0; index < nb_drives; index++) { - if(drives_table[index].type == type && - drives_table[index].bus > max_bus) - max_bus = drives_table[index].bus; + TAILQ_FOREACH(dinfo, &drives, next) { + if(dinfo->type == type && + dinfo->bus > max_bus) + max_bus = dinfo->bus; } return max_bus; } const char *drive_get_serial(BlockDriverState *bdrv) { - int index; + DriveInfo *dinfo; - for (index = 0; index < nb_drives; index++) - if (drives_table[index].bdrv == bdrv) - return drives_table[index].serial; + TAILQ_FOREACH(dinfo, &drives, next) { + if (dinfo->bdrv == bdrv) + return dinfo->serial; + } return "\0"; } BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv) { - int index; + DriveInfo *dinfo; - for (index = 0; index < nb_drives; index++) - if (drives_table[index].bdrv == bdrv) - return drives_table[index].onerror; + TAILQ_FOREACH(dinfo, &drives, next) { + if (dinfo->bdrv == bdrv) + return dinfo->onerror; + } return BLOCK_ERR_STOP_ENOSPC; } @@ -1976,58 +1884,44 @@ static void bdrv_format_print(void *opaque, const char *name) void drive_uninit(BlockDriverState *bdrv) { - int i; + DriveInfo *dinfo; - for (i = 0; i < MAX_DRIVES; i++) - if (drives_table[i].bdrv == bdrv) { - drives_table[i].bdrv = NULL; - drives_table[i].used = 0; - drive_remove(drives_table[i].drive_opt_idx); - nb_drives--; - break; - } + TAILQ_FOREACH(dinfo, &drives, next) { + if (dinfo->bdrv != bdrv) + continue; + qemu_opts_del(dinfo->opts); + TAILQ_REMOVE(&drives, dinfo, next); + qemu_free(dinfo); + break; + } } -int drive_init(struct drive_opt *arg, int snapshot, void *opaque) +DriveInfo *drive_init(QemuOpts *opts, void *opaque, + int *fatal_error) { - char buf[128]; - char file[1024]; + const char *buf; + const char *file = NULL; char devname[128]; - char serial[21]; + const char *serial; const char *mediastr = ""; BlockInterfaceType type; enum { MEDIA_DISK, MEDIA_CDROM } media; int bus_id, unit_id; int cyls, heads, secs, translation; - BlockDriverState *bdrv; BlockDriver *drv = NULL; QEMUMachine *machine = opaque; int max_devs; int index; int cache; + int aio = 0; int bdrv_flags, onerror; const char *devaddr; - int drives_table_idx; - char *str = arg->opt; - static const char * const params[] = { "bus", "unit", "if", "index", - "cyls", "heads", "secs", "trans", - "media", "snapshot", "file", - "cache", "format", "serial", - "werror", "addr", - NULL }; - - if (check_params(buf, sizeof(buf), params, str) < 0) { - fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n", - buf, str); - return -1; - } - - file[0] = 0; - cyls = heads = secs = 0; - bus_id = 0; - unit_id = -1; + DriveInfo *dinfo; + int snapshot = 0; + + *fatal_error = 1; + translation = BIOS_ATA_TRANSLATION_AUTO; - index = -1; cache = 1; if (machine->use_scsi) { @@ -2042,24 +1936,20 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) media = MEDIA_DISK; /* extract parameters */ + bus_id = qemu_opt_get_number(opts, "bus", 0); + unit_id = qemu_opt_get_number(opts, "unit", -1); + index = qemu_opt_get_number(opts, "index", -1); - if (get_param_value(buf, sizeof(buf), "bus", str)) { - bus_id = strtol(buf, NULL, 0); - if (bus_id < 0) { - fprintf(stderr, "qemu: '%s' invalid bus id\n", str); - return -1; - } - } + cyls = qemu_opt_get_number(opts, "cyls", 0); + heads = qemu_opt_get_number(opts, "heads", 0); + secs = qemu_opt_get_number(opts, "secs", 0); - if (get_param_value(buf, sizeof(buf), "unit", str)) { - unit_id = strtol(buf, NULL, 0); - if (unit_id < 0) { - fprintf(stderr, "qemu: '%s' invalid unit id\n", str); - return -1; - } - } + snapshot = qemu_opt_get_bool(opts, "snapshot", 0); + + file = qemu_opt_get(opts, "file"); + serial = qemu_opt_get(opts, "serial"); - if (get_param_value(buf, sizeof(buf), "if", str)) { + if ((buf = qemu_opt_get(opts, "if")) != NULL) { pstrcpy(devname, sizeof(devname), buf); if (!strcmp(buf, "ide")) { type = IF_IDE; @@ -2085,53 +1975,36 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) } else if (!strcmp(buf, "xen")) { type = IF_XEN; max_devs = 0; + } else if (!strcmp(buf, "none")) { + type = IF_NONE; + max_devs = 0; } else { - fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf); - return -1; - } - } - - if (get_param_value(buf, sizeof(buf), "index", str)) { - index = strtol(buf, NULL, 0); - if (index < 0) { - fprintf(stderr, "qemu: '%s' invalid index\n", str); - return -1; + fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf); + return NULL; } } - if (get_param_value(buf, sizeof(buf), "cyls", str)) { - cyls = strtol(buf, NULL, 0); - } - - if (get_param_value(buf, sizeof(buf), "heads", str)) { - heads = strtol(buf, NULL, 0); - } - - if (get_param_value(buf, sizeof(buf), "secs", str)) { - secs = strtol(buf, NULL, 0); - } - if (cyls || heads || secs) { if (cyls < 1 || cyls > 16383) { - fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", str); - return -1; + fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf); + return NULL; } if (heads < 1 || heads > 16) { - fprintf(stderr, "qemu: '%s' invalid physical heads number\n", str); - return -1; + fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf); + return NULL; } if (secs < 1 || secs > 63) { - fprintf(stderr, "qemu: '%s' invalid physical secs number\n", str); - return -1; + fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf); + return NULL; } } - if (get_param_value(buf, sizeof(buf), "trans", str)) { + if ((buf = qemu_opt_get(opts, "trans")) != NULL) { if (!cyls) { fprintf(stderr, "qemu: '%s' trans must be used with cyls,heads and secs\n", - str); - return -1; + buf); + return NULL; } if (!strcmp(buf, "none")) translation = BIOS_ATA_TRANSLATION_NONE; @@ -2140,39 +2013,28 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) else if (!strcmp(buf, "auto")) translation = BIOS_ATA_TRANSLATION_AUTO; else { - fprintf(stderr, "qemu: '%s' invalid translation type\n", str); - return -1; + fprintf(stderr, "qemu: '%s' invalid translation type\n", buf); + return NULL; } } - if (get_param_value(buf, sizeof(buf), "media", str)) { + if ((buf = qemu_opt_get(opts, "media")) != NULL) { if (!strcmp(buf, "disk")) { media = MEDIA_DISK; } else if (!strcmp(buf, "cdrom")) { if (cyls || secs || heads) { fprintf(stderr, - "qemu: '%s' invalid physical CHS format\n", str); - return -1; + "qemu: '%s' invalid physical CHS format\n", buf); + return NULL; } media = MEDIA_CDROM; } else { - fprintf(stderr, "qemu: '%s' invalid media\n", str); - return -1; - } - } - - if (get_param_value(buf, sizeof(buf), "snapshot", str)) { - if (!strcmp(buf, "on")) - snapshot = 1; - else if (!strcmp(buf, "off")) - snapshot = 0; - else { - fprintf(stderr, "qemu: '%s' invalid snapshot option\n", str); - return -1; + fprintf(stderr, "qemu: '%s' invalid media\n", buf); + return NULL; } } - if (get_param_value(buf, sizeof(buf), "cache", str)) { + if ((buf = qemu_opt_get(opts, "cache")) != NULL) { if (!strcmp(buf, "off") || !strcmp(buf, "none")) cache = 0; else if (!strcmp(buf, "writethrough")) @@ -2181,37 +2043,42 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) cache = 2; else { fprintf(stderr, "qemu: invalid cache option\n"); - return -1; + return NULL; } } - if (get_param_value(buf, sizeof(buf), "format", str)) { +#ifdef CONFIG_LINUX_AIO + if ((buf = qemu_opt_get(opts, "aio")) != NULL) { + if (!strcmp(buf, "threads")) + aio = 0; + else if (!strcmp(buf, "native")) + aio = 1; + else { + fprintf(stderr, "qemu: invalid aio option\n"); + return NULL; + } + } +#endif + + if ((buf = qemu_opt_get(opts, "format")) != NULL) { if (strcmp(buf, "?") == 0) { fprintf(stderr, "qemu: Supported formats:"); bdrv_iterate_format(bdrv_format_print, NULL); fprintf(stderr, "\n"); - return -1; + return NULL; } drv = bdrv_find_format(buf); if (!drv) { fprintf(stderr, "qemu: '%s' invalid format\n", buf); - return -1; + return NULL; } } - if (arg->file == NULL) - get_param_value(file, sizeof(file), "file", str); - else - pstrcpy(file, sizeof(file), arg->file); - - if (!get_param_value(serial, sizeof(serial), "serial", str)) - memset(serial, 0, sizeof(serial)); - onerror = BLOCK_ERR_STOP_ENOSPC; - if (get_param_value(buf, sizeof(serial), "werror", str)) { + if ((buf = qemu_opt_get(opts, "werror")) != NULL) { if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) { fprintf(stderr, "werror is no supported by this format\n"); - return -1; + return NULL; } if (!strcmp(buf, "ignore")) onerror = BLOCK_ERR_IGNORE; @@ -2223,17 +2090,15 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) onerror = BLOCK_ERR_REPORT; else { fprintf(stderr, "qemu: '%s' invalid write error action\n", buf); - return -1; + return NULL; } } - devaddr = NULL; - if (get_param_value(buf, sizeof(buf), "addr", str)) { + if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { if (type != IF_VIRTIO) { - fprintf(stderr, "addr is not supported by in '%s'\n", str); - return -1; + fprintf(stderr, "addr is not supported\n"); + return NULL; } - devaddr = strdup(buf); } /* compute bus and unit according index */ @@ -2241,8 +2106,8 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) if (index != -1) { if (bus_id != 0 || unit_id != -1) { fprintf(stderr, - "qemu: '%s' index cannot be used with bus and unit\n", str); - return -1; + "qemu: index cannot be used with bus and unit\n"); + return NULL; } if (max_devs == 0) { @@ -2260,7 +2125,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) if (unit_id == -1) { unit_id = 0; - while (drive_get_index(type, bus_id, unit_id) != -1) { + while (drive_get(type, bus_id, unit_id) != NULL) { unit_id++; if (max_devs && unit_id >= max_devs) { unit_id -= max_devs; @@ -2272,39 +2137,47 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) /* check unit id */ if (max_devs && unit_id >= max_devs) { - fprintf(stderr, "qemu: '%s' unit %d too big (max is %d)\n", - str, unit_id, max_devs - 1); - return -1; + fprintf(stderr, "qemu: unit %d too big (max is %d)\n", + unit_id, max_devs - 1); + return NULL; } /* * ignore multiple definitions */ - if (drive_get_index(type, bus_id, unit_id) != -1) - return -2; + if (drive_get(type, bus_id, unit_id) != NULL) { + *fatal_error = 0; + return NULL; + } /* init */ - if (type == IF_IDE || type == IF_SCSI) - mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; - if (max_devs) - snprintf(buf, sizeof(buf), "%s%i%s%i", - devname, bus_id, mediastr, unit_id); - else - snprintf(buf, sizeof(buf), "%s%s%i", - devname, mediastr, unit_id); - bdrv = bdrv_new(buf); - drives_table_idx = drive_get_free_idx(); - drives_table[drives_table_idx].bdrv = bdrv; - drives_table[drives_table_idx].devaddr = devaddr; - drives_table[drives_table_idx].type = type; - drives_table[drives_table_idx].bus = bus_id; - drives_table[drives_table_idx].unit = unit_id; - drives_table[drives_table_idx].onerror = onerror; - drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt; - strncpy(drives_table[drives_table_idx].serial, serial, sizeof(serial)); - nb_drives++; + dinfo = qemu_mallocz(sizeof(*dinfo)); + if ((buf = qemu_opts_id(opts)) != NULL) { + dinfo->id = qemu_strdup(buf); + } else { + /* no id supplied -> create one */ + dinfo->id = qemu_mallocz(32); + if (type == IF_IDE || type == IF_SCSI) + mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; + if (max_devs) + snprintf(dinfo->id, 32, "%s%i%s%i", + devname, bus_id, mediastr, unit_id); + else + snprintf(dinfo->id, 32, "%s%s%i", + devname, mediastr, unit_id); + } + dinfo->bdrv = bdrv_new(dinfo->id); + dinfo->devaddr = devaddr; + dinfo->type = type; + dinfo->bus = bus_id; + dinfo->unit = unit_id; + dinfo->onerror = onerror; + dinfo->opts = opts; + if (serial) + strncpy(dinfo->serial, serial, sizeof(serial)); + TAILQ_INSERT_TAIL(&drives, dinfo, next); switch(type) { case IF_IDE: @@ -2313,12 +2186,12 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) switch(media) { case MEDIA_DISK: if (cyls != 0) { - bdrv_set_geometry_hint(bdrv, cyls, heads, secs); - bdrv_set_translation_hint(bdrv, translation); + bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs); + bdrv_set_translation_hint(dinfo->bdrv, translation); } break; case MEDIA_CDROM: - bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM); + bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM); break; } break; @@ -2326,17 +2199,27 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) /* FIXME: This isn't really a floppy, but it's a reasonable approximation. */ case IF_FLOPPY: - bdrv_set_type_hint(bdrv, BDRV_TYPE_FLOPPY); + bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY); break; case IF_PFLASH: case IF_MTD: + case IF_NONE: + break; case IF_VIRTIO: + /* add virtio block device */ + opts = qemu_opts_create(&qemu_device_opts, NULL, 0); + qemu_opt_set(opts, "driver", "virtio-blk-pci"); + qemu_opt_set(opts, "drive", dinfo->id); + if (devaddr) + qemu_opt_set(opts, "addr", devaddr); break; case IF_COUNT: abort(); } - if (!file[0]) - return -2; + if (!file) { + *fatal_error = 0; + return NULL; + } bdrv_flags = 0; if (snapshot) { bdrv_flags |= BDRV_O_SNAPSHOT; @@ -2346,14 +2229,57 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) bdrv_flags |= BDRV_O_NOCACHE; else if (cache == 2) /* write-back */ bdrv_flags |= BDRV_O_CACHE_WB; - if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) { + + if (aio == 1) { + bdrv_flags |= BDRV_O_NATIVE_AIO; + } else { + bdrv_flags &= ~BDRV_O_NATIVE_AIO; + } + + if (bdrv_open2(dinfo->bdrv, file, bdrv_flags, drv) < 0) { fprintf(stderr, "qemu: could not open disk image %s\n", file); - return -1; + return NULL; } - if (bdrv_key_required(bdrv)) + + if (bdrv_key_required(dinfo->bdrv)) autostart = 0; - return drives_table_idx; + *fatal_error = 0; + return dinfo; +} + +static int drive_init_func(QemuOpts *opts, void *opaque) +{ + QEMUMachine *machine = opaque; + int fatal_error = 0; + + if (drive_init(opts, machine, &fatal_error) == NULL) { + if (fatal_error) + return 1; + } + return 0; +} + +static int drive_enable_snapshot(QemuOpts *opts, void *opaque) +{ + if (NULL == qemu_opt_get(opts, "snapshot")) { + qemu_opt_set(opts, "snapshot", "on"); + } + return 0; +} + +void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque) +{ + boot_set_handler = func; + boot_set_opaque = opaque; +} + +int qemu_boot_set(const char *boot_devices) +{ + if (!boot_set_handler) { + return -EINVAL; + } + return boot_set_handler(boot_set_opaque, boot_devices); } static int parse_bootdevices(char *devices) @@ -2385,6 +2311,16 @@ static int parse_bootdevices(char *devices) return bitmap; } +static void restore_boot_devices(void *opaque) +{ + char *standard_boot_devices = opaque; + + qemu_boot_set(standard_boot_devices); + + qemu_unregister_reset(restore_boot_devices, standard_boot_devices); + qemu_free(standard_boot_devices); +} + static void numa_add(const char *optarg) { char option[128]; @@ -2441,6 +2377,56 @@ static void numa_add(const char *optarg) return; } +static void smp_parse(const char *optarg) +{ + int smp, sockets = 0, threads = 0, cores = 0; + char *endptr; + char option[128]; + + smp = strtoul(optarg, &endptr, 10); + if (endptr != optarg) { + if (*endptr == ',') { + endptr++; + } + } + if (get_param_value(option, 128, "sockets", endptr) != 0) + sockets = strtoull(option, NULL, 10); + if (get_param_value(option, 128, "cores", endptr) != 0) + cores = strtoull(option, NULL, 10); + if (get_param_value(option, 128, "threads", endptr) != 0) + threads = strtoull(option, NULL, 10); + if (get_param_value(option, 128, "maxcpus", endptr) != 0) + max_cpus = strtoull(option, NULL, 10); + + /* compute missing values, prefer sockets over cores over threads */ + if (smp == 0 || sockets == 0) { + sockets = sockets > 0 ? sockets : 1; + cores = cores > 0 ? cores : 1; + threads = threads > 0 ? threads : 1; + if (smp == 0) { + smp = cores * threads * sockets; + } else { + sockets = smp / (cores * threads); + } + } else { + if (cores == 0) { + threads = threads > 0 ? threads : 1; + cores = smp / (sockets * threads); + } else { + if (sockets == 0) { + sockets = smp / (cores * threads); + } else { + threads = smp / (cores * sockets); + } + } + } + smp_cpus = smp; + smp_cores = cores > 0 ? cores : 1; + smp_threads = threads > 0 ? threads : 1; + if (max_cpus == 0) + max_cpus = smp_cpus; +} + /***********************************************************/ /* USB devices */ @@ -2603,6 +2589,11 @@ static int usb_device_del(const char *devname) return usb_device_del_addr(bus_num, addr); } +static int usb_parse(const char *cmdline) +{ + return usb_device_add(cmdline, 0); +} + void do_usb_add(Monitor *mon, const char *devname) { usb_device_add(devname, 1); @@ -3329,6 +3320,8 @@ static QEMUMachine *find_machine(const char *name) for(m = first_machine; m != NULL; m = m->next) { if (!strcmp(m->name, name)) return m; + if (m->alias && !strcmp(m->alias, name)) + return m; } return NULL; } @@ -3425,12 +3418,13 @@ void vm_start(void) /* reset/shutdown handler */ typedef struct QEMUResetEntry { + TAILQ_ENTRY(QEMUResetEntry) entry; QEMUResetHandler *func; void *opaque; - struct QEMUResetEntry *next; } QEMUResetEntry; -static QEMUResetEntry *first_reset_entry; +static TAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers = + TAILQ_HEAD_INITIALIZER(reset_handlers); static int reset_requested; static int shutdown_requested; static int powerdown_requested; @@ -3484,24 +3478,32 @@ static void do_vm_stop(int reason) void qemu_register_reset(QEMUResetHandler *func, void *opaque) { - QEMUResetEntry **pre, *re; + QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry)); - pre = &first_reset_entry; - while (*pre != NULL) - pre = &(*pre)->next; - re = qemu_mallocz(sizeof(QEMUResetEntry)); re->func = func; re->opaque = opaque; - re->next = NULL; - *pre = re; + TAILQ_INSERT_TAIL(&reset_handlers, re, entry); } -void qemu_system_reset(void) +void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) { QEMUResetEntry *re; + TAILQ_FOREACH(re, &reset_handlers, entry) { + if (re->func == func && re->opaque == opaque) { + TAILQ_REMOVE(&reset_handlers, re, entry); + qemu_free(re); + return; + } + } +} + +void qemu_system_reset(void) +{ + QEMUResetEntry *re, *nre; + /* reset all devices */ - for(re = first_reset_entry; re != NULL; re = re->next) { + TAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) { re->func(re->opaque); } } @@ -3634,6 +3636,8 @@ void qemu_init_vcpu(void *_env) if (kvm_enabled()) kvm_init_vcpu(env); + env->nr_cores = smp_cores; + env->nr_threads = smp_threads; return; } @@ -3661,11 +3665,7 @@ void qemu_notify_event(void) if (env) { cpu_exit(env); -#ifdef USE_KQEMU - if (env->kqemu_enabled) - kqemu_cpu_interrupt(env); -#endif - } + } } #define qemu_mutex_lock_iothread() do { } while (0) @@ -3961,6 +3961,8 @@ void qemu_init_vcpu(void *_env) kvm_start_vcpu(env); else tcg_init_vcpu(env); + env->nr_cores = smp_cores; + env->nr_threads = smp_threads; } void qemu_notify_event(void) @@ -4286,6 +4288,8 @@ static int vm_can_run(void) return 1; } +qemu_irq qemu_system_powerdown; + static void main_loop(void) { int r; @@ -4326,8 +4330,9 @@ static void main_loop(void) qemu_system_reset(); resume_all_vcpus(); } - if (qemu_powerdown_requested()) - qemu_system_powerdown(); + if (qemu_powerdown_requested()) { + qemu_irq_raise(qemu_system_powerdown); + } if ((r = qemu_vmstop_requested())) vm_stop(r); } @@ -4547,18 +4552,15 @@ static void select_vgahw (const char *p) { const char *opts; - cirrus_vga_enabled = 0; - std_vga_enabled = 0; - vmsvga_enabled = 0; - xenfb_enabled = 0; + vga_interface_type = VGA_NONE; if (strstart(p, "std", &opts)) { - std_vga_enabled = 1; + vga_interface_type = VGA_STD; } else if (strstart(p, "cirrus", &opts)) { - cirrus_vga_enabled = 1; + vga_interface_type = VGA_CIRRUS; } else if (strstart(p, "vmware", &opts)) { - vmsvga_enabled = 1; + vga_interface_type = VGA_VMWARE; } else if (strstart(p, "xenfb", &opts)) { - xenfb_enabled = 1; + vga_interface_type = VGA_XENFB; } else if (!strstart(p, "none", &opts)) { invalid_vga: fprintf(stderr, "Unknown vga type: %s\n", p); @@ -4582,23 +4584,27 @@ static void select_vgahw (const char *p) #ifdef TARGET_I386 static int balloon_parse(const char *arg) { - char buf[128]; - const char *p; + QemuOpts *opts; - if (!strcmp(arg, "none")) { - virtio_balloon = 0; - } else if (!strncmp(arg, "virtio", 6)) { - virtio_balloon = 1; - if (arg[6] == ',') { - p = arg + 7; - if (get_param_value(buf, sizeof(buf), "addr", p)) { - virtio_balloon_devaddr = strdup(buf); - } + if (strcmp(arg, "none") == 0) { + return 0; + } + + if (!strncmp(arg, "virtio", 6)) { + if (arg[6] == ',') { + /* have params -> parse them */ + opts = qemu_opts_parse(&qemu_device_opts, arg+7, NULL); + if (!opts) + return -1; + } else { + /* create empty opts */ + opts = qemu_opts_create(&qemu_device_opts, NULL, 0); } - } else { - return -1; + qemu_opt_set(opts, "driver", "virtio-balloon-pci"); + return 0; } - return 0; + + return -1; } #endif @@ -4786,6 +4792,51 @@ char *qemu_find_file(int type, const char *name) return buf; } +static int device_init_func(QemuOpts *opts, void *opaque) +{ + DeviceState *dev; + + dev = qdev_device_add(opts); + if (!dev) + return -1; + return 0; +} + +struct device_config { + enum { + DEV_USB, /* -usbdevice */ + DEV_BT, /* -bt */ + } type; + const char *cmdline; + TAILQ_ENTRY(device_config) next; +}; +TAILQ_HEAD(, device_config) device_configs = TAILQ_HEAD_INITIALIZER(device_configs); + +static void add_device_config(int type, const char *cmdline) +{ + struct device_config *conf; + + conf = qemu_mallocz(sizeof(*conf)); + conf->type = type; + conf->cmdline = cmdline; + TAILQ_INSERT_TAIL(&device_configs, conf, next); +} + +static int foreach_device_config(int type, int (*func)(const char *cmdline)) +{ + struct device_config *conf; + int rc; + + TAILQ_FOREACH(conf, &device_configs, next) { + if (conf->type != type) + continue; + rc = func(conf->cmdline); + if (0 != rc) + return rc; + } + return 0; +} + int main(int argc, char **argv, char **envp) { const char *gdbstub_dev = NULL; @@ -4800,9 +4851,7 @@ int main(int argc, char **argv, char **envp) int cyls, heads, secs, translation; const char *net_clients[MAX_NET_CLIENTS]; int nb_net_clients; - const char *bt_opts[MAX_BT_CMDLINE]; - int nb_bt_opts; - int hda_index; + QemuOpts *hda_opts = NULL, *opts; int optind; const char *r, *optarg; CharDriverState *monitor_hd = NULL; @@ -4816,8 +4865,6 @@ int main(int argc, char **argv, char **envp) const char *loadvm = NULL; QEMUMachine *machine; const char *cpu_model; - const char *usb_devices[MAX_USB_CMDLINE]; - int usb_devices_index; #ifndef _WIN32 int fds[2]; #endif @@ -4833,6 +4880,7 @@ int main(int argc, char **argv, char **envp) CPUState *env; int show_vnc_port = 0; + qemu_errors_to_file(stderr); qemu_cache_utils_init(envp); LIST_INIT (&vm_change_state_head); @@ -4897,29 +4945,20 @@ int main(int argc, char **argv, char **envp) node_cpumask[i] = 0; } - usb_devices_index = 0; - nb_net_clients = 0; - nb_bt_opts = 0; - nb_drives = 0; - nb_drives_opt = 0; nb_numa_nodes = 0; - hda_index = -1; - nb_nics = 0; tb_size = 0; autostart= 1; - register_watchdogs(); - optind = 1; for(;;) { if (optind >= argc) break; r = argv[optind]; if (r[0] != '-') { - hda_index = drive_add(argv[optind++], HD_ALIAS, 0); + hda_opts = drive_add(argv[optind++], HD_ALIAS, 0); } else { const QEMUOption *popt; @@ -4956,6 +4995,9 @@ int main(int argc, char **argv, char **envp) 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)" : ""); @@ -4980,9 +5022,9 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_hda: if (cyls == 0) - hda_index = drive_add(optarg, HD_ALIAS, 0); + hda_opts = drive_add(optarg, HD_ALIAS, 0); else - hda_index = drive_add(optarg, HD_ALIAS + hda_opts = drive_add(optarg, HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s", 0, cyls, heads, secs, translation == BIOS_ATA_TRANSLATION_LBA ? @@ -4998,6 +5040,10 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_drive: drive_add(NULL, "%s", optarg); break; + case QEMU_OPTION_set: + if (qemu_set_option(optarg) != 0) + exit(1); + break; case QEMU_OPTION_mtdblock: drive_add(optarg, MTD_ALIAS); break; @@ -5044,15 +5090,19 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "qemu: invalid physical CHS format\n"); exit(1); } - if (hda_index != -1) - snprintf(drives_opt[hda_index].opt, - sizeof(drives_opt[hda_index].opt), - HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s", - 0, cyls, heads, secs, - translation == BIOS_ATA_TRANSLATION_LBA ? - ",trans=lba" : - translation == BIOS_ATA_TRANSLATION_NONE ? - ",trans=none" : ""); + if (hda_opts != NULL) { + char num[16]; + snprintf(num, sizeof(num), "%d", cyls); + qemu_opt_set(hda_opts, "cyls", num); + snprintf(num, sizeof(num), "%d", heads); + qemu_opt_set(hda_opts, "heads", num); + snprintf(num, sizeof(num), "%d", secs); + qemu_opt_set(hda_opts, "secs", num); + if (translation == BIOS_ATA_TRANSLATION_LBA) + qemu_opt_set(hda_opts, "trans", "lba"); + if (translation == BIOS_ATA_TRANSLATION_NONE) + qemu_opt_set(hda_opts, "trans", "none"); + } } break; case QEMU_OPTION_numa: @@ -5085,9 +5135,10 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_boot: { static const char * const params[] = { - "order", NULL + "order", "once", "menu", NULL }; char buf[sizeof(boot_devices)]; + char *standard_boot_devices; int legacy = 0; if (!strchr(optarg, '=')) { @@ -5105,6 +5156,29 @@ int main(int argc, char **argv, char **envp) boot_devices_bitmap = parse_bootdevices(buf); pstrcpy(boot_devices, sizeof(boot_devices), buf); } + if (!legacy) { + if (get_param_value(buf, sizeof(buf), + "once", optarg)) { + boot_devices_bitmap |= parse_bootdevices(buf); + standard_boot_devices = qemu_strdup(boot_devices); + pstrcpy(boot_devices, sizeof(boot_devices), buf); + qemu_register_reset(restore_boot_devices, + standard_boot_devices); + } + if (get_param_value(buf, sizeof(buf), + "menu", optarg)) { + if (!strcmp(buf, "on")) { + boot_menu = 1; + } else if (!strcmp(buf, "off")) { + boot_menu = 0; + } else { + fprintf(stderr, + "qemu: invalid option value '%s'\n", + buf); + exit(1); + } + } + } } break; case QEMU_OPTION_fda: @@ -5141,11 +5215,7 @@ int main(int argc, char **argv, char **envp) break; #endif case QEMU_OPTION_bt: - if (nb_bt_opts >= MAX_BT_CMDLINE) { - fprintf(stderr, "qemu: too many bluetooth options\n"); - exit(1); - } - bt_opts[nb_bt_opts++] = optarg; + add_device_config(DEV_BT, optarg); break; #ifdef HAS_AUDIO case QEMU_OPTION_audio_help: @@ -5181,11 +5251,7 @@ int main(int argc, char **argv, char **envp) } /* On 32-bit hosts, QEMU is limited by virtual address space */ - if (value > (2047 << 20) -#ifndef CONFIG_KQEMU - && HOST_LONG_BITS == 32 -#endif - ) { + if (value > (2047 << 20) && HOST_LONG_BITS == 32) { fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n"); exit(1); } @@ -5297,9 +5363,12 @@ int main(int argc, char **argv, char **envp) serial_device_index++; break; case QEMU_OPTION_watchdog: - i = select_watchdog(optarg); - if (i > 0) - exit (i == 1 ? 1 : 0); + if (watchdog) { + fprintf(stderr, + "qemu: only one watchdog option may be given\n"); + return 1; + } + watchdog = optarg; break; case QEMU_OPTION_watchdog_action: if (select_watchdog_action(optarg) == -1) { @@ -5366,20 +5435,9 @@ int main(int argc, char **argv, char **envp) } break; #endif -#ifdef CONFIG_KQEMU - case QEMU_OPTION_enable_kqemu: - kqemu_allowed = 1; - break; - case QEMU_OPTION_kernel_kqemu: - kqemu_allowed = 2; - break; -#endif #ifdef CONFIG_KVM case QEMU_OPTION_enable_kvm: kvm_allowed = 1; -#ifdef CONFIG_KQEMU - kqemu_allowed = 0; -#endif break; #endif case QEMU_OPTION_usb: @@ -5387,19 +5445,30 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_usbdevice: usb_enabled = 1; - if (usb_devices_index >= MAX_USB_CMDLINE) { - fprintf(stderr, "Too many USB devices\n"); + add_device_config(DEV_USB, optarg); + break; + case QEMU_OPTION_device: + opts = qemu_opts_parse(&qemu_device_opts, optarg, "driver"); + if (!opts) { + fprintf(stderr, "parse error: %s\n", optarg); exit(1); } - usb_devices[usb_devices_index] = optarg; - usb_devices_index++; break; case QEMU_OPTION_smp: - smp_cpus = atoi(optarg); + smp_parse(optarg); if (smp_cpus < 1) { fprintf(stderr, "Invalid number of CPUs\n"); exit(1); } + if (max_cpus < smp_cpus) { + fprintf(stderr, "maxcpus must be equal to or greater than " + "smp\n"); + exit(1); + } + if (max_cpus > 255) { + fprintf(stderr, "Unsupported number of maxcpus\n"); + exit(1); + } break; case QEMU_OPTION_vnc: display_type = DT_VNC; @@ -5573,13 +5642,12 @@ int main(int argc, char **argv, char **envp) data_dir = CONFIG_QEMU_SHAREDIR; } -#if defined(CONFIG_KVM) && defined(CONFIG_KQEMU) - if (kvm_allowed && kqemu_allowed) { - fprintf(stderr, - "You can not enable both KVM and kqemu at the same time\n"); - exit(1); - } -#endif + /* + * Default to max_cpus = smp_cpus, in case the user doesn't + * specify a max_cpus value. + */ + if (!max_cpus) + max_cpus = smp_cpus; machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */ if (smp_cpus > machine->max_cpus) { @@ -5652,10 +5720,6 @@ int main(int argc, char **argv, char **envp) } #endif -#ifdef CONFIG_KQEMU - if (smp_cpus > 1) - kqemu_allowed = 0; -#endif if (qemu_init_main_loop()) { fprintf(stderr, "qemu_init_main_loop failed\n"); exit(1); @@ -5672,7 +5736,10 @@ int main(int argc, char **argv, char **envp) exit(1); } +#ifndef _WIN32 + /* Win32 doesn't support line-buffering and requires size >= 2 */ setvbuf(stdout, NULL, _IOLBF, 0); +#endif init_timers(); if (init_timer_alarm() < 0) { @@ -5711,52 +5778,32 @@ int main(int argc, char **argv, char **envp) net_client_check(); /* init the bluetooth world */ - for (i = 0; i < nb_bt_opts; i++) - if (bt_parse(bt_opts[i])) - exit(1); + if (foreach_device_config(DEV_BT, bt_parse)) + exit(1); /* init the memory */ if (ram_size == 0) ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; -#ifdef CONFIG_KQEMU - /* FIXME: This is a nasty hack because kqemu can't cope with dynamic - guest ram allocation. It needs to go away. */ - if (kqemu_allowed) { - kqemu_phys_ram_size = ram_size + 8 * 1024 * 1024 + 4 * 1024 * 1024; - kqemu_phys_ram_base = qemu_vmalloc(kqemu_phys_ram_size); - if (!kqemu_phys_ram_base) { - fprintf(stderr, "Could not allocate physical memory\n"); - exit(1); - } - } -#endif - /* init the dynamic translator */ cpu_exec_init_all(tb_size * 1024 * 1024); bdrv_init(); /* we always create the cdrom drive, even if no disk is there */ - - if (nb_drives_opt < MAX_DRIVES) - drive_add(NULL, CDROM_ALIAS); + drive_add(NULL, CDROM_ALIAS); /* we always create at least one floppy */ - - if (nb_drives_opt < MAX_DRIVES) - drive_add(NULL, FD_ALIAS, 0); + drive_add(NULL, FD_ALIAS, 0); /* we always create one sd slot, even if no card is in it */ - - if (nb_drives_opt < MAX_DRIVES) - drive_add(NULL, SD_ALIAS); + drive_add(NULL, SD_ALIAS); /* open the virtual block devices */ - - for(i = 0; i < nb_drives_opt; i++) - if (drive_init(&drives_opt[i], snapshot, machine) == -1) - exit(1); + if (snapshot) + qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0); + if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, machine, 1) != 0) + exit(1); register_savevm("timer", 0, 2, timer_save, timer_load, NULL); register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL); @@ -5885,6 +5932,15 @@ int main(int argc, char **argv, char **envp) module_call_init(MODULE_INIT_DEVICE); + if (watchdog) { + i = select_watchdog(watchdog); + if (i > 0) + exit (i == 1 ? 1 : 0); + } + + if (machine->compat_props) { + qdev_prop_register_compat(machine->compat_props); + } machine->init(ram_size, boot_devices, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); @@ -5901,14 +5957,13 @@ int main(int argc, char **argv, char **envp) /* init USB devices */ if (usb_enabled) { - for(i = 0; i < usb_devices_index; i++) { - if (usb_device_add(usb_devices[i], 0) < 0) { - fprintf(stderr, "Warning: could not add USB device %s\n", - usb_devices[i]); - } - } + foreach_device_config(DEV_USB, usb_parse); } + /* init generic devices */ + if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0) + exit(1); + if (!display_state) dumb_display_init(); /* just use the first displaystate for the moment */ @@ -6006,16 +6061,17 @@ int main(int argc, char **argv, char **envp) exit(1); } - if (loadvm) - do_loadvm(cur_mon, loadvm); + if (loadvm) { + if (load_vmstate(cur_mon, loadvm) < 0) { + autostart = 0; + } + } if (incoming) { - autostart = 0; /* fixme how to deal with -daemonize */ qemu_start_incoming_migration(incoming); - } - - if (autostart) + } else if (autostart) { vm_start(); + } #ifndef _WIN32 if (daemonize) {