summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/9p.c33
-rw-r--r--hw/block/m25p80.c4
-rw-r--r--hw/core/generic-loader.c4
-rw-r--r--hw/core/qdev-properties.c2
-rw-r--r--hw/display/framebuffer.c2
-rw-r--r--hw/display/milkymist-tmu2.c2
-rw-r--r--hw/display/virtio-gpu.c40
-rw-r--r--hw/display/xlnx_dp.c4
-rw-r--r--hw/i386/kvmvapic.c6
-rw-r--r--hw/i386/pc.c2
-rw-r--r--hw/i386/pci-assign-load-rom.c16
-rw-r--r--hw/intc/Makefile.objs1
-rw-r--r--hw/intc/arm_gic_kvm.c17
-rw-r--r--hw/intc/arm_gicv3_its_kvm.c20
-rw-r--r--hw/intc/arm_gicv3_kvm.c19
-rw-r--r--hw/intc/nios2_iic.c103
-rw-r--r--hw/intc/s390_flic_kvm.c8
-rw-r--r--hw/isa/isa-bus.c1
-rw-r--r--hw/misc/ivshmem.c14
-rw-r--r--hw/net/cadence_gem.c2
-rw-r--r--hw/net/e1000e.c2
-rw-r--r--hw/net/spapr_llan.c4
-rw-r--r--hw/net/vmxnet3.c26
-rw-r--r--hw/nios2/10m50_devboard.c126
-rw-r--r--hw/nios2/Makefile.objs1
-rw-r--r--hw/nios2/boot.c223
-rw-r--r--hw/nios2/boot.h11
-rw-r--r--hw/nios2/cpu_pic.c70
-rw-r--r--hw/nvram/eeprom93xx.c8
-rw-r--r--hw/nvram/fw_cfg.c8
-rw-r--r--hw/pci-bridge/ioh3420.c2
-rw-r--r--hw/pci-bridge/xio3130_downstream.c2
-rw-r--r--hw/pci-bridge/xio3130_upstream.c2
-rw-r--r--hw/pci/msix.c8
-rw-r--r--hw/pci/pci.c57
-rw-r--r--hw/pci/pcie.c2
-rw-r--r--hw/pci/shpc.c7
-rw-r--r--hw/ppc/spapr_drc.c2
-rw-r--r--hw/s390x/s390-pci-bus.h4
-rw-r--r--hw/scsi/megasas.c2
-rw-r--r--hw/scsi/scsi-bus.c8
-rw-r--r--hw/scsi/scsi-disk.c1
-rw-r--r--hw/scsi/vhost-scsi.c25
-rw-r--r--hw/scsi/vmw_pvscsi.c2
-rw-r--r--hw/timer/Makefile.objs1
-rw-r--r--hw/timer/altera_timer.c237
-rw-r--r--hw/timer/twl92230.c8
-rw-r--r--hw/usb/bus.c19
-rw-r--r--hw/usb/dev-mtp.c4
-rw-r--r--hw/usb/hcd-xhci.c2
-rw-r--r--hw/usb/redirect.c26
-rw-r--r--hw/vfio/pci-quirks.c2
-rw-r--r--hw/vfio/pci.c4
-rw-r--r--hw/virtio/vhost.c8
-rw-r--r--hw/virtio/virtio-crypto.c2
-rw-r--r--hw/virtio/virtio-pci.c8
-rw-r--r--hw/virtio/virtio.c15
-rw-r--r--hw/xtensa/pic_cpu.c75
58 files changed, 1092 insertions, 222 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 138d8e825d..99e94723b9 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -979,6 +979,7 @@ static void coroutine_fn v9fs_attach(void *opaque)
     size_t offset = 7;
     V9fsQID qid;
     ssize_t err;
+    Error *local_err = NULL;
 
     v9fs_string_init(&uname);
     v9fs_string_init(&aname);
@@ -1007,26 +1008,36 @@ static void coroutine_fn v9fs_attach(void *opaque)
         clunk_fid(s, fid);
         goto out;
     }
-    err = pdu_marshal(pdu, offset, "Q", &qid);
-    if (err < 0) {
-        clunk_fid(s, fid);
-        goto out;
-    }
-    err += offset;
-    memcpy(&s->root_qid, &qid, sizeof(qid));
-    trace_v9fs_attach_return(pdu->tag, pdu->id,
-                             qid.type, qid.version, qid.path);
+
     /*
      * disable migration if we haven't done already.
      * attach could get called multiple times for the same export.
      */
     if (!s->migration_blocker) {
-        s->root_fid = fid;
         error_setg(&s->migration_blocker,
                    "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'",
                    s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
-        migrate_add_blocker(s->migration_blocker);
+        err = migrate_add_blocker(s->migration_blocker, &local_err);
+        if (local_err) {
+            error_free(local_err);
+            error_free(s->migration_blocker);
+            s->migration_blocker = NULL;
+            clunk_fid(s, fid);
+            goto out;
+        }
+        s->root_fid = fid;
+    }
+
+    err = pdu_marshal(pdu, offset, "Q", &qid);
+    if (err < 0) {
+        clunk_fid(s, fid);
+        goto out;
     }
+    err += offset;
+
+    memcpy(&s->root_qid, &qid, sizeof(qid));
+    trace_v9fs_attach_return(pdu->tag, pdu->id,
+                             qid.type, qid.version, qid.path);
 out:
     put_fid(pdu, fidp);
 out_nofid:
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index e90451496e..2d6eb46a04 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -147,7 +147,7 @@ typedef struct FlashPartInfo {
 #define CFG_DUMMY_CLK_LEN 4
 #define NVCFG_DUMMY_CLK_POS 12
 #define VCFG_DUMMY_CLK_POS 4
-#define EVCFG_OUT_DRIVER_STRENGHT_DEF 7
+#define EVCFG_OUT_DRIVER_STRENGTH_DEF 7
 #define EVCFG_VPP_ACCELERATOR (1 << 3)
 #define EVCFG_RESET_HOLD_ENABLED (1 << 4)
 #define NVCFG_DUAL_IO_MASK (1 << 2)
@@ -747,7 +747,7 @@ static void reset_memory(Flash *s)
                             );
 
         s->enh_volatile_cfg = 0;
-        s->enh_volatile_cfg |= EVCFG_OUT_DRIVER_STRENGHT_DEF;
+        s->enh_volatile_cfg |= EVCFG_OUT_DRIVER_STRENGTH_DEF;
         s->enh_volatile_cfg |= EVCFG_VPP_ACCELERATOR;
         s->enh_volatile_cfg |= EVCFG_RESET_HOLD_ENABLED;
         if (s->nonvolatile_cfg & NVCFG_DUAL_IO_MASK) {
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
index 208f549dff..58f1f02902 100644
--- a/hw/core/generic-loader.c
+++ b/hw/core/generic-loader.c
@@ -27,7 +27,7 @@
  * this it needs a backend to manage the datas, the same as other
  * memory-related devices. In this case as the backend is so trivial we
  * have merged it with the frontend instead of creating and maintaining a
- * seperate backend.
+ * separate backend.
  */
 
 #include "qemu/osdep.h"
@@ -79,7 +79,7 @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
                        "loading memory values");
             return;
         } else if (!s->data_len) {
-            /* We cant' check for !data here as a value of 0 is still valid. */
+            /* We can't check for !data here as a value of 0 is still valid. */
             error_setg(errp, "Both data and data-len must be specified");
             return;
         } else if (s->data_len > 8) {
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 2a82768067..6ab4265eb4 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -711,7 +711,7 @@ static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
 
     /*
      * Catch "invalid" device reference from vfio-pci and allow the
-     * default buffer representing the non-existant device to be used.
+     * default buffer representing the non-existent device to be used.
      */
     if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
         rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c
index df51358e72..25aa46c8c7 100644
--- a/hw/display/framebuffer.c
+++ b/hw/display/framebuffer.c
@@ -78,7 +78,7 @@ void framebuffer_update_display(
 
     i = *first_row;
     *first_row = -1;
-    src_len = src_width * rows;
+    src_len = (hwaddr)src_width * rows;
 
     mem = mem_section->mr;
     if (!mem) {
diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c
index 5c666f9b24..920374b985 100644
--- a/hw/display/milkymist-tmu2.c
+++ b/hw/display/milkymist-tmu2.c
@@ -257,7 +257,7 @@ static void tmu2_start(MilkymistTMU2State *s)
     glColor4f(m, m, m, (float)(s->regs[R_ALPHA] + 1) / 64.0f);
 
     /* Read the QEMU dest. framebuffer into the OpenGL framebuffer */
-    fb_len = 2 * s->regs[R_DSTHRES] * s->regs[R_DSTVRES];
+    fb_len = 2ULL * s->regs[R_DSTHRES] * s->regs[R_DSTVRES];
     fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, 0);
     if (fb == NULL) {
         glDeleteTextures(1, &texture);
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 7a15c61c76..444ca064c1 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1003,7 +1003,8 @@ static const VMStateDescription vmstate_virtio_gpu_scanouts = {
     },
 };
 
-static void virtio_gpu_save(QEMUFile *f, void *opaque, size_t size)
+static int virtio_gpu_save(QEMUFile *f, void *opaque, size_t size,
+                           VMStateField *field, QJSON *vmdesc)
 {
     VirtIOGPU *g = opaque;
     struct virtio_gpu_simple_resource *res;
@@ -1028,9 +1029,12 @@ static void virtio_gpu_save(QEMUFile *f, void *opaque, size_t size)
     qemu_put_be32(f, 0); /* end of list */
 
     vmstate_save_state(f, &vmstate_virtio_gpu_scanouts, g, NULL);
+
+    return 0;
 }
 
-static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size)
+static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
+                           VMStateField *field)
 {
     VirtIOGPU *g = opaque;
     struct virtio_gpu_simple_resource *res;
@@ -1132,6 +1136,7 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
     VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
     VirtIOGPU *g = VIRTIO_GPU(qdev);
     bool have_virgl;
+    Error *local_err = NULL;
     int i;
 
     if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) {
@@ -1139,14 +1144,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
         return;
     }
 
-    g->config_size = sizeof(struct virtio_gpu_config);
-    g->virtio_config.num_scanouts = g->conf.max_outputs;
-    virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
-                g->config_size);
-
-    g->req_state[0].width = 1024;
-    g->req_state[0].height = 768;
-
     g->use_virgl_renderer = false;
 #if !defined(CONFIG_VIRGL) || defined(HOST_WORDS_BIGENDIAN)
     have_virgl = false;
@@ -1158,6 +1155,24 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
     }
 
     if (virtio_gpu_virgl_enabled(g->conf)) {
+        error_setg(&g->migration_blocker, "virgl is not yet migratable");
+        migrate_add_blocker(g->migration_blocker, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            error_free(g->migration_blocker);
+            return;
+        }
+    }
+
+    g->config_size = sizeof(struct virtio_gpu_config);
+    g->virtio_config.num_scanouts = g->conf.max_outputs;
+    virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
+                g->config_size);
+
+    g->req_state[0].width = 1024;
+    g->req_state[0].height = 768;
+
+    if (virtio_gpu_virgl_enabled(g->conf)) {
         /* use larger control queue in 3d mode */
         g->ctrl_vq   = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb);
         g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
@@ -1183,11 +1198,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
             dpy_gfx_replace_surface(g->scanout[i].con, NULL);
         }
     }
-
-    if (virtio_gpu_virgl_enabled(g->conf)) {
-        error_setg(&g->migration_blocker, "virgl is not yet migratable");
-        migrate_add_blocker(g->migration_blocker);
-    }
 }
 
 static void virtio_gpu_device_unrealize(DeviceState *qdev, Error **errp)
diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index f43eb09304..f7b7b80c68 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -555,7 +555,7 @@ static void xlnx_dp_recreate_surface(XlnxDPState *s)
     if ((width != 0) && (height != 0)) {
         /*
          * As dpy_gfx_replace_surface calls qemu_free_displaysurface on the
-         * surface we need to be carefull and don't free the surface associated
+         * surface we need to be careful and don't free the surface associated
          * to the console or double free will happen.
          */
         if (s->bout_plane.surface != current_console_surface) {
@@ -1160,7 +1160,7 @@ static void xlnx_dp_update_display(void *opaque)
      */
     if (!xlnx_dpdma_start_operation(s->dpdma, 3, false)) {
         /*
-         * An error occured don't do anything with the data..
+         * An error occurred don't do anything with the data..
          * Trigger an underflow interrupt.
          */
         s->core_registers[DP_INT_STATUS] |= (1 << 21);
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 2f767b620e..702e281dc8 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -535,7 +535,6 @@ static int patch_hypercalls(VAPICROMState *s)
     uint8_t alternates[2];
     const uint8_t *pattern;
     const uint8_t *patch;
-    int patches = 0;
     off_t pos;
     uint8_t *rom;
 
@@ -566,11 +565,6 @@ static int patch_hypercalls(VAPICROMState *s)
     }
 
     g_free(rom);
-
-    if (patches != 0 && patches != 2) {
-        return -1;
-    }
-
     return 0;
 }
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c949cf0ecc..706e2330ac 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1777,7 +1777,7 @@ static int pc_apic_cmp(const void *a, const void *b)
 
 /* returns pointer to CPUArchId descriptor that matches CPU's apic_id
  * in pcms->possible_cpus->cpus, if pcms->possible_cpus->cpus has no
- * entry correponding to CPU's apic_id returns NULL.
+ * entry corresponding to CPU's apic_id returns NULL.
  */
 static CPUArchId *pc_find_cpu_slot(PCMachineState *pcms, CPUState *cpu,
                                    int *idx)
diff --git a/hw/i386/pci-assign-load-rom.c b/hw/i386/pci-assign-load-rom.c
index 0d8e4b2826..fd59076e7a 100644
--- a/hw/i386/pci-assign-load-rom.c
+++ b/hw/i386/pci-assign-load-rom.c
@@ -39,19 +39,19 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner,
              "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom",
              domain, bus, slot, function);
 
-    if (stat(rom_file, &st)) {
-        if (errno != ENOENT) {
-            error_report("pci-assign: Invalid ROM.");
-        }
-        return NULL;
-    }
-
     /* Write "1" to the ROM file to enable it */
     fp = fopen(rom_file, "r+");
     if (fp == NULL) {
-        error_report("pci-assign: Cannot open %s: %s", rom_file, strerror(errno));
+        if (errno != ENOENT) {
+            error_report("pci-assign: Cannot open %s: %s", rom_file, strerror(errno));
+        }
         return NULL;
     }
+    if (fstat(fileno(fp), &st) == -1) {
+        error_report("pci-assign: Cannot stat %s: %s", rom_file, strerror(errno));
+        goto close_rom;
+    }
+
     val = 1;
     if (fwrite(&val, 1, 1, fp) != 1) {
         goto close_rom;
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 2f44a2da26..8948106ac4 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -41,3 +41,4 @@ obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_vic.o
 obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpuif.o
 obj-$(CONFIG_MIPS_CPS) += mips_gic.o
+obj-$(CONFIG_NIOS2) += nios2_iic.o
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 11729ee902..ec952ece93 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -510,6 +510,17 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (!kvm_arm_gic_can_save_restore(s)) {
+        error_setg(&s->migration_blocker, "This operating system kernel does "
+                                          "not support vGICv2 migration");
+        migrate_add_blocker(s->migration_blocker, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            error_free(s->migration_blocker);
+            return;
+        }
+    }
+
     gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL);
 
     for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
@@ -558,12 +569,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
                             KVM_VGIC_V2_ADDR_TYPE_CPU,
                             s->dev_fd);
 
-    if (!kvm_arm_gic_can_save_restore(s)) {
-        error_setg(&s->migration_blocker, "This operating system kernel does "
-                                          "not support vGICv2 migration");
-        migrate_add_blocker(s->migration_blocker);
-    }
-
     if (kvm_has_gsi_routing()) {
         /* set up irq routing */
         kvm_init_irq_routing(kvm_state);
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
index fc246e0cb5..bd4f3aafc6 100644
--- a/hw/intc/arm_gicv3_its_kvm.c
+++ b/hw/intc/arm_gicv3_its_kvm.c
@@ -56,6 +56,19 @@ static int kvm_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid)
 static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
 {
     GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
+    Error *local_err = NULL;
+
+    /*
+     * Block migration of a KVM GICv3 ITS device: the API for saving and
+     * restoring the state in the kernel is not yet available
+     */
+    error_setg(&s->migration_blocker, "vITS migration is not implemented");
+    migrate_add_blocker(s->migration_blocker, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        error_free(s->migration_blocker);
+        return;
+    }
 
     s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_ITS, false);
     if (s->dev_fd < 0) {
@@ -73,13 +86,6 @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
 
     gicv3_its_init_mmio(s, NULL);
 
-    /*
-     * Block migration of a KVM GICv3 ITS device: the API for saving and
-     * restoring the state in the kernel is not yet available
-     */
-    error_setg(&s->migration_blocker, "vITS migration is not implemented");
-    migrate_add_blocker(s->migration_blocker);
-
     kvm_msi_use_devid = true;
     kvm_gsi_direct_mapping = false;
     kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 199a439ccf..d69dc47370 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -103,6 +103,18 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
 
     gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
 
+    /* Block migration of a KVM GICv3 device: the API for saving and restoring
+     * the state in the kernel is not yet finalised in the kernel or
+     * implemented in QEMU.
+     */
+    error_setg(&s->migration_blocker, "vGICv3 migration is not implemented");
+    migrate_add_blocker(s->migration_blocker, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        error_free(s->migration_blocker);
+        return;
+    }
+
     /* Try to create the device via the device control API */
     s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false);
     if (s->dev_fd < 0) {
@@ -122,13 +134,6 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
     kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
                             KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
 
-    /* Block migration of a KVM GICv3 device: the API for saving and restoring
-     * the state in the kernel is not yet finalised in the kernel or
-     * implemented in QEMU.
-     */
-    error_setg(&s->migration_blocker, "vGICv3 migration is not implemented");
-    migrate_add_blocker(s->migration_blocker);
-
     if (kvm_has_gsi_routing()) {
         /* set up irq routing */
         kvm_init_irq_routing(kvm_state);
diff --git a/hw/intc/nios2_iic.c b/hw/intc/nios2_iic.c
new file mode 100644
index 0000000000..818ab1b315
--- /dev/null
+++ b/hw/intc/nios2_iic.c
@@ -0,0 +1,103 @@
+/*
+ * QEMU Altera Internal Interrupt Controller.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+
+#include "hw/sysbus.h"
+#include "cpu.h"
+
+#define TYPE_ALTERA_IIC "altera,iic"
+#define ALTERA_IIC(obj) \
+    OBJECT_CHECK(AlteraIIC, (obj), TYPE_ALTERA_IIC)
+
+typedef struct AlteraIIC {
+    SysBusDevice  parent_obj;
+    void         *cpu;
+    qemu_irq      parent_irq;
+} AlteraIIC;
+
+static void update_irq(AlteraIIC *pv)
+{
+    CPUNios2State *env = &((Nios2CPU *)(pv->cpu))->env;
+
+    qemu_set_irq(pv->parent_irq,
+                 env->regs[CR_IPENDING] & env->regs[CR_IENABLE]);
+}
+
+static void irq_handler(void *opaque, int irq, int level)
+{
+    AlteraIIC *pv = opaque;
+    CPUNios2State *env = &((Nios2CPU *)(pv->cpu))->env;
+
+    env->regs[CR_IPENDING] &= ~(1 << irq);
+    env->regs[CR_IPENDING] |= !!level << irq;
+
+    update_irq(pv);
+}
+
+static void altera_iic_init(Object *obj)
+{
+    AlteraIIC *pv = ALTERA_IIC(obj);
+
+    qdev_init_gpio_in(DEVICE(pv), irq_handler, 32);
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &pv->parent_irq);
+}
+
+static Property altera_iic_properties[] = {
+    DEFINE_PROP_PTR("cpu", AlteraIIC, cpu),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_iic_realize(DeviceState *dev, Error **errp)
+{
+    struct AlteraIIC *pv = ALTERA_IIC(dev);
+
+    if (!pv->cpu) {
+        error_setg(errp, "altera,iic: CPU not connected");
+        return;
+    }
+}
+
+static void altera_iic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = altera_iic_properties;
+    /* Reason: pointer property "cpu" */
+    dc->cannot_instantiate_with_device_add_yet = true;
+    dc->realize = altera_iic_realize;
+}
+
+static TypeInfo altera_iic_info = {
+    .name          = "altera,iic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AlteraIIC),
+    .instance_init = altera_iic_init,
+    .class_init    = altera_iic_class_init,
+};
+
+static void altera_iic_register(void)
+{
+    type_register_static(&altera_iic_info);
+}
+
+type_init(altera_iic_register)
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index c313166fbe..da8e4dfab6 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -286,7 +286,8 @@ static void kvm_s390_release_adapter_routes(S390FLICState *fs,
  * increase until buffer is sufficient or maxium size is
  * reached
  */
-static void kvm_flic_save(QEMUFile *f, void *opaque, size_t size)
+static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
+                         VMStateField *field, QJSON *vmdesc)
 {
     KVMS390FLICState *flic = opaque;
     int len = FLIC_SAVE_INITIAL_SIZE;
@@ -319,6 +320,8 @@ static void kvm_flic_save(QEMUFile *f, void *opaque, size_t size)
                         count * sizeof(struct kvm_s390_irq));
     }
     g_free(buf);
+
+    return 0;
 }
 
 /**
@@ -331,7 +334,8 @@ static void kvm_flic_save(QEMUFile *f, void *opaque, size_t size)
  * Note: Do nothing when no interrupts where stored
  * in QEMUFile
  */
-static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size)
+static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size,
+                         VMStateField *field)
 {
     uint64_t len = 0;
     uint64_t count = 0;
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 9d07b118c0..0ffbc8dd28 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -219,6 +219,7 @@ static void isabus_bridge_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
+    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
     dc->fw_name = "isa";
 }
 
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index abeaf3da08..fd14d7a07e 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -840,6 +840,7 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
     uint8_t *pci_conf;
     uint8_t attr = PCI_BASE_ADDRESS_SPACE_MEMORY |
         PCI_BASE_ADDRESS_MEM_PREFETCH;
+    Error *local_err = NULL;
 
     /* IRQFD requires MSI */
     if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD) &&
@@ -903,9 +904,6 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
         }
     }
 
-    vmstate_register_ram(s->ivshmem_bar2, DEVICE(s));
-    pci_register_bar(PCI_DEVICE(s), 2, attr, s->ivshmem_bar2);
-
     if (s->master == ON_OFF_AUTO_AUTO) {
         s->master = s->vm_id == 0 ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
     }
@@ -913,8 +911,16 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
     if (!ivshmem_is_master(s)) {
         error_setg(&s->migration_blocker,
                    "Migration is disabled when using feature 'peer mode' in device 'ivshmem'");
-        migrate_add_blocker(s->migration_blocker);
+        migrate_add_blocker(s->migration_blocker, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            error_free(s->migration_blocker);
+            return;
+        }
     }
+
+    vmstate_register_ram(s->ivshmem_bar2, DEVICE(s));
+    pci_register_bar(PCI_DEVICE(s), 2, attr, s->ivshmem_bar2);
 }
 
 static void ivshmem_exit(PCIDevice *dev)
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 7915732f74..e99d4544a2 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -896,7 +896,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 
     DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
 
-    /* Find which queue we are targetting */
+    /* Find which queue we are targeting */
     q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize);
 
     while (bytes_to_copy) {
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 77a4b3e5bf..0e9a25b7ab 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -593,7 +593,7 @@ static const VMStateDescription e1000e_vmstate = {
     .pre_save = e1000e_pre_save,
     .post_load = e1000e_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(parent_obj, E1000EState),
+        VMSTATE_PCI_DEVICE(parent_obj, E1000EState),
         VMSTATE_MSIX(parent_obj, E1000EState),
 
         VMSTATE_UINT32(ioaddr, E1000EState),
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index 01ecb02773..058908d8d7 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -105,7 +105,7 @@ typedef struct VIOsPAPRVLANDevice {
     uint32_t add_buf_ptr, use_buf_ptr, rx_bufs;
     hwaddr rxq_ptr;
     QEMUTimer *rxp_timer;
-    uint32_t compat_flags;             /* Compatability flags for migration */
+    uint32_t compat_flags;             /* Compatibility flags for migration */
     RxBufPool *rx_pool[RX_MAX_POOLS];  /* Receive buffer descriptor pools */
 } VIOsPAPRVLANDevice;
 
@@ -559,7 +559,7 @@ static target_long spapr_vlan_add_rxbuf_to_pool(VIOsPAPRVLANDevice *dev,
     if (pool < 0) {
         /*
          * No matching pool found? Try to use a new one. If the guest used all
-         * pools before, but changed the size of one pool inbetween, we might
+         * pools before, but changed the size of one pool in the meantime, we might
          * need to recycle that pool here (if it's empty already). Thus scan
          * all buffer pools now, starting with the last (likely empty) one.
          */
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 92f6af9620..2cb2731e29 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2451,7 +2451,8 @@ static void vmxnet3_put_tx_stats_to_file(QEMUFile *f,
     qemu_put_be64(f, tx_stat->pktsTxDiscard);
 }
 
-static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field)
 {
     Vmxnet3TxqDescr *r = pv;
 
@@ -2465,7 +2466,8 @@ static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field, QJSON *vmdesc)
 {
     Vmxnet3TxqDescr *r = pv;
 
@@ -2474,6 +2476,8 @@ static void vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size)
     qemu_put_byte(f, r->intr_idx);
     qemu_put_be64(f, r->tx_stats_pa);
     vmxnet3_put_tx_stats_to_file(f, &r->txq_stats);
+
+    return 0;
 }
 
 static const VMStateInfo txq_descr_info = {
@@ -2512,7 +2516,8 @@ static void vmxnet3_put_rx_stats_to_file(QEMUFile *f,
     qemu_put_be64(f, rx_stat->pktsRxError);
 }
 
-static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field)
 {
     Vmxnet3RxqDescr *r = pv;
     int i;
@@ -2530,7 +2535,8 @@ static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field, QJSON *vmdesc)
 {
     Vmxnet3RxqDescr *r = pv;
     int i;
@@ -2543,6 +2549,8 @@ static void vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size)
     qemu_put_byte(f, r->intr_idx);
     qemu_put_be64(f, r->rx_stats_pa);
     vmxnet3_put_rx_stats_to_file(f, &r->rxq_stats);
+
+    return 0;
 }
 
 static int vmxnet3_post_load(void *opaque, int version_id)
@@ -2575,7 +2583,8 @@ static const VMStateInfo rxq_descr_info = {
     .put = vmxnet3_put_rxq_descr
 };
 
-static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field)
 {
     Vmxnet3IntState *r = pv;
 
@@ -2586,13 +2595,16 @@ static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field, QJSON *vmdesc)
 {
     Vmxnet3IntState *r = pv;
 
     qemu_put_byte(f, r->is_masked);
     qemu_put_byte(f, r->is_pending);
     qemu_put_byte(f, r->is_asserted);
+
+    return 0;
 }
 
 static const VMStateInfo int_state_info = {
@@ -2619,7 +2631,7 @@ static const VMStateDescription vmstate_vmxnet3_pcie_device = {
     .minimum_version_id = 1,
     .needed = vmxnet3_vmstate_need_pcie_device,
     .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(parent_obj, VMXNET3State),
+        VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State),
         VMSTATE_END_OF_LIST()
     }
 };
diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c
new file mode 100644
index 0000000000..62e5738b65
--- /dev/null
+++ b/hw/nios2/10m50_devboard.c
@@ -0,0 +1,126 @@
+/*
+ * Altera 10M50 Nios2 GHRD
+ *
+ * Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on LabX device code
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/char/serial.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "qemu/config-file.h"
+
+#include "boot.h"
+
+#define BINARY_DEVICE_TREE_FILE    "10m50-devboard.dtb"
+
+static void nios2_10m50_ghrd_init(MachineState *machine)
+{
+    Nios2CPU *cpu;
+    DeviceState *dev;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *phys_tcm = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_tcm_alias = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_ram_alias = g_new(MemoryRegion, 1);
+    ram_addr_t tcm_base = 0x0;
+    ram_addr_t tcm_size = 0x1000;    /* 1 kiB, but QEMU limit is 4 kiB */
+    ram_addr_t ram_base = 0x08000000;
+    ram_addr_t ram_size = 0x08000000;
+    qemu_irq *cpu_irq, irq[32];
+    int i;
+
+    /* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */
+    memory_region_init_ram(phys_tcm, NULL, "nios2.tcm", tcm_size, &error_abort);
+    memory_region_init_alias(phys_tcm_alias, NULL, "nios2.tcm.alias",
+                             phys_tcm, 0, tcm_size);
+    vmstate_register_ram_global(phys_tcm);
+    memory_region_add_subregion(address_space_mem, tcm_base, phys_tcm);
+    memory_region_add_subregion(address_space_mem, 0xc0000000 + tcm_base,
+                                phys_tcm_alias);
+
+    /* Physical DRAM with alias at 0xc0000000 */
+    memory_region_init_ram(phys_ram, NULL, "nios2.ram", ram_size, &error_abort);
+    memory_region_init_alias(phys_ram_alias, NULL, "nios2.ram.alias",
+                             phys_ram, 0, ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
+    memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base,
+                                phys_ram_alias);
+
+    /* Create CPU -- FIXME */
+    cpu = cpu_nios2_init("nios2");
+
+    /* Register: CPU interrupt controller (PIC) */
+    cpu_irq = nios2_cpu_pic_init(cpu);
+
+    /* Register: Internal Interrupt Controller (IIC) */
+    dev = qdev_create(NULL, "altera,iic");
+    qdev_prop_set_ptr(dev, "cpu", cpu);
+    qdev_init_nofail(dev);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    /* Register: Altera 16550 UART */
+    serial_mm_init(address_space_mem, 0xf8001600, 2, irq[1], 115200,
+                   serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    /* Register: Timer sys_clk_timer  */
+    dev = qdev_create(NULL, "ALTR.timer");
+    qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xf8001440);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[0]);
+
+    /* Register: Timer sys_clk_timer_1  */
+    dev = qdev_create(NULL, "ALTR.timer");
+    qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xe0000880);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[5]);
+
+    /* Configure new exception vectors and reset CPU for it to take effect. */
+    cpu->reset_addr = 0xd4000000;
+    cpu->exception_addr = 0xc8000120;
+    cpu->fast_tlb_miss_addr = 0xc0000100;
+
+    nios2_load_kernel(cpu, ram_base, ram_size, machine->initrd_filename,
+                      BINARY_DEVICE_TREE_FILE, NULL);
+}
+
+static void nios2_10m50_ghrd_machine_init(struct MachineClass *mc)
+{
+    mc->desc = "Altera 10M50 GHRD Nios II design";
+    mc->init = nios2_10m50_ghrd_init;
+    mc->is_default = 1;
+}
+
+DEFINE_MACHINE("10m50-ghrd", nios2_10m50_ghrd_machine_init);
diff --git a/hw/nios2/Makefile.objs b/hw/nios2/Makefile.objs
new file mode 100644
index 0000000000..6b5c421760
--- /dev/null
+++ b/hw/nios2/Makefile.objs
@@ -0,0 +1 @@
+obj-y = boot.o cpu_pic.o 10m50_devboard.o
diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
new file mode 100644
index 0000000000..e0a9aff2f4
--- /dev/null
+++ b/hw/nios2/boot.c
@@ -0,0 +1,223 @@
+/*
+ * Nios2 kernel loader
+ *
+ * Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on microblaze kernel loader
+ *
+ * Copyright (c) 2012 Peter Crosthwaite <peter.crosthwaite@petalogix.com>
+ * Copyright (c) 2012 PetaLogix
+ * Copyright (c) 2009 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "qemu/option.h"
+#include "qemu/config-file.h"
+#include "qemu/error-report.h"
+#include "qemu-common.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "qemu/cutils.h"
+
+#include "boot.h"
+
+#define NIOS2_MAGIC    0x534f494e
+
+static struct nios2_boot_info {
+    void (*machine_cpu_reset)(Nios2CPU *);
+    uint32_t bootstrap_pc;
+    uint32_t cmdline;
+    uint32_t initrd_start;
+    uint32_t initrd_end;
+    uint32_t fdt;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+    Nios2CPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
+    CPUNios2State *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+
+    env->regs[R_ARG0] = NIOS2_MAGIC;
+    env->regs[R_ARG1] = boot_info.initrd_start;
+    env->regs[R_ARG2] = boot_info.fdt;
+    env->regs[R_ARG3] = boot_info.cmdline;
+
+    cpu_set_pc(cs, boot_info.bootstrap_pc);
+    if (boot_info.machine_cpu_reset) {
+        boot_info.machine_cpu_reset(cpu);
+    }
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0xc0000000LL;
+}
+
+static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t ramsize,
+                          const char *kernel_cmdline, const char *dtb_filename)
+{
+    int fdt_size;
+    void *fdt = NULL;
+    int r;
+
+    if (dtb_filename) {
+        fdt = load_device_tree(dtb_filename, &fdt_size);
+    }
+    if (!fdt) {
+        return 0;
+    }
+
+    if (kernel_cmdline) {
+        r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
+                                    kernel_cmdline);
+        if (r < 0) {
+            fprintf(stderr, "couldn't set /chosen/bootargs\n");
+        }
+    }
+
+    if (bi.initrd_start) {
+        qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                              translate_kernel_address(NULL, bi.initrd_start));
+
+        qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                              translate_kernel_address(NULL, bi.initrd_end));
+    }
+
+    cpu_physical_memory_write(bi.fdt, fdt, fdt_size);
+    return fdt_size;
+}
+
+void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
+                            uint32_t ramsize,
+                            const char *initrd_filename,
+                            const char *dtb_filename,
+                            void (*machine_cpu_reset)(Nios2CPU *))
+{
+    QemuOpts *machine_opts;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *dtb_arg;
+    char *filename = NULL;
+
+    machine_opts = qemu_get_machine_opts();
+    kernel_filename = qemu_opt_get(machine_opts, "kernel");
+    kernel_cmdline = qemu_opt_get(machine_opts, "append");
+    dtb_arg = qemu_opt_get(machine_opts, "dtb");
+    /* default to pcbios dtb as passed by machine_init */
+    if (!dtb_arg) {
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
+    }
+
+    boot_info.machine_cpu_reset = machine_cpu_reset;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    if (kernel_filename) {
+        int kernel_size, fdt_size;
+        uint64_t entry, low, high;
+        uint32_t base32;
+        int big_endian = 0;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+        big_endian = 1;
+#endif
+
+        /* Boots a kernel elf binary. */
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &entry, &low, &high,
+                               big_endian, EM_ALTERA_NIOS2, 0, 0);
+        base32 = entry;
+        if (base32 == 0xc0000000) {
+            kernel_size = load_elf(kernel_filename, translate_kernel_address,
+                                   NULL, &entry, NULL, NULL,
+                                   big_endian, EM_ALTERA_NIOS2, 0, 0);
+        }
+
+        /* Always boot into physical ram. */
+        boot_info.bootstrap_pc = ddr_base + 0xc0000000 + (entry & 0x07ffffff);
+
+        /* If it wasn't an ELF image, try an u-boot image. */
+        if (kernel_size < 0) {
+            hwaddr uentry, loadaddr;
+
+            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0,
+                                      NULL, NULL);
+            boot_info.bootstrap_pc = uentry;
+            high = loadaddr + kernel_size;
+        }
+
+        /* Not an ELF image nor an u-boot image, try a RAW image. */
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, ddr_base,
+                                              ram_size);
+            boot_info.bootstrap_pc = ddr_base;
+            high = ddr_base + kernel_size;
+        }
+
+        high = ROUND_UP(high, 1024 * 1024);
+
+        /* If initrd is available, it goes after the kernel, aligned to 1M. */
+        if (initrd_filename) {
+            int initrd_size;
+            uint32_t initrd_offset;
+
+            boot_info.initrd_start = high;
+            initrd_offset = boot_info.initrd_start - ddr_base;
+
+            initrd_size = load_ramdisk(initrd_filename,
+                                       boot_info.initrd_start,
+                                       ram_size - initrd_offset);
+            if (initrd_size < 0) {
+                initrd_size = load_image_targphys(initrd_filename,
+                                                  boot_info.initrd_start,
+                                                  ram_size - initrd_offset);
+            }
+            if (initrd_size < 0) {
+                error_report("qemu: could not load initrd '%s'",
+                             initrd_filename);
+                exit(EXIT_FAILURE);
+            }
+            high += initrd_size;
+        }
+        high = ROUND_UP(high, 4);
+        boot_info.initrd_end = high;
+
+        /* Device tree must be placed right after initrd (if available) */
+        boot_info.fdt = high;
+        fdt_size = nios2_load_dtb(boot_info, ram_size, kernel_cmdline,
+                                  /* Preference a -dtb argument */
+                                  dtb_arg ? dtb_arg : filename);
+        high += fdt_size;
+
+        /* Kernel command is at the end, 4k aligned. */
+        boot_info.cmdline = ROUND_UP(high, 4096);
+        if (kernel_cmdline && strlen(kernel_cmdline)) {
+            pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
+        }
+    }
+    g_free(filename);
+}
diff --git a/hw/nios2/boot.h b/hw/nios2/boot.h
new file mode 100644
index 0000000000..3116753818
--- /dev/null
+++ b/hw/nios2/boot.h
@@ -0,0 +1,11 @@
+#ifndef NIOS2_BOOT_H
+#define NIOS2_BOOT_H
+
+#include "hw/hw.h"
+#include "cpu.h"
+
+void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, uint32_t ramsize,
+                       const char *initrd_filename, const char *dtb_filename,
+                       void (*machine_cpu_reset)(Nios2CPU *));
+
+#endif /* NIOS2_BOOT_H */
diff --git a/hw/nios2/cpu_pic.c b/hw/nios2/cpu_pic.c
new file mode 100644
index 0000000000..0f95987ef3
--- /dev/null
+++ b/hw/nios2/cpu_pic.c
@@ -0,0 +1,70 @@
+/*
+ * Altera Nios2 CPU PIC
+ *
+ * Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+
+#include "qemu/config-file.h"
+
+#include "boot.h"
+
+static void nios2_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    Nios2CPU *cpu = opaque;
+    CPUNios2State *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+
+    if (type == CPU_INTERRUPT_HARD) {
+        env->irq_pending = level;
+
+        if (level && (env->regs[CR_STATUS] & CR_STATUS_PIE)) {
+            env->irq_pending = 0;
+            cpu_interrupt(cs, type);
+        } else if (!level) {
+            env->irq_pending = 0;
+            cpu_reset_interrupt(cs, type);
+        }
+    } else {
+        if (level) {
+            cpu_interrupt(cs, type);
+        } else {
+            cpu_reset_interrupt(cs, type);
+        }
+    }
+}
+
+void nios2_check_interrupts(CPUNios2State *env)
+{
+    Nios2CPU *cpu = nios2_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+
+    if (env->irq_pending) {
+        env->irq_pending = 0;
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+    }
+}
+
+qemu_irq *nios2_cpu_pic_init(Nios2CPU *cpu)
+{
+    return qemu_allocate_irqs(nios2_pic_cpu_handler, cpu, 2);
+}
diff --git a/hw/nvram/eeprom93xx.c b/hw/nvram/eeprom93xx.c
index 2c16fc23df..848692abc0 100644
--- a/hw/nvram/eeprom93xx.c
+++ b/hw/nvram/eeprom93xx.c
@@ -94,18 +94,22 @@ struct _eeprom_t {
    This is a Big hack, but it is how the old state did it.
  */
 
-static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size)
+static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field)
 {
     uint16_t *v = pv;
     *v = qemu_get_ubyte(f);
     return 0;
 }
 
-static void put_unused(QEMUFile *f, void *pv, size_t size)
+static int put_unused(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                      QJSON *vmdesc)
 {
     fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n");
     fprintf(stderr, "Never should be used to write a new state.\n");
     exit(0);
+
+    return 0;
 }
 
 static const VMStateInfo vmstate_hack_uint16_from_uint8 = {
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 523d585dcf..316fca9bc1 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -555,17 +555,21 @@ static void fw_cfg_reset(DeviceState *d)
    Or we broke compatibility in the state, or we can't use struct tm
  */
 
-static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size)
+static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size,
+                                VMStateField *field)
 {
     uint32_t *v = pv;
     *v = qemu_get_be16(f);
     return 0;
 }
 
-static void put_unused(QEMUFile *f, void *pv, size_t size)
+static int put_unused(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                      QJSON *vmdesc)
 {
     fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
     fprintf(stderr, "This functions shouldn't be called.\n");
+
+    return 0;
 }
 
 static const VMStateInfo vmstate_hack_uint32_as_uint16 = {
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
index 84b7946c31..0eef87a4f8 100644
--- a/hw/pci-bridge/ioh3420.c
+++ b/hw/pci-bridge/ioh3420.c
@@ -180,7 +180,7 @@ static const VMStateDescription vmstate_ioh3420 = {
     .minimum_version_id = 1,
     .post_load = pcie_cap_slot_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
+        VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
         VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
                        PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
         VMSTATE_END_OF_LIST()
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index 04b8e5b847..cfe8a3657f 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -166,7 +166,7 @@ static const VMStateDescription vmstate_xio3130_downstream = {
     .minimum_version_id = 1,
     .post_load = pcie_cap_slot_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
+        VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
         VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
                        PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
         VMSTATE_END_OF_LIST()
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index d1f59c8834..401c78452b 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -138,7 +138,7 @@ static const VMStateDescription vmstate_xio3130_upstream = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(parent_obj.parent_obj, PCIEPort),
+        VMSTATE_PCI_DEVICE(parent_obj.parent_obj, PCIEPort),
         VMSTATE_STRUCT(parent_obj.parent_obj.exp.aer_log, PCIEPort, 0,
                        vmstate_pcie_aer_log, PCIEAERLog),
         VMSTATE_END_OF_LIST()
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 0ec1cb14fc..ee1714d2cf 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -587,12 +587,16 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
     dev->msix_vector_poll_notifier = NULL;
 }
 
-static void put_msix_state(QEMUFile *f, void *pv, size_t size)
+static int put_msix_state(QEMUFile *f, void *pv, size_t size,
+                          VMStateField *field, QJSON *vmdesc)
 {
     msix_save(pv, f);
+
+    return 0;
 }
 
-static int get_msix_state(QEMUFile *f, void *pv, size_t size)
+static int get_msix_state(QEMUFile *f, void *pv, size_t size,
+                          VMStateField *field)
 {
     msix_load(pv, f);
     return 0;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index fe9acecbbf..47ca3af69a 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -445,7 +445,8 @@ int pci_bus_numa_node(PCIBus *bus)
     return PCI_BUS_GET_CLASS(bus)->numa_node(bus);
 }
 
-static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
+static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field)
 {
     PCIDevice *s = container_of(pv, PCIDevice, config);
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s);
@@ -484,11 +485,14 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 }
 
 /* just put buffer */
-static void put_pci_config_device(QEMUFile *f, void *pv, size_t size)
+static int put_pci_config_device(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field, QJSON *vmdesc)
 {
     const uint8_t **v = pv;
     assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
     qemu_put_buffer(f, *v, size);
+
+    return 0;
 }
 
 static VMStateInfo vmstate_info_pci_config = {
@@ -497,7 +501,8 @@ static VMStateInfo vmstate_info_pci_config = {
     .put  = put_pci_config_device,
 };
 
-static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
+static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size,
+                             VMStateField *field)
 {
     PCIDevice *s = container_of(pv, PCIDevice, irq_state);
     uint32_t irq_state[PCI_NUM_PINS];
@@ -518,7 +523,8 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
+static int put_pci_irq_state(QEMUFile *f, void *pv, size_t size,
+                             VMStateField *field, QJSON *vmdesc)
 {
     int i;
     PCIDevice *s = container_of(pv, PCIDevice, irq_state);
@@ -526,6 +532,8 @@ static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
     for (i = 0; i < PCI_NUM_PINS; ++i) {
         qemu_put_be32(f, pci_irq_state(s, i));
     }
+
+    return 0;
 }
 
 static VMStateInfo vmstate_info_pci_irq_state = {
@@ -534,30 +542,29 @@ static VMStateInfo vmstate_info_pci_irq_state = {
     .put  = put_pci_irq_state,
 };
 
+static bool migrate_is_pcie(void *opaque, int version_id)
+{
+    return pci_is_express((PCIDevice *)opaque);
+}
+
+static bool migrate_is_not_pcie(void *opaque, int version_id)
+{
+    return !pci_is_express((PCIDevice *)opaque);
+}
+
 const VMStateDescription vmstate_pci_device = {
     .name = "PCIDevice",
     .version_id = 2,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
-        VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
-                                   vmstate_info_pci_config,
+        VMSTATE_BUFFER_UNSAFE_INFO_TEST(config, PCIDevice,
+                                   migrate_is_not_pcie,
+                                   0, vmstate_info_pci_config,
                                    PCI_CONFIG_SPACE_SIZE),
-        VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
-				   vmstate_info_pci_irq_state,
-				   PCI_NUM_PINS * sizeof(int32_t)),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-const VMStateDescription vmstate_pcie_device = {
-    .name = "PCIEDevice",
-    .version_id = 2,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
-        VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
-                                   vmstate_info_pci_config,
+        VMSTATE_BUFFER_UNSAFE_INFO_TEST(config, PCIDevice,
+                                   migrate_is_pcie,
+                                   0, vmstate_info_pci_config,
                                    PCIE_CONFIG_SPACE_SIZE),
         VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
 				   vmstate_info_pci_irq_state,
@@ -566,10 +573,6 @@ const VMStateDescription vmstate_pcie_device = {
     }
 };
 
-static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s)
-{
-    return pci_is_express(s) ? &vmstate_pcie_device : &vmstate_pci_device;
-}
 
 void pci_device_save(PCIDevice *s, QEMUFile *f)
 {
@@ -578,7 +581,7 @@ void pci_device_save(PCIDevice *s, QEMUFile *f)
      * This makes us compatible with old devices
      * which never set or clear this bit. */
     s->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT;
-    vmstate_save_state(f, pci_get_vmstate(s), s, NULL);
+    vmstate_save_state(f, &vmstate_pci_device, s, NULL);
     /* Restore the interrupt status bit. */
     pci_update_irq_status(s);
 }
@@ -586,7 +589,7 @@ void pci_device_save(PCIDevice *s, QEMUFile *f)
 int pci_device_load(PCIDevice *s, QEMUFile *f)
 {
     int ret;
-    ret = vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
+    ret = vmstate_load_state(f, &vmstate_pci_device, s, s->version_id);
     /* Restore the interrupt status bit. */
     pci_update_irq_status(s);
     return ret;
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index adeda04036..cbd4bb4f8c 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -656,7 +656,7 @@ static void pcie_ext_cap_set_next(PCIDevice *dev, uint16_t pos, uint16_t next)
 }
 
 /*
- * caller must supply valid (offset, size) * such that the range shouldn't
+ * Caller must supply valid (offset, size) such that the range wouldn't
  * overlap with other capability or other registers.
  * This function doesn't check it.
  */
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 3dcd472eba..42fafac91b 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -695,13 +695,16 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
     shpc_cap_update_dword(d);
 }
 
-static void shpc_save(QEMUFile *f, void *pv, size_t size)
+static int shpc_save(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                     QJSON *vmdesc)
 {
     PCIDevice *d = container_of(pv, PCIDevice, shpc);
     qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
+
+    return 0;
 }
 
-static int shpc_load(QEMUFile *f, void *pv, size_t size)
+static int shpc_load(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     PCIDevice *d = container_of(pv, PCIDevice, shpc);
     int ret = qemu_get_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index a0c44ee593..2de6377cca 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -59,7 +59,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc,
     trace_spapr_drc_set_isolation_state(get_index(drc), state);
 
     if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
-        /* cannot unisolate a non-existant resource, and, or resources
+        /* cannot unisolate a non-existent resource, and, or resources
          * which are in an 'UNUSABLE' allocation state. (PAPR 2.7, 13.5.3.5)
          */
         if (!drc->dev ||
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index b0adefa788..0aad9cc272 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -183,8 +183,8 @@ enum ZpciIoatDtype {
  *          may enter an error state
  * blocked: ignore all DMA and interrupts; transition back to enabled or from
  *          error state via mpcifc
- * error: an error occured; transition back to enabled via mpcifc
- * permanent error: an unrecoverable error occured; transition to standby via
+ * error: an error occurred; transition back to enabled via mpcifc
+ * permanent error: an unrecoverable error occurred; transition to standby via
  *                  sclp deconfigure
  */
 typedef enum {
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 6233865494..6aad7c9a06 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2289,7 +2289,7 @@ static const VMStateDescription vmstate_megasas_gen2 = {
     .minimum_version_id = 0,
     .minimum_version_id_old = 0,
     .fields      = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(parent_obj, MegasasState),
+        VMSTATE_PCI_DEVICE(parent_obj, MegasasState),
         VMSTATE_MSIX(parent_obj, MegasasState),
 
         VMSTATE_INT32(fw_state, MegasasState),
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 297216dfcb..5940cb160c 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1945,7 +1945,8 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
 
 /* SCSI request list.  For simplicity, pv points to the whole device */
 
-static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
+static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
+                             VMStateField *field, QJSON *vmdesc)
 {
     SCSIDevice *s = pv;
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
@@ -1968,9 +1969,12 @@ static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
         }
     }
     qemu_put_sbyte(f, 0);
+
+    return 0;
 }
 
-static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
+static int get_scsi_requests(QEMUFile *f, void *pv, size_t size,
+                             VMStateField *field)
 {
     SCSIDevice *s = pv;
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index c080888413..cc06fe5f6c 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2157,6 +2157,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
         DPRINTF("Write %s(sector %" PRId64 ", count %u)\n",
                 (command & 0xe) == 0xe ? "And Verify " : "",
                 r->req.cmd.lba, len);
+        /* fall through */
     case VERIFY_10:
     case VERIFY_12:
     case VERIFY_16:
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 5b2694615f..c491ece1f2 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -238,8 +238,16 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
                                vhost_dummy_handle_output);
     if (err != NULL) {
         error_propagate(errp, err);
-        close(vhostfd);
-        return;
+        goto close_fd;
+    }
+
+    error_setg(&s->migration_blocker,
+               "vhost-scsi does not support migration");
+    migrate_add_blocker(s->migration_blocker, &err);
+    if (err) {
+        error_propagate(errp, err);
+        error_free(s->migration_blocker);
+        goto close_fd;
     }
 
     s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
@@ -252,7 +260,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
     if (ret < 0) {
         error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
                    strerror(-ret));
-        return;
+        goto free_vqs;
     }
 
     /* At present, channel and lun both are 0 for bootable vhost-scsi disk */
@@ -261,9 +269,14 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
     /* Note: we can also get the minimum tpgt from kernel */
     s->target = vs->conf.boot_tpgt;
 
-    error_setg(&s->migration_blocker,
-            "vhost-scsi does not support migration");
-    migrate_add_blocker(s->migration_blocker);
+    return;
+
+ free_vqs:
+    migrate_del_blocker(s->migration_blocker);
+    g_free(s->dev.vqs);
+ close_fd:
+    close(vhostfd);
+    return;
 }
 
 static void vhost_scsi_unrealize(DeviceState *dev, Error **errp)
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index a5ce7dea8e..75575461e2 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1207,7 +1207,7 @@ static const VMStateDescription vmstate_pvscsi_pcie_device = {
     .name = "pvscsi/pcie",
     .needed = pvscsi_vmstate_need_pcie_device,
     .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(parent_obj, PVSCSIState),
+        VMSTATE_PCI_DEVICE(parent_obj, PVSCSIState),
         VMSTATE_END_OF_LIST()
     }
 };
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index c1e93a3924..71994f2d88 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -18,6 +18,7 @@ common-obj-$(CONFIG_IMX) += imx_gpt.o
 common-obj-$(CONFIG_LM32) += lm32_timer.o
 common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
 
+obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_pwm.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_rtc.o
diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c
new file mode 100644
index 0000000000..6d4862661d
--- /dev/null
+++ b/hw/timer/altera_timer.c
@@ -0,0 +1,237 @@
+/*
+ * QEMU model of the Altera timer.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+
+#include "hw/sysbus.h"
+#include "sysemu/sysemu.h"
+#include "hw/ptimer.h"
+
+#define R_STATUS      0
+#define R_CONTROL     1
+#define R_PERIODL     2
+#define R_PERIODH     3
+#define R_SNAPL       4
+#define R_SNAPH       5
+#define R_MAX         6
+
+#define STATUS_TO     0x0001
+#define STATUS_RUN    0x0002
+
+#define CONTROL_ITO   0x0001
+#define CONTROL_CONT  0x0002
+#define CONTROL_START 0x0004
+#define CONTROL_STOP  0x0008
+
+#define TYPE_ALTERA_TIMER "ALTR.timer"
+#define ALTERA_TIMER(obj) \
+    OBJECT_CHECK(AlteraTimer, (obj), TYPE_ALTERA_TIMER)
+
+typedef struct AlteraTimer {
+    SysBusDevice  busdev;
+    MemoryRegion  mmio;
+    qemu_irq      irq;
+    uint32_t      freq_hz;
+    QEMUBH       *bh;
+    ptimer_state *ptimer;
+    uint32_t      regs[R_MAX];
+} AlteraTimer;
+
+static int timer_irq_state(AlteraTimer *t)
+{
+    bool irq = (t->regs[R_STATUS] & STATUS_TO) &&
+               (t->regs[R_CONTROL] & CONTROL_ITO);
+    return irq;
+}
+
+static uint64_t timer_read(void *opaque, hwaddr addr,
+                           unsigned int size)
+{
+    AlteraTimer *t = opaque;
+    uint64_t r = 0;
+
+    addr >>= 2;
+
+    switch (addr) {
+    case R_CONTROL:
+        r = t->regs[R_CONTROL] & (CONTROL_ITO | CONTROL_CONT);
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(t->regs)) {
+            r = t->regs[addr];
+        }
+        break;
+    }
+
+    return r;
+}
+
+static void timer_write(void *opaque, hwaddr addr,
+                        uint64_t value, unsigned int size)
+{
+    AlteraTimer *t = opaque;
+    uint64_t tvalue;
+    uint32_t count = 0;
+    int irqState = timer_irq_state(t);
+
+    addr >>= 2;
+
+    switch (addr) {
+    case R_STATUS:
+        /* The timeout bit is cleared by writing the status register. */
+        t->regs[R_STATUS] &= ~STATUS_TO;
+        break;
+
+    case R_CONTROL:
+        t->regs[R_CONTROL] = value & (CONTROL_ITO | CONTROL_CONT);
+        if ((value & CONTROL_START) &&
+            !(t->regs[R_STATUS] & STATUS_RUN)) {
+            ptimer_run(t->ptimer, 1);
+            t->regs[R_STATUS] |= STATUS_RUN;
+        }
+        if ((value & CONTROL_STOP) && (t->regs[R_STATUS] & STATUS_RUN)) {
+            ptimer_stop(t->ptimer);
+            t->regs[R_STATUS] &= ~STATUS_RUN;
+        }
+        break;
+
+    case R_PERIODL:
+    case R_PERIODH:
+        t->regs[addr] = value & 0xFFFF;
+        if (t->regs[R_STATUS] & STATUS_RUN) {
+            ptimer_stop(t->ptimer);
+            t->regs[R_STATUS] &= ~STATUS_RUN;
+        }
+        tvalue = (t->regs[R_PERIODH] << 16) | t->regs[R_PERIODL];
+        ptimer_set_limit(t->ptimer, tvalue + 1, 1);
+        break;
+
+    case R_SNAPL:
+    case R_SNAPH:
+        count = ptimer_get_count(t->ptimer);
+        t->regs[R_SNAPL] = count & 0xFFFF;
+        t->regs[R_SNAPH] = count >> 16;
+        break;
+
+    default:
+        break;
+    }
+
+    if (irqState != timer_irq_state(t)) {
+        qemu_set_irq(t->irq, timer_irq_state(t));
+    }
+}
+
+static const MemoryRegionOps timer_ops = {
+    .read = timer_read,
+    .write = timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4
+    }
+};
+
+static void timer_hit(void *opaque)
+{
+    AlteraTimer *t = opaque;
+    const uint64_t tvalue = (t->regs[R_PERIODH] << 16) | t->regs[R_PERIODL];
+
+    t->regs[R_STATUS] |= STATUS_TO;
+
+    ptimer_set_limit(t->ptimer, tvalue + 1, 1);
+
+    if (!(t->regs[R_CONTROL] & CONTROL_CONT)) {
+        t->regs[R_STATUS] &= ~STATUS_RUN;
+        ptimer_set_count(t->ptimer, tvalue);
+    } else {
+        ptimer_run(t->ptimer, 1);
+    }
+
+    qemu_set_irq(t->irq, timer_irq_state(t));
+}
+
+static void altera_timer_realize(DeviceState *dev, Error **errp)
+{
+    AlteraTimer *t = ALTERA_TIMER(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    if (t->freq_hz == 0) {
+        error_setg(errp, "\"clock-frequency\" property must be provided.");
+        return;
+    }
+
+    t->bh = qemu_bh_new(timer_hit, t);
+    t->ptimer = ptimer_init(t->bh, PTIMER_POLICY_DEFAULT);
+    ptimer_set_freq(t->ptimer, t->freq_hz);
+
+    memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
+                          TYPE_ALTERA_TIMER, R_MAX * sizeof(uint32_t));
+    sysbus_init_mmio(sbd, &t->mmio);
+}
+
+static void altera_timer_init(Object *obj)
+{
+    AlteraTimer *t = ALTERA_TIMER(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    sysbus_init_irq(sbd, &t->irq);
+}
+
+static void altera_timer_reset(DeviceState *dev)
+{
+    AlteraTimer *t = ALTERA_TIMER(dev);
+
+    ptimer_stop(t->ptimer);
+    ptimer_set_limit(t->ptimer, 0xffffffff, 1);
+    memset(t->regs, 0, ARRAY_SIZE(t->regs));
+}
+
+static Property altera_timer_properties[] = {
+    DEFINE_PROP_UINT32("clock-frequency", AlteraTimer, freq_hz, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_timer_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = altera_timer_realize;
+    dc->props = altera_timer_properties;
+    dc->reset = altera_timer_reset;
+}
+
+static const TypeInfo altera_timer_info = {
+    .name          = TYPE_ALTERA_TIMER,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AlteraTimer),
+    .instance_init = altera_timer_init,
+    .class_init    = altera_timer_class_init,
+};
+
+static void altera_timer_register(void)
+{
+    type_register_static(&altera_timer_info);
+}
+
+type_init(altera_timer_register)
diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c
index b8d914e49b..c0aa8ae3de 100644
--- a/hw/timer/twl92230.c
+++ b/hw/timer/twl92230.c
@@ -749,17 +749,21 @@ static int menelaus_rx(I2CSlave *i2c)
    Or we broke compatibility in the state, or we can't use struct tm
  */
 
-static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
+static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
+                               VMStateField *field)
 {
     int *v = pv;
     *v = qemu_get_be16(f);
     return 0;
 }
 
-static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
+static int put_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
+                               VMStateField *field, QJSON *vmdesc)
 {
     int *v = pv;
     qemu_put_be16(f, *v);
+
+    return 0;
 }
 
 static const VMStateInfo vmstate_hack_int32_as_uint16 = {
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 25913ad488..1dcc35c8f8 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -8,6 +8,7 @@
 #include "monitor/monitor.h"
 #include "trace.h"
 #include "qemu/cutils.h"
+#include "migration/migration.h"
 
 static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
 
@@ -686,6 +687,8 @@ USBDevice *usbdevice_create(const char *cmdline)
     const char *params;
     int len;
     USBDevice *dev;
+    ObjectClass *klass;
+    DeviceClass *dc;
 
     params = strchr(cmdline,':');
     if (params) {
@@ -720,6 +723,22 @@ USBDevice *usbdevice_create(const char *cmdline)
         return NULL;
     }
 
+    klass = object_class_by_name(f->name);
+    if (klass == NULL) {
+        error_report("Device '%s' not found", f->name);
+        return NULL;
+    }
+
+    dc = DEVICE_CLASS(klass);
+
+    if (only_migratable) {
+        if (dc->vmsd->unmigratable) {
+            error_report("Device %s is not migratable, but --only-migratable "
+                         "was specified", f->name);
+            return NULL;
+        }
+    }
+
     if (f->usbdevice_init) {
         dev = f->usbdevice_init(bus, params);
     } else {
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 9cb0f50750..94c2e94f10 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -1093,7 +1093,7 @@ static MTPData *usb_mtp_get_object_prop_value(MTPState *s, MTPControl *c,
         }
         break;
     case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER:
-        /* Should be persistant between sessions,
+        /* Should be persistent between sessions,
          * but using our objedt ID is "good enough"
          * for now */
         usb_mtp_add_u64(d, 0x0000000000000000);
@@ -1580,6 +1580,8 @@ static void usb_mtp_class_initfn(ObjectClass *klass, void *data)
     uc->handle_reset   = usb_mtp_handle_reset;
     uc->handle_control = usb_mtp_handle_control;
     uc->handle_data    = usb_mtp_handle_data;
+    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
+    dc->desc = "USB Media Transfer Protocol device";
     dc->fw_name = "mtp";
     dc->vmsd = &vmstate_usb_mtp;
     dc->props = mtp_properties;
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 4acf0c6dd8..e0b516987f 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3894,7 +3894,7 @@ static const VMStateDescription vmstate_xhci = {
     .version_id = 1,
     .post_load = usb_xhci_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(parent_obj, XHCIState),
+        VMSTATE_PCI_DEVICE(parent_obj, XHCIState),
         VMSTATE_MSIX(parent_obj, XHCIState),
 
         VMSTATE_STRUCT_VARRAY_UINT32(ports, XHCIState, numports, 1,
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index a65723781e..4a0ebbfb32 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -2165,7 +2165,8 @@ static int usbredir_post_load(void *priv, int version_id)
 }
 
 /* For usbredirparser migration */
-static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
+                               VMStateField *field, QJSON *vmdesc)
 {
     USBRedirDevice *dev = priv;
     uint8_t *data;
@@ -2173,7 +2174,7 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
 
     if (dev->parser == NULL) {
         qemu_put_be32(f, 0);
-        return;
+        return 0;
     }
 
     usbredirparser_serialize(dev->parser, &data, &len);
@@ -2183,9 +2184,12 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
     qemu_put_buffer(f, data, len);
 
     free(data);
+
+    return 0;
 }
 
-static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused,
+                               VMStateField *field)
 {
     USBRedirDevice *dev = priv;
     uint8_t *data;
@@ -2228,7 +2232,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
 
 
 /* For buffered packets (iso/irq) queue migration */
-static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
+                              VMStateField *field, QJSON *vmdesc)
 {
     struct endp_data *endp = priv;
     USBRedirDevice *dev = endp->dev;
@@ -2246,9 +2251,12 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
         i++;
     }
     assert(i == endp->bufpq_size);
+
+    return 0;
 }
 
-static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused,
+                              VMStateField *field)
 {
     struct endp_data *endp = priv;
     USBRedirDevice *dev = endp->dev;
@@ -2351,7 +2359,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
 
 
 /* For PacketIdQueue migration */
-static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
+                                    VMStateField *field, QJSON *vmdesc)
 {
     struct PacketIdQueue *q = priv;
     USBRedirDevice *dev = q->dev;
@@ -2365,9 +2374,12 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
         remain--;
     }
     assert(remain == 0);
+
+    return 0;
 }
 
-static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused,
+                                    VMStateField *field)
 {
     struct PacketIdQueue *q = priv;
     USBRedirDevice *dev = q->dev;
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index 811eecd1b4..6c771f778b 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -1171,7 +1171,7 @@ static int vfio_pci_igd_host_init(VFIOPCIDevice *vdev,
  * IGD LPC/ISA bridge support code.  The vBIOS needs this, but we can't write
  * arbitrary values into just any bridge, so we must create our own.  We try
  * to handle if the user has created it for us, which they might want to do
- * to enable multifuction so we don't occupy the whole PCI slot.
+ * to enable multifunction so we don't occupy the whole PCI slot.
  */
 static void vfio_pci_igd_lpc_bridge_realize(PCIDevice *pdev, Error **errp)
 {
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index d7dbe0e3e0..882d3a91b6 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -1881,8 +1881,8 @@ static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
      * 0 is reserved for this since absence of capabilities is indicated by
      * 0 for the ID, version, AND next pointer.  However, pcie_add_capability()
      * uses ID 0 as reserved for list management and will incorrectly match and
-     * assert if we attempt to pre-load the head of the chain with with this
-     * ID.  Use ID 0xFFFF temporarily since it is also seems to be reserved in
+     * assert if we attempt to pre-load the head of the chain with this ID.
+     * Use ID 0xFFFF temporarily since it is also seems to be reserved in
      * part for identifying absence of capabilities in a root complex register
      * block.  If the ID still exists after adding capabilities, switch back to
      * zero.  We'll mark this entire first dword as emulated for this purpose.
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 9cacf557f2..b124d97d7c 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1176,6 +1176,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 {
     uint64_t features;
     int i, r, n_initialized_vqs = 0;
+    Error *local_err = NULL;
 
     hdev->vdev = NULL;
     hdev->migration_blocker = NULL;
@@ -1256,7 +1257,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
     }
 
     if (hdev->migration_blocker != NULL) {
-        migrate_add_blocker(hdev->migration_blocker);
+        r = migrate_add_blocker(hdev->migration_blocker, &local_err);
+        if (local_err) {
+            error_report_err(local_err);
+            error_free(hdev->migration_blocker);
+            goto fail_busyloop;
+        }
     }
 
     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 296472fc6e..0353eb6d5d 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -786,7 +786,7 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
     vcrypto->max_queues = MAX(vcrypto->cryptodev->conf.peers.queues, 1);
     if (vcrypto->max_queues + 1 > VIRTIO_QUEUE_MAX) {
         error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
-                   "must be a postive integer less than %d.",
+                   "must be a positive integer less than %d.",
                    vcrypto->max_queues, VIRTIO_QUEUE_MAX);
         return;
     }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 09230c05df..b5af2a00f3 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d)
     return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA;
 }
 
-static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
+static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
+                                       VMStateField *field)
 {
     VirtIOPCIProxy *proxy = pv;
     int i;
@@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq,
     qemu_put_be32(f, vq->used[1]);
 }
 
-static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
+static int put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
+                                       VMStateField *field, QJSON *vmdesc)
 {
     VirtIOPCIProxy *proxy = pv;
     int i;
@@ -149,6 +151,8 @@ static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
     for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
         virtio_pci_save_modern_queue_state(&proxy->vqs[i], f);
     }
+
+    return 0;
 }
 
 static const VMStateInfo vmstate_info_virtio_pci_modern_state = {
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index cc17b97899..f292a53940 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1555,7 +1555,8 @@ static const VMStateDescription vmstate_virtio_ringsize = {
     }
 };
 
-static int get_extra_state(QEMUFile *f, void *pv, size_t size)
+static int get_extra_state(QEMUFile *f, void *pv, size_t size,
+                           VMStateField *field)
 {
     VirtIODevice *vdev = pv;
     BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
@@ -1568,13 +1569,15 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size)
     }
 }
 
-static void put_extra_state(QEMUFile *f, void *pv, size_t size)
+static int put_extra_state(QEMUFile *f, void *pv, size_t size,
+                           VMStateField *field, QJSON *vmdesc)
 {
     VirtIODevice *vdev = pv;
     BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
 
     k->save_extra_state(qbus->parent, f);
+    return 0;
 }
 
 static const VMStateInfo vmstate_info_extra_state = {
@@ -1709,13 +1712,17 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
 }
 
 /* A wrapper for use as a VMState .put function */
-static void virtio_device_put(QEMUFile *f, void *opaque, size_t size)
+static int virtio_device_put(QEMUFile *f, void *opaque, size_t size,
+                              VMStateField *field, QJSON *vmdesc)
 {
     virtio_save(VIRTIO_DEVICE(opaque), f);
+
+    return 0;
 }
 
 /* A wrapper for use as a VMState .get function */
-static int virtio_device_get(QEMUFile *f, void *opaque, size_t size)
+static int virtio_device_get(QEMUFile *f, void *opaque, size_t size,
+                             VMStateField *field)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
     DeviceClass *dc = DEVICE_CLASS(VIRTIO_DEVICE_GET_CLASS(vdev));
diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
index 2bed64f15b..0e812d7f06 100644
--- a/hw/xtensa/pic_cpu.c
+++ b/hw/xtensa/pic_cpu.c
@@ -31,22 +31,6 @@
 #include "qemu/log.h"
 #include "qemu/timer.h"
 
-void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
-{
-    uint32_t old_ccount = env->sregs[CCOUNT] + 1;
-
-    env->sregs[CCOUNT] += d;
-
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
-        int i;
-        for (i = 0; i < env->config->nccompare; ++i) {
-            if (env->sregs[CCOMPARE + i] - old_ccount < d) {
-                xtensa_timer_irq(env, i, 1);
-            }
-        }
-    }
-}
-
 void check_interrupts(CPUXtensaState *env)
 {
     CPUState *cs = CPU(xtensa_env_get_cpu(env));
@@ -54,17 +38,6 @@ void check_interrupts(CPUXtensaState *env)
     uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
     int level;
 
-    /* If the CPU is halted advance CCOUNT according to the QEMU_CLOCK_VIRTUAL time
-     * elapsed since the moment when it was advanced last time.
-     */
-    if (cs->halted) {
-        int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
-        xtensa_advance_ccount(env,
-                muldiv64(now - env->halt_clock,
-                    env->config->clock_freq_khz, 1000000));
-        env->halt_clock = now;
-    }
     for (level = env->config->nlevel; level > minlevel; --level) {
         if (env->config->level_mask[level] & int_set_enabled) {
             env->pending_irq_level = level;
@@ -109,49 +82,29 @@ void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active)
     qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
 }
 
-void xtensa_rearm_ccompare_timer(CPUXtensaState *env)
-{
-    int i;
-    uint32_t wake_ccount = env->sregs[CCOUNT] - 1;
-
-    for (i = 0; i < env->config->nccompare; ++i) {
-        if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] <
-                wake_ccount - env->sregs[CCOUNT]) {
-            wake_ccount = env->sregs[CCOMPARE + i];
-        }
-    }
-    env->wake_ccount = wake_ccount;
-    timer_mod(env->ccompare_timer, env->halt_clock +
-            (uint64_t)(wake_ccount - env->sregs[CCOUNT]) *
-            1000000 / env->config->clock_freq_khz);
-}
-
 static void xtensa_ccompare_cb(void *opaque)
 {
-    XtensaCPU *cpu = opaque;
-    CPUXtensaState *env = &cpu->env;
-    CPUState *cs = CPU(cpu);
+    XtensaCcompareTimer *ccompare = opaque;
+    CPUXtensaState *env = ccompare->env;
+    unsigned i = ccompare - env->ccompare;
 
-    if (cs->halted) {
-        env->halt_clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-        xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
-        if (!cpu_has_work(cs)) {
-            env->sregs[CCOUNT] = env->wake_ccount + 1;
-            xtensa_rearm_ccompare_timer(env);
-        }
-    }
+    xtensa_timer_irq(env, i, 1);
 }
 
 void xtensa_irq_init(CPUXtensaState *env)
 {
-    XtensaCPU *cpu = xtensa_env_get_cpu(env);
-
     env->irq_inputs = (void **)qemu_allocate_irqs(
             xtensa_set_irq, env, env->config->ninterrupt);
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) &&
-            env->config->nccompare > 0) {
-        env->ccompare_timer =
-            timer_new_ns(QEMU_CLOCK_VIRTUAL, &xtensa_ccompare_cb, cpu);
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
+        unsigned i;
+
+        env->time_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+        env->ccount_base = env->sregs[CCOUNT];
+        for (i = 0; i < env->config->nccompare; ++i) {
+            env->ccompare[i].env = env;
+            env->ccompare[i].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+                    xtensa_ccompare_cb, env->ccompare + i);
+        }
     }
 }