Merge remote branch 'qemu-kvm/uq/stable-0.12' into stable-0.12
diff --git a/Changelog b/Changelog
index dede703..67d0efd 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,55 @@
+version 0.12.3
+  - kvm: Fix eflags corruption in kvm mode (Jan Kiszka)
+  - qcow2: Fix access after end of array (Kevin Wolf)
+  - ide save/restore pio/atapi cmd transfer fields and io buffer (Marcelo Tosatti)
+  - net: Monitor command set_link finds only VLAN clients, fix (Markus Armbruster)
+  - net: info network shows only VLAN clients, fix (Markus Armbruster)
+  - net: net_check_clients() checks only VLAN clients, fix (Markus Armbruster)
+  - net: Fix bogus "Warning: vlan 0 with no nics" with -device (Markus Armbruster)
+  - net: net_check_clients() runs too early to see -device, fix (Markus Armbruster)
+  - net: Remove unused net_client_uninit() (Markus Armbruster)
+  - don't dereference NULL after failed strdup (Jim Meyering)
+  - virtio-net: fix network stall under load (Tom Lendacky)
+  - json: fix PRId64 on Win32 (Roy Tam)
+  - fix inet_parse typo (Marcelo Tosatti)
+  - iothread: fix vcpu stop with smp tcg (Marcelo Tosatti)
+  - segfault due to buffer overrun in usb-serial (David S. Ahern)
+  - qcow2: Fix signedness bugs (Kevin Wolf)
+  - Do not ignore error, if open file failed (-serial /dev/tty) (Evgeniy Dushistov)
+  - pc-bios: update to newer version of (stable) seabios (Anthony Liguori)
+  - target-mips: fix ROTR and DROTR by zero (Aurelien Jarno)
+  - target-mips: fix CpU exception for coprocessor 0 (Nathan Froyd)
+  - tcg/mips: fix crash in tcg_out_qemu_ld() (Aurelien Jarno)
+  - target-mips: don't call cpu_loop_exit() from helper.c (Aurelien Jarno)
+  - virtio-blk: Fix error cases which ignored rerror/werror (Kevin Wolf)
+  - virtio-blk: Fix restart after read error (Kevin Wolf)
+  - virtio_blk: Factor virtio_blk_handle_request out (Kevin Wolf)
+  - cirrus: Properly re-register cirrus_linear_io_addr on vram unmap (Jan Kiszka)
+  - qcow2: Don't ignore qcow2_alloc_clusters return value (Kevin Wolf)
+  - qcow2: Don't ignore update_refcount return value (Kevin Wolf)
+  - qcow2: Allow updating no refcounts (Kevin Wolf)
+  - qcow2: Improve error handling in update_refcount (Kevin Wolf)
+  - qcow2: Fix error handling in grow_refcount_table (Kevin Wolf)
+  - block: Return original error codes in bdrv_pread/write (Kevin Wolf)
+  - qcow2: Return 0/-errno in qcow2_alloc_cluster_offset (Kevin Wolf)
+  - qcow2: Return 0/-errno in get_cluster_table (Kevin Wolf)
+  - qcow2: Fix error handling in qcow_save_vmstate (Kevin Wolf)
+  - qcow2: Fix error handling in qcow2_grow_l1_table (Kevin Wolf)
+  - win32/sdl: Fix toggle full screen (Herve Poussineau)
+  - win32: pair qemu_memalign() with qemu_vfree() (Herve Poussineau)
+  - vnc_refresh: calling vnc_update_client might free vs (Stefano Stabellini)
+  - Musicpal: Fix descriptor walk in eth_send (Jan Kiszka)
+  - Musicpal: Fix wm8750 I2C address (Jan Kiszka)
+  - fix savevm command without id or tag (Marcelo Tosatti)
+  - reduce number of reinjects on ACK (Gleb Natapov)
+  - QMP: Fix asynchronous events delivery (Luiz Capitulino)
+  - Documentation: Add missing documentation for qdev related command line options (Stefan Weil)
+  - pc: add driver version compat properties (Gerd Hoffmann)
+  - scsi: device version property (Gerd Hoffmann)
+  - ide: device version property (Gerd Hoffmann)
+  - QMP: Emit asynchronous events on all QMP monitors (Adam Litke)
+  - Fix QEMU_WARN_UNUSED_RESULT (Kevin Wolf)
+
 version 0.12.2:
   - Qemu's internal TFTP server breaks lock-step-iness of TFTP (Milan Plzik)
   - osdep.c: Fix accept4 fallback (Kevin Wolf)
diff --git a/VERSION b/VERSION
index 26acbf0..aa22d3c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.12.2
+0.12.3
diff --git a/block/curl.c b/block/curl.c
index 5223ce8..c9c4574 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -309,7 +309,7 @@
 
     static int inited = 0;
 
-    file = strdup(filename);
+    file = qemu_strdup(filename);
     s->readahead_size = READ_AHEAD_SIZE;
 
     /* Parse a trailing ":readahead=#:" param, if present. */
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 4e30d16..b13b693 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -219,7 +219,8 @@
     BDRVQcowState *s = bs->opaque;
     int min_index;
     uint64_t old_l2_offset;
-    uint64_t *l2_table, l2_offset;
+    uint64_t *l2_table;
+    int64_t l2_offset;
 
     old_l2_offset = s->l1_table[l1_index];
 
@@ -560,7 +561,8 @@
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index, ret;
-    uint64_t l2_offset, *l2_table, cluster_offset;
+    uint64_t l2_offset, *l2_table;
+    int64_t cluster_offset;
     int nb_csectors;
 
     ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
@@ -704,10 +706,8 @@
  *
  * Return 0 on success and -errno in error cases
  */
-uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
-                                    uint64_t offset,
-                                    int n_start, int n_end,
-                                    int *num, QCowL2Meta *m)
+int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
+    int n_start, int n_end, int *num, QCowL2Meta *m)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index, ret;
@@ -750,12 +750,15 @@
     while (i < nb_clusters) {
         i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
                 &l2_table[l2_index], i, 0);
-
-        if(be64_to_cpu(l2_table[l2_index + i]))
+        if ((i >= nb_clusters) || be64_to_cpu(l2_table[l2_index + i])) {
             break;
+        }
 
         i += count_contiguous_free_clusters(nb_clusters - i,
                 &l2_table[l2_index + i]);
+        if (i >= nb_clusters) {
+            break;
+        }
 
         cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
 
@@ -763,6 +766,7 @@
                 (cluster_offset & QCOW_OFLAG_COMPRESSED))
             break;
     }
+    assert(i <= nb_clusters);
     nb_clusters = i;
 
     /*
diff --git a/block/qcow2.h b/block/qcow2.h
index d9ea6ab..de9397a 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -192,10 +192,8 @@
 
 uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
     int *num);
-uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
-                              uint64_t offset,
-                              int n_start, int n_end,
-                              int *num, QCowL2Meta *m);
+int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
+    int n_start, int n_end, int *num, QCowL2Meta *m);
 uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
                                          uint64_t offset,
                                          int compressed_size);
diff --git a/block/vvfat.c b/block/vvfat.c
index 063f731..c1acb35 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -882,7 +882,7 @@
     mapping->dir_index = 0;
     mapping->info.dir.parent_mapping_index = -1;
     mapping->first_mapping_index = -1;
-    mapping->path = strdup(dirname);
+    mapping->path = qemu_strdup(dirname);
     i = strlen(mapping->path);
     if (i > 0 && mapping->path[i - 1] == '/')
 	mapping->path[i - 1] = '\0';
@@ -1632,10 +1632,10 @@
 
 	    /* rename */
 	    if (strcmp(basename, basename2))
-		schedule_rename(s, cluster_num, strdup(path));
+		schedule_rename(s, cluster_num, qemu_strdup(path));
 	} else if (is_file(direntry))
 	    /* new file */
-	    schedule_new_file(s, strdup(path), cluster_num);
+	    schedule_new_file(s, qemu_strdup(path), cluster_num);
 	else {
 	    assert(0);
 	    return 0;
@@ -1752,10 +1752,10 @@
 	mapping->mode &= ~MODE_DELETED;
 
 	if (strcmp(basename, basename2))
-	    schedule_rename(s, cluster_num, strdup(path));
+	    schedule_rename(s, cluster_num, qemu_strdup(path));
     } else
 	/* new directory */
-	schedule_mkdir(s, cluster_num, strdup(path));
+	schedule_mkdir(s, cluster_num, qemu_strdup(path));
 
     lfn_init(&lfn);
     do {
diff --git a/hw/ide/core.c b/hw/ide/core.c
index b6643e8..64aebc2 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2640,6 +2640,7 @@
         s->unit = i;
         s->drive_serial = drive_serial++;
         s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
+        s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
         s->smart_selftest_data = qemu_blockalign(s->bs, 512);
         s->sector_write_timer = qemu_new_timer(vm_clock,
                                                ide_sector_write_timer_cb, s);
@@ -2674,6 +2675,25 @@
     return s->identify_set != 0;
 }
 
+static EndTransferFunc* transfer_end_table[] = {
+        ide_sector_read,
+        ide_sector_write,
+        ide_transfer_stop,
+        ide_atapi_cmd_reply_end,
+        ide_atapi_cmd,
+};
+
+static int transfer_end_table_idx(EndTransferFunc *fn)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(transfer_end_table); i++)
+        if (transfer_end_table[i] == fn)
+            return i;
+
+    return -1;
+}
+
 static int ide_drive_post_load(void *opaque, int version_id)
 {
     IDEState *s = opaque;
@@ -2684,14 +2704,42 @@
             s->cdrom_changed = 1;
         }
     }
+
+    if (s->cur_io_buffer_len) {
+        s->end_transfer_func = transfer_end_table[s->end_transfer_fn_idx];
+        s->data_ptr = s->io_buffer + s->cur_io_buffer_offset;
+        s->data_end = s->data_ptr + s->cur_io_buffer_len;
+    }
+        
     return 0;
 }
 
+static void ide_drive_pre_save(void *opaque)
+{
+    IDEState *s = opaque;
+
+    s->cur_io_buffer_len = 0;
+
+    if (!(s->status & DRQ_STAT))
+        return;
+
+    s->cur_io_buffer_offset = s->data_ptr - s->io_buffer;
+    s->cur_io_buffer_len = s->data_end - s->data_ptr;
+
+    s->end_transfer_fn_idx = transfer_end_table_idx(s->end_transfer_func);
+    if (s->end_transfer_fn_idx == -1) {
+        fprintf(stderr, "%s: invalid end_transfer_func for DRQ_STAT\n",
+                        __func__);
+        s->end_transfer_fn_idx = 2;
+    }
+}
+
 const VMStateDescription vmstate_ide_drive = {
     .name = "ide_drive",
-    .version_id = 3,
+    .version_id = 4,
     .minimum_version_id = 0,
     .minimum_version_id_old = 0,
+    .pre_save = ide_drive_pre_save,
     .post_load = ide_drive_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_INT32(mult_sectors, IDEState),
@@ -2714,7 +2762,14 @@
         VMSTATE_UINT8(sense_key, IDEState),
         VMSTATE_UINT8(asc, IDEState),
         VMSTATE_UINT8_V(cdrom_changed, IDEState, 3),
-        /* XXX: if a transfer is pending, we do not save it yet */
+        VMSTATE_INT32_V(req_nb_sectors, IDEState, 4),
+        VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 4,
+			     vmstate_info_uint8, uint8_t),
+        VMSTATE_INT32_V(cur_io_buffer_offset, IDEState, 4),
+        VMSTATE_INT32_V(cur_io_buffer_len, IDEState, 4),
+        VMSTATE_UINT8_V(end_transfer_fn_idx, IDEState, 4),
+        VMSTATE_INT32_V(elementary_transfer_size, IDEState, 4),
+        VMSTATE_INT32_V(packet_transfer_size, IDEState, 4),
         VMSTATE_END_OF_LIST()
     }
 };
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index f9a34b8..8869a08 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -417,6 +417,11 @@
     uint8_t *data_ptr;
     uint8_t *data_end;
     uint8_t *io_buffer;
+    /* PIO save/restore */
+    int32_t io_buffer_total_len;
+    int cur_io_buffer_offset;
+    int cur_io_buffer_len;
+    uint8_t end_transfer_fn_idx;
     QEMUTimer *sector_write_timer; /* only used for win2k install hack */
     uint32_t irq_count; /* counts IRQs when using win2k install hack */
     /* CF-ATA extended error */
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 37293ea..c3f3401 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -497,12 +497,28 @@
 static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
 {
     USBSerialState *s = opaque;
-    int first_size = RECV_BUF - s->recv_ptr;
-    if (first_size > size)
-        first_size = size;
-    memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size);
-    if (size > first_size)
-        memcpy(s->recv_buf, buf + first_size, size - first_size);
+    int first_size, start;
+
+    /* room in the buffer? */
+    if (size > (RECV_BUF - s->recv_used))
+        size = RECV_BUF - s->recv_used;
+
+    start = s->recv_ptr + s->recv_used;
+    if (start < RECV_BUF) {
+        /* copy data to end of buffer */
+        first_size = RECV_BUF - start;
+        if (first_size > size)
+            first_size = size;
+
+        memcpy(s->recv_buf + start, buf, first_size);
+
+        /* wrap around to front if needed */
+        if (size > first_size)
+            memcpy(s->recv_buf, buf + first_size, size - first_size);
+    } else {
+        start -= RECV_BUF;
+        memcpy(s->recv_buf + start, buf, size);
+    }
     s->recv_used += size;
 }
 
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 2f201ff..d8a1629 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -384,7 +384,15 @@
         (n->mergeable_rx_bufs &&
          !virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) {
         virtio_queue_set_notification(n->rx_vq, 1);
-        return 0;
+
+        /* To avoid a race condition where the guest has made some buffers
+         * available after the above check but before notification was
+         * enabled, check for available buffers again.
+         */
+        if (virtio_queue_empty(n->rx_vq) ||
+            (n->mergeable_rx_bufs &&
+             !virtqueue_avail_bytes(n->rx_vq, bufsize, 0)))
+            return 0;
     }
 
     virtio_queue_set_notification(n->rx_vq, 0);
diff --git a/json-lexer.c b/json-lexer.c
index 53697c5..9d64920 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -54,6 +54,9 @@
     IN_ESCAPE,
     IN_ESCAPE_L,
     IN_ESCAPE_LL,
+    IN_ESCAPE_I,
+    IN_ESCAPE_I6,
+    IN_ESCAPE_I64,
     IN_ESCAPE_DONE,
     IN_WHITESPACE,
     IN_OPERATOR_DONE,
@@ -223,6 +226,18 @@
         ['l'] = IN_ESCAPE_LL,
     },
 
+    [IN_ESCAPE_I64] = {
+        ['d'] = IN_ESCAPE_DONE,
+    },
+
+    [IN_ESCAPE_I6] = {
+        ['4'] = IN_ESCAPE_I64,
+    },
+
+    [IN_ESCAPE_I] = {
+        ['6'] = IN_ESCAPE_I6,
+    },
+
     [IN_ESCAPE] = {
         ['d'] = IN_ESCAPE_DONE,
         ['i'] = IN_ESCAPE_DONE,
@@ -230,6 +245,7 @@
         ['s'] = IN_ESCAPE_DONE,
         ['f'] = IN_ESCAPE_DONE,
         ['l'] = IN_ESCAPE_L,
+        ['I'] = IN_ESCAPE_I,
     },
 
     /* top level rule */
diff --git a/json-parser.c b/json-parser.c
index 7624c0f..2ab6f6c 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -476,7 +476,8 @@
         obj = QOBJECT(qint_from_int(va_arg(*ap, int)));
     } else if (token_is_escape(token, "%ld")) {
         obj = QOBJECT(qint_from_int(va_arg(*ap, long)));
-    } else if (token_is_escape(token, "%lld")) {
+    } else if (token_is_escape(token, "%lld") ||
+               token_is_escape(token, "%I64d")) {
         obj = QOBJECT(qint_from_int(va_arg(*ap, long long)));
     } else if (token_is_escape(token, "%s")) {
         obj = QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
diff --git a/net.c b/net.c
index 6ef93e6..029b0d7 100644
--- a/net.c
+++ b/net.c
@@ -96,7 +96,7 @@
                         struct sockaddr_in *saddr,
                         const char *input_str)
 {
-    char *str = strdup(input_str);
+    char *str = qemu_strdup(input_str);
     char *host_str = str;
     char *src_str;
     const char *src_str2;
@@ -812,9 +812,6 @@
     }
 
     nd->used = 1;
-    if (vlan) {
-        nd->vlan->nb_guest_devs++;
-    }
     nb_nics++;
 
     return idx;
@@ -1128,20 +1125,6 @@
     return -1;
 }
 
-void net_client_uninit(NICInfo *nd)
-{
-    if (nd->vlan) {
-        nd->vlan->nb_guest_devs--;
-    }
-    nb_nics--;
-
-    qemu_free(nd->model);
-    qemu_free(nd->name);
-    qemu_free(nd->devaddr);
-
-    nd->used = 0;
-}
-
 static int net_host_check_device(const char *device)
 {
     int i;
@@ -1227,16 +1210,23 @@
 void do_info_network(Monitor *mon)
 {
     VLANState *vlan;
+    VLANClientState *vc;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
-        VLANClientState *vc;
-
         monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
 
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
             monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
         }
     }
+    monitor_printf(mon, "Devices not on any VLAN:\n");
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        monitor_printf(mon, "  %s: %s", vc->name, vc->info_str);
+        if (vc->peer) {
+            monitor_printf(mon, " peer=%s", vc->peer->name);
+        }
+        monitor_printf(mon, "\n");
+    }
 }
 
 void do_set_link(Monitor *mon, const QDict *qdict)
@@ -1253,6 +1243,7 @@
             }
         }
     }
+    vc = qemu_find_netdev(name);
 done:
 
     if (!vc) {
@@ -1289,20 +1280,41 @@
     }
 }
 
-static void net_check_clients(void)
+void net_check_clients(void)
 {
     VLANState *vlan;
+    VLANClientState *vc;
+    int has_nic, has_host_dev;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
-        if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0)
-            continue;
-        if (vlan->nb_guest_devs == 0)
+        QTAILQ_FOREACH(vc, &vlan->clients, next) {
+            switch (vc->info->type) {
+            case NET_CLIENT_TYPE_NIC:
+                has_nic = 1;
+                break;
+            case NET_CLIENT_TYPE_SLIRP:
+            case NET_CLIENT_TYPE_TAP:
+            case NET_CLIENT_TYPE_SOCKET:
+            case NET_CLIENT_TYPE_VDE:
+                has_host_dev = 1;
+                break;
+            default: ;
+            }
+        }
+        if (has_host_dev && !has_nic)
             fprintf(stderr, "Warning: vlan %d with no nics\n", vlan->id);
-        if (vlan->nb_host_devs == 0)
+        if (has_nic && !has_host_dev)
             fprintf(stderr,
                     "Warning: vlan %d is not connected to host network\n",
                     vlan->id);
     }
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        if (!vc->peer) {
+            fprintf(stderr, "Warning: %s %s has no peer\n",
+                    vc->info->type == NET_CLIENT_TYPE_NIC ? "nic" : "netdev",
+                    vc->name);
+        }
+    }
 }
 
 static int net_init_client(QemuOpts *opts, void *dummy)
@@ -1337,8 +1349,6 @@
         return -1;
     }
 
-    net_check_clients();
-
     return 0;
 }
 
diff --git a/net.h b/net.h
index 4971fcb..673b355 100644
--- a/net.h
+++ b/net.h
@@ -76,7 +76,6 @@
     int id;
     QTAILQ_HEAD(, VLANClientState) clients;
     QTAILQ_ENTRY(VLANState) next;
-    unsigned int nb_guest_devs, nb_host_devs;
     NetQueue *send_queue;
 };
 
@@ -160,9 +159,9 @@
 extern const char *legacy_bootp_filename;
 
 int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev);
-void net_client_uninit(NICInfo *nd);
 int net_client_parse(QemuOptsList *opts_list, const char *str);
 int net_init_clients(void);
+void net_check_clients(void);
 void net_cleanup(void);
 void net_set_boot_mask(int boot_mask);
 void net_host_device_add(Monitor *mon, const QDict *qdict);
diff --git a/net/slirp.c b/net/slirp.c
index 3f91c4b..50ac0b9 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -728,10 +728,6 @@
         qemu_free(config);
     }
 
-    if (ret != -1 && vlan) {
-        vlan->nb_host_devs++;
-    }
-
     qemu_free(vnet);
 
     return ret;
diff --git a/net/socket.c b/net/socket.c
index 5533737..442a9c7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -569,9 +569,5 @@
         return -1;
     }
 
-    if (vlan) {
-        vlan->nb_host_devs++;
-    }
-
     return 0;
 }
diff --git a/net/tap-win32.c b/net/tap-win32.c
index b717c17..8370c80 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -714,10 +714,6 @@
         return -1;
     }
 
-    if (vlan) {
-        vlan->nb_host_devs++;
-    }
-
     return 0;
 }
 
diff --git a/net/tap.c b/net/tap.c
index 0d8b424..adbc979 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -441,9 +441,5 @@
         }
     }
 
-    if (vlan) {
-        vlan->nb_host_devs++;
-    }
-
     return 0;
 }
diff --git a/net/vde.c b/net/vde.c
index 42b4633..0b46fa6 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -127,9 +127,5 @@
         return -1;
     }
 
-    if (vlan) {
-        vlan->nb_host_devs++;
-    }
-
     return 0;
 }
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 1741eec..855f468 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/qemu-char.c b/qemu-char.c
index b13f8d4..5a1b535 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1180,6 +1180,9 @@
     int fd;
 
     TFR(fd = open(filename, O_RDWR | O_NONBLOCK));
+    if (fd < 0) {
+        return NULL;
+    }
     tty_serial_init(fd, 115200, 'N', 8, 1);
     chr = qemu_chr_open_fd(fd, fd);
     if (!chr) {
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 8850516..a88b2a7 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -424,7 +424,7 @@
                     __FUNCTION__, str);
             return -1;
         }
-        qemu_opt_set(opts, "ipv6", "yes");
+        qemu_opt_set(opts, "ipv6", "on");
     } else if (qemu_isdigit(str[0])) {
         /* IPv4 addr */
         if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
@@ -432,7 +432,7 @@
                     __FUNCTION__, str);
             return -1;
         }
-        qemu_opt_set(opts, "ipv4", "yes");
+        qemu_opt_set(opts, "ipv4", "on");
     } else {
         /* hostname */
         if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
@@ -450,9 +450,9 @@
     if (h)
         qemu_opt_set(opts, "to", h+4);
     if (strstr(optstr, ",ipv4"))
-        qemu_opt_set(opts, "ipv4", "yes");
+        qemu_opt_set(opts, "ipv4", "on");
     if (strstr(optstr, ",ipv6"))
-        qemu_opt_set(opts, "ipv6", "yes");
+        qemu_opt_set(opts, "ipv6", "on");
     return 0;
 }
 
diff --git a/roms/seabios b/roms/seabios
index 5da6833..9fb3f4d 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 5da68339ecf44677b8f4f115cdf3cb1da46a9f6c
+Subproject commit 9fb3f4d950744e97cc655b7d7b523d8bf101e4a0
diff --git a/slirp/misc.c b/slirp/misc.c
index c76ad8f..b68af6d 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -179,7 +179,7 @@
 		   close(s);
 
 		i = 0;
-		bptr = strdup(ex); /* No need to free() this */
+		bptr = qemu_strdup(ex); /* No need to free() this */
 		if (do_pty == 1) {
 			/* Setup "slirp.telnetd -x" */
 			argv[i++] = "slirp.telnetd";
diff --git a/target-mips/translate.c b/target-mips/translate.c
index f756ab9..f811f50 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -821,7 +821,7 @@
 static inline void check_cp0_enabled(DisasContext *ctx)
 {
     if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
-        generate_exception_err(ctx, EXCP_CpU, 1);
+        generate_exception_err(ctx, EXCP_CpU, 0);
 }
 
 static inline void check_cp1_enabled(DisasContext *ctx)
@@ -1451,6 +1451,8 @@
                     tcg_gen_rotri_i32(t1, t1, uimm);
                     tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
                     tcg_temp_free_i32(t1);
+                } else {
+                    tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
                 }
                 opn = "rotr";
             } else {
@@ -1489,6 +1491,8 @@
             if (env->insn_flags & ISA_MIPS32R2) {
                 if (uimm != 0) {
                     tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
+                } else {
+                    tcg_gen_mov_tl(cpu_gpr[rt], t0);
                 }
                 opn = "drotr";
             } else {
diff --git a/vl.c b/vl.c
index 007709a..40b07fe 100644
--- a/vl.c
+++ b/vl.c
@@ -4042,14 +4042,15 @@
     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;
@@ -5968,6 +5969,8 @@
     if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
         exit(1);
 
+    net_check_clients();
+
     if (!display_state)
         dumb_display_init();
     /* just use the first displaystate for the moment */