vga: Rename vga_state -> vga
[qemu] / vl.c
diff --git a/vl.c b/vl.c
index 4f942ff..a894285 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -29,7 +29,7 @@
 #include <sys/time.h>
 #include <zlib.h>
 
-/* 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"
@@ -56,7 +56,7 @@
 #include <dirent.h>
 #include <netdb.h>
 #include <sys/select.h>
-#ifdef HOST_BSD
+#ifdef CONFIG_BSD
 #include <sys/stat.h>
 #if defined(__FreeBSD__) || defined(__DragonFly__)
 #include <libutil.h>
 
 #ifdef _WIN32
 #include <windows.h>
-#include <malloc.h>
-#include <sys/timeb.h>
 #include <mmsystem.h>
-#define getopt_long_only getopt_long
-#define memalign(align, size) malloc(size)
 #endif
 
 #ifdef CONFIG_SDL
@@ -162,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"
 
@@ -181,6 +178,7 @@ const char *bios_name = NULL;
 /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
    to store the VM snapshots */
 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;
@@ -190,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;
@@ -221,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;
@@ -248,8 +244,6 @@ 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;
@@ -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,43 +1790,25 @@ 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)
-{
-    int index;
-
-    for (index = 0; index < MAX_DRIVES; index++)
-        if (!drives_opt[index].used) {
-            drives_opt[index].used = 1;
-            return index;
-        }
-
-    return -1;
-}
-
-int drive_add(const char *file, const char *fmt, ...)
+QemuOpts *drive_add(const char *file, const char *fmt, ...)
 {
     va_list ap;
-    int index = drive_opt_get_free_idx();
+    char optstr[1024];
+    QemuOpts *opts;
 
-    if (nb_drives_opt >= MAX_DRIVES || index == -1) {
-        fprintf(stderr, "qemu: too many drives\n");
-        return -1;
-    }
-
-    drives_opt[index].file = file;
     va_start(ap, fmt);
-    vsnprintf(drives_opt[index].opt,
-              sizeof(drives_opt[0].opt), fmt, ap);
+    vsnprintf(optstr, sizeof(optstr), fmt, ap);
     va_end(ap);
 
-    nb_drives_opt++;
-    return index;
-}
-
-void drive_remove(int index)
-{
-    drives_opt[index].used = 0;
-    nb_drives_opt--;
+    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;
 }
 
 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
@@ -1920,6 +1827,18 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
     return NULL;
 }
 
+DriveInfo *drive_get_by_id(const char *id)
+{
+    DriveInfo *dinfo;
+
+    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;
@@ -1970,55 +1889,39 @@ void drive_uninit(BlockDriverState *bdrv)
     TAILQ_FOREACH(dinfo, &drives, next) {
         if (dinfo->bdrv != bdrv)
             continue;
-        drive_remove(dinfo->drive_opt_idx);
+        qemu_opts_del(dinfo->opts);
         TAILQ_REMOVE(&drives, dinfo, next);
         qemu_free(dinfo);
         break;
     }
 }
 
-DriveInfo *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;
     DriveInfo *dinfo;
-    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 };
-    *fatal_error = 1;
+    int snapshot = 0;
 
-    if (check_params(buf, sizeof(buf), params, str) < 0) {
-         fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
-                         buf, str);
-         return NULL;
-    }
+    *fatal_error = 1;
 
-    file[0] = 0;
-    cyls = heads = secs = 0;
-    bus_id = 0;
-    unit_id = -1;
     translation = BIOS_ATA_TRANSLATION_AUTO;
-    index = -1;
     cache = 1;
 
     if (machine->use_scsi) {
@@ -2033,24 +1936,20 @@ DriveInfo *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 NULL;
-       }
-    }
+    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 NULL;
-       }
-    }
+    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;
@@ -2076,52 +1975,35 @@ DriveInfo *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);
+            fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
             return NULL;
        }
     }
 
-    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 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);
+            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);
+            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);
+            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);
+                    buf);
             return NULL;
         }
         if (!strcmp(buf, "none"))
@@ -2131,39 +2013,28 @@ DriveInfo *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);
+            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);
+                        "qemu: '%s' invalid physical CHS format\n", buf);
                return NULL;
             }
            media = MEDIA_CDROM;
        } else {
-           fprintf(stderr, "qemu: '%s' invalid media\n", str);
-           return NULL;
-       }
-    }
-
-    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);
+           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"))
@@ -2176,7 +2047,20 @@ DriveInfo *drive_init(struct drive_opt *arg, int snapshot, void *opaque,
         }
     }
 
-    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);
@@ -2190,16 +2074,8 @@ DriveInfo *drive_init(struct drive_opt *arg, int snapshot, void *opaque,
         }
     }
 
-    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 NULL;
@@ -2218,13 +2094,11 @@ DriveInfo *drive_init(struct drive_opt *arg, int snapshot, void *opaque,
         }
     }
 
-    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);
+            fprintf(stderr, "addr is not supported\n");
             return NULL;
         }
-        devaddr = strdup(buf);
     }
 
     /* compute bus and unit according index */
@@ -2232,7 +2106,7 @@ DriveInfo *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);
+                    "qemu: index cannot be used with bus and unit\n");
             return NULL;
         }
         if (max_devs == 0)
@@ -2263,8 +2137,8 @@ DriveInfo *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);
+        fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
+                unit_id, max_devs - 1);
         return NULL;
     }
 
@@ -2279,24 +2153,30 @@ DriveInfo *drive_init(struct drive_opt *arg, int snapshot, void *opaque,
 
     /* 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);
     dinfo = qemu_mallocz(sizeof(*dinfo));
-    dinfo->bdrv = bdrv;
+    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->drive_opt_idx = arg - drives_opt;
-    strncpy(dinfo->serial, serial, sizeof(serial));
+    dinfo->opts = opts;
+    if (serial)
+        strncpy(dinfo->serial, serial, sizeof(serial));
     TAILQ_INSERT_TAIL(&drives, dinfo, next);
 
     switch(type) {
@@ -2306,12 +2186,12 @@ DriveInfo *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;
@@ -2319,16 +2199,24 @@ DriveInfo *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]) {
+    if (!file) {
         *fatal_error = 0;
         return NULL;
     }
@@ -2341,17 +2229,45 @@ DriveInfo *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 NULL;
     }
-    if (bdrv_key_required(bdrv))
+
+    if (bdrv_key_required(dinfo->bdrv))
         autostart = 0;
     *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;
@@ -2461,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 */
 
@@ -3670,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;
 }
 
@@ -3697,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)
@@ -3997,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)
@@ -4322,6 +4288,8 @@ static int vm_can_run(void)
     return 1;
 }
 
+qemu_irq qemu_system_powerdown;
+
 static void main_loop(void)
 {
     int r;
@@ -4362,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);
     }
@@ -4583,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);
@@ -4618,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
 
@@ -4822,9 +4792,18 @@ 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_GENERIC,   /* -device      */
         DEV_USB,       /* -usbdevice   */
         DEV_BT,        /* -bt          */
     } type;
@@ -4858,16 +4837,6 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline))
     return 0;
 }
 
-static int generic_parse(const char *cmdline)
-{
-    DeviceState *dev;
-
-    dev = qdev_device_add(cmdline);
-    if (!dev)
-        return -1;
-    return 0;
-}
-
 int main(int argc, char **argv, char **envp)
 {
     const char *gdbstub_dev = NULL;
@@ -4882,7 +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;
-    int hda_index;
+    QemuOpts *hda_opts = NULL, *opts;
     int optind;
     const char *r, *optarg;
     CharDriverState *monitor_hd = NULL;
@@ -4911,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);
@@ -4976,24 +4946,19 @@ int main(int argc, char **argv, char **envp)
     }
 
     nb_net_clients = 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;
 
@@ -5057,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 ?
@@ -5075,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;
@@ -5121,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:
@@ -5278,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);
                 }
@@ -5394,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) {
@@ -5463,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:
@@ -5487,14 +5448,27 @@ int main(int argc, char **argv, char **envp)
                 add_device_config(DEV_USB, optarg);
                 break;
             case QEMU_OPTION_device:
-                add_device_config(DEV_GENERIC, optarg);
+                opts = qemu_opts_parse(&qemu_device_opts, optarg, "driver");
+                if (!opts) {
+                    fprintf(stderr, "parse error: %s\n", optarg);
+                    exit(1);
+                }
                 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;
@@ -5668,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) {
@@ -5747,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);
@@ -5767,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) {
@@ -5813,47 +5785,25 @@ int main(int argc, char **argv, char **envp)
     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++) {
-        int fatal_error;
-        if (drive_init(&drives_opt[i], snapshot, machine, &fatal_error) == NULL)
-            if (fatal_error)
-                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);
@@ -5982,6 +5932,12 @@ 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);
     }
@@ -6005,7 +5961,7 @@ int main(int argc, char **argv, char **envp)
     }
 
     /* init generic devices */
-    if (foreach_device_config(DEV_GENERIC, generic_parse))
+    if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
         exit(1);
 
     if (!display_state)
@@ -6105,14 +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)
+    if (incoming) {
         qemu_start_incoming_migration(incoming);
-
-    if (autostart)
+    } else if (autostart) {
         vm_start();
+    }
 
 #ifndef _WIN32
     if (daemonize) {