]> git.proxmox.com Git - qemu.git/blobdiff - vl.c
error: Include the program name in error messages to stderr
[qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index 172828afada14896b67da7c6151638d948f7ff4a..c3abeeff2e8a14a423020697434de60ec2559fa8 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -156,6 +156,7 @@ int main(int argc, char **argv)
 #include "balloon.h"
 #include "qemu-option.h"
 #include "qemu-config.h"
+#include "qemu-objects.h"
 
 #include "disas.h"
 
@@ -172,8 +173,7 @@ int main(int argc, char **argv)
 
 #define DEFAULT_RAM_SIZE 128
 
-/* Maximum number of monitor devices */
-#define MAX_MONITOR_DEVICES 10
+#define MAX_VIRTIO_CONSOLES 1
 
 static const char *data_dir;
 const char *bios_name = NULL;
@@ -182,10 +182,13 @@ const char *bios_name = NULL;
 struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
 struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
-static DisplayState *display_state;
 DisplayType display_type = DT_DEFAULT;
 const char* keyboard_layout = NULL;
 ram_addr_t ram_size;
+const char *mem_path = NULL;
+#ifdef MAP_POPULATE
+int mem_prealloc = 0; /* force preallocation of physical target memory */
+#endif
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
 int vm_running;
@@ -193,7 +196,7 @@ int autostart;
 static int rtc_utc = 1;
 static int rtc_date_offset = -1; /* -1 means no change */
 QEMUClock *rtc_clock;
-int vga_interface_type = VGA_CIRRUS;
+int vga_interface_type = VGA_NONE;
 #ifdef TARGET_SPARC
 int graphic_width = 1024;
 int graphic_height = 768;
@@ -271,6 +274,52 @@ uint8_t qemu_uuid[16];
 static QEMUBootSetHandler *boot_set_handler;
 static void *boot_set_opaque;
 
+#ifdef SIGRTMIN
+#define SIG_IPI (SIGRTMIN+4)
+#else
+#define SIG_IPI SIGUSR1
+#endif
+
+static int default_serial = 1;
+static int default_parallel = 1;
+static int default_virtcon = 1;
+static int default_monitor = 1;
+static int default_vga = 1;
+static int default_floppy = 1;
+static int default_cdrom = 1;
+static int default_sdcard = 1;
+
+static struct {
+    const char *driver;
+    int *flag;
+} default_list[] = {
+    { .driver = "isa-serial",           .flag = &default_serial    },
+    { .driver = "isa-parallel",         .flag = &default_parallel  },
+    { .driver = "isa-fdc",              .flag = &default_floppy    },
+    { .driver = "ide-drive",            .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       },
+};
+
+static int default_driver_check(QemuOpts *opts, void *opaque)
+{
+    const char *driver = qemu_opt_get(opts, "driver");
+    int i;
+
+    if (!driver)
+        return 0;
+    for (i = 0; i < ARRAY_SIZE(default_list); i++) {
+        if (strcmp(default_list[i].driver, driver) != 0)
+            continue;
+        *(default_list[i].flag) = 0;
+    }
+    return 0;
+}
+
 /***********************************************************/
 /* x86 ISA bus support */
 
@@ -325,182 +374,29 @@ void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque)
     qemu_balloon_event_opaque = opaque;
 }
 
-void qemu_balloon(ram_addr_t target)
-{
-    if (qemu_balloon_event)
-        qemu_balloon_event(qemu_balloon_event_opaque, target);
-}
-
-ram_addr_t qemu_balloon_status(void)
-{
-    if (qemu_balloon_event)
-        return qemu_balloon_event(qemu_balloon_event_opaque, 0);
-    return 0;
-}
-
-/***********************************************************/
-/* keyboard/mouse */
-
-static QEMUPutKBDEvent *qemu_put_kbd_event;
-static void *qemu_put_kbd_event_opaque;
-static QEMUPutMouseEntry *qemu_put_mouse_event_head;
-static QEMUPutMouseEntry *qemu_put_mouse_event_current;
-
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
-{
-    qemu_put_kbd_event_opaque = opaque;
-    qemu_put_kbd_event = func;
-}
-
-QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
-                                                void *opaque, int absolute,
-                                                const char *name)
-{
-    QEMUPutMouseEntry *s, *cursor;
-
-    s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
-
-    s->qemu_put_mouse_event = func;
-    s->qemu_put_mouse_event_opaque = opaque;
-    s->qemu_put_mouse_event_absolute = absolute;
-    s->qemu_put_mouse_event_name = qemu_strdup(name);
-    s->next = NULL;
-
-    if (!qemu_put_mouse_event_head) {
-        qemu_put_mouse_event_head = qemu_put_mouse_event_current = s;
-        return s;
-    }
-
-    cursor = qemu_put_mouse_event_head;
-    while (cursor->next != NULL)
-        cursor = cursor->next;
-
-    cursor->next = s;
-    qemu_put_mouse_event_current = s;
-
-    return s;
-}
-
-void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
+int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque)
 {
-    QEMUPutMouseEntry *prev = NULL, *cursor;
-
-    if (!qemu_put_mouse_event_head || entry == NULL)
-        return;
-
-    cursor = qemu_put_mouse_event_head;
-    while (cursor != NULL && cursor != entry) {
-        prev = cursor;
-        cursor = cursor->next;
-    }
-
-    if (cursor == NULL) // does not exist or list empty
-        return;
-    else if (prev == NULL) { // entry is head
-        qemu_put_mouse_event_head = cursor->next;
-        if (qemu_put_mouse_event_current == entry)
-            qemu_put_mouse_event_current = cursor->next;
-        qemu_free(entry->qemu_put_mouse_event_name);
-        qemu_free(entry);
-        return;
-    }
-
-    prev->next = entry->next;
-
-    if (qemu_put_mouse_event_current == entry)
-        qemu_put_mouse_event_current = prev;
-
-    qemu_free(entry->qemu_put_mouse_event_name);
-    qemu_free(entry);
-}
-
-void kbd_put_keycode(int keycode)
-{
-    if (qemu_put_kbd_event) {
-        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
-    }
-}
-
-void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
-{
-    QEMUPutMouseEvent *mouse_event;
-    void *mouse_event_opaque;
-    int width;
-
-    if (!qemu_put_mouse_event_current) {
-        return;
-    }
-
-    mouse_event =
-        qemu_put_mouse_event_current->qemu_put_mouse_event;
-    mouse_event_opaque =
-        qemu_put_mouse_event_current->qemu_put_mouse_event_opaque;
-
-    if (mouse_event) {
-        if (graphic_rotate) {
-            if (qemu_put_mouse_event_current->qemu_put_mouse_event_absolute)
-                width = 0x7fff;
-            else
-                width = graphic_width - 1;
-            mouse_event(mouse_event_opaque,
-                                 width - dy, dx, dz, buttons_state);
-        } else
-            mouse_event(mouse_event_opaque,
-                                 dx, dy, dz, buttons_state);
+    if (qemu_balloon_event) {
+        qemu_balloon_event(qemu_balloon_event_opaque, target, cb, opaque);
+        return 1;
+    } else {
+        return 0;
     }
 }
 
-int kbd_mouse_is_absolute(void)
+int qemu_balloon_status(MonitorCompletion cb, void *opaque)
 {
-    if (!qemu_put_mouse_event_current)
+    if (qemu_balloon_event) {
+        qemu_balloon_event(qemu_balloon_event_opaque, 0, cb, opaque);
+        return 1;
+    } else {
         return 0;
-
-    return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
-}
-
-void do_info_mice(Monitor *mon)
-{
-    QEMUPutMouseEntry *cursor;
-    int index = 0;
-
-    if (!qemu_put_mouse_event_head) {
-        monitor_printf(mon, "No mouse devices connected\n");
-        return;
-    }
-
-    monitor_printf(mon, "Mouse devices available:\n");
-    cursor = qemu_put_mouse_event_head;
-    while (cursor != NULL) {
-        monitor_printf(mon, "%c Mouse #%d: %s\n",
-                       (cursor == qemu_put_mouse_event_current ? '*' : ' '),
-                       index, cursor->qemu_put_mouse_event_name);
-        index++;
-        cursor = cursor->next;
     }
 }
 
-void do_mouse_set(Monitor *mon, const QDict *qdict)
-{
-    QEMUPutMouseEntry *cursor;
-    int i = 0;
-    int index = qdict_get_int(qdict, "index");
-
-    if (!qemu_put_mouse_event_head) {
-        monitor_printf(mon, "No mouse devices connected\n");
-        return;
-    }
-
-    cursor = qemu_put_mouse_event_head;
-    while (cursor != NULL && index != i) {
-        i++;
-        cursor = cursor->next;
-    }
 
-    if (cursor != NULL)
-        qemu_put_mouse_event_current = cursor;
-    else
-        monitor_printf(mon, "Mouse at given index not found\n");
-}
+/***********************************************************/
+/* real time host monotonic timer */
 
 /* compute with 96 bit intermediate result: (a*b)/c */
 uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
@@ -526,9 +422,6 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
     return res.ll;
 }
 
-/***********************************************************/
-/* real time host monotonic timer */
-
 static int64_t get_clock_realtime(void)
 {
     struct timeval tv;
@@ -1047,6 +940,23 @@ int64_t qemu_get_clock(QEMUClock *clock)
     }
 }
 
+int64_t qemu_get_clock_ns(QEMUClock *clock)
+{
+    switch(clock->type) {
+    case QEMU_CLOCK_REALTIME:
+        return get_clock();
+    default:
+    case QEMU_CLOCK_VIRTUAL:
+        if (use_icount) {
+            return cpu_get_icount();
+        } else {
+            return cpu_get_clock();
+        }
+    case QEMU_CLOCK_HOST:
+        return get_clock_realtime();
+    }
+}
+
 static void init_clocks(void)
 {
     init_get_clock();
@@ -1582,6 +1492,15 @@ int qemu_timedate_diff(struct tm *tm)
     return seconds - time(NULL);
 }
 
+void rtc_change_mon_event(struct tm *tm)
+{
+    QObject *data;
+
+    data = qobject_from_jsonf("{ 'offset': %d }", qemu_timedate_diff(tm));
+    monitor_protocol_event(QEVENT_RTC_CHANGE, data);
+    qobject_decref(data);
+}
+
 static void configure_rtc_date_offset(const char *startdate, int legacy)
 {
     time_t rtc_start_date;
@@ -1964,10 +1883,6 @@ BlockInterfaceErrorAction drive_get_on_error(
 {
     DriveInfo *dinfo;
 
-    if (is_read) {
-        return BLOCK_ERR_REPORT;
-    }
-
     QTAILQ_FOREACH(dinfo, &drives, next) {
         if (dinfo->bdrv == bdrv)
             return is_read ? dinfo->on_read_error : dinfo->on_write_error;
@@ -2357,12 +2272,19 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
     }
 
     if (ro == 1) {
-        if (type == IF_IDE) {
-            fprintf(stderr, "qemu: readonly flag not supported for drive with ide interface\n");
+        if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY) {
+            fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
             return NULL;
         }
-        (void)bdrv_set_read_only(dinfo->bdrv, 1);
     }
+    /* 
+     * cdrom is read-only. Set it now, after above interface checking
+     * since readonly attribute not explicitly required, so no error.
+     */
+    if (media == MEDIA_CDROM) {
+        ro = 1;
+    }
+    bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
 
     if (bdrv_open2(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
         fprintf(stderr, "qemu: could not open disk image %s: %s\n",
@@ -2493,9 +2415,9 @@ static void numa_add(const char *optarg)
                         fprintf(stderr,
                             "only 63 CPUs in NUMA mode supported.\n");
                     }
-                    value = (1 << (endvalue + 1)) - (1 << value);
+                    value = (2ULL << endvalue) - (1ULL << value);
                 } else {
-                    value = 1 << value;
+                    value = 1ULL << value;
                 }
             }
             node_cpumask[nodenr] = value;
@@ -2533,17 +2455,13 @@ static void smp_parse(const char *optarg)
         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 {
+            if (sockets) {
                 threads = smp / (cores * sockets);
             }
         }
@@ -2574,24 +2492,6 @@ static int usb_device_add(const char *devname, int is_hotplug)
     /* the other ones */
     if (strstart(devname, "host:", &p)) {
         dev = usb_host_device_open(p);
-    } else if (strstart(devname, "net:", &p)) {
-        QemuOpts *opts;
-        int idx;
-
-        opts = qemu_opts_parse(&qemu_net_opts, p, NULL);
-        if (!opts) {
-            return -1;
-        }
-
-        qemu_opt_set(opts, "type", "nic");
-        qemu_opt_set(opts, "model", "usb");
-
-        idx = net_client_init(NULL, opts, 0);
-        if (idx == -1) {
-            return -1;
-        }
-
-        dev = usb_net_init(&nd_table[idx]);
     } else 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)));
@@ -2627,17 +2527,28 @@ static int usb_device_del(const char *devname)
 
 static int usb_parse(const char *cmdline)
 {
-    return usb_device_add(cmdline, 0);
+    int r;
+    r = usb_device_add(cmdline, 0);
+    if (r < 0) {
+        fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
+    }
+    return r;
 }
 
 void do_usb_add(Monitor *mon, const QDict *qdict)
 {
-    usb_device_add(qdict_get_str(qdict, "devname"), 1);
+    const char *devname = qdict_get_str(qdict, "devname");
+    if (usb_device_add(devname, 1) < 0) {
+        error_report("could not add USB device '%s'", devname);
+    }
 }
 
 void do_usb_del(Monitor *mon, const QDict *qdict)
 {
-    usb_device_del(qdict_get_str(qdict, "devname"));
+    const char *devname = qdict_get_str(qdict, "devname");
+    if (usb_device_del(devname) < 0) {
+        error_report("could not delete USB device '%s'", devname);
+    }
 }
 
 /***********************************************************/
@@ -2683,46 +2594,6 @@ void pcmcia_info(Monitor *mon)
                        "Empty");
 }
 
-/***********************************************************/
-/* register display */
-
-struct DisplayAllocator default_allocator = {
-    defaultallocator_create_displaysurface,
-    defaultallocator_resize_displaysurface,
-    defaultallocator_free_displaysurface
-};
-
-void register_displaystate(DisplayState *ds)
-{
-    DisplayState **s;
-    s = &display_state;
-    while (*s != NULL)
-        s = &(*s)->next;
-    ds->next = NULL;
-    *s = ds;
-}
-
-DisplayState *get_displaystate(void)
-{
-    return display_state;
-}
-
-DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
-{
-    if(ds->allocator ==  &default_allocator) ds->allocator = da;
-    return ds->allocator;
-}
-
-/* dumb display */
-
-static void dumb_display_init(void)
-{
-    DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
-    ds->allocator = &default_allocator;
-    ds->surface = qemu_create_displaysurface(ds, 640, 480);
-    register_displaystate(ds);
-}
-
 /***********************************************************/
 /* I/O handling */
 
@@ -2990,7 +2861,7 @@ static int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     bytes_transferred_last = bytes_transferred;
-    bwidth = get_clock();
+    bwidth = qemu_get_clock_ns(rt_clock);
 
     while (!qemu_file_rate_limit(f)) {
         int ret;
@@ -3001,7 +2872,7 @@ static int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
             break;
     }
 
-    bwidth = get_clock() - bwidth;
+    bwidth = qemu_get_clock_ns(rt_clock) - bwidth;
     bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
 
     /* if we haven't transferred anything this round, force expected_time to a
@@ -3120,6 +2991,7 @@ static void gui_update(void *opaque)
     DisplayState *ds = opaque;
     DisplayChangeListener *dcl = ds->listeners;
 
+    qemu_flush_coalesced_mmio_buffer();
     dpy_refresh(ds);
 
     while (dcl != NULL) {
@@ -3135,9 +3007,37 @@ 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));
 }
 
+void cpu_synchronize_all_states(void)
+{
+    CPUState *cpu;
+
+    for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
+        cpu_synchronize_state(cpu);
+    }
+}
+
+void cpu_synchronize_all_post_reset(void)
+{
+    CPUState *cpu;
+
+    for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
+        cpu_synchronize_post_reset(cpu);
+    }
+}
+
+void cpu_synchronize_all_post_init(void)
+{
+    CPUState *cpu;
+
+    for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
+        cpu_synchronize_post_init(cpu);
+    }
+}
+
 struct vm_change_state_entry {
     VMChangeStateHandler *cb;
     void *opaque;
@@ -3246,6 +3146,7 @@ static void do_vm_stop(int reason)
         vm_running = 0;
         pause_all_vcpus();
         vm_state_notify(0, reason);
+        monitor_protocol_event(QEVENT_STOP, NULL);
     }
 }
 
@@ -3279,6 +3180,8 @@ void qemu_system_reset(void)
     QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
         re->func(re->opaque);
     }
+    monitor_protocol_event(QEVENT_RESET, NULL);
+    cpu_synchronize_all_post_reset();
 }
 
 void qemu_system_reset_request(void)
@@ -3316,24 +3219,35 @@ static int io_thread_fd = -1;
 
 static void qemu_event_increment(void)
 {
-    static const char byte = 0;
+    /* Write 8 bytes to be compatible with eventfd.  */
+    static uint64_t val = 1;
+    ssize_t ret;
 
     if (io_thread_fd == -1)
         return;
 
-    write(io_thread_fd, &byte, sizeof(byte));
+    do {
+        ret = write(io_thread_fd, &val, sizeof(val));
+    } while (ret < 0 && errno == EINTR);
+
+    /* EAGAIN is fine, a read must be pending.  */
+    if (ret < 0 && errno != EAGAIN) {
+        fprintf(stderr, "qemu_event_increment: write() filed: %s\n",
+                strerror(errno));
+        exit (1);
+    }
 }
 
 static void qemu_event_read(void *opaque)
 {
     int fd = (unsigned long)opaque;
     ssize_t len;
+    char buffer[512];
 
-    /* Drain the notify pipe */
+    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
     do {
-        char buffer[512];
         len = read(fd, buffer, sizeof(buffer));
-    } while ((len == -1 && errno == EINTR) || len > 0);
+    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
 }
 
 static int qemu_event_init(void)
@@ -3341,7 +3255,7 @@ static int qemu_event_init(void)
     int err;
     int fds[2];
 
-    err = qemu_pipe(fds);
+    err = qemu_eventfd(fds);
     if (err == -1)
         return -errno;
 
@@ -3398,6 +3312,8 @@ static int cpu_can_run(CPUState *env)
         return 0;
     if (env->stopped)
         return 0;
+    if (!vm_running)
+        return 0;
     return 1;
 }
 
@@ -3411,10 +3327,10 @@ void qemu_init_vcpu(void *_env)
 {
     CPUState *env = _env;
 
-    if (kvm_enabled())
-        kvm_init_vcpu(env);
     env->nr_cores = smp_cores;
     env->nr_threads = smp_threads;
+    if (kvm_enabled())
+        kvm_init_vcpu(env);
     return;
 }
 
@@ -3472,9 +3388,11 @@ static QemuCond qemu_cpu_cond;
 static QemuCond qemu_system_cond;
 static QemuCond qemu_pause_cond;
 
-static void block_io_signals(void);
+static void tcg_block_io_signals(void);
+static void kvm_block_io_signals(CPUState *env);
 static void unblock_io_signals(void);
 static int tcg_has_work(void);
+static int cpu_has_work(CPUState *env);
 
 static int qemu_init_main_loop(void)
 {
@@ -3495,6 +3413,15 @@ static int qemu_init_main_loop(void)
     return 0;
 }
 
+static void qemu_wait_io_event_common(CPUState *env)
+{
+    if (env->stop) {
+        env->stop = 0;
+        env->stopped = 1;
+        qemu_cond_signal(&qemu_pause_cond);
+    }
+}
+
 static void qemu_wait_io_event(CPUState *env)
 {
     while (!tcg_has_work())
@@ -3511,24 +3438,54 @@ static void qemu_wait_io_event(CPUState *env)
     qemu_mutex_unlock(&qemu_fair_mutex);
 
     qemu_mutex_lock(&qemu_global_mutex);
-    if (env->stop) {
-        env->stop = 0;
-        env->stopped = 1;
-        qemu_cond_signal(&qemu_pause_cond);
+    qemu_wait_io_event_common(env);
+}
+
+static void qemu_kvm_eat_signal(CPUState *env, int timeout)
+{
+    struct timespec ts;
+    int r, e;
+    siginfo_t siginfo;
+    sigset_t waitset;
+
+    ts.tv_sec = timeout / 1000;
+    ts.tv_nsec = (timeout % 1000) * 1000000;
+
+    sigemptyset(&waitset);
+    sigaddset(&waitset, SIG_IPI);
+
+    qemu_mutex_unlock(&qemu_global_mutex);
+    r = sigtimedwait(&waitset, &siginfo, &ts);
+    e = errno;
+    qemu_mutex_lock(&qemu_global_mutex);
+
+    if (r == -1 && !(e == EAGAIN || e == EINTR)) {
+        fprintf(stderr, "sigtimedwait: %s\n", strerror(e));
+        exit(1);
     }
 }
 
+static void qemu_kvm_wait_io_event(CPUState *env)
+{
+    while (!cpu_has_work(env))
+        qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
+
+    qemu_kvm_eat_signal(env, 0);
+    qemu_wait_io_event_common(env);
+}
+
 static int qemu_cpu_exec(CPUState *env);
 
 static void *kvm_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
 
-    block_io_signals();
     qemu_thread_self(env->thread);
     if (kvm_enabled())
         kvm_init_vcpu(env);
 
+    kvm_block_io_signals(env);
+
     /* signal CPU creation */
     qemu_mutex_lock(&qemu_global_mutex);
     env->created = 1;
@@ -3541,7 +3498,7 @@ static void *kvm_cpu_thread_fn(void *arg)
     while (1) {
         if (cpu_can_run(env))
             qemu_cpu_exec(env);
-        qemu_wait_io_event(env);
+        qemu_kvm_wait_io_event(env);
     }
 
     return NULL;
@@ -3553,7 +3510,7 @@ static void *tcg_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
 
-    block_io_signals();
+    tcg_block_io_signals();
     qemu_thread_self(env->thread);
 
     /* signal CPU creation */
@@ -3579,7 +3536,7 @@ void qemu_cpu_kick(void *_env)
     CPUState *env = _env;
     qemu_cond_broadcast(env->halt_cond);
     if (kvm_enabled())
-        qemu_thread_signal(env->thread, SIGUSR1);
+        qemu_thread_signal(env->thread, SIG_IPI);
 }
 
 int qemu_cpu_self(void *_env)
@@ -3598,7 +3555,7 @@ static void cpu_signal(int sig)
         cpu_exit(cpu_single_env);
 }
 
-static void block_io_signals(void)
+static void tcg_block_io_signals(void)
 {
     sigset_t set;
     struct sigaction sigact;
@@ -3607,15 +3564,48 @@ static void block_io_signals(void)
     sigaddset(&set, SIGUSR2);
     sigaddset(&set, SIGIO);
     sigaddset(&set, SIGALRM);
+    sigaddset(&set, SIGCHLD);
     pthread_sigmask(SIG_BLOCK, &set, NULL);
 
     sigemptyset(&set);
-    sigaddset(&set, SIGUSR1);
+    sigaddset(&set, SIG_IPI);
     pthread_sigmask(SIG_UNBLOCK, &set, NULL);
 
     memset(&sigact, 0, sizeof(sigact));
     sigact.sa_handler = cpu_signal;
-    sigaction(SIGUSR1, &sigact, NULL);
+    sigaction(SIG_IPI, &sigact, NULL);
+}
+
+static void dummy_signal(int sig)
+{
+}
+
+static void kvm_block_io_signals(CPUState *env)
+{
+    int r;
+    sigset_t set;
+    struct sigaction sigact;
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGUSR2);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGALRM);
+    sigaddset(&set, SIGCHLD);
+    sigaddset(&set, SIG_IPI);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    pthread_sigmask(SIG_BLOCK, NULL, &set);
+    sigdelset(&set, SIG_IPI);
+
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = dummy_signal;
+    sigaction(SIG_IPI, &sigact, NULL);
+
+    r = kvm_set_signal_mask(env, &set);
+    if (r) {
+        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(r));
+        exit(1);
+    }
 }
 
 static void unblock_io_signals(void)
@@ -3629,7 +3619,7 @@ static void unblock_io_signals(void)
     pthread_sigmask(SIG_UNBLOCK, &set, NULL);
 
     sigemptyset(&set);
-    sigaddset(&set, SIGUSR1);
+    sigaddset(&set, SIG_IPI);
     pthread_sigmask(SIG_BLOCK, &set, NULL);
 }
 
@@ -3638,7 +3628,7 @@ static void qemu_signal_lock(unsigned int msecs)
     qemu_mutex_lock(&qemu_fair_mutex);
 
     while (qemu_mutex_trylock(&qemu_global_mutex)) {
-        qemu_thread_signal(tcg_cpu_thread, SIGUSR1);
+        qemu_thread_signal(tcg_cpu_thread, SIG_IPI);
         if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
             break;
     }
@@ -3679,7 +3669,7 @@ static void pause_all_vcpus(void)
 
     while (penv) {
         penv->stop = 1;
-        qemu_thread_signal(penv->thread, SIGUSR1);
+        qemu_thread_signal(penv->thread, SIG_IPI);
         qemu_cpu_kick(penv);
         penv = (CPUState *)penv->next_cpu;
     }
@@ -3688,7 +3678,7 @@ static void pause_all_vcpus(void)
         qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
         penv = first_cpu;
         while (penv) {
-            qemu_thread_signal(penv->thread, SIGUSR1);
+            qemu_thread_signal(penv->thread, SIG_IPI);
             penv = (CPUState *)penv->next_cpu;
         }
     }
@@ -3701,7 +3691,7 @@ static void resume_all_vcpus(void)
     while (penv) {
         penv->stop = 0;
         penv->stopped = 0;
-        qemu_thread_signal(penv->thread, SIGUSR1);
+        qemu_thread_signal(penv->thread, SIG_IPI);
         qemu_cpu_kick(penv);
         penv = (CPUState *)penv->next_cpu;
     }
@@ -3740,12 +3730,12 @@ void qemu_init_vcpu(void *_env)
 {
     CPUState *env = _env;
 
+    env->nr_cores = smp_cores;
+    env->nr_threads = smp_threads;
     if (kvm_enabled())
         kvm_start_vcpu(env);
     else
         tcg_init_vcpu(env);
-    env->nr_cores = smp_cores;
-    env->nr_threads = smp_threads;
 }
 
 void qemu_notify_event(void)
@@ -3969,14 +3959,15 @@ static void tcg_cpu_exec(void)
     for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
         CPUState *env = cur_cpu = next_cpu;
 
-        if (!vm_running)
-            break;
         if (timer_alarm_pending) {
             timer_alarm_pending = 0;
             break;
         }
         if (cpu_can_run(env))
             ret = qemu_cpu_exec(env);
+        else if (env->stop)
+            break;
+
         if (ret == EXCP_DEBUG) {
             gdb_set_stop_cpu(env);
             debug_requested = 1;
@@ -4103,7 +4094,6 @@ static void main_loop(void)
         } while (vm_can_run());
 
         if (qemu_debug_requested()) {
-            monitor_protocol_event(QEVENT_DEBUG, NULL);
             vm_stop(EXCP_DEBUG);
         }
         if (qemu_shutdown_requested()) {
@@ -4115,7 +4105,6 @@ static void main_loop(void)
                 break;
         }
         if (qemu_reset_requested()) {
-            monitor_protocol_event(QEVENT_RESET, NULL);
             pause_all_vcpus();
             qemu_system_reset();
             resume_all_vcpus();
@@ -4125,7 +4114,6 @@ static void main_loop(void)
             qemu_irq_raise(qemu_system_powerdown);
         }
         if ((r = qemu_vmstop_requested())) {
-            monitor_protocol_event(QEVENT_STOP, NULL);
             vm_stop(r);
         }
     }
@@ -4139,11 +4127,7 @@ static void version(void)
 
 static void help(int exitcode)
 {
-    version();
-    printf("usage: %s [options] [disk_image]\n"
-           "\n"
-           "'disk_image' is a raw hard image image for IDE hard disk 0\n"
-           "\n"
+    const char *options_help =
 #define DEF(option, opt_arg, opt_enum, opt_help)        \
            opt_help
 #define DEFHEADING(text) stringify(text) "\n"
@@ -4151,22 +4135,21 @@ static void help(int exitcode)
 #undef DEF
 #undef DEFHEADING
 #undef GEN_DOCS
+        ;
+    version();
+    printf("usage: %s [options] [disk_image]\n"
+           "\n"
+           "'disk_image' is a raw hard image image for IDE hard disk 0\n"
            "\n"
+           "%s\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
            "ctrl-alt-n      switch to virtual console 'n'\n"
            "ctrl-alt        toggle mouse and keyboard grab\n"
            "\n"
-           "When using -nographic, press 'ctrl-a h' to get some help.\n"
-           ,
+           "When using -nographic, press 'ctrl-a h' to get some help.\n",
            "qemu",
-           DEFAULT_RAM_SIZE,
-#ifndef _WIN32
-           DEFAULT_NETWORK_SCRIPT,
-           DEFAULT_NETWORK_DOWN_SCRIPT,
-#endif
-           DEFAULT_GDBSTUB_PORT,
-           "/tmp/qemu.log");
+           options_help);
     exit(exitcode);
 }
 
@@ -4345,6 +4328,7 @@ static void select_vgahw (const char *p)
 {
     const char *opts;
 
+    default_vga = 0;
     vga_interface_type = VGA_NONE;
     if (strstart(p, "std", &opts)) {
         vga_interface_type = VGA_STD;
@@ -4576,6 +4560,11 @@ char *qemu_find_file(int type, const char *name)
     return buf;
 }
 
+static int device_help_func(QemuOpts *opts, void *opaque)
+{
+    return qdev_device_help(opts);
+}
+
 static int device_init_func(QemuOpts *opts, void *opaque)
 {
     DeviceState *dev;
@@ -4596,10 +4585,85 @@ static int chardev_init_func(QemuOpts *opts, void *opaque)
     return 0;
 }
 
+static int mon_init_func(QemuOpts *opts, void *opaque)
+{
+    CharDriverState *chr;
+    const char *chardev;
+    const char *mode;
+    int flags;
+
+    mode = qemu_opt_get(opts, "mode");
+    if (mode == NULL) {
+        mode = "readline";
+    }
+    if (strcmp(mode, "readline") == 0) {
+        flags = MONITOR_USE_READLINE;
+    } else if (strcmp(mode, "control") == 0) {
+        flags = MONITOR_USE_CONTROL;
+    } else {
+        fprintf(stderr, "unknown monitor mode \"%s\"\n", mode);
+        exit(1);
+    }
+
+    if (qemu_opt_get_bool(opts, "default", 0))
+        flags |= MONITOR_IS_DEFAULT;
+
+    chardev = qemu_opt_get(opts, "chardev");
+    chr = qemu_chr_find(chardev);
+    if (chr == NULL) {
+        fprintf(stderr, "chardev \"%s\" not found\n", chardev);
+        exit(1);
+    }
+
+    monitor_init(chr, flags);
+    return 0;
+}
+
+static void monitor_parse(const char *optarg, const char *mode)
+{
+    static int monitor_device_index = 0;
+    QemuOpts *opts;
+    const char *p;
+    char label[32];
+    int def = 0;
+
+    if (strstart(optarg, "chardev:", &p)) {
+        snprintf(label, sizeof(label), "%s", p);
+    } else {
+        if (monitor_device_index) {
+            snprintf(label, sizeof(label), "monitor%d",
+                     monitor_device_index);
+        } else {
+            snprintf(label, sizeof(label), "monitor");
+            def = 1;
+        }
+        opts = qemu_chr_parse_compat(label, optarg);
+        if (!opts) {
+            fprintf(stderr, "parse error: %s\n", optarg);
+            exit(1);
+        }
+    }
+
+    opts = qemu_opts_create(&qemu_mon_opts, label, 1);
+    if (!opts) {
+        fprintf(stderr, "duplicate chardev: %s\n", label);
+        exit(1);
+    }
+    qemu_opt_set(opts, "mode", mode);
+    qemu_opt_set(opts, "chardev", label);
+    if (def)
+        qemu_opt_set(opts, "default", "on");
+    monitor_device_index++;
+}
+
 struct device_config {
     enum {
-        DEV_USB,       /* -usbdevice   */
-        DEV_BT,        /* -bt          */
+        DEV_USB,       /* -usbdevice     */
+        DEV_BT,        /* -bt            */
+        DEV_SERIAL,    /* -serial        */
+        DEV_PARALLEL,  /* -parallel      */
+        DEV_VIRTCON,   /* -virtioconsole */
+        DEV_DEBUGCON,  /* -debugcon */
     } type;
     const char *cmdline;
     QTAILQ_ENTRY(device_config) next;
@@ -4631,6 +4695,139 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline))
     return 0;
 }
 
+static int serial_parse(const char *devname)
+{
+    static int index = 0;
+    char label[32];
+
+    if (strcmp(devname, "none") == 0)
+        return 0;
+    if (index == MAX_SERIAL_PORTS) {
+        fprintf(stderr, "qemu: too many serial ports\n");
+        exit(1);
+    }
+    snprintf(label, sizeof(label), "serial%d", index);
+    serial_hds[index] = qemu_chr_open(label, devname, NULL);
+    if (!serial_hds[index]) {
+        fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
+                devname, strerror(errno));
+        return -1;
+    }
+    index++;
+    return 0;
+}
+
+static int parallel_parse(const char *devname)
+{
+    static int index = 0;
+    char label[32];
+
+    if (strcmp(devname, "none") == 0)
+        return 0;
+    if (index == MAX_PARALLEL_PORTS) {
+        fprintf(stderr, "qemu: too many parallel ports\n");
+        exit(1);
+    }
+    snprintf(label, sizeof(label), "parallel%d", index);
+    parallel_hds[index] = qemu_chr_open(label, devname, NULL);
+    if (!parallel_hds[index]) {
+        fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
+                devname, strerror(errno));
+        return -1;
+    }
+    index++;
+    return 0;
+}
+
+static int virtcon_parse(const char *devname)
+{
+    static int index = 0;
+    char label[32];
+    QemuOpts *bus_opts, *dev_opts;
+
+    if (strcmp(devname, "none") == 0)
+        return 0;
+    if (index == MAX_VIRTIO_CONSOLES) {
+        fprintf(stderr, "qemu: too many virtio consoles\n");
+        exit(1);
+    }
+
+    bus_opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
+    qemu_opt_set(bus_opts, "driver", "virtio-serial");
+
+    dev_opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
+    qemu_opt_set(dev_opts, "driver", "virtconsole");
+
+    snprintf(label, sizeof(label), "virtcon%d", index);
+    virtcon_hds[index] = qemu_chr_open(label, devname, NULL);
+    if (!virtcon_hds[index]) {
+        fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
+                devname, strerror(errno));
+        return -1;
+    }
+    qemu_opt_set(dev_opts, "chardev", label);
+
+    index++;
+    return 0;
+}
+
+static int debugcon_parse(const char *devname)
+{   
+    QemuOpts *opts;
+
+    if (!qemu_chr_open("debugcon", devname, NULL)) {
+        exit(1);
+    }
+    opts = qemu_opts_create(&qemu_device_opts, "debugcon", 1);
+    if (!opts) {
+        fprintf(stderr, "qemu: already have a debugcon device\n");
+        exit(1);
+    }
+    qemu_opt_set(opts, "driver", "isa-debugcon");
+    qemu_opt_set(opts, "chardev", "debugcon");
+    return 0;
+}
+
+static const QEMUOption *lookup_opt(int argc, char **argv,
+                                    const char **poptarg, int *poptind)
+{
+    const QEMUOption *popt;
+    int optind = *poptind;
+    char *r = argv[optind];
+    const char *optarg;
+
+    optind++;
+    /* Treat --foo the same as -foo.  */
+    if (r[1] == '-')
+        r++;
+    popt = qemu_options;
+    for(;;) {
+        if (!popt->name) {
+            fprintf(stderr, "%s: invalid option -- '%s'\n",
+                    argv[0], r);
+            exit(1);
+        }
+        if (!strcmp(popt->name, r + 1))
+            break;
+        popt++;
+    }
+    if (popt->flags & HAS_ARG) {
+        if (optind >= argc) {
+            fprintf(stderr, "%s: option '%s' requires an argument\n",
+                    argv[0], r);
+            exit(1);
+        }
+        optarg = argv[optind++];
+    } else {
+        optarg = NULL;
+    }
+
+    *poptarg = optarg;
+    *poptind = optind;
+
+    return popt;
+}
+
 int main(int argc, char **argv, char **envp)
 {
     const char *gdbstub_dev = NULL;
@@ -4645,16 +4842,7 @@ int main(int argc, char **argv, char **envp)
     int cyls, heads, secs, translation;
     QemuOpts *hda_opts = NULL, *opts;
     int optind;
-    const char *r, *optarg;
-    CharDriverState *monitor_hds[MAX_MONITOR_DEVICES];
-    const char *monitor_devices[MAX_MONITOR_DEVICES];
-    int monitor_device_index;
-    const char *serial_devices[MAX_SERIAL_PORTS];
-    int serial_device_index;
-    const char *parallel_devices[MAX_PARALLEL_PORTS];
-    int parallel_device_index;
-    const char *virtio_consoles[MAX_VIRTIO_CONSOLES];
-    int virtio_console_index;
+    const char *optarg;
     const char *loadvm = NULL;
     QEMUMachine *machine;
     const char *cpu_model;
@@ -4672,10 +4860,12 @@ int main(int argc, char **argv, char **envp)
 #endif
     CPUState *env;
     int show_vnc_port = 0;
+    int defconfig = 1;
+
+    error_set_progname(argv[0]);
 
     init_clocks();
 
-    qemu_errors_to_file(stderr);
     qemu_cache_utils_init(envp);
 
     QLIST_INIT (&vm_change_state_head);
@@ -4720,26 +4910,6 @@ int main(int argc, char **argv, char **envp)
     cyls = heads = secs = 0;
     translation = BIOS_ATA_TRANSLATION_AUTO;
 
-    serial_devices[0] = "vc:80Cx24C";
-    for(i = 1; i < MAX_SERIAL_PORTS; i++)
-        serial_devices[i] = NULL;
-    serial_device_index = 0;
-
-    parallel_devices[0] = "vc:80Cx24C";
-    for(i = 1; i < MAX_PARALLEL_PORTS; i++)
-        parallel_devices[i] = NULL;
-    parallel_device_index = 0;
-
-    for(i = 0; i < MAX_VIRTIO_CONSOLES; i++)
-        virtio_consoles[i] = NULL;
-    virtio_console_index = 0;
-
-    monitor_devices[0] = "vc:80Cx24C";
-    for (i = 1; i < MAX_MONITOR_DEVICES; i++) {
-        monitor_devices[i] = NULL;
-    }
-    monitor_device_index = 0;
-
     for (i = 0; i < MAX_NODES; i++) {
         node_mem[i] = 0;
         node_cpumask[i] = 0;
@@ -4751,42 +4921,58 @@ int main(int argc, char **argv, char **envp)
     tb_size = 0;
     autostart= 1;
 
+    /* first pass of option parsing */
+    optind = 1;
+    while (optind < argc) {
+        if (argv[optind][0] != '-') {
+            /* disk image */
+            optind++;
+            continue;
+        } else {
+            const QEMUOption *popt;
+
+            popt = lookup_opt(argc, argv, &optarg, &optind);
+            switch (popt->index) {
+            case QEMU_OPTION_nodefconfig:
+                defconfig=0;
+                break;
+            }
+        }
+    }
+
+    if (defconfig) {
+        FILE *fp;
+        fp = fopen(CONFIG_QEMU_CONFDIR "/qemu.conf", "r");
+        if (fp) {
+            if (qemu_config_parse(fp) != 0) {
+                exit(1);
+            }
+            fclose(fp);
+        }
+
+        fp = fopen(CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf", "r");
+        if (fp) {
+            if (qemu_config_parse(fp) != 0) {
+                exit(1);
+            }
+            fclose(fp);
+        }
+    }
+#if defined(cpudef_setup)
+    cpudef_setup(); /* parse cpu definitions in target config file */
+#endif
+
+    /* second pass of option parsing */
     optind = 1;
     for(;;) {
         if (optind >= argc)
             break;
-        r = argv[optind];
-        if (r[0] != '-') {
+        if (argv[optind][0] != '-') {
            hda_opts = drive_add(argv[optind++], HD_ALIAS, 0);
         } else {
             const QEMUOption *popt;
 
-            optind++;
-            /* Treat --foo the same as -foo.  */
-            if (r[1] == '-')
-                r++;
-            popt = qemu_options;
-            for(;;) {
-                if (!popt->name) {
-                    fprintf(stderr, "%s: invalid option -- '%s'\n",
-                            argv[0], r);
-                    exit(1);
-                }
-                if (!strcmp(popt->name, r + 1))
-                    break;
-                popt++;
-            }
-            if (popt->flags & HAS_ARG) {
-                if (optind >= argc) {
-                    fprintf(stderr, "%s: option '%s' requires an argument\n",
-                            argv[0], r);
-                    exit(1);
-                }
-                optarg = argv[optind++];
-            } else {
-                optarg = NULL;
-            }
-
+            popt = lookup_opt(argc, argv, &optarg, &optind);
             switch(popt->index) {
             case QEMU_OPTION_M:
                 machine = find_machine(optarg);
@@ -4808,8 +4994,10 @@ int main(int argc, char **argv, char **envp)
                 /* hw initialization will check this */
                 if (*optarg == '?') {
 /* XXX: implement xxx_cpu_list for targets that still miss it */
-#if defined(cpu_list)
-                    cpu_list(stdout, &fprintf);
+#if defined(cpu_list_id)
+                    cpu_list_id(stdout, &fprintf, optarg);
+#elif defined(cpu_list)
+                    cpu_list(stdout, &fprintf);                /* deprecated */
 #endif
                     exit(0);
                 } else {
@@ -5069,6 +5257,14 @@ int main(int argc, char **argv, char **envp)
                 ram_size = value;
                 break;
             }
+            case QEMU_OPTION_mempath:
+                mem_path = optarg;
+                break;
+#ifdef MAP_POPULATE
+            case QEMU_OPTION_mem_prealloc:
+                mem_prealloc = 1;
+                break;
+#endif
             case QEMU_OPTION_d:
                 {
                     int mask;
@@ -5157,12 +5353,20 @@ int main(int argc, char **argv, char **envp)
                     break;
                 }
             case QEMU_OPTION_monitor:
-                if (monitor_device_index >= MAX_MONITOR_DEVICES) {
-                    fprintf(stderr, "qemu: too many monitor devices\n");
+                monitor_parse(optarg, "readline");
+                default_monitor = 0;
+                break;
+            case QEMU_OPTION_qmp:
+                monitor_parse(optarg, "control");
+                default_monitor = 0;
+                break;
+            case QEMU_OPTION_mon:
+                opts = qemu_opts_parse(&qemu_mon_opts, optarg, "chardev");
+                if (!opts) {
+                    fprintf(stderr, "parse error: %s\n", optarg);
                     exit(1);
                 }
-                monitor_devices[monitor_device_index] = optarg;
-                monitor_device_index++;
+                default_monitor = 0;
                 break;
             case QEMU_OPTION_chardev:
                 opts = qemu_opts_parse(&qemu_chardev_opts, optarg, "backend");
@@ -5172,12 +5376,8 @@ int main(int argc, char **argv, char **envp)
                 }
                 break;
             case QEMU_OPTION_serial:
-                if (serial_device_index >= MAX_SERIAL_PORTS) {
-                    fprintf(stderr, "qemu: too many serial ports\n");
-                    exit(1);
-                }
-                serial_devices[serial_device_index] = optarg;
-                serial_device_index++;
+                add_device_config(DEV_SERIAL, optarg);
+                default_serial = 0;
                 break;
             case QEMU_OPTION_watchdog:
                 if (watchdog) {
@@ -5194,20 +5394,15 @@ int main(int argc, char **argv, char **envp)
                 }
                 break;
             case QEMU_OPTION_virtiocon:
-                if (virtio_console_index >= MAX_VIRTIO_CONSOLES) {
-                    fprintf(stderr, "qemu: too many virtio consoles\n");
-                    exit(1);
-                }
-                virtio_consoles[virtio_console_index] = optarg;
-                virtio_console_index++;
+                add_device_config(DEV_VIRTCON, optarg);
+                default_virtcon = 0;
                 break;
             case QEMU_OPTION_parallel:
-                if (parallel_device_index >= MAX_PARALLEL_PORTS) {
-                    fprintf(stderr, "qemu: too many parallel ports\n");
-                    exit(1);
-                }
-                parallel_devices[parallel_device_index] = optarg;
-                parallel_device_index++;
+                add_device_config(DEV_PARALLEL, optarg);
+                default_parallel = 0;
+                break;
+            case QEMU_OPTION_debugcon:
+                add_device_config(DEV_DEBUGCON, optarg);
                 break;
            case QEMU_OPTION_loadvm:
                loadvm = optarg;
@@ -5400,6 +5595,17 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_incoming:
                 incoming = optarg;
                 break;
+            case QEMU_OPTION_nodefaults:
+                default_serial = 0;
+                default_parallel = 0;
+                default_virtcon = 0;
+                default_monitor = 0;
+                default_vga = 0;
+                default_net = 0;
+                default_floppy = 0;
+                default_cdrom = 0;
+                default_sdcard = 0;
+                break;
 #ifndef _WIN32
             case QEMU_OPTION_chroot:
                 chroot_dir = optarg;
@@ -5478,15 +5684,58 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    if (display_type == DT_NOGRAPHIC) {
-       if (serial_device_index == 0)
-           serial_devices[0] = "stdio";
-       if (parallel_device_index == 0)
-           parallel_devices[0] = "null";
-       if (strncmp(monitor_devices[0], "vc", 2) == 0) {
-           monitor_devices[0] = "stdio";
-       }
+    qemu_opts_foreach(&qemu_device_opts, default_driver_check, NULL, 0);
+    qemu_opts_foreach(&qemu_global_opts, default_driver_check, NULL, 0);
+
+    if (machine->no_serial) {
+        default_serial = 0;
+    }
+    if (machine->no_parallel) {
+        default_parallel = 0;
     }
+    if (!machine->use_virtcon) {
+        default_virtcon = 0;
+    }
+    if (machine->no_vga) {
+        default_vga = 0;
+    }
+    if (machine->no_floppy) {
+        default_floppy = 0;
+    }
+    if (machine->no_cdrom) {
+        default_cdrom = 0;
+    }
+    if (machine->no_sdcard) {
+        default_sdcard = 0;
+    }
+
+    if (display_type == DT_NOGRAPHIC) {
+        if (default_parallel)
+            add_device_config(DEV_PARALLEL, "null");
+        if (default_serial && default_monitor) {
+            add_device_config(DEV_SERIAL, "mon:stdio");
+        } else if (default_virtcon && default_monitor) {
+            add_device_config(DEV_VIRTCON, "mon:stdio");
+        } else {
+            if (default_serial)
+                add_device_config(DEV_SERIAL, "stdio");
+            if (default_virtcon)
+                add_device_config(DEV_VIRTCON, "stdio");
+            if (default_monitor)
+                monitor_parse("stdio", "readline");
+        }
+    } else {
+        if (default_serial)
+            add_device_config(DEV_SERIAL, "vc:80Cx24C");
+        if (default_parallel)
+            add_device_config(DEV_PARALLEL, "vc:80Cx24C");
+        if (default_monitor)
+            monitor_parse("vc:80Cx24C", "readline");
+        if (default_virtcon)
+            add_device_config(DEV_VIRTCON, "vc:80Cx24C");
+    }
+    if (default_vga)
+        vga_interface_type = VGA_CIRRUS;
 
     if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
         exit(1);
@@ -5537,16 +5786,20 @@ int main(int argc, char **argv, char **envp)
         signal(SIGTTOU, SIG_IGN);
         signal(SIGTTIN, SIG_IGN);
     }
+#endif
 
     if (pid_file && qemu_create_pidfile(pid_file) != 0) {
+#ifndef _WIN32
         if (daemonize) {
             uint8_t status = 1;
-            write(fds[1], &status, 1);
+            if (write(fds[1], &status, 1) != 1) {
+                perror("daemonize. Writing to pipe\n");
+            }
         } else
+#endif
             fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
         exit(1);
     }
-#endif
 
     if (kvm_enabled()) {
         int ret;
@@ -5617,14 +5870,20 @@ int main(int argc, char **argv, char **envp)
 
     blk_mig_init();
 
-    /* we always create the cdrom drive, even if no disk is there */
-    drive_add(NULL, CDROM_ALIAS);
+    if (default_cdrom) {
+        /* we always create the cdrom drive, even if no disk is there */
+        drive_add(NULL, CDROM_ALIAS);
+    }
 
-    /* we always create at least one floppy */
-    drive_add(NULL, FD_ALIAS, 0);
+    if (default_floppy) {
+        /* we always create at least one floppy */
+        drive_add(NULL, FD_ALIAS, 0);
+    }
 
-    /* we always create one sd slot, even if no card is in it */
-    drive_add(NULL, SD_ALIAS);
+    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)
@@ -5636,21 +5895,6 @@ int main(int argc, char **argv, char **envp)
     register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL, 
                          ram_load, NULL);
 
-    /* Maintain compatibility with multiple stdio monitors */
-    if (!strcmp(monitor_devices[0],"stdio")) {
-        for (i = 0; i < MAX_SERIAL_PORTS; i++) {
-            const char *devname = serial_devices[i];
-            if (devname && !strcmp(devname,"mon:stdio")) {
-                monitor_devices[0] = NULL;
-                break;
-            } else if (devname && !strcmp(devname,"stdio")) {
-                monitor_devices[0] = NULL;
-                serial_devices[i] = "mon:stdio";
-                break;
-            }
-        }
-    }
-
     if (nb_numa_nodes > 0) {
         int i;
 
@@ -5693,68 +5937,20 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
-    for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
-        const char *devname = monitor_devices[i];
-        if (devname && strcmp(devname, "none")) {
-            char label[32];
-            if (i == 0) {
-                snprintf(label, sizeof(label), "monitor");
-            } else {
-                snprintf(label, sizeof(label), "monitor%d", i);
-            }
-            monitor_hds[i] = qemu_chr_open(label, devname, NULL);
-            if (!monitor_hds[i]) {
-                fprintf(stderr, "qemu: could not open monitor device '%s'\n",
-                        devname);
-                exit(1);
-            }
-        }
-    }
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        const char *devname = serial_devices[i];
-        if (devname && strcmp(devname, "none")) {
-            char label[32];
-            snprintf(label, sizeof(label), "serial%d", i);
-            serial_hds[i] = qemu_chr_open(label, devname, NULL);
-            if (!serial_hds[i]) {
-                fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
-                        devname, strerror(errno));
-                exit(1);
-            }
-        }
-    }
-
-    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        const char *devname = parallel_devices[i];
-        if (devname && strcmp(devname, "none")) {
-            char label[32];
-            snprintf(label, sizeof(label), "parallel%d", i);
-            parallel_hds[i] = qemu_chr_open(label, devname, NULL);
-            if (!parallel_hds[i]) {
-                fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
-                        devname, strerror(errno));
-                exit(1);
-            }
-        }
-    }
-
-    for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
-        const char *devname = virtio_consoles[i];
-        if (devname && strcmp(devname, "none")) {
-            char label[32];
-            snprintf(label, sizeof(label), "virtcon%d", i);
-            virtcon_hds[i] = qemu_chr_open(label, devname, NULL);
-            if (!virtcon_hds[i]) {
-                fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
-                        devname, strerror(errno));
-                exit(1);
-            }
-        }
-    }
+    if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
+        exit(1);
+    if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
+        exit(1);
+    if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
+        exit(1);
+    if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
+        exit(1);
 
     module_call_init(MODULE_INIT_DEVICE);
 
+    if (qemu_opts_foreach(&qemu_device_opts, device_help_func, NULL, 0) != 0)
+        exit(0);
+
     if (watchdog) {
         i = select_watchdog(watchdog);
         if (i > 0)
@@ -5769,6 +5965,7 @@ int main(int argc, char **argv, char **envp)
     machine->init(ram_size, boot_devices,
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
 
+    cpu_synchronize_all_post_init();
 
 #ifndef _WIN32
     /* must be after terminal init, SDL library changes signal handlers */
@@ -5795,10 +5992,10 @@ int main(int argc, char **argv, char **envp)
     if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
         exit(1);
 
-    if (!display_state)
-        dumb_display_init();
+    net_check_clients();
+
     /* just use the first displaystate for the moment */
-    ds = display_state;
+    ds = get_displaystate();
 
     if (display_type == DT_DEFAULT) {
 #if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
@@ -5856,39 +6053,10 @@ int main(int argc, char **argv, char **envp)
         qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
     }
 
-    text_consoles_set_display(display_state);
-
-    for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
-        if (monitor_devices[i] && monitor_hds[i]) {
-            monitor_init(monitor_hds[i],
-                         MONITOR_USE_READLINE |
-                         ((i == 0) ? MONITOR_IS_DEFAULT : 0));
-        }
-    }
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        const char *devname = serial_devices[i];
-        if (devname && strcmp(devname, "none")) {
-            if (strstart(devname, "vc", 0))
-                qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
-        }
-    }
+    text_consoles_set_display(ds);
 
-    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        const char *devname = parallel_devices[i];
-        if (devname && strcmp(devname, "none")) {
-            if (strstart(devname, "vc", 0))
-                qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
-        }
-    }
-
-    for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
-        const char *devname = virtio_consoles[i];
-        if (virtcon_hds[i] && devname) {
-            if (strstart(devname, "vc", 0))
-                qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
-        }
-    }
+    if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0)
+        exit(1);
 
     if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
         fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
@@ -5898,11 +6066,14 @@ int main(int argc, char **argv, char **envp)
 
     qdev_machine_creation_done();
 
-    rom_load_all();
+    if (rom_load_all() != 0) {
+        fprintf(stderr, "rom loading failed\n");
+        exit(1);
+    }
 
     qemu_system_reset();
     if (loadvm) {
-        if (load_vmstate(cur_mon, loadvm) < 0) {
+        if (load_vmstate(loadvm) < 0) {
             autostart = 0;
         }
     }
@@ -5926,7 +6097,10 @@ int main(int argc, char **argv, char **envp)
        if (len != 1)
            exit(1);
 
-       chdir("/");
+        if (chdir("/")) {
+            perror("not able to chdir to /");
+            exit(1);
+        }
        TFR(fd = qemu_open("/dev/null", O_RDWR));
        if (fd == -1)
            exit(1);
@@ -5945,7 +6119,10 @@ int main(int argc, char **argv, char **envp)
             fprintf(stderr, "chroot failed\n");
             exit(1);
         }
-        chdir("/");
+        if (chdir("/")) {
+            perror("not able to chdir to /");
+            exit(1);
+        }
     }
 
     if (run_as) {