summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--block.c33
-rw-r--r--block/iscsi.c3
-rw-r--r--block/qcow2.c25
-rw-r--r--block/qed.c4
-rw-r--r--block/raw-posix.c39
-rw-r--r--block/raw_bsd.c3
-rw-r--r--block/stream.c2
-rw-r--r--block/vmdk.c4
-rw-r--r--hw/acpi/ich9.c4
-rw-r--r--hw/char/cadence_uart.c15
-rw-r--r--hw/char/virtio-serial-bus.c14
-rw-r--r--hw/i386/pc_piix.c13
-rw-r--r--hw/virtio/vhost-user.c6
-rw-r--r--include/block/block.h2
-rw-r--r--include/block/block_int.h2
-rw-r--r--linux-user/ioctls.h2
-rw-r--r--linux-user/signal.c7
-rw-r--r--linux-user/syscall.c32
-rw-r--r--linux-user/syscall_defs.h10
-rwxr-xr-xscripts/vmstate-static-checker.py27
-rw-r--r--tests/Makefile2
-rwxr-xr-xtests/qemu-iotests/0284
-rw-r--r--tests/qemu-iotests/028.out2
-rwxr-xr-xtests/qemu-iotests/03652
-rw-r--r--tests/qemu-iotests/036.out35
-rwxr-xr-xtests/qemu-iotests/qcow2.py15
-rw-r--r--tests/vhost-user-test.c11
-rw-r--r--vl.c1
29 files changed, 283 insertions, 88 deletions
diff --git a/VERSION b/VERSION
index a162201152..0a7e4e52e5 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.91
+2.0.92
diff --git a/block.c b/block.c
index 3e252a26c2..8cf519ba3a 100644
--- a/block.c
+++ b/block.c
@@ -508,19 +508,24 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
     return ret;
 }
 
-int bdrv_refresh_limits(BlockDriverState *bs)
+void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
 {
     BlockDriver *drv = bs->drv;
+    Error *local_err = NULL;
 
     memset(&bs->bl, 0, sizeof(bs->bl));
 
     if (!drv) {
-        return 0;
+        return;
     }
 
     /* Take some limits from the children as a default */
     if (bs->file) {
-        bdrv_refresh_limits(bs->file);
+        bdrv_refresh_limits(bs->file, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
         bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
         bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
     } else {
@@ -528,7 +533,11 @@ int bdrv_refresh_limits(BlockDriverState *bs)
     }
 
     if (bs->backing_hd) {
-        bdrv_refresh_limits(bs->backing_hd);
+        bdrv_refresh_limits(bs->backing_hd, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
         bs->bl.opt_transfer_length =
             MAX(bs->bl.opt_transfer_length,
                 bs->backing_hd->bl.opt_transfer_length);
@@ -539,10 +548,8 @@ int bdrv_refresh_limits(BlockDriverState *bs)
 
     /* Then let the driver override it */
     if (drv->bdrv_refresh_limits) {
-        return drv->bdrv_refresh_limits(bs);
+        drv->bdrv_refresh_limits(bs, errp);
     }
-
-    return 0;
 }
 
 /*
@@ -993,7 +1000,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
         goto free_and_fail;
     }
 
-    bdrv_refresh_limits(bs);
+    bdrv_refresh_limits(bs, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        ret = -EINVAL;
+        goto free_and_fail;
+    }
+
     assert(bdrv_opt_mem_align(bs) != 0);
     assert((bs->request_alignment != 0) || bs->sg);
     return 0;
@@ -1154,7 +1167,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
     bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT,
                     bs->backing_blocker);
 out:
-    bdrv_refresh_limits(bs);
+    bdrv_refresh_limits(bs, NULL);
 }
 
 /*
@@ -1778,7 +1791,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
                                               BDRV_O_CACHE_WB);
     reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
 
-    bdrv_refresh_limits(reopen_state->bs);
+    bdrv_refresh_limits(reopen_state->bs, NULL);
 }
 
 /*
diff --git a/block/iscsi.c b/block/iscsi.c
index f3e83e2332..a7bb6970ac 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1450,7 +1450,7 @@ static void iscsi_close(BlockDriverState *bs)
     memset(iscsilun, 0, sizeof(IscsiLun));
 }
 
-static int iscsi_refresh_limits(BlockDriverState *bs)
+static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
 {
     IscsiLun *iscsilun = bs->opaque;
 
@@ -1475,7 +1475,6 @@ static int iscsi_refresh_limits(BlockDriverState *bs)
     }
     bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
                                                  iscsilun);
-    return 0;
 }
 
 /* Since iscsi_open() ignores bdrv_flags, there is nothing to do here in
diff --git a/block/qcow2.c b/block/qcow2.c
index b0faa6917b..1e3ab6bd02 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -210,20 +210,31 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
 static void report_unsupported_feature(BlockDriverState *bs,
     Error **errp, Qcow2Feature *table, uint64_t mask)
 {
+    char *features = g_strdup("");
+    char *old;
+
     while (table && table->name[0] != '\0') {
         if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) {
-            if (mask & (1 << table->bit)) {
-                report_unsupported(bs, errp, "%.46s", table->name);
-                mask &= ~(1 << table->bit);
+            if (mask & (1ULL << table->bit)) {
+                old = features;
+                features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "",
+                                           table->name);
+                g_free(old);
+                mask &= ~(1ULL << table->bit);
             }
         }
         table++;
     }
 
     if (mask) {
-        report_unsupported(bs, errp, "Unknown incompatible feature: %" PRIx64,
-                           mask);
+        old = features;
+        features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64,
+                                   old, *old ? ", " : "", mask);
+        g_free(old);
     }
+
+    report_unsupported(bs, errp, "%s", features);
+    g_free(features);
 }
 
 /*
@@ -855,13 +866,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     return ret;
 }
 
-static int qcow2_refresh_limits(BlockDriverState *bs)
+static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
 {
     BDRVQcowState *s = bs->opaque;
 
     bs->bl.write_zeroes_alignment = s->cluster_sectors;
-
-    return 0;
 }
 
 static int qcow2_set_key(BlockDriverState *bs, const char *key)
diff --git a/block/qed.c b/block/qed.c
index cd4872b529..7944832181 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -528,13 +528,11 @@ out:
     return ret;
 }
 
-static int bdrv_qed_refresh_limits(BlockDriverState *bs)
+static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp)
 {
     BDRVQEDState *s = bs->opaque;
 
     bs->bl.write_zeroes_alignment = s->header.cluster_size >> BDRV_SECTOR_BITS;
-
-    return 0;
 }
 
 /* We have nothing to do for QED reopen, stubs just return
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 2bcc73dc37..8e9758e920 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -221,7 +221,7 @@ static int raw_normalize_devicepath(const char **filename)
 }
 #endif
 
-static void raw_probe_alignment(BlockDriverState *bs)
+static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
 {
     BDRVRawState *s = bs->opaque;
     char *buf;
@@ -240,24 +240,24 @@ static void raw_probe_alignment(BlockDriverState *bs)
     s->buf_align = 0;
 
 #ifdef BLKSSZGET
-    if (ioctl(s->fd, BLKSSZGET, &sector_size) >= 0) {
+    if (ioctl(fd, BLKSSZGET, &sector_size) >= 0) {
         bs->request_alignment = sector_size;
     }
 #endif
 #ifdef DKIOCGETBLOCKSIZE
-    if (ioctl(s->fd, DKIOCGETBLOCKSIZE, &sector_size) >= 0) {
+    if (ioctl(fd, DKIOCGETBLOCKSIZE, &sector_size) >= 0) {
         bs->request_alignment = sector_size;
     }
 #endif
 #ifdef DIOCGSECTORSIZE
-    if (ioctl(s->fd, DIOCGSECTORSIZE, &sector_size) >= 0) {
+    if (ioctl(fd, DIOCGSECTORSIZE, &sector_size) >= 0) {
         bs->request_alignment = sector_size;
     }
 #endif
 #ifdef CONFIG_XFS
     if (s->is_xfs) {
         struct dioattr da;
-        if (xfsctl(NULL, s->fd, XFS_IOC_DIOINFO, &da) >= 0) {
+        if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) {
             bs->request_alignment = da.d_miniosz;
             /* The kernel returns wrong information for d_mem */
             /* s->buf_align = da.d_mem; */
@@ -270,7 +270,7 @@ static void raw_probe_alignment(BlockDriverState *bs)
         size_t align;
         buf = qemu_memalign(MAX_BLOCKSIZE, 2 * MAX_BLOCKSIZE);
         for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
-            if (pread(s->fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) {
+            if (pread(fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) {
                 s->buf_align = align;
                 break;
             }
@@ -282,13 +282,18 @@ static void raw_probe_alignment(BlockDriverState *bs)
         size_t align;
         buf = qemu_memalign(s->buf_align, MAX_BLOCKSIZE);
         for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
-            if (pread(s->fd, buf, align, 0) >= 0) {
+            if (pread(fd, buf, align, 0) >= 0) {
                 bs->request_alignment = align;
                 break;
             }
         }
         qemu_vfree(buf);
     }
+
+    if (!s->buf_align || !bs->request_alignment) {
+        error_setg(errp, "Could not find working O_DIRECT alignment. "
+                         "Try cache.direct=off.");
+    }
 }
 
 static void raw_parse_flags(int bdrv_flags, int *open_flags)
@@ -505,6 +510,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
     BDRVRawState *s;
     BDRVRawReopenState *raw_s;
     int ret = 0;
+    Error *local_err = NULL;
 
     assert(state != NULL);
     assert(state->bs != NULL);
@@ -577,6 +583,19 @@ static int raw_reopen_prepare(BDRVReopenState *state,
             ret = -1;
         }
     }
+
+    /* Fail already reopen_prepare() if we can't get a working O_DIRECT
+     * alignment with the new fd. */
+    if (raw_s->fd != -1) {
+        raw_probe_alignment(state->bs, raw_s->fd, &local_err);
+        if (local_err) {
+            qemu_close(raw_s->fd);
+            raw_s->fd = -1;
+            error_propagate(errp, local_err);
+            ret = -EINVAL;
+        }
+    }
+
     return ret;
 }
 
@@ -615,14 +634,12 @@ static void raw_reopen_abort(BDRVReopenState *state)
     state->opaque = NULL;
 }
 
-static int raw_refresh_limits(BlockDriverState *bs)
+static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
 {
     BDRVRawState *s = bs->opaque;
 
-    raw_probe_alignment(bs);
+    raw_probe_alignment(bs, s->fd, errp);
     bs->bl.opt_mem_alignment = s->buf_align;
-
-    return 0;
 }
 
 static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index 492f58de69..f82f4c25df 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -94,10 +94,9 @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
     return bdrv_get_info(bs->file, bdi);
 }
 
-static int raw_refresh_limits(BlockDriverState *bs)
+static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
 {
     bs->bl = bs->file->bl;
-    return 0;
 }
 
 static int raw_truncate(BlockDriverState *bs, int64_t offset)
diff --git a/block/stream.c b/block/stream.c
index 34de8ba0d9..cdea3e8d0c 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -76,7 +76,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
         bdrv_unref(unused);
     }
 
-    bdrv_refresh_limits(top);
+    bdrv_refresh_limits(top, NULL);
 }
 
 static void coroutine_fn stream_run(void *opaque)
diff --git a/block/vmdk.c b/block/vmdk.c
index 27a78daa02..0517bbaf91 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -938,7 +938,7 @@ fail:
 }
 
 
-static int vmdk_refresh_limits(BlockDriverState *bs)
+static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
 {
     BDRVVmdkState *s = bs->opaque;
     int i;
@@ -950,8 +950,6 @@ static int vmdk_refresh_limits(BlockDriverState *bs)
                     s->extents[i].cluster_sectors);
         }
     }
-
-    return 0;
 }
 
 static int get_whole_cluster(BlockDriverState *bs,
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index e7d6c77b34..7b14bbbee1 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -232,11 +232,11 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
     memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm,
-                          "apci-gpe0", ICH9_PMIO_GPE0_LEN);
+                          "acpi-gpe0", ICH9_PMIO_GPE0_LEN);
     memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
 
     memory_region_init_io(&pm->io_smi, OBJECT(lpc_pci), &ich9_smi_ops, pm,
-                          "apci-smi", 8);
+                          "acpi-smi", 8);
     memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
 
     pm->irq = sci_irq;
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index dbbc167425..a5736cbc07 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -175,8 +175,10 @@ static void uart_send_breaks(UartState *s)
 {
     int break_enabled = 1;
 
-    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
-                               &break_enabled);
+    if (s->chr) {
+        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
+                                   &break_enabled);
+    }
 }
 
 static void uart_parameters_setup(UartState *s)
@@ -227,7 +229,9 @@ static void uart_parameters_setup(UartState *s)
 
     packet_size += ssp.data_bits + ssp.stop_bits;
     s->char_tx_time = (get_ticks_per_sec() / ssp.speed) * packet_size;
-    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+    if (s->chr) {
+        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+    }
 }
 
 static int uart_can_receive(void *opaque)
@@ -295,6 +299,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
     /* instant drain the fifo when there's no back-end */
     if (!s->chr) {
         s->tx_count = 0;
+        return FALSE;
     }
 
     if (!s->tx_count) {
@@ -375,7 +380,9 @@ static void uart_read_rx_fifo(UartState *s, uint32_t *c)
         *c = s->rx_fifo[rx_rpos];
         s->rx_count--;
 
-        qemu_chr_accept_input(s->chr);
+        if (s->chr) {
+            qemu_chr_accept_input(s->chr);
+        }
     } else {
         *c = 0;
     }
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 07bebc03ac..23123b730e 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -797,10 +797,18 @@ static void add_port(VirtIOSerial *vser, uint32_t port_id)
 static void remove_port(VirtIOSerial *vser, uint32_t port_id)
 {
     VirtIOSerialPort *port;
-    unsigned int i;
 
-    i = port_id / 32;
-    vser->ports_map[i] &= ~(1U << (port_id % 32));
+    /*
+     * Don't mark port 0 removed -- we explicitly reserve it for
+     * backward compat with older guests, ensure a virtconsole device
+     * unplug retains the reservation.
+     */
+    if (port_id) {
+        unsigned int i;
+
+        i = port_id / 32;
+        vser->ports_map[i] &= ~(1U << (port_id % 32));
+    }
 
     port = find_port_by_id(vser, port_id);
     /*
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 2dccb3401b..ec8ccdb673 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -386,19 +386,10 @@ static void pc_init_pci_1_2(MachineState *machine)
     pc_init_pci(machine);
 }
 
-/* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
+/* PC init function for pc-0.10 to pc-0.13 */
 static void pc_init_pci_no_kvmclock(MachineState *machine)
 {
-    has_pci_info = false;
-    has_acpi_build = false;
-    smbios_defaults = false;
-    gigabyte_align = false;
-    smbios_legacy_mode = true;
-    has_reserved_memory = false;
-    option_rom_has_mr = true;
-    rom_file_has_mr = false;
-    x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
-    enable_compat_apic_id_mode();
+    pc_compat_1_2(machine);
     pc_init1(machine, 1, 0);
 }
 
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 38e580642f..4e88d9c5e9 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -216,7 +216,11 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
     case VHOST_SET_MEM_TABLE:
         for (i = 0; i < dev->mem->nregions; ++i) {
             struct vhost_memory_region *reg = dev->mem->regions + i;
-            fd = qemu_get_ram_fd(reg->guest_phys_addr);
+            ram_addr_t ram_addr;
+
+            assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
+            qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_addr, &ram_addr);
+            fd = qemu_get_ram_fd(ram_addr);
             if (fd > 0) {
                 msg.memory.regions[fd_num].userspace_addr = reg->userspace_addr;
                 msg.memory.regions[fd_num].memory_size  = reg->memory_size;
diff --git a/include/block/block.h b/include/block/block.h
index 32d36760fd..f08471d7e1 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -278,7 +278,7 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset);
 int64_t bdrv_getlength(BlockDriverState *bs);
 int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
 void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
-int bdrv_refresh_limits(BlockDriverState *bs);
+void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
 int bdrv_commit(BlockDriverState *bs);
 int bdrv_commit_all(void);
 int bdrv_change_backing_file(BlockDriverState *bs,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index f6c3befed8..7b541a0691 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -240,7 +240,7 @@ struct BlockDriver {
     int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag);
     bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);
 
-    int (*bdrv_refresh_limits)(BlockDriverState *bs);
+    void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp);
 
     /*
      * Returns 1 if newly created images are guaranteed to contain only
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 07a00da727..609b27cf0b 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -118,7 +118,7 @@
   IOCTL(SIOCSIFMEM, IOC_W, MK_PTR(MK_STRUCT(STRUCT_ptr_ifreq)))
   IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
   IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
-  IOCTL(SIOCGIFINDEX, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
+  IOCTL(SIOCGIFINDEX, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
   IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
   IOCTL_SPECIAL(SIOCGIFCONF, IOC_W | IOC_R, do_ioctl_ifconf,
                 MK_PTR(MK_STRUCT(STRUCT_ifconf)))
diff --git a/linux-user/signal.c b/linux-user/signal.c
index f3b43787fd..1141054be2 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1305,7 +1305,7 @@ static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
     /*
      * This is the X/Open sanctioned signal stack switching.
      */
-    if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
         sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
     }
 
@@ -3509,8 +3509,9 @@ static abi_ulong get_sigframe(struct target_sigaction *ka,
 {
     abi_ulong sp = env->regs[1];
 
-    if ((ka->sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
         sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
 
     return ((sp - frame_size) & -8UL);
 }
@@ -3891,7 +3892,7 @@ static inline abi_ulong get_sigframe(struct target_sigaction *ka,
 
     /* redzone */
     /* This is the X/Open sanctioned signal stack switching.  */
-    if ((ka->sa_flags & SA_ONSTACK) != 0 && !onsigstack) {
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
         sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
     }
 
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5a272d3d08..a50229d0d7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1140,6 +1140,13 @@ static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
 
     memcpy(addr, target_saddr, len);
     addr->sa_family = sa_family;
+    if (sa_family == AF_PACKET) {
+	struct target_sockaddr_ll *lladdr;
+
+	lladdr = (struct target_sockaddr_ll *)addr;
+	lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
+	lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
+    }
     unlock_user(target_saddr, target_addr, 0);
 
     return 0;
@@ -1497,6 +1504,25 @@ set_timeout:
                 unlock_user_struct(tfprog, optval_addr, 1);
                 return ret;
         }
+	case TARGET_SO_BINDTODEVICE:
+	{
+		char *dev_ifname, *addr_ifname;
+
+		if (optlen > IFNAMSIZ - 1) {
+		    optlen = IFNAMSIZ - 1;
+		}
+		dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
+		if (!dev_ifname) {
+		    return -TARGET_EFAULT;
+		}
+		optname = SO_BINDTODEVICE;
+		addr_ifname = alloca(IFNAMSIZ);
+		memcpy(addr_ifname, dev_ifname, optlen);
+		addr_ifname[optlen] = 0;
+		ret = get_errno(setsockopt(sockfd, level, optname, addr_ifname, optlen));
+		unlock_user (dev_ifname, optval_addr, 0);
+		return ret;
+	}
             /* Options with 'int' argument.  */
         case TARGET_SO_DEBUG:
 		optname = SO_DEBUG;
@@ -1958,7 +1984,7 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr,
         return -TARGET_EINVAL;
     }
 
-    addr = alloca(addrlen);
+    addr = alloca(addrlen+1);
 
     ret = target_to_host_sockaddr(addr, target_addr, addrlen);
     if (ret)
@@ -1979,7 +2005,7 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
 
     if (msgp->msg_name) {
         msg.msg_namelen = tswap32(msgp->msg_namelen);
-        msg.msg_name = alloca(msg.msg_namelen);
+        msg.msg_name = alloca(msg.msg_namelen+1);
         ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
                                 msg.msg_namelen);
         if (ret) {
@@ -2242,7 +2268,7 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
     if (!host_msg)
         return -TARGET_EFAULT;
     if (target_addr) {
-        addr = alloca(addrlen);
+        addr = alloca(addrlen+1);
         ret = target_to_host_sockaddr(addr, target_addr, addrlen);
         if (ret) {
             unlock_user(host_msg, msg, 0);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 856302780f..c9e6323905 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -121,6 +121,16 @@ struct target_sockaddr {
     uint8_t sa_data[14];
 };
 
+struct target_sockaddr_ll {
+    uint16_t sll_family;   /* Always AF_PACKET */
+    uint16_t sll_protocol; /* Physical layer protocol */
+    int      sll_ifindex;  /* Interface number */
+    uint16_t sll_hatype;   /* ARP hardware type */
+    uint8_t  sll_pkttype;  /* Packet type */
+    uint8_t  sll_halen;    /* Length of address */
+    uint8_t  sll_addr[8];  /* Physical layer address */
+};
+
 struct target_sock_filter {
     abi_ushort code;
     uint8_t jt;
diff --git a/scripts/vmstate-static-checker.py b/scripts/vmstate-static-checker.py
index 1604e680dc..3bae769a37 100755
--- a/scripts/vmstate-static-checker.py
+++ b/scripts/vmstate-static-checker.py
@@ -79,6 +79,18 @@ def check_fields_match(name, s_field, d_field):
 
     return False
 
+def get_changed_sec_name(sec):
+    # Section names can change -- see commit 292b1634 for an example.
+    changes = {
+        "ICH9 LPC": "ICH9-LPC",
+    }
+
+    for item in changes:
+        if item == sec:
+            return changes[item]
+        if changes[item] == sec:
+            return item
+    return ""
 
 def exists_in_substruct(fields, item):
     # Some QEMU versions moved a few fields inside a substruct.  This
@@ -314,13 +326,18 @@ def main():
         dest_data = temp
 
     for sec in src_data:
-        if not sec in dest_data:
-            print "Section \"" + sec + "\" does not exist in dest"
-            bump_taint()
-            continue
+        dest_sec = sec
+        if not dest_sec in dest_data:
+            # Either the section name got changed, or the section
+            # doesn't exist in dest.
+            dest_sec = get_changed_sec_name(sec)
+            if not dest_sec in dest_data:
+                print "Section \"" + sec + "\" does not exist in dest"
+                bump_taint()
+                continue
 
         s = src_data[sec]
-        d = dest_data[sec]
+        d = dest_data[dest_sec]
 
         if sec == "vmschkmachine":
             check_machine_type(s, d)
diff --git a/tests/Makefile b/tests/Makefile
index c4422eef36..4b2e1bbea9 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -160,7 +160,7 @@ gcov-files-i386-y += hw/usb/hcd-ehci.c
 gcov-files-i386-y += hw/usb/hcd-uhci.c
 gcov-files-i386-y += hw/usb/dev-hid.c
 gcov-files-i386-y += hw/usb/dev-storage.c
-check-qtest-i386-$(CONFIG_POSIX) += tests/vhost-user-test$(EXESUF)
+check-qtest-i386-$(CONFIG_LINUX) += tests/vhost-user-test$(EXESUF)
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
index d5718c5594..9e701e1c2b 100755
--- a/tests/qemu-iotests/028
+++ b/tests/qemu-iotests/028
@@ -110,7 +110,9 @@ _launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
 h=$QEMU_HANDLE
 QEMU_COMM_TIMEOUT=1
 
-_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)"
+# Silence output since it contains the disk image path and QEMU's readline
+# character echoing makes it very hard to filter the output
+_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" >/dev/null
 qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
 _send_qemu_cmd $h 'quit' ""
 
diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out
index 38099e44c9..0e1a5ae65d 100644
--- a/tests/qemu-iotests/028.out
+++ b/tests/qemu-iotests/028.out
@@ -468,8 +468,6 @@ No errors were found on the image.
 
 block-backup
 
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) ddrdridrivdrivedrive_drive_bdrive_badrive_bacdrive_backdrive_backudrive_backupdrive_backup drive_backup ddrive_backup didrive_backup disdrive_backup diskdrive_backup disk drive_backup disk /drive_backup disk /hdrive_backup disk /hodrive_backup disk /homdrive_backup disk /homedrive_backup disk /home/drive_backup disk /home/kdrive_backup disk /home/kwdrive_backup disk /home/kwodrive_backup disk /home/kwoldrive_backup disk /home/kwolfdrive_backup disk /home/kwolf/drive_backup disk /home/kwolf/sdrive_backup disk /home/kwolf/sodrive_backup disk /home/kwolf/soudrive_backup disk /home/kwolf/sourdrive_backup disk /home/kwolf/sourcdrive_backup disk /home/kwolf/sourcedrive_backup disk /home/kwolf/source/drive_backup disk /home/kwolf/source/qdrive_backup disk /home/kwolf/source/qedrive_backup disk /home/kwolf/source/qemdrive_backup disk /home/kwolf/source/qemudrive_backup disk /home/kwolf/source/qemu/drive_backup disk /home/kwolf/source/qemu/tdrive_backup disk /home/kwolf/source/qemu/tedrive_backup disk /home/kwolf/source/qemu/tesdrive_backup disk /home/kwolf/source/qemu/testdrive_backup disk /home/kwolf/source/qemu/testsdrive_backup disk /home/kwolf/source/qemu/tests/drive_backup disk /home/kwolf/source/qemu/tests/qdrive_backup disk /home/kwolf/source/qemu/tests/qedrive_backup disk /home/kwolf/source/qemu/tests/qemdrive_backup disk /home/kwolf/source/qemu/tests/qemudrive_backup disk /home/kwolf/source/qemu/tests/qemu-drive_backup disk /home/kwolf/source/qemu/tests/qemu-idrive_backup disk /home/kwolf/source/qemu/tests/qemu-iodrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotedrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotesdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotestdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotestsdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/drive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/sdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scrdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scradrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scratdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scratcdrive_backup disk TEST_DIRdrive_backup disk TEST_DIR/drive_backup disk TEST_DIR/tdrive_backup disk TEST_DIR/t.drive_backup disk TEST_DIR/t.qdrive_backup disk TEST_DIR/t.qcdrive_backup disk TEST_DIR/t.qcodrive_backup disk TEST_DIR/t.qcowdrive_backup disk TEST_DIR/t.qcow2drive_backup disk TEST_DIR/t.qcow2.drive_backup disk TEST_DIR/t.qcow2.cdrive_backup disk TEST_DIR/t.qcow2.codrive_backup disk TEST_DIR/t.qcow2.copdrive_backup disk TEST_DIR/t.qcow2.copy
 Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=4294968832 backing_file='TEST_DIR/t.qcow2.base' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off
 (qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block-info block-jinfo block-joinfo block-jobinfo block-jobs
 Type backup, device disk: Completed 0 of 4294968832 bytes, speed limit 0 bytes/s
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
index a77365347d..392f1ef3e6 100755
--- a/tests/qemu-iotests/036
+++ b/tests/qemu-iotests/036
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Test that qcow2 unknown autoclear feature bits are cleared
+# Test qcow2 feature bits
 #
 # Copyright (C) 2011 Red Hat, Inc.
 # Copyright IBM, Corp. 2010
@@ -50,6 +50,56 @@ _supported_os Linux
 # Only qcow2v3 and later supports feature bits
 IMGOPTS="compat=1.1"
 
+echo
+echo === Image with unknown incompatible feature bit ===
+echo
+_make_test_img 64M
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
+
+# Without feature table
+$PYTHON qcow2.py "$TEST_IMG" dump-header
+_img_info
+
+# With feature table containing bit 63
+printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+echo
+echo === Image with multiple incompatible feature bits ===
+echo
+_make_test_img 64M
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 61
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 62
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
+
+# Without feature table
+_img_info
+
+# With feature table containing bit 63
+printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing bit 61
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing bits 61 and 62
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s" "test1" "" "test2" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing all bits
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s\x00\x3f%s\x00%40s" "test1" "" "test2" "" "test3" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing unrelated bits, including compatible/autoclear
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x01\x3d%s\x00%40s\x00\x3e%s\x00%40s\x02\x3f%s\x00%40s\x00\x3c%s\x00%40s" "test1" "" "test2" "" "test3" "" "test4" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+
 echo === Create image with unknown autoclear feature bit ===
 echo
 _make_test_img 64M
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
index 55a3e6e441..720bd89161 100644
--- a/tests/qemu-iotests/036.out
+++ b/tests/qemu-iotests/036.out
@@ -1,4 +1,39 @@
 QA output created by 036
+
+=== Image with unknown incompatible feature bit ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+magic                     0x514649fb
+version                   3
+backing_file_offset       0x0
+backing_file_size         0x0
+cluster_bits              16
+size                      67108864
+crypt_method              0
+l1_size                   1
+l1_table_offset           0x30000
+refcount_table_offset     0x10000
+refcount_table_clusters   1
+nb_snapshots              0
+snapshot_offset           0x0
+incompatible_features     0x8000000000000000
+compatible_features       0x0
+autoclear_features        0x0
+refcount_order            4
+header_length             104
+
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: 8000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature
+
+=== Image with multiple incompatible feature bits ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: e000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: 6000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: c000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, Unknown incompatible feature: 8000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, test3
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test2, Unknown incompatible feature: a000000000000000
 === Create image with unknown autoclear feature bit ===
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
index 44a2b45641..2058596964 100755
--- a/tests/qemu-iotests/qcow2.py
+++ b/tests/qemu-iotests/qcow2.py
@@ -176,6 +176,10 @@ def cmd_add_header_ext(fd, magic, data):
     h.extensions.append(QcowHeaderExtension.create(magic, data))
     h.update(fd)
 
+def cmd_add_header_ext_stdio(fd, magic):
+    data = sys.stdin.read()
+    cmd_add_header_ext(fd, magic, data)
+
 def cmd_del_header_ext(fd, magic):
     try:
         magic = int(magic, 0)
@@ -220,11 +224,12 @@ def cmd_set_feature_bit(fd, group, bit):
     h.update(fd)
 
 cmds = [
-    [ 'dump-header',    cmd_dump_header,    0, 'Dump image header and header extensions' ],
-    [ 'set-header',     cmd_set_header,     2, 'Set a field in the header'],
-    [ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
-    [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
-    [ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
+    [ 'dump-header',          cmd_dump_header,          0, 'Dump image header and header extensions' ],
+    [ 'set-header',           cmd_set_header,           2, 'Set a field in the header'],
+    [ 'add-header-ext',       cmd_add_header_ext,       2, 'Add a header extension' ],
+    [ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ],
+    [ 'del-header-ext',       cmd_del_header_ext,       1, 'Delete a header extension' ],
+    [ 'set-feature-bit',      cmd_set_feature_bit,      2, 'Set a feature bit'],
 ]
 
 def main(filename, cmd, args):
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 406ba70941..75fedf0977 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -76,6 +76,7 @@ typedef struct VhostUserMemoryRegion {
     uint64_t guest_phys_addr;
     uint64_t memory_size;
     uint64_t userspace_addr;
+    uint64_t mmap_offset;
 } VhostUserMemoryRegion;
 
 typedef struct VhostUserMemory {
@@ -205,6 +206,7 @@ static void read_guest_mem(void)
     uint32_t *guest_mem;
     gint64 end_time;
     int i, j;
+    size_t size;
 
     g_mutex_lock(data_mutex);
 
@@ -231,8 +233,13 @@ static void read_guest_mem(void)
 
         g_assert_cmpint(memory.regions[i].memory_size, >, 1024);
 
-        guest_mem = mmap(0, memory.regions[i].memory_size,
-        PROT_READ | PROT_WRITE, MAP_SHARED, fds[i], 0);
+        size =  memory.regions[i].memory_size + memory.regions[i].mmap_offset;
+
+        guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
+                         MAP_SHARED, fds[i], 0);
+
+        g_assert(guest_mem != MAP_FAILED);
+        guest_mem += (memory.regions[i].mmap_offset / sizeof(*guest_mem));
 
         for (j = 0; j < 256; j++) {
             uint32_t a = readl(memory.regions[i].guest_phys_addr + j*4);
diff --git a/vl.c b/vl.c
index 6e084c2da2..6abedcfae7 100644
--- a/vl.c
+++ b/vl.c
@@ -3315,6 +3315,7 @@ int main(int argc, char **argv, char **envp)
                     error_report("ram size too large");
                     exit(EXIT_FAILURE);
                 }
+                maxram_size = ram_size;
 
                 maxmem_str = qemu_opt_get(opts, "maxmem");
                 slots_str = qemu_opt_get(opts, "slots");