[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#798969: jessie-pu: package qemu/1:2.1+dfsg-12+deb8u5



I updated the patch to be based on current latest
jessie-security version, and also used git diff
instead of plain diff, which can detect renames,
so the difference become a bit smaller than before,
yet it is still large, still due to the same
diff reorganization (when we applied some individual
patches to debian package, but they later has been
incorporated to the upstream stable release).

Please note that there's another security release
planned, with a bunch of unrelated security fixes, --
I can't wait any more with this amount of security
bugs unfixed in jessie (my initial plan was to wait
for this jessie-pu bug to be processed, and do address
the security issues next).

Thank you for your time!

/mjt
diff --git a/debian/changelog b/debian/changelog
index 4266d72..466046b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+qemu (1:2.1+dfsg-12+deb8u5) UNRELEASED; urgency=medium
+
+  * block-fix-max-nb_sectors-in-bdrv_make_zero.patch (Closes: #797221)
+  * qemu-char-handle-EINTR-for-TCP-character-devices.patch and
+    qemu-char-fix-missed-data-on-unix-socket.patch
+    (Closes: #793817)
+  * update to upstream stable point release v2.1.3 v2.1.3
+    incorporates CVE-2014-3689 (#765496) vmware-vga fix
+    and tcg-mips-fix-store-softmmu-slow-path.patch,
+    and brings up many other fixes in various places
+    (Closes: #786789)
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Thu, 21 Jan 2016 14:57:04 +0300
+
 qemu (1:2.1+dfsg-12+deb8u4) jessie-security; urgency=high
 
   * ne2000-add-checks-to-validate-ring-buffer-pointers-CVE-2015-5279.patch
diff --git a/debian/patches/CVE-2014-3689-vmware-vga/1-CVE-2014-3689-turn-off-hw-accel.patch b/debian/patches/CVE-2014-3689-vmware-vga/1-CVE-2014-3689-turn-off-hw-accel.patch
deleted file mode 100644
index febc9bd..0000000
--- a/debian/patches/CVE-2014-3689-vmware-vga/1-CVE-2014-3689-turn-off-hw-accel.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 83afa38eb20ca27e30683edc7729880e091387fc Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Mon, 6 Oct 2014 11:42:34 +0200
-Subject: vmware-vga: CVE-2014-3689: turn off hw accel
-
-Quick & easy stopgap for CVE-2014-3689:  We just compile out the
-hardware acceleration functions which lack sanity checks.  Thankfully
-we have capability bits for them (SVGA_CAP_RECT_COPY and
-SVGA_CAP_RECT_FILL), so guests should deal just fine, in theory.
-
-Subsequent patches will add the missing checks and re-enable the
-hardware acceleration emulation.
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-Reviewed-by: Don Koch <dkoch@verizon.com>
----
- hw/display/vmware_vga.c |    2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
-index 0c36c72..ec63290 100644
---- a/hw/display/vmware_vga.c
-+++ b/hw/display/vmware_vga.c
-@@ -29,8 +29,10 @@
- #include "hw/pci/pci.h"
- 
- #undef VERBOSE
-+#if 0
- #define HW_RECT_ACCEL
- #define HW_FILL_ACCEL
-+#endif
- #define HW_MOUSE_ACCEL
- 
- #include "vga_int.h"
--- 
-1.7.10.4
-
diff --git a/debian/patches/CVE-2014-3689-vmware-vga/2-add-vmsvga_verify_rect.patch b/debian/patches/CVE-2014-3689-vmware-vga/2-add-vmsvga_verify_rect.patch
deleted file mode 100644
index 72374a8..0000000
--- a/debian/patches/CVE-2014-3689-vmware-vga/2-add-vmsvga_verify_rect.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-From 07258900fd45b646f5b69048d64c4490b3243e1b Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Mon, 6 Oct 2014 11:51:54 +0200
-Subject: vmware-vga: add vmsvga_verify_rect
-
-Add verification function for rectangles, returning
-true if verification passes and false otherwise.
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-Reviewed-by: Don Koch <dkoch@verizon.com>
----
- hw/display/vmware_vga.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 52 insertions(+), 1 deletion(-)
-
-diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
-index ec63290..ba73a1c 100644
---- a/hw/display/vmware_vga.c
-+++ b/hw/display/vmware_vga.c
-@@ -294,8 +294,59 @@ enum {
-     SVGA_CURSOR_ON_RESTORE_TO_FB = 3,
- };
- 
-+static inline bool vmsvga_verify_rect(DisplaySurface *surface,
-+                                      const char *name,
-+                                      int x, int y, int w, int h)
-+{
-+    if (x < 0) {
-+        fprintf(stderr, "%s: x was < 0 (%d)\n", name, x);
-+        return false;
-+    }
-+    if (x > SVGA_MAX_WIDTH) {
-+        fprintf(stderr, "%s: x was > %d (%d)\n", name, SVGA_MAX_WIDTH, x);
-+        return false;
-+    }
-+    if (w < 0) {
-+        fprintf(stderr, "%s: w was < 0 (%d)\n", name, w);
-+        return false;
-+    }
-+    if (w > SVGA_MAX_WIDTH) {
-+        fprintf(stderr, "%s: w was > %d (%d)\n", name, SVGA_MAX_WIDTH, w);
-+        return false;
-+    }
-+    if (x + w > surface_width(surface)) {
-+        fprintf(stderr, "%s: width was > %d (x: %d, w: %d)\n",
-+                name, surface_width(surface), x, w);
-+        return false;
-+    }
-+
-+    if (y < 0) {
-+        fprintf(stderr, "%s: y was < 0 (%d)\n", name, y);
-+        return false;
-+    }
-+    if (y > SVGA_MAX_HEIGHT) {
-+        fprintf(stderr, "%s: y was > %d (%d)\n", name, SVGA_MAX_HEIGHT, y);
-+        return false;
-+    }
-+    if (h < 0) {
-+        fprintf(stderr, "%s: h was < 0 (%d)\n", name, h);
-+        return false;
-+    }
-+    if (h > SVGA_MAX_HEIGHT) {
-+        fprintf(stderr, "%s: h was > %d (%d)\n", name, SVGA_MAX_HEIGHT, h);
-+        return false;
-+    }
-+    if (y + h > surface_height(surface)) {
-+        fprintf(stderr, "%s: update height > %d (y: %d, h: %d)\n",
-+                name, surface_height(surface), y, h);
-+        return false;
-+    }
-+
-+    return true;
-+}
-+
- static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
--                int x, int y, int w, int h)
-+                                      int x, int y, int w, int h)
- {
-     DisplaySurface *surface = qemu_console_surface(s->vga.con);
-     int line;
--- 
-1.7.10.4
-
diff --git a/debian/patches/CVE-2014-3689-vmware-vga/3-use-vmsvga_verify_rect-in-vmsvga_update_rect.patch b/debian/patches/CVE-2014-3689-vmware-vga/3-use-vmsvga_verify_rect-in-vmsvga_update_rect.patch
deleted file mode 100644
index a140690..0000000
--- a/debian/patches/CVE-2014-3689-vmware-vga/3-use-vmsvga_verify_rect-in-vmsvga_update_rect.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From 1735fe1edba9cc86bc0f26937ed5a62d3cb47c9c Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Mon, 6 Oct 2014 11:58:22 +0200
-Subject: vmware-vga: use vmsvga_verify_rect in vmsvga_update_rect
-
-Switch vmsvga_update_rect over to use vmsvga_verify_rect.  Slight change
-in behavior:  We don't try to automatically fixup rectangles any more.
-In case we find invalid update requests we'll do a full-screen update
-instead.
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-Reviewed-by: Don Koch <dkoch@verizon.com>
----
- hw/display/vmware_vga.c |   32 ++++----------------------------
- 1 file changed, 4 insertions(+), 28 deletions(-)
-
-diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
-index ba73a1c..9d79de6 100644
---- a/hw/display/vmware_vga.c
-+++ b/hw/display/vmware_vga.c
-@@ -356,36 +356,12 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
-     uint8_t *src;
-     uint8_t *dst;
- 
--    if (x < 0) {
--        fprintf(stderr, "%s: update x was < 0 (%d)\n", __func__, x);
--        w += x;
-+    if (!vmsvga_verify_rect(surface, __func__, x, y, w, h)) {
-+        /* go for a fullscreen update as fallback */
-         x = 0;
--    }
--    if (w < 0) {
--        fprintf(stderr, "%s: update w was < 0 (%d)\n", __func__, w);
--        w = 0;
--    }
--    if (x + w > surface_width(surface)) {
--        fprintf(stderr, "%s: update width too large x: %d, w: %d\n",
--                __func__, x, w);
--        x = MIN(x, surface_width(surface));
--        w = surface_width(surface) - x;
--    }
--
--    if (y < 0) {
--        fprintf(stderr, "%s: update y was < 0 (%d)\n",  __func__, y);
--        h += y;
-         y = 0;
--    }
--    if (h < 0) {
--        fprintf(stderr, "%s: update h was < 0 (%d)\n",  __func__, h);
--        h = 0;
--    }
--    if (y + h > surface_height(surface)) {
--        fprintf(stderr, "%s: update height too large y: %d, h: %d\n",
--                __func__, y, h);
--        y = MIN(y, surface_height(surface));
--        h = surface_height(surface) - y;
-+        w = surface_width(surface);
-+        h = surface_height(surface);
-     }
- 
-     bypl = surface_stride(surface);
--- 
-1.7.10.4
-
diff --git a/debian/patches/CVE-2014-3689-vmware-vga/4-use-vmsvga_verify_rect-in-vmsvga_copy_rect.patch b/debian/patches/CVE-2014-3689-vmware-vga/4-use-vmsvga_verify_rect-in-vmsvga_copy_rect.patch
deleted file mode 100644
index 061a272..0000000
--- a/debian/patches/CVE-2014-3689-vmware-vga/4-use-vmsvga_verify_rect-in-vmsvga_copy_rect.patch
+++ /dev/null
@@ -1,79 +0,0 @@
-From 61b41b4c20eba08d2185297767e69153d7f3e09d Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Mon, 6 Oct 2014 11:58:51 +0200
-Subject: vmware-vga: use vmsvga_verify_rect in vmsvga_copy_rect
-
-Add verification to vmsvga_copy_rect, re-enable HW_RECT_ACCEL.
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-Reviewed-by: Don Koch <dkoch@verizon.com>
----
- hw/display/vmware_vga.c |   20 ++++++++++++++------
- 1 file changed, 14 insertions(+), 6 deletions(-)
-
-diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
-index 9d79de6..73a1b52 100644
---- a/hw/display/vmware_vga.c
-+++ b/hw/display/vmware_vga.c
-@@ -29,8 +29,8 @@
- #include "hw/pci/pci.h"
- 
- #undef VERBOSE
--#if 0
- #define HW_RECT_ACCEL
-+#if 0
- #define HW_FILL_ACCEL
- #endif
- #define HW_MOUSE_ACCEL
-@@ -406,7 +406,7 @@ static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
- }
- 
- #ifdef HW_RECT_ACCEL
--static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
-+static inline int vmsvga_copy_rect(struct vmsvga_state_s *s,
-                 int x0, int y0, int x1, int y1, int w, int h)
- {
-     DisplaySurface *surface = qemu_console_surface(s->vga.con);
-@@ -417,6 +417,13 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
-     int line = h;
-     uint8_t *ptr[2];
- 
-+    if (!vmsvga_verify_rect(surface, "vmsvga_copy_rect/src", x0, y0, w, h)) {
-+        return -1;
-+    }
-+    if (!vmsvga_verify_rect(surface, "vmsvga_copy_rect/dst", x1, y1, w, h)) {
-+        return -1;
-+    }
-+
-     if (y1 > y0) {
-         ptr[0] = vram + bypp * x0 + bypl * (y0 + h - 1);
-         ptr[1] = vram + bypp * x1 + bypl * (y1 + h - 1);
-@@ -432,6 +439,7 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
-     }
- 
-     vmsvga_update_rect_delayed(s, x1, y1, w, h);
-+    return 0;
- }
- #endif
- 
-@@ -625,12 +633,12 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
-             width = vmsvga_fifo_read(s);
-             height = vmsvga_fifo_read(s);
- #ifdef HW_RECT_ACCEL
--            vmsvga_copy_rect(s, x, y, dx, dy, width, height);
--            break;
--#else
-+            if (vmsvga_copy_rect(s, x, y, dx, dy, width, height) == 0) {
-+                break;
-+            }
-+#endif
-             args = 0;
-             goto badcmd;
--#endif
- 
-         case SVGA_CMD_DEFINE_CURSOR:
-             len -= 8;
--- 
-1.7.10.4
-
diff --git a/debian/patches/CVE-2014-3689-vmware-vga/5-use-vmsvga_verify_rect-in-vmsvga_fill_rect.patch b/debian/patches/CVE-2014-3689-vmware-vga/5-use-vmsvga_verify_rect-in-vmsvga_fill_rect.patch
deleted file mode 100644
index 2435470..0000000
--- a/debian/patches/CVE-2014-3689-vmware-vga/5-use-vmsvga_verify_rect-in-vmsvga_fill_rect.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From bd9ccd8517e83b7c33a9167815dbfffb30d70b13 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Mon, 6 Oct 2014 11:59:51 +0200
-Subject: vmware-vga: use vmsvga_verify_rect in vmsvga_fill_rect
-
-Add verification to vmsvga_fill_rect, re-enable HW_FILL_ACCEL.
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-Reviewed-by: Don Koch <dkoch@verizon.com>
----
- hw/display/vmware_vga.c |   17 ++++++++++-------
- 1 file changed, 10 insertions(+), 7 deletions(-)
-
-diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
-index 73a1b52..1751f19 100644
---- a/hw/display/vmware_vga.c
-+++ b/hw/display/vmware_vga.c
-@@ -30,9 +30,7 @@
- 
- #undef VERBOSE
- #define HW_RECT_ACCEL
--#if 0
- #define HW_FILL_ACCEL
--#endif
- #define HW_MOUSE_ACCEL
- 
- #include "vga_int.h"
-@@ -444,7 +442,7 @@ static inline int vmsvga_copy_rect(struct vmsvga_state_s *s,
- #endif
- 
- #ifdef HW_FILL_ACCEL
--static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
-+static inline int vmsvga_fill_rect(struct vmsvga_state_s *s,
-                 uint32_t c, int x, int y, int w, int h)
- {
-     DisplaySurface *surface = qemu_console_surface(s->vga.con);
-@@ -457,6 +455,10 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
-     uint8_t *src;
-     uint8_t col[4];
- 
-+    if (!vmsvga_verify_rect(surface, __func__, x, y, w, h)) {
-+        return -1;
-+    }
-+
-     col[0] = c;
-     col[1] = c >> 8;
-     col[2] = c >> 16;
-@@ -481,6 +483,7 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
-     }
- 
-     vmsvga_update_rect_delayed(s, x, y, w, h);
-+    return 0;
- }
- #endif
- 
-@@ -613,12 +616,12 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
-             width = vmsvga_fifo_read(s);
-             height = vmsvga_fifo_read(s);
- #ifdef HW_FILL_ACCEL
--            vmsvga_fill_rect(s, colour, x, y, width, height);
--            break;
--#else
-+            if (vmsvga_fill_rect(s, colour, x, y, width, height) == 0) {
-+                break;
-+            }
-+#endif
-             args = 0;
-             goto badcmd;
--#endif
- 
-         case SVGA_CMD_RECT_COPY:
-             len -= 7;
--- 
-1.7.10.4
-
diff --git a/debian/patches/block-fix-max-nb_sectors-in-bdrv_make_zero.patch b/debian/patches/block-fix-max-nb_sectors-in-bdrv_make_zero.patch
new file mode 100644
index 0000000..b4e157e
--- /dev/null
+++ b/debian/patches/block-fix-max-nb_sectors-in-bdrv_make_zero.patch
@@ -0,0 +1,35 @@
+From f3a9cfddaec127078ac1898de6b063db8ac3bb48 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 10 Nov 2014 15:07:44 +0800
+Subject: block: Fix max nb_sectors in bdrv_make_zero
+Bug-Debian: http://bugs.debian.org/797221
+
+In bdrv_rw_co we report -EINVAL for nb_sectors > INT_MAX /
+BDRV_SECTOR_SIZE, so a caller shouldn't exceed it.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Message-id: 1415603264-21497-1-git-send-email-famz@redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ block.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/block.c b/block.c
+index c612826..a612594 100644
+--- a/block.c
++++ b/block.c
+@@ -2790,8 +2790,8 @@ int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
+         if (nb_sectors <= 0) {
+             return 0;
+         }
+-        if (nb_sectors > INT_MAX) {
+-            nb_sectors = INT_MAX;
++        if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
++            nb_sectors = INT_MAX / BDRV_SECTOR_SIZE;
+         }
+         ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n);
+         if (ret < 0) {
+-- 
+2.1.4
+
diff --git a/debian/patches/qemu-char-fix-missed-data-on-unix-socket.patch b/debian/patches/qemu-char-fix-missed-data-on-unix-socket.patch
new file mode 100644
index 0000000..dd74a36
--- /dev/null
+++ b/debian/patches/qemu-char-fix-missed-data-on-unix-socket.patch
@@ -0,0 +1,67 @@
+From 4bf1cb03fbc43b0055af60d4ff093d6894aa4338 Mon Sep 17 00:00:00 2001
+From: Nils Carlson <pyssling@ludd.ltu.se>
+Date: Sun, 19 Jul 2015 20:39:56 +0000
+Subject: [PATCH 2/2] qemu-char: Fix missed data on unix socket
+Bug-Debian: http://bugs.debian.org/793817
+
+Commit 812c1057 introduced HUP detection on unix and tcp sockets prior
+to a read in tcp_chr_read. This unfortunately broke CloudStack 4.2
+which relied on the old behaviour where data on a socket was readable
+even if a HUP was present.
+
+A working solution is to properly check the return values from recv,
+handling a closed socket once there is no more data to read.
+
+Also enable polling for G_IO_NVAL to ensure the callback is called
+for all possible events as these should now be possible to handle
+with the improved error detection.
+
+Signed-off-by: Nils Carlson <pyssling@ludd.ltu.se>
+Message-Id: <1437338396-22336-1-git-send-email-pyssling@ludd.ltu.se>
+[Do not handle EINTR; use socket_error(). - Paolo]
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+---
+ qemu-char.c | 13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 3200200..d956f8d 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -807,7 +807,8 @@ static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_)
+     }
+ 
+     if (now_active) {
+-        iwp->src = g_io_create_watch(iwp->channel, G_IO_IN | G_IO_ERR | G_IO_HUP);
++        iwp->src = g_io_create_watch(iwp->channel,
++                                     G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
+         g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
+         g_source_attach(iwp->src, NULL);
+     } else {
+@@ -2856,12 +2857,6 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
+     uint8_t buf[READ_BUF_LEN];
+     int len, size;
+ 
+-    if (cond & G_IO_HUP) {
+-        /* connection closed */
+-        tcp_chr_disconnect(chr);
+-        return TRUE;
+-    }
+-
+     if (!s->connected || s->max_size <= 0) {
+         return TRUE;
+     }
+@@ -2869,7 +2864,9 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
+     if (len > s->max_size)
+         len = s->max_size;
+     size = tcp_chr_recv(chr, (void *)buf, len);
+-    if (size == 0) {
++    if (size == 0 ||
++        (size < 0 &&
++         socket_error() != EAGAIN && socket_error() != EWOULDBLOCK)) {
+         /* connection closed */
+         tcp_chr_disconnect(chr);
+     } else if (size > 0) {
+-- 
+2.1.4
+
diff --git a/debian/patches/qemu-char-handle-EINTR-for-TCP-character-devices.patch b/debian/patches/qemu-char-handle-EINTR-for-TCP-character-devices.patch
new file mode 100644
index 0000000..08b1ac4
--- /dev/null
+++ b/debian/patches/qemu-char-handle-EINTR-for-TCP-character-devices.patch
@@ -0,0 +1,45 @@
+From 9172f428afc1461b1d9b33ebca3a679b9adf7c3a Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 21 Jul 2015 09:25:54 +0200
+Subject: [PATCH 1/2] qemu-char: handle EINTR for TCP character devices
+Bug-Debian: http://bugs.debian.org/793817
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+---
+ qemu-char.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 617e034..3200200 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -2797,7 +2797,10 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
+ #ifdef MSG_CMSG_CLOEXEC
+     flags |= MSG_CMSG_CLOEXEC;
+ #endif
+-    ret = recvmsg(s->fd, &msg, flags);
++    do {
++        ret = recvmsg(s->fd, &msg, flags);
++    } while (ret == -1 && errno == EINTR);
++
+     if (ret > 0 && s->is_unix) {
+         unix_process_msgfd(chr, &msg);
+     }
+@@ -2808,7 +2811,13 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
+ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
+ {
+     TCPCharDriver *s = chr->opaque;
+-    return qemu_recv(s->fd, buf, len, 0);
++    ssize_t ret;
++
++    do {
++        ret = qemu_recv(s->fd, buf, len, 0);
++    } while (ret == -1 && socket_error() == EINTR);
++
++    return ret;
+ }
+ #endif
+ 
+-- 
+2.1.4
+
diff --git a/debian/patches/series b/debian/patches/series
index 24a6397..2701db4 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,5 +1,5 @@
-# upstream 2.1.2 stable patch
-v2.1.2.diff
+# upstream 2.1.3 stable patch
+v2.1.3.diff
 
 02_kfreebsd.patch
 use-fixed-data-path.patch
@@ -9,12 +9,6 @@ imx_timer_TIMER_MAX_clash.diff
 9p-readdir.patch
 9p-use-little-endian-format-for-xattr-values.patch
 qemu-options-add-missing--drive-discard-option-to-cmdline-help.diff
-# 5 patches to fix CVE-2014-3689 from upstream, #765496
-CVE-2014-3689-vmware-vga/1-CVE-2014-3689-turn-off-hw-accel.patch
-CVE-2014-3689-vmware-vga/2-add-vmsvga_verify_rect.patch
-CVE-2014-3689-vmware-vga/3-use-vmsvga_verify_rect-in-vmsvga_update_rect.patch
-CVE-2014-3689-vmware-vga/4-use-vmsvga_verify_rect-in-vmsvga_copy_rect.patch
-CVE-2014-3689-vmware-vga/5-use-vmsvga_verify_rect-in-vmsvga_fill_rect.patch
 
 vnc-sanitize-bits_per_pixel-from-the-client-CVE-2014-7815.patch
 
@@ -23,7 +17,6 @@ slirp-smbd-modify-set-several-parameters-in-generated-smb-conf.patch
 
 block-raw-posix-Fix-disk-corruption-in-try_fiemap.patch
 block-raw-posix-use-seek_hole-ahead-of-fiemap.patch
-tcg-mips-fix-store-softmmu-slow-path.patch
 # CVE-2014-7840
 migration-fix-parameter-validation-on-ram-load.patch
 usb-host-fix-usb_host_speed_compat-tyops.patch
@@ -71,3 +64,7 @@ e1000-avoid-infinite-loop-in-transmit-CVE-2015-6815.patch
 ide-fix-ATAPI-command-permissions-CVE-2015-6855.patch
 ne2000-add-checks-to-validate-ring-buffer-pointers-CVE-2015-5279.patch
 ne2000-avoid-infinite-loop-when-receiving-packets-CVE-2015-5278.patch
+block-fix-max-nb_sectors-in-bdrv_make_zero.patch
+#793817
+qemu-char-handle-EINTR-for-TCP-character-devices.patch
+qemu-char-fix-missed-data-on-unix-socket.patch
diff --git a/debian/patches/tcg-mips-fix-store-softmmu-slow-path.patch b/debian/patches/tcg-mips-fix-store-softmmu-slow-path.patch
deleted file mode 100644
index 282d8ff..0000000
--- a/debian/patches/tcg-mips-fix-store-softmmu-slow-path.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 0a2923f8488498000eec54871456aa64a4391da4 Mon Sep 17 00:00:00 2001
-From: Aurelien Jarno <aurelien@aurel32.net>
-Date: Mon, 27 Oct 2014 15:53:35 +0100
-Subject: tcg/mips: fix store softmmu slow path
-Bug-Debian: http://bugs.debian.org/769470
-
-Commit 9d8bf2d1 moved the softmmu slow path out of line and introduce a
-regression at the same time by always calling tcg_out_tlb_load with
-is_load=1. This makes impossible to run any significant code under
-qemu-system-mips*.
-
-Cc: Paolo Bonzini <pbonzini@redhat.com>
-Cc: qemu-stable@nongnu.org
-Reviewed-by: Richard Henderson <rth@twiddle.net>
-Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
----
- tcg/mips/tcg-target.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
-index 9cce356..b7f4d67 100644
---- a/tcg/mips/tcg-target.c
-+++ b/tcg/mips/tcg-target.c
-@@ -1302,7 +1302,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
-        so we can reuse that for the base.  */
-     base = (TARGET_LONG_BITS == 32 ? TCG_REG_A1 : TCG_REG_A2);
-     tcg_out_tlb_load(s, base, addr_regl, addr_regh, mem_index,
--                     s_bits, label_ptr, 1);
-+                     s_bits, label_ptr, 0);
-     tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
-     add_qemu_ldst_label(s, 0, opc, data_regl, data_regh, addr_regl, addr_regh,
-                         mem_index, s->code_ptr, label_ptr);
--- 
-2.1.3
-
diff --git a/debian/patches/v2.1.2.diff b/debian/patches/v2.1.3.diff
similarity index 32%
rename from debian/patches/v2.1.2.diff
rename to debian/patches/v2.1.3.diff
index e836ad3..003d74f 100644
--- a/debian/patches/v2.1.2.diff
+++ b/debian/patches/v2.1.3.diff
@@ -1,14 +1,25 @@
-Subject: upstream 2.1.2 patch
-From: Michael Roth <mdroth@linux.vnet.ibm.com>
-Date: Thu, 25 Sep 2014 16:13:51 -0500
-
 diff --git a/VERSION b/VERSION
-index 7ec1d6d..eca07e4 100644
+index 7ec1d6d..ac2cdeb 100644
 --- a/VERSION
 +++ b/VERSION
 @@ -1 +1 @@
 -2.1.0
-+2.1.2
++2.1.3
+diff --git a/audio/audio_template.h b/audio/audio_template.h
+index 8173188..584e536 100644
+--- a/audio/audio_template.h
++++ b/audio/audio_template.h
+@@ -191,9 +191,9 @@ static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
+         audio_detach_capture (hw);
+ #endif
+         QLIST_REMOVE (hw, entries);
++        glue (hw->pcm_ops->fini_, TYPE) (hw);
+         glue (s->nb_hw_voices_, TYPE) += 1;
+         glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
+-        glue (hw->pcm_ops->fini_, TYPE) (hw);
+         g_free (hw);
+         *hwp = NULL;
+     }
 diff --git a/backends/hostmem.c b/backends/hostmem.c
 index ca10c51..a9905c0 100644
 --- a/backends/hostmem.c
@@ -34,8 +45,150 @@ index 25bb3b4..2962795 100644
          s->chr_name = g_strdup(value);
      }
  }
+diff --git a/block-migration.c b/block-migration.c
+index 73cdd07..36403ee 100644
+--- a/block-migration.c
++++ b/block-migration.c
+@@ -652,6 +652,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
+ {
+     int ret;
+     int64_t last_ftell = qemu_ftell(f);
++    int64_t delta_ftell;
+ 
+     DPRINTF("Enter save live iterate submitted %d transferred %d\n",
+             block_mig_state.submitted, block_mig_state.transferred);
+@@ -701,7 +702,14 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
+     }
+ 
+     qemu_put_be64(f, BLK_MIG_FLAG_EOS);
+-    return qemu_ftell(f) - last_ftell;
++    delta_ftell = qemu_ftell(f) - last_ftell;
++    if (delta_ftell > 0) {
++        return 1;
++    } else if (delta_ftell < 0) {
++        return -1;
++    } else {
++        return 0;
++    }
+ }
+ 
+ /* Called with iothread lock taken.  */
+@@ -756,8 +764,8 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
+                        block_mig_state.read_done * BLOCK_SIZE;
+ 
+     /* Report at least one block pending during bulk phase */
+-    if (pending == 0 && !block_mig_state.bulk_completed) {
+-        pending = BLOCK_SIZE;
++    if (pending <= max_size && !block_mig_state.bulk_completed) {
++        pending = max_size + BLOCK_SIZE;
+     }
+     blk_mig_unlock();
+     qemu_mutex_unlock_iothread();
+diff --git a/block.c b/block.c
+index 8cf519b..ed87b7e 100644
+--- a/block.c
++++ b/block.c
+@@ -633,7 +633,7 @@ BlockDriver *bdrv_find_protocol(const char *filename,
+     }
+ 
+     if (!path_has_protocol(filename) || !allow_protocol_prefix) {
+-        return bdrv_find_format("file");
++        return &bdrv_file;
+     }
+ 
+     p = strchr(filename, ':');
+@@ -662,12 +662,7 @@ static int find_image_format(BlockDriverState *bs, const char *filename,
+ 
+     /* Return the raw BlockDriver * to scsi-generic devices or empty drives */
+     if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) {
+-        drv = bdrv_find_format("raw");
+-        if (!drv) {
+-            error_setg(errp, "Could not find raw image format");
+-            ret = -ENOENT;
+-        }
+-        *pdrv = drv;
++        *pdrv = &bdrv_raw;
+         return ret;
+     }
+ 
+@@ -1182,7 +1177,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
+ {
+     char *backing_filename = g_malloc0(PATH_MAX);
+     int ret = 0;
+-    BlockDriver *back_drv = NULL;
+     BlockDriverState *backing_hd;
+     Error *local_err = NULL;
+ 
+@@ -1215,14 +1209,14 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
+ 
+     backing_hd = bdrv_new("", errp);
+ 
+-    if (bs->backing_format[0] != '\0') {
+-        back_drv = bdrv_find_format(bs->backing_format);
++    if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) {
++        qdict_put(options, "driver", qstring_from_str(bs->backing_format));
+     }
+ 
+     assert(bs->backing_hd == NULL);
+     ret = bdrv_open(&backing_hd,
+                     *backing_filename ? backing_filename : NULL, NULL, options,
+-                    bdrv_backing_flags(bs->open_flags), back_drv, &local_err);
++                    bdrv_backing_flags(bs->open_flags), NULL, &local_err);
+     if (ret < 0) {
+         bdrv_unref(backing_hd);
+         backing_hd = NULL;
+@@ -1296,7 +1290,6 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
+     /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
+     char *tmp_filename = g_malloc0(PATH_MAX + 1);
+     int64_t total_size;
+-    BlockDriver *bdrv_qcow2;
+     QemuOpts *opts = NULL;
+     QDict *snapshot_options;
+     BlockDriverState *bs_snapshot;
+@@ -1322,11 +1315,10 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
+         goto out;
+     }
+ 
+-    bdrv_qcow2 = bdrv_find_format("qcow2");
+-    opts = qemu_opts_create(bdrv_qcow2->create_opts, NULL, 0,
++    opts = qemu_opts_create(bdrv_qcow2.create_opts, NULL, 0,
+                             &error_abort);
+     qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size);
+-    ret = bdrv_create(bdrv_qcow2, tmp_filename, opts, &local_err);
++    ret = bdrv_create(&bdrv_qcow2, tmp_filename, opts, &local_err);
+     qemu_opts_del(opts);
+     if (ret < 0) {
+         error_setg_errno(errp, -ret, "Could not create temporary overlay "
+@@ -1346,7 +1338,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
+     bs_snapshot = bdrv_new("", &error_abort);
+ 
+     ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
+-                    flags, bdrv_qcow2, &local_err);
++                    flags, &bdrv_qcow2, &local_err);
+     if (ret < 0) {
+         error_propagate(errp, local_err);
+         goto out;
+@@ -5535,6 +5527,18 @@ void bdrv_img_create(const char *filename, const char *fmt,
+         return;
+     }
+ 
++    if (!drv->create_opts) {
++        error_setg(errp, "Format driver '%s' does not support image creation",
++                   drv->format_name);
++        return;
++    }
++
++    if (!proto_drv->create_opts) {
++        error_setg(errp, "Protocol driver '%s' does not support image creation",
++                   proto_drv->format_name);
++        return;
++    }
++
+     create_opts = qemu_opts_append(create_opts, drv->create_opts);
+     create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
+ 
 diff --git a/block/blkdebug.c b/block/blkdebug.c
-index f51407d..01b8e73 100644
+index f51407d..dac7666 100644
 --- a/block/blkdebug.c
 +++ b/block/blkdebug.c
 @@ -449,6 +449,10 @@ static void error_callback_bh(void *opaque)
@@ -49,6 +202,40 @@ index f51407d..01b8e73 100644
      qemu_aio_release(acb);
  }
  
+@@ -522,6 +526,25 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
+     return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
+ }
+ 
++static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
++    BlockDriverCompletionFunc *cb, void *opaque)
++{
++    BDRVBlkdebugState *s = bs->opaque;
++    BlkdebugRule *rule = NULL;
++
++    QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
++        if (rule->options.inject.sector == -1) {
++            break;
++        }
++    }
++
++    if (rule && rule->options.inject.error) {
++        return inject_error(bs, cb, opaque, rule);
++    }
++
++    return bdrv_aio_flush(bs->file, cb, opaque);
++}
++
+ 
+ static void blkdebug_close(BlockDriverState *bs)
+ {
+@@ -699,6 +722,7 @@ static BlockDriver bdrv_blkdebug = {
+ 
+     .bdrv_aio_readv         = blkdebug_aio_readv,
+     .bdrv_aio_writev        = blkdebug_aio_writev,
++    .bdrv_aio_flush         = blkdebug_aio_flush,
+ 
+     .bdrv_debug_event           = blkdebug_debug_event,
+     .bdrv_debug_breakpoint      = blkdebug_debug_breakpoint,
 diff --git a/block/iscsi.c b/block/iscsi.c
 index a7bb697..ed883c3 100644
 --- a/block/iscsi.c
@@ -63,11 +250,163 @@ index a7bb697..ed883c3 100644
                                      iscsilun->cluster_sectors));
      }
  
+diff --git a/block/nfs.c b/block/nfs.c
+index 8439e0d..1bb05ad 100644
+--- a/block/nfs.c
++++ b/block/nfs.c
+@@ -401,6 +401,19 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
+     return 0;
+ }
+ 
++static QemuOptsList nfs_create_opts = {
++    .name = "nfs-create-opts",
++    .head = QTAILQ_HEAD_INITIALIZER(nfs_create_opts.head),
++    .desc = {
++        {
++            .name = BLOCK_OPT_SIZE,
++            .type = QEMU_OPT_SIZE,
++            .help = "Virtual disk size"
++        },
++        { /* end of list */ }
++    }
++};
++
+ static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp)
+ {
+     int ret = 0;
+@@ -461,6 +474,8 @@ static BlockDriver bdrv_nfs = {
+ 
+     .instance_size                  = sizeof(NFSClient),
+     .bdrv_needs_filename            = true,
++    .create_opts                    = &nfs_create_opts,
++
+     .bdrv_has_zero_init             = nfs_has_zero_init,
+     .bdrv_get_allocated_file_size   = nfs_get_allocated_file_size,
+     .bdrv_truncate                  = nfs_file_truncate,
+diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
+index 4208dc0..769e68d 100644
+--- a/block/qcow2-cluster.c
++++ b/block/qcow2-cluster.c
+@@ -158,12 +158,14 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset,
+ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
+ {
+     BDRVQcowState *s = bs->opaque;
+-    uint64_t buf[L1_ENTRIES_PER_SECTOR];
++    uint64_t buf[L1_ENTRIES_PER_SECTOR] = { 0 };
+     int l1_start_index;
+     int i, ret;
+ 
+     l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
+-    for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) {
++    for (i = 0; i < L1_ENTRIES_PER_SECTOR && l1_start_index + i < s->l1_size;
++         i++)
++    {
+         buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
+     }
+ 
+@@ -1200,7 +1202,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
+ 
+ again:
+     start = offset;
+-    remaining = *num << BDRV_SECTOR_BITS;
++    remaining = (uint64_t)*num << BDRV_SECTOR_BITS;
+     cluster_offset = 0;
+     *host_offset = 0;
+     cur_bytes = 0;
+diff --git a/block/qcow2.c b/block/qcow2.c
+index 1e3ab6b..ea6d3f2 100644
+--- a/block/qcow2.c
++++ b/block/qcow2.c
+@@ -114,7 +114,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
+ #ifdef DEBUG_EXT
+         printf("ext.magic = 0x%x\n", ext.magic);
+ #endif
+-        if (ext.len > end_offset - offset) {
++        if (offset > end_offset || ext.len > end_offset - offset) {
+             error_setg(errp, "Header extension too large");
+             return -EINVAL;
+         }
+@@ -1275,10 +1275,23 @@ static void qcow2_close(BlockDriverState *bs)
+     s->l1_table = NULL;
+ 
+     if (!(bs->open_flags & BDRV_O_INCOMING)) {
+-        qcow2_cache_flush(bs, s->l2_table_cache);
+-        qcow2_cache_flush(bs, s->refcount_block_cache);
++        int ret1, ret2;
+ 
+-        qcow2_mark_clean(bs);
++        ret1 = qcow2_cache_flush(bs, s->l2_table_cache);
++        ret2 = qcow2_cache_flush(bs, s->refcount_block_cache);
++
++        if (ret1) {
++            error_report("Failed to flush the L2 table cache: %s",
++                         strerror(-ret1));
++        }
++        if (ret2) {
++            error_report("Failed to flush the refcount block cache: %s",
++                         strerror(-ret2));
++        }
++
++        if (!ret1 && !ret2) {
++            qcow2_mark_clean(bs);
++        }
+     }
+ 
+     qcow2_cache_destroy(bs, s->l2_table_cache);
+@@ -1712,10 +1725,9 @@ static int qcow2_create2(const char *filename, int64_t total_size,
+      * refcount of the cluster that is occupied by the header and the refcount
+      * table)
+      */
+-    BlockDriver* drv = bdrv_find_format("qcow2");
+-    assert(drv != NULL);
+     ret = bdrv_open(&bs, filename, NULL, NULL,
+-        BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, &local_err);
++                    BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH,
++                    &bdrv_qcow2, &local_err);
+     if (ret < 0) {
+         error_propagate(errp, local_err);
+         goto out;
+@@ -1767,7 +1779,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
+     /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */
+     ret = bdrv_open(&bs, filename, NULL, NULL,
+                     BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING,
+-                    drv, &local_err);
++                    &bdrv_qcow2, &local_err);
+     if (local_err) {
+         error_propagate(errp, local_err);
+         goto out;
+@@ -1948,8 +1960,7 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
+            sector based I/Os */
+         cluster_offset = bdrv_getlength(bs->file);
+         cluster_offset = (cluster_offset + 511) & ~511;
+-        bdrv_truncate(bs->file, cluster_offset);
+-        return 0;
++        return bdrv_truncate(bs->file, cluster_offset);
+     }
+ 
+     if (nb_sectors != s->cluster_sectors) {
+@@ -2404,7 +2415,7 @@ static QemuOptsList qcow2_create_opts = {
+     }
+ };
+ 
+-static BlockDriver bdrv_qcow2 = {
++BlockDriver bdrv_qcow2 = {
+     .format_name        = "qcow2",
+     .instance_size      = sizeof(BDRVQcowState),
+     .bdrv_probe         = qcow2_probe,
 diff --git a/block/raw-posix.c b/block/raw-posix.c
-index 8e9758e..87fc170 100644
+index 8e9758e..efa5686 100644
 --- a/block/raw-posix.c
 +++ b/block/raw-posix.c
-@@ -747,6 +747,15 @@ static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
+@@ -447,6 +447,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
+     s->has_write_zeroes = true;
+ 
+     if (fstat(s->fd, &st) < 0) {
++        ret = -errno;
+         error_setg_errno(errp, errno, "Could not stat file");
+         goto fail;
+     }
+@@ -747,6 +748,15 @@ static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
          }
          if (len == -1 && errno == EINTR) {
              continue;
@@ -83,6 +422,73 @@ index 8e9758e..87fc170 100644
          } else if (len == -1) {
              offset = -errno;
              break;
+@@ -1576,7 +1586,7 @@ static QemuOptsList raw_create_opts = {
+     }
+ };
+ 
+-static BlockDriver bdrv_file = {
++BlockDriver bdrv_file = {
+     .format_name = "file",
+     .protocol_name = "file",
+     .instance_size = sizeof(BDRVRawState),
+diff --git a/block/raw-win32.c b/block/raw-win32.c
+index 902eab6..0f24dd8 100644
+--- a/block/raw-win32.c
++++ b/block/raw-win32.c
+@@ -540,7 +540,7 @@ static QemuOptsList raw_create_opts = {
+     }
+ };
+ 
+-static BlockDriver bdrv_file = {
++BlockDriver bdrv_file = {
+     .format_name	= "file",
+     .protocol_name	= "file",
+     .instance_size	= sizeof(BDRVRawState),
+diff --git a/block/raw_bsd.c b/block/raw_bsd.c
+index f82f4c2..431af8f 100644
+--- a/block/raw_bsd.c
++++ b/block/raw_bsd.c
+@@ -173,7 +173,7 @@ static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
+     return 1;
+ }
+ 
+-static BlockDriver bdrv_raw = {
++BlockDriver bdrv_raw = {
+     .format_name          = "raw",
+     .bdrv_probe           = &raw_probe,
+     .bdrv_reopen_prepare  = &raw_reopen_prepare,
+diff --git a/block/snapshot.c b/block/snapshot.c
+index 85c52ff..698e1a1 100644
+--- a/block/snapshot.c
++++ b/block/snapshot.c
+@@ -236,6 +236,10 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
+         error_setg(errp, "snapshot_id and name are both NULL");
+         return -EINVAL;
+     }
++
++    /* drain all pending i/o before deleting snapshot */
++    bdrv_drain_all();
++
+     if (drv->bdrv_snapshot_delete) {
+         return drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
+     }
+diff --git a/block/vvfat.c b/block/vvfat.c
+index 70176b1..1de8808 100644
+--- a/block/vvfat.c
++++ b/block/vvfat.c
+@@ -2926,6 +2926,12 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
+     }
+ 
+     bdrv_qcow = bdrv_find_format("qcow");
++    if (!bdrv_qcow) {
++        error_setg(errp, "Failed to locate qcow driver");
++        ret = -ENOENT;
++        goto err;
++    }
++
+     opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
+     qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512);
+     qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:");
 diff --git a/configure b/configure
 index f7685b5..f49e618 100755
 --- a/configure
@@ -95,8 +501,28 @@ index f7685b5..f49e618 100755
  int main(void) { return sizeof(struct mmsghdr); }
  EOF
  if compile_prog "" "" ; then
+diff --git a/cpus.c b/cpus.c
+index 5e7f2cf..492defe 100644
+--- a/cpus.c
++++ b/cpus.c
+@@ -523,6 +523,15 @@ void cpu_synchronize_all_post_init(void)
+     }
+ }
+ 
++void cpu_clean_all_dirty(void)
++{
++    CPUState *cpu;
++
++    CPU_FOREACH(cpu) {
++        cpu_clean_state(cpu);
++    }
++}
++
+ static int do_vm_stop(RunState state)
+ {
+     int ret = 0;
 diff --git a/exec.c b/exec.c
-index 765bd94..307bc24 100644
+index 765bd94..bfee04a 100644
 --- a/exec.c
 +++ b/exec.c
 @@ -430,15 +430,50 @@ static int cpu_common_post_load(void *opaque, int version_id)
@@ -150,6 +576,40 @@ index 765bd94..307bc24 100644
      }
  };
  
+@@ -1095,6 +1130,7 @@ static void *file_ram_alloc(RAMBlock *block,
+ 
+ error:
+     if (mem_prealloc) {
++        error_report("%s\n", error_get_pretty(*errp));
+         exit(1);
+     }
+     return NULL;
+@@ -1973,10 +2009,8 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
+ static void invalidate_and_set_dirty(hwaddr addr,
+                                      hwaddr length)
+ {
+-    if (cpu_physical_memory_is_clean(addr)) {
+-        /* invalidate code */
+-        tb_invalidate_phys_page_range(addr, addr + length, 0);
+-        /* set dirty bit */
++    if (cpu_physical_memory_range_includes_clean(addr, length)) {
++        tb_invalidate_phys_range(addr, addr + length, 0);
+         cpu_physical_memory_set_dirty_range_nocode(addr, length);
+     }
+     xen_modified_memory(addr, length);
+diff --git a/gdbstub.c b/gdbstub.c
+index 8afe0b7..71aaa23 100644
+--- a/gdbstub.c
++++ b/gdbstub.c
+@@ -1707,7 +1707,7 @@ int gdbserver_start(const char *device)
+         qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
+ 
+         /* Initialize a monitor terminal for gdb */
+-        mon_chr = g_malloc0(sizeof(*mon_chr));
++        mon_chr = qemu_chr_alloc();
+         mon_chr->chr_write = gdb_monitor_write;
+         monitor_init(mon_chr, 0);
+     } else {
 diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
 index fae663a..34dedf1 100644
 --- a/hw/acpi/pcihp.c
@@ -163,8 +623,21 @@ index fae663a..34dedf1 100644
          return 0;
      }
  
+diff --git a/hw/arm/boot.c b/hw/arm/boot.c
+index 3d1f4a2..50b6c5c 100644
+--- a/hw/arm/boot.c
++++ b/hw/arm/boot.c
+@@ -508,7 +508,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
+     entry = elf_entry;
+     if (kernel_size < 0) {
+         kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
+-                                  &is_linux);
++                                  &is_linux, NULL, NULL);
+     }
+     if (kernel_size < 0) {
+         entry = info->loader_start + kernel_load_offset;
 diff --git a/hw/arm/virt.c b/hw/arm/virt.c
-index 89532bd..c8fdac4 100644
+index 89532bd..bdc1573 100644
 --- a/hw/arm/virt.c
 +++ b/hw/arm/virt.c
 @@ -194,20 +194,41 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi)
@@ -214,6 +687,24 @@ index 89532bd..c8fdac4 100644
      }
  }
  
+@@ -350,7 +371,7 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
+                                      2, base, 2, size);
+     qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
+                                GIC_FDT_IRQ_TYPE_SPI, irq,
+-                               GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
++                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+     qemu_fdt_setprop_cells(vbi->fdt, nodename, "clocks",
+                                vbi->clock_phandle, vbi->clock_phandle);
+     qemu_fdt_setprop(vbi->fdt, nodename, "clock-names",
+@@ -375,7 +396,7 @@ static void create_rtc(const VirtBoardInfo *vbi, qemu_irq *pic)
+                                  2, base, 2, size);
+     qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
+                            GIC_FDT_IRQ_TYPE_SPI, irq,
+-                           GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
++                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+     qemu_fdt_setprop_cell(vbi->fdt, nodename, "clocks", vbi->clock_phandle);
+     qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk");
+     g_free(nodename);
 diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
 index c241c50..0e3925b 100644
 --- a/hw/block/virtio-blk.c
@@ -229,6 +720,54 @@ index c241c50..0e3925b 100644
      }
  
      virtio_submit_multiwrite(s->bs, &mrb);
+diff --git a/hw/core/loader.c b/hw/core/loader.c
+index 2bf6b8f..8b84c12 100644
+--- a/hw/core/loader.c
++++ b/hw/core/loader.c
+@@ -456,7 +456,9 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
+ 
+ /* Load a U-Boot image.  */
+ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
+-                            int *is_linux, uint8_t image_type)
++                            int *is_linux, uint8_t image_type,
++                            uint64_t (*translate_fn)(void *, uint64_t),
++                            void *translate_opaque)
+ {
+     int fd;
+     int size;
+@@ -490,6 +492,9 @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
+     switch (hdr->ih_type) {
+     case IH_TYPE_KERNEL:
+         address = hdr->ih_load;
++        if (translate_fn) {
++            address = translate_fn(translate_opaque, address);
++        }
+         if (loadaddr) {
+             *loadaddr = hdr->ih_load;
+         }
+@@ -566,15 +571,19 @@ out:
+ }
+ 
+ int load_uimage(const char *filename, hwaddr *ep, hwaddr *loadaddr,
+-                int *is_linux)
++                int *is_linux,
++                uint64_t (*translate_fn)(void *, uint64_t),
++                void *translate_opaque)
+ {
+-    return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL);
++    return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
++                            translate_fn, translate_opaque);
+ }
+ 
+ /* Load a ramdisk.  */
+ int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
+ {
+-    return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK);
++    return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
++                            NULL, NULL);
+ }
+ 
+ /*
 diff --git a/hw/core/machine.c b/hw/core/machine.c
 index 7a66c57..d145aca 100644
 --- a/hw/core/machine.c
@@ -297,6 +836,116 @@ index 7a66c57..d145aca 100644
      ms->firmware = g_strdup(value);
  }
  
+diff --git a/hw/core/qdev.c b/hw/core/qdev.c
+index da1ba48..0e21fad 100644
+--- a/hw/core/qdev.c
++++ b/hw/core/qdev.c
+@@ -834,12 +834,14 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
+             dc->realize(dev, &local_err);
+         }
+ 
+-        if (dev->parent_bus && dev->parent_bus->hotplug_handler &&
+-            local_err == NULL) {
++        if (local_err != NULL) {
++            goto fail;
++        }
++
++        if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
+             hotplug_handler_plug(dev->parent_bus->hotplug_handler,
+                                  dev, &local_err);
+-        } else if (local_err == NULL &&
+-                   object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) {
++        } else if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) {
+             HotplugHandler *hotplug_ctrl;
+             MachineState *machine = MACHINE(qdev_get_machine());
+             MachineClass *mc = MACHINE_GET_CLASS(machine);
+@@ -852,47 +854,69 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
+             }
+         }
+ 
+-        if (qdev_get_vmsd(dev) && local_err == NULL) {
++        if (local_err != NULL) {
++            goto post_realize_fail;
++        }
++
++        if (qdev_get_vmsd(dev)) {
+             vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+                                            dev->instance_id_alias,
+                                            dev->alias_required_for_version);
+         }
+-        if (local_err == NULL) {
+-            QLIST_FOREACH(bus, &dev->child_bus, sibling) {
+-                object_property_set_bool(OBJECT(bus), true, "realized",
++
++        QLIST_FOREACH(bus, &dev->child_bus, sibling) {
++            object_property_set_bool(OBJECT(bus), true, "realized",
+                                          &local_err);
+-                if (local_err != NULL) {
+-                    break;
+-                }
++            if (local_err != NULL) {
++                goto child_realize_fail;
+             }
+         }
+-        if (dev->hotplugged && local_err == NULL) {
++        if (dev->hotplugged) {
+             device_reset(dev);
+         }
+         dev->pending_deleted_event = false;
+     } else if (!value && dev->realized) {
++        Error **local_errp = NULL;
+         QLIST_FOREACH(bus, &dev->child_bus, sibling) {
++            local_errp = local_err ? NULL : &local_err;
+             object_property_set_bool(OBJECT(bus), false, "realized",
+-                                     &local_err);
+-            if (local_err != NULL) {
+-                break;
+-            }
++                                     local_errp);
+         }
+-        if (qdev_get_vmsd(dev) && local_err == NULL) {
++        if (qdev_get_vmsd(dev)) {
+             vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+         }
+-        if (dc->unrealize && local_err == NULL) {
+-            dc->unrealize(dev, &local_err);
++        if (dc->unrealize) {
++            local_errp = local_err ? NULL : &local_err;
++            dc->unrealize(dev, local_errp);
+         }
+         dev->pending_deleted_event = true;
+     }
+ 
+     if (local_err != NULL) {
+-        error_propagate(errp, local_err);
+-        return;
++        goto fail;
+     }
+ 
+     dev->realized = value;
++    return;
++
++child_realize_fail:
++    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
++        object_property_set_bool(OBJECT(bus), false, "realized",
++                                 NULL);
++    }
++
++    if (qdev_get_vmsd(dev)) {
++        vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
++    }
++
++post_realize_fail:
++    if (dc->unrealize) {
++        dc->unrealize(dev, NULL);
++    }
++
++fail:
++    error_propagate(errp, local_err);
++    return;
+ }
+ 
+ static bool device_get_hotpluggable(Object *obj, Error **errp)
 diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
 index cc2c2b1..bcc5c37 100644
 --- a/hw/display/qxl-render.c
@@ -545,8 +1194,205 @@ index 5320abd..cb6d8f6 100644
      uint32_t latch;
      MemoryRegion *chain4_alias;
      uint8_t sr_index;
+diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
+index 591b645..d44e3e8 100644
+--- a/hw/display/vmware_vga.c
++++ b/hw/display/vmware_vga.c
+@@ -292,47 +292,74 @@ enum {
+     SVGA_CURSOR_ON_RESTORE_TO_FB = 3,
+ };
+ 
+-static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
+-                int x, int y, int w, int h)
++static inline bool vmsvga_verify_rect(DisplaySurface *surface,
++                                      const char *name,
++                                      int x, int y, int w, int h)
+ {
+-    DisplaySurface *surface = qemu_console_surface(s->vga.con);
+-    int line;
+-    int bypl;
+-    int width;
+-    int start;
+-    uint8_t *src;
+-    uint8_t *dst;
+-
+     if (x < 0) {
+-        fprintf(stderr, "%s: update x was < 0 (%d)\n", __func__, x);
+-        w += x;
+-        x = 0;
++        fprintf(stderr, "%s: x was < 0 (%d)\n", name, x);
++        return false;
++    }
++    if (x > SVGA_MAX_WIDTH) {
++        fprintf(stderr, "%s: x was > %d (%d)\n", name, SVGA_MAX_WIDTH, x);
++        return false;
+     }
+     if (w < 0) {
+-        fprintf(stderr, "%s: update w was < 0 (%d)\n", __func__, w);
+-        w = 0;
++        fprintf(stderr, "%s: w was < 0 (%d)\n", name, w);
++        return false;
++    }
++    if (w > SVGA_MAX_WIDTH) {
++        fprintf(stderr, "%s: w was > %d (%d)\n", name, SVGA_MAX_WIDTH, w);
++        return false;
+     }
+     if (x + w > surface_width(surface)) {
+-        fprintf(stderr, "%s: update width too large x: %d, w: %d\n",
+-                __func__, x, w);
+-        x = MIN(x, surface_width(surface));
+-        w = surface_width(surface) - x;
++        fprintf(stderr, "%s: width was > %d (x: %d, w: %d)\n",
++                name, surface_width(surface), x, w);
++        return false;
+     }
+ 
+     if (y < 0) {
+-        fprintf(stderr, "%s: update y was < 0 (%d)\n",  __func__, y);
+-        h += y;
+-        y = 0;
++        fprintf(stderr, "%s: y was < 0 (%d)\n", name, y);
++        return false;
++    }
++    if (y > SVGA_MAX_HEIGHT) {
++        fprintf(stderr, "%s: y was > %d (%d)\n", name, SVGA_MAX_HEIGHT, y);
++        return false;
+     }
+     if (h < 0) {
+-        fprintf(stderr, "%s: update h was < 0 (%d)\n",  __func__, h);
+-        h = 0;
++        fprintf(stderr, "%s: h was < 0 (%d)\n", name, h);
++        return false;
++    }
++    if (h > SVGA_MAX_HEIGHT) {
++        fprintf(stderr, "%s: h was > %d (%d)\n", name, SVGA_MAX_HEIGHT, h);
++        return false;
+     }
+     if (y + h > surface_height(surface)) {
+-        fprintf(stderr, "%s: update height too large y: %d, h: %d\n",
+-                __func__, y, h);
+-        y = MIN(y, surface_height(surface));
+-        h = surface_height(surface) - y;
++        fprintf(stderr, "%s: update height > %d (y: %d, h: %d)\n",
++                name, surface_height(surface), y, h);
++        return false;
++    }
++
++    return true;
++}
++
++static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
++                                      int x, int y, int w, int h)
++{
++    DisplaySurface *surface = qemu_console_surface(s->vga.con);
++    int line;
++    int bypl;
++    int width;
++    int start;
++    uint8_t *src;
++    uint8_t *dst;
++
++    if (!vmsvga_verify_rect(surface, __func__, x, y, w, h)) {
++        /* go for a fullscreen update as fallback */
++        x = 0;
++        y = 0;
++        w = surface_width(surface);
++        h = surface_height(surface);
+     }
+ 
+     bypl = surface_stride(surface);
+@@ -377,7 +404,7 @@ static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
+ }
+ 
+ #ifdef HW_RECT_ACCEL
+-static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
++static inline int vmsvga_copy_rect(struct vmsvga_state_s *s,
+                 int x0, int y0, int x1, int y1, int w, int h)
+ {
+     DisplaySurface *surface = qemu_console_surface(s->vga.con);
+@@ -388,6 +415,13 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
+     int line = h;
+     uint8_t *ptr[2];
+ 
++    if (!vmsvga_verify_rect(surface, "vmsvga_copy_rect/src", x0, y0, w, h)) {
++        return -1;
++    }
++    if (!vmsvga_verify_rect(surface, "vmsvga_copy_rect/dst", x1, y1, w, h)) {
++        return -1;
++    }
++
+     if (y1 > y0) {
+         ptr[0] = vram + bypp * x0 + bypl * (y0 + h - 1);
+         ptr[1] = vram + bypp * x1 + bypl * (y1 + h - 1);
+@@ -403,11 +437,12 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
+     }
+ 
+     vmsvga_update_rect_delayed(s, x1, y1, w, h);
++    return 0;
+ }
+ #endif
+ 
+ #ifdef HW_FILL_ACCEL
+-static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
++static inline int vmsvga_fill_rect(struct vmsvga_state_s *s,
+                 uint32_t c, int x, int y, int w, int h)
+ {
+     DisplaySurface *surface = qemu_console_surface(s->vga.con);
+@@ -420,6 +455,10 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
+     uint8_t *src;
+     uint8_t col[4];
+ 
++    if (!vmsvga_verify_rect(surface, __func__, x, y, w, h)) {
++        return -1;
++    }
++
+     col[0] = c;
+     col[1] = c >> 8;
+     col[2] = c >> 16;
+@@ -444,6 +483,7 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
+     }
+ 
+     vmsvga_update_rect_delayed(s, x, y, w, h);
++    return 0;
+ }
+ #endif
+ 
+@@ -576,12 +616,12 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
+             width = vmsvga_fifo_read(s);
+             height = vmsvga_fifo_read(s);
+ #ifdef HW_FILL_ACCEL
+-            vmsvga_fill_rect(s, colour, x, y, width, height);
+-            break;
+-#else
++            if (vmsvga_fill_rect(s, colour, x, y, width, height) == 0) {
++                break;
++            }
++#endif
+             args = 0;
+             goto badcmd;
+-#endif
+ 
+         case SVGA_CMD_RECT_COPY:
+             len -= 7;
+@@ -596,12 +636,12 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
+             width = vmsvga_fifo_read(s);
+             height = vmsvga_fifo_read(s);
+ #ifdef HW_RECT_ACCEL
+-            vmsvga_copy_rect(s, x, y, dx, dy, width, height);
+-            break;
+-#else
++            if (vmsvga_copy_rect(s, x, y, dx, dy, width, height) == 0) {
++                break;
++            }
++#endif
+             args = 0;
+             goto badcmd;
+-#endif
+ 
+         case SVGA_CMD_DEFINE_CURSOR:
+             len -= 8;
 diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
-index 816c6d9..8609871 100644
+index 816c6d9..5d9f654 100644
 --- a/hw/i386/acpi-build.c
 +++ b/hw/i386/acpi-build.c
 @@ -546,6 +546,12 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm)
@@ -562,7 +1408,30 @@ index 816c6d9..8609871 100644
  }
  
  
-@@ -1393,7 +1399,7 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
+@@ -1222,8 +1228,7 @@ acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
+ }
+ 
+ static void
+-build_srat(GArray *table_data, GArray *linker,
+-           AcpiCpuInfo *cpu, PcGuestInfo *guest_info)
++build_srat(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
+ {
+     AcpiSystemResourceAffinityTable *srat;
+     AcpiSratProcessorAffinity *core;
+@@ -1253,11 +1258,7 @@ build_srat(GArray *table_data, GArray *linker,
+         core->proximity_lo = curnode;
+         memset(core->proximity_hi, 0, 3);
+         core->local_sapic_eid = 0;
+-        if (test_bit(i, cpu->found_cpus)) {
+-            core->flags = cpu_to_le32(1);
+-        } else {
+-            core->flags = cpu_to_le32(0);
+-        }
++        core->flags = cpu_to_le32(1);
+     }
+ 
+ 
+@@ -1393,7 +1394,7 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
  {
      AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
  
@@ -571,6 +1440,15 @@ index 816c6d9..8609871 100644
                               true /* fseg memory */);
  
      memcpy(&rsdp->signature, "RSD PTR ", 8);
+@@ -1533,7 +1534,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
+     }
+     if (guest_info->numa_nodes) {
+         acpi_add_table(table_offsets, tables->table_data);
+-        build_srat(tables->table_data, tables->linker, &cpu, guest_info);
++        build_srat(tables->table_data, tables->linker, guest_info);
+     }
+     if (acpi_get_mcfg(&mcfg)) {
+         acpi_add_table(table_offsets, tables->table_data);
 diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
 index 6ba0170..559f4b6 100644
 --- a/hw/i386/acpi-dsdt.dsl
@@ -619,6 +1497,110 @@ index 6c8a1fc..a21bf41 100644
  0x20,
  0x10,
  0x49,
+diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
+index 07b9c0e..58be2bd 100644
+--- a/hw/i386/kvm/clock.c
++++ b/hw/i386/kvm/clock.c
+@@ -14,8 +14,10 @@
+  */
+ 
+ #include "qemu-common.h"
++#include "qemu/host-utils.h"
+ #include "sysemu/sysemu.h"
+ #include "sysemu/kvm.h"
++#include "sysemu/cpus.h"
+ #include "hw/sysbus.h"
+ #include "hw/kvm/clock.h"
+ 
+@@ -34,6 +36,48 @@ typedef struct KVMClockState {
+     bool clock_valid;
+ } KVMClockState;
+ 
++struct pvclock_vcpu_time_info {
++    uint32_t   version;
++    uint32_t   pad0;
++    uint64_t   tsc_timestamp;
++    uint64_t   system_time;
++    uint32_t   tsc_to_system_mul;
++    int8_t     tsc_shift;
++    uint8_t    flags;
++    uint8_t    pad[2];
++} __attribute__((__packed__)); /* 32 bytes */
++
++static uint64_t kvmclock_current_nsec(KVMClockState *s)
++{
++    CPUState *cpu = first_cpu;
++    CPUX86State *env = cpu->env_ptr;
++    hwaddr kvmclock_struct_pa = env->system_time_msr & ~1ULL;
++    uint64_t migration_tsc = env->tsc;
++    struct pvclock_vcpu_time_info time;
++    uint64_t delta;
++    uint64_t nsec_lo;
++    uint64_t nsec_hi;
++    uint64_t nsec;
++
++    if (!(env->system_time_msr & 1ULL)) {
++        /* KVM clock not active */
++        return 0;
++    }
++
++    cpu_physical_memory_read(kvmclock_struct_pa, &time, sizeof(time));
++
++    assert(time.tsc_timestamp <= migration_tsc);
++    delta = migration_tsc - time.tsc_timestamp;
++    if (time.tsc_shift < 0) {
++        delta >>= -time.tsc_shift;
++    } else {
++        delta <<= time.tsc_shift;
++    }
++
++    mulu64(&nsec_lo, &nsec_hi, delta, time.tsc_to_system_mul);
++    nsec = (nsec_lo >> 32) | (nsec_hi << 32);
++    return nsec + time.system_time;
++}
+ 
+ static void kvmclock_vm_state_change(void *opaque, int running,
+                                      RunState state)
+@@ -45,9 +89,15 @@ static void kvmclock_vm_state_change(void *opaque, int running,
+ 
+     if (running) {
+         struct kvm_clock_data data;
++        uint64_t time_at_migration = kvmclock_current_nsec(s);
+ 
+         s->clock_valid = false;
+ 
++        /* We can't rely on the migrated clock value, just discard it */
++        if (time_at_migration) {
++            s->clock = time_at_migration;
++        }
++
+         data.clock = s->clock;
+         data.flags = 0;
+         ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
+@@ -75,6 +125,23 @@ static void kvmclock_vm_state_change(void *opaque, int running,
+         if (s->clock_valid) {
+             return;
+         }
++
++        cpu_synchronize_all_states();
++        /* In theory, the cpu_synchronize_all_states() call above wouldn't
++         * affect the rest of the code, as the VCPU state inside CPUState
++         * is supposed to always match the VCPU state on the kernel side.
++         *
++         * In practice, calling cpu_synchronize_state() too soon will load the
++         * kernel-side APIC state into X86CPU.apic_state too early, APIC state
++         * won't be reloaded later because CPUState.vcpu_dirty==true, and
++         * outdated APIC state may be migrated to another host.
++         *
++         * The real fix would be to make sure outdated APIC state is read
++         * from the kernel again when necessary. While this is not fixed, we
++         * need the cpu_clean_all_dirty() call below.
++         */
++        cpu_clean_all_dirty();
++
+         ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
+         if (ret < 0) {
+             fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
 diff --git a/hw/i386/pc.c b/hw/i386/pc.c
 index 2cf22b1..ef9fad8 100644
 --- a/hw/i386/pc.c
@@ -654,7 +1636,7 @@ index 2cf22b1..ef9fad8 100644
      fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
      fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline)+1);
 diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
-index 9694f88..8dc8290 100644
+index 9694f88..96b8a18 100644
 --- a/hw/i386/pc_piix.c
 +++ b/hw/i386/pc_piix.c
 @@ -318,6 +318,7 @@ static void pc_compat_2_0(MachineState *machine)
@@ -665,6 +1647,15 @@ index 9694f88..8dc8290 100644
  }
  
  static void pc_compat_1_7(MachineState *machine)
+@@ -645,7 +646,7 @@ static QEMUMachine pc_machine_v1_1 = {
+             .property = "class",\
+             .value    = stringify(PCI_CLASS_MEMORY_RAM),\
+         },{\
+-            .driver   = "apic",\
++            .driver   = "apic-common",\
+             .property = "vapic",\
+             .value    = "off",\
+         },{\
 diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
 index c39ee98..4e2dd49 100644
 --- a/hw/i386/pc_q35.c
@@ -699,6 +1690,19 @@ index 8c3eae7..054b035 100644
          }
          Method(_L04) {
          }
+diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
+index e3fa1b2..0ae5960 100644
+--- a/hw/i386/smbios.c
++++ b/hw/i386/smbios.c
+@@ -821,7 +821,7 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len,
+         smbios_build_type_2_table();
+         smbios_build_type_3_table();
+ 
+-        smbios_smp_sockets = smp_cpus / (smp_cores * smp_threads);
++        smbios_smp_sockets = DIV_ROUND_UP(smp_cpus, smp_cores * smp_threads);
+         assert(smbios_smp_sockets >= 1);
+ 
+         for (i = 0; i < smbios_smp_sockets; i++) {
 diff --git a/hw/i386/ssdt-mem.dsl b/hw/i386/ssdt-mem.dsl
 index 8e17bd1..22ff5dd 100644
 --- a/hw/i386/ssdt-mem.dsl
@@ -756,7 +1760,7 @@ index d329b8b..0fd4480 100644
              Name(_UID, "Memory hotplug resources")
  
 diff --git a/hw/ide/core.c b/hw/ide/core.c
-index db191a6..7256592 100644
+index db191a6..fa4cafa 100644
 --- a/hw/ide/core.c
 +++ b/hw/ide/core.c
 @@ -688,7 +688,8 @@ void ide_dma_cb(void *opaque, int ret)
@@ -769,15 +1773,66 @@ index db191a6..7256592 100644
          dma_buf_commit(s);
          ide_dma_error(s);
          return;
+@@ -2298,7 +2299,7 @@ static int ide_drive_post_load(void *opaque, int version_id)
+ {
+     IDEState *s = opaque;
+ 
+-    if (s->identify_set) {
++    if (s->bs && s->identify_set) {
+         bdrv_set_enable_write_cache(s->bs, !!(s->identify_data[85] & (1 << 5)));
+     }
+     return 0;
+diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
+index 684496a..388420e 100644
+--- a/hw/m68k/an5206.c
++++ b/hw/m68k/an5206.c
+@@ -74,7 +74,8 @@ static void an5206_init(MachineState *machine)
+                            NULL, NULL, 1, ELF_MACHINE, 0);
+     entry = elf_entry;
+     if (kernel_size < 0) {
+-        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
++        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
++                                  NULL, NULL);
+     }
+     if (kernel_size < 0) {
+         kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
+diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c
+index 6db1b71..fb9ca0e 100644
+--- a/hw/m68k/dummy_m68k.c
++++ b/hw/m68k/dummy_m68k.c
+@@ -50,7 +50,8 @@ static void dummy_m68k_init(MachineState *machine)
+                                NULL, NULL, 1, ELF_MACHINE, 0);
+         entry = elf_entry;
+         if (kernel_size < 0) {
+-            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
++            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
++                                      NULL, NULL);
+         }
+         if (kernel_size < 0) {
+             kernel_size = load_image_targphys(kernel_filename,
+diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
+index 2ef617f..07683db 100644
+--- a/hw/m68k/mcf5208.c
++++ b/hw/m68k/mcf5208.c
+@@ -279,7 +279,8 @@ static void mcf5208evb_init(MachineState *machine)
+                            NULL, NULL, 1, ELF_MACHINE, 0);
+     entry = elf_entry;
+     if (kernel_size < 0) {
+-        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
++        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
++                                  NULL, NULL);
+     }
+     if (kernel_size < 0) {
+         kernel_size = load_image_targphys(kernel_filename, 0x40000000,
 diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
-index 08f49ed..5bfc5b7 100644
+index 08f49ed..a800ea7 100644
 --- a/hw/mem/pc-dimm.c
 +++ b/hw/mem/pc-dimm.c
 @@ -252,6 +252,12 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
          error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
          return;
      }
-+    if (dimm->node >= nb_numa_nodes) {
++    if ((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) {
 +        error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %"
 +                   PRIu32 "' which exceeds the number of numa nodes: %d",
 +                   dimm->node, nb_numa_nodes);
@@ -786,6 +1841,169 @@ index 08f49ed..5bfc5b7 100644
  }
  
  static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm)
+diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
+index 6bf36d0..a2843cd 100644
+--- a/hw/microblaze/boot.c
++++ b/hw/microblaze/boot.c
+@@ -154,7 +154,8 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
+         if (kernel_size < 0) {
+             hwaddr uentry, loadaddr;
+ 
+-            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
++            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0,
++                                      NULL, NULL);
+             boot_info.bootstrap_pc = uentry;
+             high = (loadaddr + kernel_size + 3) & ~3;
+         }
+diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
+index 768e528..7252f64 100644
+--- a/hw/misc/ivshmem.c
++++ b/hw/misc/ivshmem.c
+@@ -24,10 +24,12 @@
+ #include "migration/migration.h"
+ #include "qapi/qmp/qerror.h"
+ #include "qemu/event_notifier.h"
++#include "qemu/fifo8.h"
+ #include "sysemu/char.h"
+ 
+ #include <sys/mman.h>
+ #include <sys/types.h>
++#include <limits.h>
+ 
+ #define PCI_VENDOR_ID_IVSHMEM   PCI_VENDOR_ID_REDHAT_QUMRANET
+ #define PCI_DEVICE_ID_IVSHMEM   0x1110
+@@ -73,6 +75,7 @@ typedef struct IVShmemState {
+ 
+     CharDriverState **eventfd_chr;
+     CharDriverState *server_chr;
++    Fifo8 incoming_fifo;
+     MemoryRegion ivshmem_mmio;
+ 
+     /* We might need to register the BAR before we actually have the memory.
+@@ -383,6 +386,9 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
+     if (!ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
+         return;
+     }
++    if (posn < 0 || posn >= s->nb_peers) {
++        return;
++    }
+ 
+     guest_curr_max = s->peers[posn].nb_eventfds;
+ 
+@@ -401,14 +407,24 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
+ 
+ /* this function increase the dynamic storage need to store data about other
+  * guests */
+-static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
++static int increase_dynamic_storage(IVShmemState *s, int new_min_size)
++{
+ 
+     int j, old_nb_alloc;
+ 
++    /* check for integer overflow */
++    if (new_min_size >= INT_MAX / sizeof(Peer) - 1 || new_min_size <= 0) {
++        return -1;
++    }
++
+     old_nb_alloc = s->nb_peers;
+ 
+-    while (new_min_size >= s->nb_peers)
+-        s->nb_peers = s->nb_peers * 2;
++    if (new_min_size >= s->nb_peers) {
++        /* +1 because #new_min_size is used as last array index */
++        s->nb_peers = new_min_size + 1;
++    } else {
++        return 0;
++    }
+ 
+     IVSHMEM_DPRINTF("bumping storage to %d guests\n", s->nb_peers);
+     s->peers = g_realloc(s->peers, s->nb_peers * sizeof(Peer));
+@@ -418,23 +434,57 @@ static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
+         s->peers[j].eventfds = NULL;
+         s->peers[j].nb_eventfds = 0;
+     }
++
++    return 0;
+ }
+ 
+-static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
++static void ivshmem_read(void *opaque, const uint8_t *buf, int size)
+ {
+     IVShmemState *s = opaque;
+     int incoming_fd, tmp_fd;
+     int guest_max_eventfd;
+     long incoming_posn;
+ 
+-    memcpy(&incoming_posn, buf, sizeof(long));
++    if (fifo8_is_empty(&s->incoming_fifo) && size == sizeof(incoming_posn)) {
++        memcpy(&incoming_posn, buf, size);
++    } else {
++        const uint8_t *p;
++        uint32_t num;
++
++        IVSHMEM_DPRINTF("short read of %d bytes\n", size);
++        num = MAX(size, sizeof(long) - fifo8_num_used(&s->incoming_fifo));
++        fifo8_push_all(&s->incoming_fifo, buf, num);
++        if (fifo8_num_used(&s->incoming_fifo) < sizeof(incoming_posn)) {
++            return;
++        }
++        size -= num;
++        buf += num;
++        p = fifo8_pop_buf(&s->incoming_fifo, sizeof(incoming_posn), &num);
++        g_assert(num == sizeof(incoming_posn));
++        memcpy(&incoming_posn, p, sizeof(incoming_posn));
++        if (size > 0) {
++            fifo8_push_all(&s->incoming_fifo, buf, size);
++        }
++    }
++
++    if (incoming_posn < -1) {
++        IVSHMEM_DPRINTF("invalid incoming_posn %ld\n", incoming_posn);
++        return;
++    }
++
+     /* pick off s->server_chr->msgfd and store it, posn should accompany msg */
+     tmp_fd = qemu_chr_fe_get_msgfd(s->server_chr);
+     IVSHMEM_DPRINTF("posn is %ld, fd is %d\n", incoming_posn, tmp_fd);
+ 
+     /* make sure we have enough space for this guest */
+     if (incoming_posn >= s->nb_peers) {
+-        increase_dynamic_storage(s, incoming_posn);
++        if (increase_dynamic_storage(s, incoming_posn) < 0) {
++            error_report("increase_dynamic_storage() failed");
++            if (tmp_fd != -1) {
++                close(tmp_fd);
++            }
++            return;
++        }
+     }
+ 
+     if (tmp_fd == -1) {
+@@ -458,6 +508,7 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
+     if (incoming_fd == -1) {
+         fprintf(stderr, "could not allocate file descriptor %s\n",
+                                                             strerror(errno));
++        close(tmp_fd);
+         return;
+     }
+ 
+@@ -659,6 +710,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
+         s->ivshmem_size = ivshmem_get_size(s);
+     }
+ 
++    fifo8_create(&s->incoming_fifo, sizeof(long));
++
+     register_savevm(DEVICE(dev), "ivshmem", 0, 0, ivshmem_save, ivshmem_load,
+                                                                         dev);
+ 
+@@ -795,6 +848,7 @@ static void pci_ivshmem_uninit(PCIDevice *dev)
+     memory_region_destroy(&s->ivshmem);
+     memory_region_destroy(&s->bar);
+     unregister_savevm(DEVICE(dev), "ivshmem", s);
++    fifo8_destroy(&s->incoming_fifo);
+ }
+ 
+ static Property ivshmem_properties[] = {
 diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
 index 0b9eba0..e88b610 100644
 --- a/hw/misc/vfio.c
@@ -846,7 +2064,7 @@ index 0b9eba0..e88b610 100644
  
      ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
 diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
-index f87c798..b37438b 100644
+index f87c798..7e3386d 100644
 --- a/hw/net/vhost_net.c
 +++ b/hw/net/vhost_net.c
 @@ -115,6 +115,7 @@ unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
@@ -857,6 +2075,22 @@ index f87c798..b37438b 100644
      vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
  }
  
+@@ -162,11 +163,11 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
+     if (r < 0) {
+         goto fail;
+     }
+-    if (!qemu_has_vnet_hdr_len(options->net_backend,
+-                               sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
+-        net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+-    }
+     if (backend_kernel) {
++        if (!qemu_has_vnet_hdr_len(options->net_backend,
++                               sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
++            net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
++        }
+         if (~net->dev.features & net->dev.backend_features) {
+             fprintf(stderr, "vhost lacks feature mask %" PRIu64
+                    " for backend\n",
 @@ -188,9 +189,13 @@ bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
      return vhost_dev_query(&net->dev, dev);
  }
@@ -953,7 +2187,7 @@ index f87c798..b37438b 100644
  
  void vhost_net_cleanup(struct vhost_net *net)
 diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
-index 268eff9..2040eac 100644
+index 268eff9..6360374 100644
 --- a/hw/net/virtio-net.c
 +++ b/hw/net/virtio-net.c
 @@ -125,10 +125,23 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
@@ -981,7 +2215,34 @@ index 268eff9..2040eac 100644
          n->vhost_started = 1;
          r = vhost_net_start(vdev, n->nic->ncs, queues);
          if (r < 0) {
-@@ -1112,8 +1125,6 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
+@@ -785,7 +798,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+     virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
+     VirtQueueElement elem;
+     size_t s;
+-    struct iovec *iov;
++    struct iovec *iov, *iov2;
+     unsigned int iov_cnt;
+ 
+     while (virtqueue_pop(vq, &elem)) {
+@@ -795,8 +808,8 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+             exit(1);
+         }
+ 
+-        iov = elem.out_sg;
+         iov_cnt = elem.out_num;
++        iov2 = iov = g_memdup(elem.out_sg, sizeof(struct iovec) * elem.out_num);
+         s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
+         iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
+         if (s != sizeof(ctrl)) {
+@@ -820,6 +833,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+ 
+         virtqueue_push(vq, &elem, sizeof(status));
+         virtio_notify(vdev, vq);
++        g_free(iov2);
+     }
+ }
+ 
+@@ -1112,8 +1126,6 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
          return num_packets;
      }
  
@@ -990,7 +2251,7 @@ index 268eff9..2040eac 100644
      if (q->async_tx.elem.out_num) {
          virtio_queue_set_notification(q->tx_vq, 0);
          return num_packets;
-@@ -1224,7 +1235,12 @@ static void virtio_net_tx_timer(void *opaque)
+@@ -1224,7 +1236,12 @@ static void virtio_net_tx_timer(void *opaque)
      VirtIONetQueue *q = opaque;
      VirtIONet *n = q->n;
      VirtIODevice *vdev = VIRTIO_DEVICE(n);
@@ -1004,7 +2265,7 @@ index 268eff9..2040eac 100644
  
      q->tx_waiting = 0;
  
-@@ -1244,7 +1260,12 @@ static void virtio_net_tx_bh(void *opaque)
+@@ -1244,7 +1261,12 @@ static void virtio_net_tx_bh(void *opaque)
      VirtIODevice *vdev = VIRTIO_DEVICE(n);
      int32_t ret;
  
@@ -1052,6 +2313,45 @@ index 77bea6f..ae3e50f 100644
      if (s->peer_has_vhdr) {
          vmxnet_rx_pkt_set_vhdr(s->rx_pkt, (struct virtio_net_hdr *)buf);
          buf += sizeof(struct virtio_net_hdr);
+diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
+index b2b4f9b..123cf4d 100644
+--- a/hw/openrisc/openrisc_sim.c
++++ b/hw/openrisc/openrisc_sim.c
+@@ -72,7 +72,7 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
+         entry = elf_entry;
+         if (kernel_size < 0) {
+             kernel_size = load_uimage(kernel_filename,
+-                                      &entry, NULL, NULL);
++                                      &entry, NULL, NULL, NULL, NULL);
+         }
+         if (kernel_size < 0) {
+             kernel_size = load_image_targphys(kernel_filename,
+diff --git a/hw/pci/msi.c b/hw/pci/msi.c
+index a4a3040..52d2313 100644
+--- a/hw/pci/msi.c
++++ b/hw/pci/msi.c
+@@ -291,7 +291,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
+                    "notify vector 0x%x"
+                    " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
+                    vector, msg.address, msg.data);
+-    stl_le_phys(&address_space_memory, msg.address, msg.data);
++    stl_le_phys(&dev->bus_master_as, msg.address, msg.data);
+ }
+ 
+ /* Normally called by pci_default_write_config(). */
+diff --git a/hw/pci/msix.c b/hw/pci/msix.c
+index 5c49bfc..20ae476 100644
+--- a/hw/pci/msix.c
++++ b/hw/pci/msix.c
+@@ -439,7 +439,7 @@ void msix_notify(PCIDevice *dev, unsigned vector)
+ 
+     msg = msix_get_message(dev, vector);
+ 
+-    stl_le_phys(&address_space_memory, msg.address, msg.data);
++    stl_le_phys(&dev->bus_master_as, msg.address, msg.data);
+ }
+ 
+ void msix_reset(PCIDevice *dev)
 diff --git a/hw/pci/pci.c b/hw/pci/pci.c
 index 351d320..42995e6 100644
 --- a/hw/pci/pci.c
@@ -1079,11 +2379,437 @@ index 351d320..42995e6 100644
  }
  
  /***********************************************************/
+diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
+index 1a5b30d..c268b91 100644
+--- a/hw/ppc/e500.c
++++ b/hw/ppc/e500.c
+@@ -830,7 +830,8 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
+          * Hrm. No ELF image? Try a uImage, maybe someone is giving us an
+          * ePAPR compliant kernel
+          */
+-        kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL);
++        kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
++                                  NULL, NULL);
+         if (kernel_size < 0) {
+             fprintf(stderr, "qemu: could not load firmware '%s'\n", filename);
+             exit(1);
+diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
+index 81a06d3..778970a 100644
+--- a/hw/ppc/ppc440_bamboo.c
++++ b/hw/ppc/ppc440_bamboo.c
+@@ -253,7 +253,8 @@ static void bamboo_init(MachineState *machine)
+ 
+     /* Load kernel. */
+     if (kernel_filename) {
+-        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
++        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL,
++                              NULL, NULL);
+         if (success < 0) {
+             success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                                &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
+index d01978f..4196a70 100644
+--- a/hw/ppc/spapr.c
++++ b/hw/ppc/spapr.c
+@@ -1377,7 +1377,6 @@ static void ppc_spapr_init(MachineState *machine)
+     spapr_create_nvram(spapr);
+ 
+     /* Set up PCI */
+-    spapr_pci_msi_init(spapr, SPAPR_PCI_MSI_WINDOW);
+     spapr_pci_rtas_init();
+ 
+     phb = spapr_create_phb(spapr, 0);
+diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
+index f6e32a4..067796d 100644
+--- a/hw/ppc/spapr_iommu.c
++++ b/hw/ppc/spapr_iommu.c
+@@ -172,9 +172,9 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
+     return tcet;
+ }
+ 
+-static void spapr_tce_table_finalize(Object *obj)
++static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)
+ {
+-    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(obj);
++    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
+ 
+     QLIST_REMOVE(tcet, list);
+ 
+@@ -419,6 +419,7 @@ static void spapr_tce_table_class_init(ObjectClass *klass, void *data)
+     DeviceClass *dc = DEVICE_CLASS(klass);
+     dc->init = spapr_tce_table_realize;
+     dc->reset = spapr_tce_reset;
++    dc->unrealize = spapr_tce_table_unrealize;
+ 
+     QLIST_INIT(&spapr_tce_tables);
+ 
+@@ -434,7 +435,6 @@ static TypeInfo spapr_tce_table_info = {
+     .parent = TYPE_DEVICE,
+     .instance_size = sizeof(sPAPRTCETable),
+     .class_init = spapr_tce_table_class_init,
+-    .instance_finalize = spapr_tce_table_finalize,
+ };
+ 
+ static void register_types(void)
+diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
+index 9ed39a9..7c18e68 100644
+--- a/hw/ppc/spapr_pci.c
++++ b/hw/ppc/spapr_pci.c
+@@ -341,7 +341,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+     }
+ 
+     /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */
+-    spapr_msi_setmsg(pdev, spapr->msi_win_addr, ret_intr_type == RTAS_TYPE_MSIX,
++    spapr_msi_setmsg(pdev, SPAPR_PCI_MSI_WINDOW, ret_intr_type == RTAS_TYPE_MSIX,
+                      irq, req_num);
+ 
+     /* Add MSI device to cache */
+@@ -465,34 +465,6 @@ static const MemoryRegionOps spapr_msi_ops = {
+     .endianness = DEVICE_LITTLE_ENDIAN
+ };
+ 
+-void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr)
+-{
+-    uint64_t window_size = 4096;
+-
+-    /*
+-     * As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
+-     * we need to allocate some memory to catch those writes coming
+-     * from msi_notify()/msix_notify().
+-     * As MSIMessage:addr is going to be the same and MSIMessage:data
+-     * is going to be a VIRQ number, 4 bytes of the MSI MR will only
+-     * be used.
+-     *
+-     * For KVM we want to ensure that this memory is a full page so that
+-     * our memory slot is of page size granularity.
+-     */
+-#ifdef CONFIG_KVM
+-    if (kvm_enabled()) {
+-        window_size = getpagesize();
+-    }
+-#endif
+-
+-    spapr->msi_win_addr = addr;
+-    memory_region_init_io(&spapr->msiwindow, NULL, &spapr_msi_ops, spapr,
+-                          "msi", window_size);
+-    memory_region_add_subregion(get_system_memory(), spapr->msi_win_addr,
+-                                &spapr->msiwindow);
+-}
+-
+ /*
+  * PHB PCI device
+  */
+@@ -512,6 +484,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
+     char *namebuf;
+     int i;
+     PCIBus *bus;
++    uint64_t msi_window_size = 4096;
+ 
+     if (sphb->index != -1) {
+         hwaddr windows_base;
+@@ -604,6 +577,28 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
+     address_space_init(&sphb->iommu_as, &sphb->iommu_root,
+                        sphb->dtbusname);
+ 
++    /*
++     * As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
++     * we need to allocate some memory to catch those writes coming
++     * from msi_notify()/msix_notify().
++     * As MSIMessage:addr is going to be the same and MSIMessage:data
++     * is going to be a VIRQ number, 4 bytes of the MSI MR will only
++     * be used.
++     *
++     * For KVM we want to ensure that this memory is a full page so that
++     * our memory slot is of page size granularity.
++     */
++#ifdef CONFIG_KVM
++    if (kvm_enabled()) {
++        msi_window_size = getpagesize();
++    }
++#endif
++
++    memory_region_init_io(&sphb->msiwindow, NULL, &spapr_msi_ops, spapr,
++                          "msi", msi_window_size);
++    memory_region_add_subregion(&sphb->iommu_root, SPAPR_PCI_MSI_WINDOW,
++                                &sphb->msiwindow);
++
+     pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
+ 
+     pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq);
+@@ -705,28 +700,34 @@ static const VMStateDescription vmstate_spapr_pci_msi = {
+     },
+ };
+ 
++static void spapr_pci_fill_msi_devs(gpointer key, gpointer value,
++                                    gpointer opaque)
++{
++    sPAPRPHBState *sphb = opaque;
++
++    sphb->msi_devs[sphb->msi_devs_num].key = *(uint32_t *)key;
++    sphb->msi_devs[sphb->msi_devs_num].value = *(spapr_pci_msi *)value;
++    sphb->msi_devs_num++;
++}
++
+ static void spapr_pci_pre_save(void *opaque)
+ {
+     sPAPRPHBState *sphb = opaque;
+-    GHashTableIter iter;
+-    gpointer key, value;
+-    int i;
++    int msi_devs_num;
+ 
+     if (sphb->msi_devs) {
+         g_free(sphb->msi_devs);
+         sphb->msi_devs = NULL;
+     }
+-    sphb->msi_devs_num = g_hash_table_size(sphb->msi);
+-    if (!sphb->msi_devs_num) {
++    sphb->msi_devs_num = 0;
++    msi_devs_num = g_hash_table_size(sphb->msi);
++    if (!msi_devs_num) {
+         return;
+     }
+-    sphb->msi_devs = g_malloc(sphb->msi_devs_num * sizeof(spapr_pci_msi_mig));
++    sphb->msi_devs = g_malloc(msi_devs_num * sizeof(spapr_pci_msi_mig));
+ 
+-    g_hash_table_iter_init(&iter, sphb->msi);
+-    for (i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) {
+-        sphb->msi_devs[i].key = *(uint32_t *) key;
+-        sphb->msi_devs[i].value = *(spapr_pci_msi *) value;
+-    }
++    g_hash_table_foreach(sphb->msi, spapr_pci_fill_msi_devs, sphb);
++    assert(sphb->msi_devs_num == msi_devs_num);
+ }
+ 
+ static int spapr_pci_post_load(void *opaque, int version_id)
+diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
+index 6b6fb61..ca682bb 100644
+--- a/hw/s390x/s390-virtio-bus.c
++++ b/hw/s390x/s390-virtio-bus.c
+@@ -161,6 +161,8 @@ static void s390_virtio_net_instance_init(Object *obj)
+     VirtIONetS390 *dev = VIRTIO_NET_S390(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ 
+ static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
+@@ -224,6 +226,8 @@ static void s390_virtio_serial_instance_init(Object *obj)
+     VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
++    object_unref(OBJECT(&dev->vdev));
+ }
+ 
+ static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
+@@ -256,6 +260,8 @@ static void s390_virtio_scsi_instance_init(Object *obj)
+     VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ 
+ #ifdef CONFIG_VHOST_SCSI
+@@ -277,6 +283,8 @@ static void s390_vhost_scsi_instance_init(Object *obj)
+     VHostSCSIS390 *dev = VHOST_SCSI_S390(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ #endif
+ 
+@@ -303,6 +311,8 @@ static void s390_virtio_rng_instance_init(Object *obj)
+     VirtIORNGS390 *dev = VIRTIO_RNG_S390(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
++    object_unref(OBJECT(&dev->vdev));
+     object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                              (Object **)&dev->vdev.conf.rng,
+                              qdev_prop_allow_set_link_before_realize,
+@@ -493,10 +503,8 @@ static unsigned virtio_s390_get_features(DeviceState *d)
+ /**************** S390 Virtio Bus Device Descriptions *******************/
+ 
+ static Property s390_virtio_net_properties[] = {
+-    DEFINE_NIC_PROPERTIES(VirtIONetS390, vdev.nic_conf),
+     DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
+     DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
+-    DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetS390, vdev.net_conf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -533,7 +541,6 @@ static const TypeInfo s390_virtio_blk = {
+ };
+ 
+ static Property s390_virtio_serial_properties[] = {
+-    DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerialS390, vdev.serial),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -556,7 +563,6 @@ static const TypeInfo s390_virtio_serial = {
+ 
+ static Property s390_virtio_rng_properties[] = {
+     DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
+-    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGS390, vdev.conf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -614,7 +620,6 @@ static const TypeInfo virtio_s390_device_info = {
+ };
+ 
+ static Property s390_virtio_scsi_properties[] = {
+-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIS390, vdev.parent_obj.conf),
+     DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
+     DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
+     DEFINE_PROP_END_OF_LIST(),
+@@ -640,7 +645,6 @@ static const TypeInfo s390_virtio_scsi = {
+ #ifdef CONFIG_VHOST_SCSI
+ static Property s390_vhost_scsi_properties[] = {
+     DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
+-    DEFINE_VHOST_SCSI_PROPERTIES(VHostSCSIS390, vdev.parent_obj.conf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
+index 33a1d86..c074f64 100644
+--- a/hw/s390x/virtio-ccw.c
++++ b/hw/s390x/virtio-ccw.c
+@@ -794,6 +794,8 @@ static void virtio_ccw_net_instance_init(Object *obj)
+     VirtIONetCcw *dev = VIRTIO_NET_CCW(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ 
+ static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
+@@ -850,6 +852,8 @@ static void virtio_ccw_serial_instance_init(Object *obj)
+     VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
++    object_unref(OBJECT(&dev->vdev));
+ }
+ 
+ static int virtio_ccw_balloon_init(VirtioCcwDevice *ccw_dev)
+@@ -896,7 +900,7 @@ static void virtio_ccw_balloon_instance_init(Object *obj)
+     VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+-
++    object_unref(OBJECT(&dev->vdev));
+     object_property_add(obj, "guest-stats", "guest statistics",
+                         balloon_ccw_stats_get_all, NULL, NULL, dev, NULL);
+ 
+@@ -936,6 +940,8 @@ static void virtio_ccw_scsi_instance_init(Object *obj)
+     VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ 
+ #ifdef CONFIG_VHOST_SCSI
+@@ -957,6 +963,8 @@ static void vhost_ccw_scsi_instance_init(Object *obj)
+     VHostSCSICcw *dev = VHOST_SCSI_CCW(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ #endif
+ 
+@@ -1374,8 +1382,6 @@ static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
+ static Property virtio_ccw_net_properties[] = {
+     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+     DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
+-    DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetCcw, vdev.net_conf),
+-    DEFINE_NIC_PROPERTIES(VirtIONetCcw, vdev.nic_conf),
+     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
+     DEFINE_PROP_END_OF_LIST(),
+@@ -1428,7 +1434,6 @@ static const TypeInfo virtio_ccw_blk = {
+ 
+ static Property virtio_ccw_serial_properties[] = {
+     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+-    DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtioSerialCcw, vdev.serial),
+     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
+     DEFINE_PROP_END_OF_LIST(),
+@@ -1481,7 +1486,6 @@ static const TypeInfo virtio_ccw_balloon = {
+ 
+ static Property virtio_ccw_scsi_properties[] = {
+     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.parent_obj.conf),
+     DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
+     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
+@@ -1510,7 +1514,6 @@ static const TypeInfo virtio_ccw_scsi = {
+ #ifdef CONFIG_VHOST_SCSI
+ static Property vhost_ccw_scsi_properties[] = {
+     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+-    DEFINE_VHOST_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.parent_obj.conf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -1539,6 +1542,8 @@ static void virtio_ccw_rng_instance_init(Object *obj)
+     VirtIORNGCcw *dev = VIRTIO_RNG_CCW(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
++    object_unref(OBJECT(&dev->vdev));
+     object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                              (Object **)&dev->vdev.conf.rng,
+                              qdev_prop_allow_set_link_before_realize,
+@@ -1547,7 +1552,6 @@ static void virtio_ccw_rng_instance_init(Object *obj)
+ 
+ static Property virtio_ccw_rng_properties[] = {
+     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+-    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGCcw, vdev.conf),
+     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
+     DEFINE_PROP_END_OF_LIST(),
+diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
+index 9971bbf..32849bd 100644
+--- a/hw/scsi/esp-pci.c
++++ b/hw/scsi/esp-pci.c
+@@ -268,6 +268,8 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
+     /* update status registers */
+     pci->dma_regs[DMA_WBC] -= len;
+     pci->dma_regs[DMA_WAC] += len;
++    if (pci->dma_regs[DMA_WBC] == 0)
++        pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
+ }
+ 
+ static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
 diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
-index ddfe76a..7146e0e 100644
+index ddfe76a..308b393 100644
 --- a/hw/scsi/vhost-scsi.c
 +++ b/hw/scsi/vhost-scsi.c
-@@ -238,6 +238,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
+@@ -23,6 +23,7 @@
+ #include "hw/virtio/vhost.h"
+ #include "hw/virtio/virtio-scsi.h"
+ #include "hw/virtio/virtio-bus.h"
++#include "hw/virtio/virtio-access.h"
+ 
+ /* Features supported by host kernel. */
+ static const int kernel_feature_bits[] = {
+@@ -163,8 +164,8 @@ static void vhost_scsi_set_config(VirtIODevice *vdev,
+     VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
+     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
+ 
+-    if ((uint32_t) ldl_p(&scsiconf->sense_size) != vs->sense_size ||
+-        (uint32_t) ldl_p(&scsiconf->cdb_size) != vs->cdb_size) {
++    if ((uint32_t) virtio_ldl_p(vdev, &scsiconf->sense_size) != vs->sense_size ||
++        (uint32_t) virtio_ldl_p(vdev, &scsiconf->cdb_size) != vs->cdb_size) {
+         error_report("vhost-scsi does not support changing the sense data and CDB sizes");
+         exit(1);
+     }
+@@ -238,6 +239,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
      s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
      s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs);
      s->dev.vq_index = 0;
@@ -1091,7 +2817,7 @@ index ddfe76a..7146e0e 100644
  
      ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
                           VHOST_BACKEND_TYPE_KERNEL, true);
-@@ -246,7 +247,6 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
+@@ -246,7 +248,6 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
                     strerror(-ret));
          return;
      }
@@ -1099,6 +2825,83 @@ index ddfe76a..7146e0e 100644
  
      error_setg(&s->migration_blocker,
              "vhost-scsi does not support migration");
+diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
+index 0eb069a..f7e77e9 100644
+--- a/hw/scsi/virtio-scsi.c
++++ b/hw/scsi/virtio-scsi.c
+@@ -135,6 +135,7 @@ static size_t qemu_sgl_concat(VirtIOSCSIReq *req, struct iovec *iov,
+ static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
+                                  unsigned req_size, unsigned resp_size)
+ {
++    VirtIODevice *vdev = (VirtIODevice *) req->dev;
+     size_t in_size, out_size;
+ 
+     if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
+@@ -147,8 +148,24 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
+                               resp_size) < resp_size) {
+         return -EINVAL;
+     }
++
+     req->resp_size = resp_size;
+ 
++    /* Old BIOSes left some padding by mistake after the req_size/resp_size.
++     * As a workaround, always consider the first buffer as the virtio-scsi
++     * request/response, making the payload start at the second element
++     * of the iovec.
++     *
++     * The actual length of the response header, stored in req->resp_size,
++     * does not change.
++     *
++     * TODO: always disable this workaround for virtio 1.0 devices.
++     */
++    if ((vdev->guest_features & VIRTIO_F_ANY_LAYOUT) == 0) {
++        req_size = req->elem.out_sg[0].iov_len;
++        resp_size = req->elem.in_sg[0].iov_len;
++    }
++
+     out_size = qemu_sgl_concat(req, req->elem.out_sg,
+                                &req->elem.out_addr[0], req->elem.out_num,
+                                req_size);
+@@ -400,7 +417,7 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
+         sense_len = scsi_req_get_sense(r, sense, sizeof(sense));
+         sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd));
+         qemu_iovec_from_buf(&req->resp_iov, sizeof(req->resp.cmd),
+-                            &req->resp, sense_len);
++                            sense, sense_len);
+         req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len);
+     }
+     virtio_scsi_complete_cmd_req(req);
+diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
+index 58c4b11..807e1ae 100644
+--- a/hw/usb/hcd-xhci.c
++++ b/hw/usb/hcd-xhci.c
+@@ -499,6 +499,7 @@ enum xhci_flags {
+     XHCI_FLAG_USE_MSI = 1,
+     XHCI_FLAG_USE_MSI_X,
+     XHCI_FLAG_SS_FIRST,
++    XHCI_FLAG_FORCE_PCIE_ENDCAP,
+ };
+ 
+ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
+@@ -3626,7 +3627,8 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
+                      PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
+                      &xhci->mem);
+ 
+-    if (pci_bus_is_express(dev->bus)) {
++    if (pci_bus_is_express(dev->bus) ||
++        xhci_get_flag(xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) {
+         ret = pcie_endpoint_cap_init(dev, 0xa0);
+         assert(ret >= 0);
+     }
+@@ -3818,6 +3820,8 @@ static Property xhci_properties[] = {
+     DEFINE_PROP_BIT("msix",     XHCIState, flags, XHCI_FLAG_USE_MSI_X, true),
+     DEFINE_PROP_BIT("superspeed-ports-first",
+                     XHCIState, flags, XHCI_FLAG_SS_FIRST, true),
++    DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags,
++                    XHCI_FLAG_FORCE_PCIE_ENDCAP, false),
+     DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS),
+     DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS),
+     DEFINE_PROP_UINT32("p2",    XHCIState, numports_2, 4),
 diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
 index e55fe1c..5d7c40a 100644
 --- a/hw/virtio/vhost.c
@@ -1119,6 +2922,240 @@ index e55fe1c..5d7c40a 100644
      assert(n >= hdev->vq_index && n < hdev->vq_index + hdev->nvqs);
  
      struct vhost_vring_file file = {
+diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
+index 2c30b3d..b5cf7ca 100644
+--- a/hw/virtio/virtio-balloon.c
++++ b/hw/virtio/virtio-balloon.c
+@@ -87,7 +87,7 @@ static void balloon_stats_destroy_timer(VirtIOBalloon *s)
+     }
+ }
+ 
+-static void balloon_stats_change_timer(VirtIOBalloon *s, int secs)
++static void balloon_stats_change_timer(VirtIOBalloon *s, int64_t secs)
+ {
+     timer_mod(s->stats_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + secs * 1000);
+ }
+@@ -170,6 +170,11 @@ static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v,
+         return;
+     }
+ 
++    if (value > UINT_MAX) {
++        error_setg(errp, "timer value is too big");
++        return;
++    }
++
+     if (value == s->stats_poll_interval) {
+         return;
+     }
+diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
+index 3007319..ba675fe 100644
+--- a/hw/virtio/virtio-pci.c
++++ b/hw/virtio/virtio-pci.c
+@@ -314,6 +314,16 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+             msix_unuse_all_vectors(&proxy->pci_dev);
+         }
+ 
++        /* Linux before 2.6.34 drives the device without enabling
++           the PCI device bus master bit. Enable it automatically
++           for the guest. This is a PCI spec violation but so is
++           initiating DMA with bus master bit clear. */
++        if (val == (VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER)) {
++            pci_default_write_config(&proxy->pci_dev, PCI_COMMAND,
++                                     proxy->pci_dev.config[PCI_COMMAND] |
++                                     PCI_COMMAND_MASTER, 1);
++        }
++
+         /* Linux before 2.6.34 sets the device as OK without enabling
+            the PCI device bus master bit. In this case we need to disable
+            some safety checks. */
+@@ -914,7 +924,6 @@ static Property virtio_9p_pci_properties[] = {
+     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+                     VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+-    DEFINE_VIRTIO_9P_PROPERTIES(V9fsPCIState, vdev.fsconf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -938,6 +947,8 @@ static void virtio_9p_pci_instance_init(Object *obj)
+     V9fsPCIState *dev = VIRTIO_9P_PCI(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_9P);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
++    object_unref(OBJECT(&dev->vdev));
+ }
+ 
+ static const TypeInfo virtio_9p_pci_info = {
+@@ -1127,7 +1138,6 @@ static Property virtio_scsi_pci_properties[] = {
+     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
+                        DEV_NVECTORS_UNSPECIFIED),
+     DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
+-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIPCI, vdev.parent_obj.conf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -1179,6 +1189,8 @@ static void virtio_scsi_pci_instance_init(Object *obj)
+     VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ 
+ static const TypeInfo virtio_scsi_pci_info = {
+@@ -1195,7 +1207,6 @@ static const TypeInfo virtio_scsi_pci_info = {
+ static Property vhost_scsi_pci_properties[] = {
+     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
+                        DEV_NVECTORS_UNSPECIFIED),
+-    DEFINE_VHOST_SCSI_PROPERTIES(VHostSCSIPCI, vdev.parent_obj.conf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -1235,6 +1246,8 @@ static void vhost_scsi_pci_instance_init(Object *obj)
+     VHostSCSIPCI *dev = VHOST_SCSI_PCI(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ 
+ static const TypeInfo vhost_scsi_pci_info = {
+@@ -1315,7 +1328,7 @@ static void virtio_balloon_pci_instance_init(Object *obj)
+     VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+-
++    object_unref(OBJECT(&dev->vdev));
+     object_property_add(obj, "guest-stats", "guest statistics",
+                         balloon_pci_stats_get_all, NULL, NULL, dev,
+                         NULL);
+@@ -1377,7 +1390,6 @@ static Property virtio_serial_pci_properties[] = {
+                     VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+     DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0),
+-    DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerialPCI, vdev.serial),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -1400,6 +1412,8 @@ static void virtio_serial_pci_instance_init(Object *obj)
+     VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
++    object_unref(OBJECT(&dev->vdev));
+ }
+ 
+ static const TypeInfo virtio_serial_pci_info = {
+@@ -1417,8 +1431,6 @@ static Property virtio_net_properties[] = {
+                     VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
+     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+     DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
+-    DEFINE_NIC_PROPERTIES(VirtIONetPCI, vdev.nic_conf),
+-    DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetPCI, vdev.net_conf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -1459,6 +1471,8 @@ static void virtio_net_pci_instance_init(Object *obj)
+     VirtIONetPCI *dev = VIRTIO_NET_PCI(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    object_unref(OBJECT(&dev->vdev));
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+ }
+ 
+ static const TypeInfo virtio_net_pci_info = {
+@@ -1472,7 +1486,6 @@ static const TypeInfo virtio_net_pci_info = {
+ /* virtio-rng-pci */
+ 
+ static Property virtio_rng_pci_properties[] = {
+-    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORngPCI, vdev.conf),
+     DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+@@ -1514,6 +1527,8 @@ static void virtio_rng_initfn(Object *obj)
+     VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
+     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
++    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
++    object_unref(OBJECT(&dev->vdev));
+     object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                              (Object **)&dev->vdev.conf.rng,
+                              qdev_prop_allow_set_link_before_realize,
+diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
+index a2dff5a..e60ff90 100644
+--- a/hw/xtensa/xtfpga.c
++++ b/hw/xtensa/xtfpga.c
+@@ -325,7 +325,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
+         } else {
+             hwaddr ep;
+             int is_linux;
+-            success = load_uimage(kernel_filename, &ep, NULL, &is_linux);
++            success = load_uimage(kernel_filename, &ep, NULL, &is_linux,
++                                  translate_phys_addr, cpu);
+             if (success > 0 && is_linux) {
+                 entry_point = ep;
+             } else {
+diff --git a/include/block/block_int.h b/include/block/block_int.h
+index 7b541a0..21b8718 100644
+--- a/include/block/block_int.h
++++ b/include/block/block_int.h
+@@ -395,6 +395,14 @@ struct BlockDriverState {
+     Error *backing_blocker;
+ };
+ 
++
++/* Essential block drivers which must always be statically linked into qemu, and
++ * which therefore can be accessed without using bdrv_find_format() */
++extern BlockDriver bdrv_file;
++extern BlockDriver bdrv_raw;
++extern BlockDriver bdrv_qcow2;
++
++
+ int get_tmp_filename(char *filename, int size);
+ 
+ void bdrv_set_io_limits(BlockDriverState *bs,
+diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
+index 6593be1..e50e71c 100644
+--- a/include/exec/ram_addr.h
++++ b/include/exec/ram_addr.h
+@@ -49,6 +49,21 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
+     return next < end;
+ }
+ 
++static inline bool cpu_physical_memory_get_clean(ram_addr_t start,
++                                                 ram_addr_t length,
++                                                 unsigned client)
++{
++    unsigned long end, page, next;
++
++    assert(client < DIRTY_MEMORY_NUM);
++
++    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
++    page = start >> TARGET_PAGE_BITS;
++    next = find_next_zero_bit(ram_list.dirty_memory[client], end, page);
++
++    return next < end;
++}
++
+ static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
+                                                       unsigned client)
+ {
+@@ -64,6 +79,16 @@ static inline bool cpu_physical_memory_is_clean(ram_addr_t addr)
+     return !(vga && code && migration);
+ }
+ 
++static inline bool cpu_physical_memory_range_includes_clean(ram_addr_t start,
++                                                            ram_addr_t length)
++{
++    bool vga = cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_VGA);
++    bool code = cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_CODE);
++    bool migration =
++        cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_MIGRATION);
++    return vga || code || migration;
++}
++
+ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
+                                                       unsigned client)
+ {
 diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h
 index bf5157d..b9db295 100644
 --- a/include/hw/acpi/pc-hotplug.h
@@ -1133,7 +3170,7 @@ index bf5157d..b9db295 100644
  #define MEMORY_HOTPLUG_IO_REGION     HPMR
  #define MEMORY_SLOT_ADDR_LOW         MRBL
 diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
-index f4b9b2b..5f0a265 100644
+index f4b9b2b..b558875 100644
 --- a/include/hw/i386/pc.h
 +++ b/include/hw/i386/pc.h
 @@ -177,6 +177,8 @@ void pc_acpi_init(const char *default_dsdt);
@@ -1142,9 +3179,259 @@ index f4b9b2b..5f0a265 100644
  
 +void pc_set_legacy_acpi_data_size(void);
 +
- #define PCI_HOST_PROP_PCI_HOLE_START   "pci-hole-start"
- #define PCI_HOST_PROP_PCI_HOLE_END     "pci-hole-end"
- #define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start"
+ #define PCI_HOST_PROP_PCI_HOLE_START   "pci-hole-start"
+ #define PCI_HOST_PROP_PCI_HOLE_END     "pci-hole-end"
+ #define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start"
+@@ -316,6 +318,11 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
+             .value    = "off",\
+         },\
+         {\
++            .driver   = "nec-usb-xhci",\
++            .property = "force-pcie-endcap",\
++            .value    = "on",\
++        },\
++        {\
+             .driver   = "pci-serial",\
+             .property = "prog_if",\
+             .value    = stringify(0),\
+diff --git a/include/hw/loader.h b/include/hw/loader.h
+index 796cbf9..11b6b5a 100644
+--- a/include/hw/loader.h
++++ b/include/hw/loader.h
+@@ -28,7 +28,9 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
+ int load_aout(const char *filename, hwaddr addr, int max_sz,
+               int bswap_needed, hwaddr target_page_size);
+ int load_uimage(const char *filename, hwaddr *ep,
+-                hwaddr *loadaddr, int *is_linux);
++                hwaddr *loadaddr, int *is_linux,
++                uint64_t (*translate_fn)(void *, uint64_t),
++                void *translate_opaque);
+ 
+ /**
+  * load_ramdisk:
+diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
+index 32f0aa7..4ea2a0d 100644
+--- a/include/hw/pci-host/spapr.h
++++ b/include/hw/pci-host/spapr.h
+@@ -70,7 +70,7 @@ struct sPAPRPHBState {
+ 
+     MemoryRegion memspace, iospace;
+     hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size;
+-    MemoryRegion memwindow, iowindow;
++    MemoryRegion memwindow, iowindow, msiwindow;
+ 
+     uint32_t dma_liobn;
+     AddressSpace iommu_as;
+diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
+index bbba51a..832ad6b 100644
+--- a/include/hw/ppc/spapr.h
++++ b/include/hw/ppc/spapr.h
+@@ -13,8 +13,6 @@ struct sPAPRNVRAM;
+ typedef struct sPAPREnvironment {
+     struct VIOsPAPRBus *vio_bus;
+     QLIST_HEAD(, sPAPRPHBState) phbs;
+-    hwaddr msi_win_addr;
+-    MemoryRegion msiwindow;
+     struct sPAPRNVRAM *nvram;
+     XICSState *icp;
+ 
+diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
+index ecc0183..09bb0fd 100644
+--- a/include/qapi/visitor-impl.h
++++ b/include/qapi/visitor-impl.h
+@@ -55,6 +55,8 @@ struct Visitor
+     void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
+     /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */
+     void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
++    bool (*start_union)(Visitor *v, bool data_present, Error **errp);
++    void (*end_union)(Visitor *v, bool data_present, Error **errp);
+ };
+ 
+ void input_type_enum(Visitor *v, int *obj, const char *strings[],
+diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
+index 4a0178f..5934f59 100644
+--- a/include/qapi/visitor.h
++++ b/include/qapi/visitor.h
+@@ -58,5 +58,7 @@ void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+ void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
+ void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
+ void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
++bool visit_start_union(Visitor *v, bool data_present, Error **errp);
++void visit_end_union(Visitor *v, bool data_present, Error **errp);
+ 
+ #endif
+diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
+index 492bce1..93c2ae2 100644
+--- a/include/qemu/atomic.h
++++ b/include/qemu/atomic.h
+@@ -122,11 +122,11 @@
+ #endif
+ 
+ #ifndef atomic_read
+-#define atomic_read(ptr)       (*(__typeof__(*ptr) *volatile) (ptr))
++#define atomic_read(ptr)       (*(__typeof__(*ptr) volatile*) (ptr))
+ #endif
+ 
+ #ifndef atomic_set
+-#define atomic_set(ptr, i)     ((*(__typeof__(*ptr) *volatile) (ptr)) = (i))
++#define atomic_set(ptr, i)     ((*(__typeof__(*ptr) volatile*) (ptr)) = (i))
+ #endif
+ 
+ /* These have the same semantics as Java volatile variables.
+diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
+index 4f79081..3f162a9 100644
+--- a/include/sysemu/cpus.h
++++ b/include/sysemu/cpus.h
+@@ -10,6 +10,7 @@ void cpu_stop_current(void);
+ void cpu_synchronize_all_states(void);
+ void cpu_synchronize_all_post_reset(void);
+ void cpu_synchronize_all_post_init(void);
++void cpu_clean_all_dirty(void);
+ 
+ void qtest_clock_warp(int64_t dest);
+ 
+diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
+index 174ea36..777dc66 100644
+--- a/include/sysemu/kvm.h
++++ b/include/sysemu/kvm.h
+@@ -348,6 +348,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
+ void kvm_cpu_synchronize_state(CPUState *cpu);
+ void kvm_cpu_synchronize_post_reset(CPUState *cpu);
+ void kvm_cpu_synchronize_post_init(CPUState *cpu);
++void kvm_cpu_clean_state(CPUState *cpu);
+ 
+ /* generic hooks - to be moved/refactored once there are more users */
+ 
+@@ -372,6 +373,13 @@ static inline void cpu_synchronize_post_init(CPUState *cpu)
+     }
+ }
+ 
++static inline void cpu_clean_state(CPUState *cpu)
++{
++    if (kvm_enabled()) {
++        kvm_cpu_clean_state(cpu);
++    }
++}
++
+ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
+ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
+ void kvm_irqchip_release_virq(KVMState *s, int virq);
+diff --git a/kvm-all.c b/kvm-all.c
+index 1402f4f..c8f9bca 100644
+--- a/kvm-all.c
++++ b/kvm-all.c
+@@ -617,8 +617,10 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
+     unsigned delta;
+ 
+     /* kvm works in page size chunks, but the function may be called
+-       with sub-page size and unaligned start address. */
+-    delta = TARGET_PAGE_ALIGN(size) - size;
++       with sub-page size and unaligned start address. Pad the start
++       address to next and truncate size to previous page boundary. */
++    delta = (TARGET_PAGE_SIZE - (start_addr & ~TARGET_PAGE_MASK));
++    delta &= ~TARGET_PAGE_MASK;
+     if (delta > size) {
+         return;
+     }
+@@ -1681,6 +1683,11 @@ void kvm_cpu_synchronize_post_init(CPUState *cpu)
+     cpu->kvm_vcpu_dirty = false;
+ }
+ 
++void kvm_cpu_clean_state(CPUState *cpu)
++{
++    cpu->kvm_vcpu_dirty = false;
++}
++
+ int kvm_cpu_exec(CPUState *cpu)
+ {
+     struct kvm_run *run = cpu->kvm_run;
+diff --git a/libcacard/cac.c b/libcacard/cac.c
+index ae8c378..f38fdce 100644
+--- a/libcacard/cac.c
++++ b/libcacard/cac.c
+@@ -115,6 +115,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+     VCardAppletPrivate *applet_private;
+     int size, next;
+     unsigned char *sign_buffer;
++    bool retain_sign_buffer = FALSE;
+     vcard_7816_status_t status;
+     VCardStatus ret = VCARD_FAIL;
+ 
+@@ -178,6 +179,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+             pki_applet->sign_buffer = sign_buffer;
+             pki_applet->sign_buffer_len = size;
+             *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
++            retain_sign_buffer = TRUE;
+             break;
+         case 0x00:
+             /* we now have the whole buffer, do the operation, result will be
+@@ -200,9 +202,11 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+                                 VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+             break;
+         }
+-        g_free(sign_buffer);
+-        pki_applet->sign_buffer = NULL;
+-        pki_applet->sign_buffer_len = 0;
++        if (!retain_sign_buffer) {
++            g_free(sign_buffer);
++            pki_applet->sign_buffer = NULL;
++            pki_applet->sign_buffer_len = 0;
++        }
+         ret = VCARD_DONE;
+         break;
+     case CAC_READ_BUFFER:
+diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
+index 80111df..fa6041d 100644
+--- a/libcacard/vscclient.c
++++ b/libcacard/vscclient.c
+@@ -597,7 +597,7 @@ connect_to_qemu(
+     const char *port
+ ) {
+     struct addrinfo hints;
+-    struct addrinfo *server;
++    struct addrinfo *server = NULL;
+     int ret, sock;
+ 
+     sock = socket(AF_INET, SOCK_STREAM, 0);
+@@ -629,9 +629,14 @@ connect_to_qemu(
+     if (verbose) {
+         printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
+     }
++
++    freeaddrinfo(server);
+     return sock;
+ 
+ cleanup_socket:
++    if (server) {
++        freeaddrinfo(server);
++    }
+     closesocket(sock);
+     return -1;
+ }
+diff --git a/monitor.c b/monitor.c
+index 5bc70a6..1ae32c0 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -5243,6 +5243,7 @@ static void monitor_event(void *opaque, int event)
+         monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
+                        "information\n", QEMU_VERSION);
+         if (!mon->mux_out) {
++            readline_restart(mon->rs);
+             readline_show_prompt(mon->rs);
+         }
+         mon->reset_seen = 1;
+diff --git a/net/l2tpv3.c b/net/l2tpv3.c
+index 528d95b..65db5ef 100644
+--- a/net/l2tpv3.c
++++ b/net/l2tpv3.c
+@@ -660,7 +660,6 @@ int net_init_l2tpv3(const NetClientOptions *opts,
+     if (fd == -1) {
+         fd = -errno;
+         error_report("l2tpv3_open : socket creation failed, errno = %d", -fd);
+-        freeaddrinfo(result);
+         goto outerr;
+     }
+     if (bind(fd, (struct sockaddr *) result->ai_addr, result->ai_addrlen)) {
 diff --git a/net/net.c b/net/net.c
 index 6d930ea..7acc162 100644
 --- a/net/net.c
@@ -1276,6 +3563,213 @@ index 7bf7834..c78cec9 100644
                           numa_total, ram_size);
              exit(1);
          }
+diff --git a/pc-bios/optionrom/linuxboot.S b/pc-bios/optionrom/linuxboot.S
+index 748c831..ba821ab 100644
+--- a/pc-bios/optionrom/linuxboot.S
++++ b/pc-bios/optionrom/linuxboot.S
+@@ -76,14 +76,71 @@ boot_kernel:
+ 
+ 
+ copy_kernel:
+-
++	/* Read info block in low memory (0x10000 or 0x90000) */
++	read_fw		FW_CFG_SETUP_ADDR
++	shr		$4, %eax
++	mov		%eax, %es
++	xor		%edi, %edi
++	read_fw_blob_addr32_edi(FW_CFG_SETUP)
++
++	cmpw            $0x203, %es:0x206      // if protocol >= 0x203
++	jae             1f                     // have initrd_max
++	movl            $0x37ffffff, %es:0x22c // else assume 0x37ffffff
++1:
++
++	/* Check if using kernel-specified initrd address */
++	read_fw		FW_CFG_INITRD_ADDR
++	mov		%eax, %edi             // (load_kernel wants it in %edi)
++	read_fw		FW_CFG_INITRD_SIZE     // find end of initrd
++	add		%edi, %eax
++	xor		%es:0x22c, %eax        // if it matches es:0x22c
++	and		$-4096, %eax           // (apart from padding for page)
++	jz		load_kernel            // then initrd is not at top
++					       // of memory
++
++	/* pc.c placed the initrd at end of memory.  Compute a better
++	 * initrd address based on e801 data.
++	 */
++	mov		$0xe801, %ax
++	xor		%cx, %cx
++	xor		%dx, %dx
++	int		$0x15
++
++	/* Output could be in AX/BX or CX/DX */
++	or		%cx, %cx
++	jnz		1f
++	or		%dx, %dx
++	jnz		1f
++	mov		%ax, %cx
++	mov		%bx, %dx
++1:
++
++	or		%dx, %dx
++	jnz		2f
++	addw		$1024, %cx            /* add 1 MB */
++	movzwl		%cx, %edi
++	shll		$10, %edi             /* convert to bytes */
++	jmp		3f
++
++2:
++	addw		$16777216 >> 16, %dx  /* add 16 MB */
++	movzwl		%dx, %edi
++	shll		$16, %edi             /* convert to bytes */
++
++3:
++	read_fw         FW_CFG_INITRD_SIZE
++	subl            %eax, %edi
++	andl            $-4096, %edi          /* EDI = start of initrd */
++	movl		%edi, %es:0x218       /* put it in the header */
++
++load_kernel:
+ 	/* We need to load the kernel into memory we can't access in 16 bit
+ 	   mode, so let's get into 32 bit mode, write the kernel and jump
+ 	   back again. */
+ 
+ 	/* Reserve space on the stack for our GDT descriptor. */
+-	mov		%esp, %ebp
+-	sub		$16, %esp
++	mov             %esp, %ebp
++	sub             $16, %esp
+ 
+ 	/* Now create the GDT descriptor */
+ 	movw		$((3 * 8) - 1), -16(%bp)
+@@ -108,10 +165,9 @@ copy_kernel:
+ 	/* We're now running in 16-bit CS, but 32-bit ES! */
+ 
+ 	/* Load kernel and initrd */
++	read_fw_blob_addr32_edi(FW_CFG_INITRD)
+ 	read_fw_blob_addr32(FW_CFG_KERNEL)
+-	read_fw_blob_addr32(FW_CFG_INITRD)
+ 	read_fw_blob_addr32(FW_CFG_CMDLINE)
+-	read_fw_blob_addr32(FW_CFG_SETUP)
+ 
+ 	/* And now jump into Linux! */
+ 	mov		$0, %eax
+diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
+index ce43608..f1a9021 100644
+--- a/pc-bios/optionrom/optionrom.h
++++ b/pc-bios/optionrom/optionrom.h
+@@ -51,8 +51,6 @@
+ .endm
+ 
+ #define read_fw_blob_pre(var)				\
+-	read_fw		var ## _ADDR;			\
+-	mov		%eax, %edi;			\
+ 	read_fw		var ## _SIZE;			\
+ 	mov		%eax, %ecx;			\
+ 	mov		$var ## _DATA, %ax;		\
+@@ -68,6 +66,8 @@
+  * Clobbers:	%eax, %edx, %es, %ecx, %edi
+  */
+ #define read_fw_blob(var)				\
++	read_fw		var ## _ADDR;			\
++	mov		%eax, %edi;			\
+ 	read_fw_blob_pre(var);				\
+ 	/* old as(1) doesn't like this insn so emit the bytes instead: \
+ 	rep insb	(%dx), %es:(%edi);		\
+@@ -80,7 +80,22 @@
+  *
+  * Clobbers:	%eax, %edx, %es, %ecx, %edi
+  */
+-#define read_fw_blob_addr32(var)				\
++#define read_fw_blob_addr32(var)			\
++	read_fw		var ## _ADDR;			\
++	mov		%eax, %edi;			\
++	read_fw_blob_pre(var);				\
++	/* old as(1) doesn't like this insn so emit the bytes instead: \
++	addr32 rep insb	(%dx), %es:(%edi);		\
++	*/						\
++	.dc.b		0x67,0xf3,0x6c
++
++/*
++ * Read a blob from the fw_cfg device in forced addr32 mode, address is in %edi.
++ * Requires _SIZE and _DATA values for the parameter.
++ *
++ * Clobbers:	%eax, %edx, %edi, %es, %ecx
++ */
++#define read_fw_blob_addr32_edi(var)			\
+ 	read_fw_blob_pre(var);				\
+ 	/* old as(1) doesn't like this insn so emit the bytes instead: \
+ 	addr32 rep insb	(%dx), %es:(%edi);		\
+diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
+index dc53545..a14a1c7 100644
+--- a/qapi/qapi-dealloc-visitor.c
++++ b/qapi/qapi-dealloc-visitor.c
+@@ -162,6 +162,31 @@ static void qapi_dealloc_type_enum(Visitor *v, int *obj, const char *strings[],
+ {
+ }
+ 
++/* If there's no data present, the dealloc visitor has nothing to free.
++ * Thus, indicate to visitor code that the subsequent union fields can
++ * be skipped. This is not an error condition, since the cleanup of the
++ * rest of an object can continue unhindered, so leave errp unset in
++ * these cases.
++ *
++ * NOTE: In cases where we're attempting to deallocate an object that
++ * may have missing fields, the field indicating the union type may
++ * be missing. In such a case, it's possible we don't have enough
++ * information to differentiate data_present == false from a case where
++ * data *is* present but happens to be a scalar with a value of 0.
++ * This is okay, since in the case of the dealloc visitor there's no
++ * work that needs to done in either situation.
++ *
++ * The current inability in QAPI code to more thoroughly verify a union
++ * type in such cases will likely need to be addressed if we wish to
++ * implement this interface for other types of visitors in the future,
++ * however.
++ */
++static bool qapi_dealloc_start_union(Visitor *v, bool data_present,
++                                     Error **errp)
++{
++    return data_present;
++}
++
+ Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
+ {
+     return &v->visitor;
+@@ -191,6 +216,7 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
+     v->visitor.type_str = qapi_dealloc_type_str;
+     v->visitor.type_number = qapi_dealloc_type_number;
+     v->visitor.type_size = qapi_dealloc_type_size;
++    v->visitor.start_union = qapi_dealloc_start_union;
+ 
+     QTAILQ_INIT(&v->stack);
+ 
+diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
+index 55f8d40..b66b93a 100644
+--- a/qapi/qapi-visit-core.c
++++ b/qapi/qapi-visit-core.c
+@@ -58,6 +58,21 @@ void visit_end_list(Visitor *v, Error **errp)
+     v->end_list(v, errp);
+ }
+ 
++bool visit_start_union(Visitor *v, bool data_present, Error **errp)
++{
++    if (v->start_union) {
++        return v->start_union(v, data_present, errp);
++    }
++    return true;
++}
++
++void visit_end_union(Visitor *v, bool data_present, Error **errp)
++{
++    if (v->end_union) {
++        v->end_union(v, data_present, errp);
++    }
++}
++
+ void visit_optional(Visitor *v, bool *present, const char *name,
+                     Error **errp)
+ {
 diff --git a/qdev-monitor.c b/qdev-monitor.c
 index f87f3d8..5fe5e75 100644
 --- a/qdev-monitor.c
@@ -1358,6 +3852,45 @@ index 956be49..2abb330 100644
      }
      return io_channel_send(s->fd, buf, len);
  }
+diff --git a/qemu-img.c b/qemu-img.c
+index d4518e7..27ac1fc 100644
+--- a/qemu-img.c
++++ b/qemu-img.c
+@@ -1378,6 +1378,20 @@ static int img_convert(int argc, char **argv)
+         goto out;
+     }
+ 
++    if (!drv->create_opts) {
++        error_report("Format driver '%s' does not support image creation",
++                     drv->format_name);
++        ret = -1;
++        goto out;
++    }
++
++    if (!proto_drv->create_opts) {
++        error_report("Protocol driver '%s' does not support image creation",
++                     proto_drv->format_name);
++        ret = -1;
++        goto out;
++    }
++
+     create_opts = qemu_opts_append(create_opts, drv->create_opts);
+     create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
+ 
+@@ -2761,6 +2775,13 @@ static int img_amend(int argc, char **argv)
+         goto out;
+     }
+ 
++    if (!bs->drv->create_opts) {
++        error_report("Format driver '%s' does not support any options to amend",
++                     fmt);
++        ret = -1;
++        goto out;
++    }
++
+     create_opts = qemu_opts_append(create_opts, bs->drv->create_opts);
+     opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+     if (options && qemu_opts_do_parse(opts, options, NULL)) {
 diff --git a/qmp.c b/qmp.c
 index 0d2553a..c6767c4 100644
 --- a/qmp.c
@@ -1370,6 +3903,59 @@ index 0d2553a..c6767c4 100644
              strcmp(prop->name, "parent_bus") == 0) {
              continue;
          }
+diff --git a/savevm.c b/savevm.c
+index e19ae0a..2d8eb96 100644
+--- a/savevm.c
++++ b/savevm.c
+@@ -1245,19 +1245,18 @@ int load_vmstate(const char *name)
+ 
+ void do_delvm(Monitor *mon, const QDict *qdict)
+ {
+-    BlockDriverState *bs, *bs1;
++    BlockDriverState *bs;
+     Error *err = NULL;
+     const char *name = qdict_get_str(qdict, "name");
+ 
+-    bs = find_vmstate_bs();
+-    if (!bs) {
++    if (!find_vmstate_bs()) {
+         monitor_printf(mon, "No block device supports snapshots\n");
+         return;
+     }
+ 
+-    bs1 = NULL;
+-    while ((bs1 = bdrv_next(bs1))) {
+-        if (bdrv_can_snapshot(bs1)) {
++    bs = NULL;
++    while ((bs = bdrv_next(bs))) {
++        if (bdrv_can_snapshot(bs)) {
+             bdrv_snapshot_delete_by_id_or_name(bs, name, &err);
+             if (err) {
+                 monitor_printf(mon,
+diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
+index c129697..cfce31b 100644
+--- a/scripts/qapi-visit.py
++++ b/scripts/qapi-visit.py
+@@ -357,6 +357,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
+         if (err) {
+             goto out_obj;
+         }
++        if (!visit_start_union(m, !!(*obj)->data, &err) || err) {
++            goto out_obj;
++        }
+         switch ((*obj)->kind) {
+ ''',
+                  disc_type = disc_type,
+@@ -385,6 +388,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
+ out_obj:
+         error_propagate(errp, err);
+         err = NULL;
++        visit_end_union(m, !!(*obj)->data, &err);
++        error_propagate(errp, err);
++        err = NULL;
+     }
+     visit_end_struct(m, &err);
+ out:
 diff --git a/slirp/udp.c b/slirp/udp.c
 index 8cc6cb6..f77e00f 100644
 --- a/slirp/udp.c
@@ -1792,6 +4378,821 @@ index 16d2f6a..fb89065 100644
          /* KVM-related states */
          VMSTATE_INT32_V(env.interrupt_injected, X86CPU, 9),
          VMSTATE_UINT32_V(env.mp_state, X86CPU, 9),
+diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
+index d797d26..6e4e2b2 100644
+--- a/target-xtensa/cpu.h
++++ b/target-xtensa/cpu.h
+@@ -471,6 +471,12 @@ static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env,
+         env->itlb[wi] + ei;
+ }
+ 
++static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env)
++{
++    return env->sregs[WINDOW_START] |
++        (env->sregs[WINDOW_START] << env->config->nareg / 4);
++}
++
+ /* MMU modes definitions */
+ #define MMU_MODE0_SUFFIX _ring0
+ #define MMU_MODE1_SUFFIX _ring1
+diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
+index dae1386..872e5a8 100644
+--- a/target-xtensa/op_helper.c
++++ b/target-xtensa/op_helper.c
+@@ -235,6 +235,12 @@ void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
+                 pc, env->sregs[PS]);
+         HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE);
+     } else {
++        uint32_t windowstart = xtensa_replicate_windowstart(env) >>
++            (env->sregs[WINDOW_BASE] + 1);
++
++        if (windowstart & ((1 << callinc) - 1)) {
++            HELPER(window_check)(env, pc, callinc);
++        }
+         env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - (imm << 3);
+         rotate_window(env, callinc);
+         env->sregs[WINDOW_START] |=
+diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
+index 2f22cce..ff7eb23 100644
+--- a/target-xtensa/translate.c
++++ b/target-xtensa/translate.c
+@@ -884,6 +884,11 @@ static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
+     return m;
+ }
+ 
++static inline unsigned xtensa_op0_insn_len(unsigned op0)
++{
++    return op0 >= 8 ? 2 : 3;
++}
++
+ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
+ {
+ #define HAS_OPTION_BITS(opt) do { \
+@@ -986,6 +991,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
+     uint8_t b0 = cpu_ldub_code(env, dc->pc);
+     uint8_t b1 = cpu_ldub_code(env, dc->pc + 1);
+     uint8_t b2 = 0;
++    unsigned len = xtensa_op0_insn_len(OP0);
+ 
+     static const uint32_t B4CONST[] = {
+         0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
+@@ -995,13 +1001,19 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
+         32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
+     };
+ 
+-    if (OP0 >= 8) {
+-        dc->next_pc = dc->pc + 2;
++    switch (len) {
++    case 2:
+         HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
+-    } else {
+-        dc->next_pc = dc->pc + 3;
++        break;
++
++    case 3:
+         b2 = cpu_ldub_code(env, dc->pc + 2);
++        break;
++
++    default:
++        RESERVED();
+     }
++    dc->next_pc = dc->pc + len;
+ 
+     switch (OP0) {
+     case 0: /*QRST*/
+@@ -2946,6 +2958,12 @@ invalid_opcode:
+ #undef HAS_OPTION
+ }
+ 
++static inline unsigned xtensa_insn_len(CPUXtensaState *env, DisasContext *dc)
++{
++    uint8_t b0 = cpu_ldub_code(env, dc->pc);
++    return xtensa_op0_insn_len(OP0);
++}
++
+ static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
+ {
+     CPUState *cs = CPU(xtensa_env_get_cpu(env));
+@@ -3078,6 +3096,7 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
+     } while (dc.is_jmp == DISAS_NEXT &&
+             insn_count < max_insns &&
+             dc.pc < next_page_start &&
++            dc.pc + xtensa_insn_len(env, &dc) <= next_page_start &&
+             tcg_ctx.gen_opc_ptr < gen_opc_end);
+ 
+     reset_litbase(&dc);
+diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
+index 9cce356..b7f4d67 100644
+--- a/tcg/mips/tcg-target.c
++++ b/tcg/mips/tcg-target.c
+@@ -1302,7 +1302,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
+        so we can reuse that for the base.  */
+     base = (TARGET_LONG_BITS == 32 ? TCG_REG_A1 : TCG_REG_A2);
+     tcg_out_tlb_load(s, base, addr_regl, addr_regh, mem_index,
+-                     s_bits, label_ptr, 1);
++                     s_bits, label_ptr, 0);
+     tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
+     add_qemu_ldst_label(s, 0, opc, data_regl, data_regh, addr_regl, addr_regh,
+                         mem_index, s->code_ptr, label_ptr);
+diff --git a/tests/Makefile b/tests/Makefile
+index 4b2e1bb..2ea54fc 100644
+--- a/tests/Makefile
++++ b/tests/Makefile
+@@ -187,7 +187,8 @@ check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
+ 
+ # qom-test works for all sysemu architectures:
+ $(foreach target,$(SYSEMU_TARGET_LIST), \
+-    $(eval check-qtest-$(target)-y += tests/qom-test$(EXESUF)))
++	$(if $(findstring tests/qom-test$(EXESUF), $(check-qtest-$(target)-y)),, \
++		$(eval check-qtest-$(target)-y += tests/qom-test$(EXESUF))))
+ 
+ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
+         comments.json empty.json funny-char.json indented-expr.json \
+diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
+index ab4d3d9..d43b5fd 100644
+--- a/tests/qapi-schema/qapi-schema-test.json
++++ b/tests/qapi-schema/qapi-schema-test.json
+@@ -33,6 +33,9 @@
+ { 'type': 'UserDefB',
+   'data': { 'integer': 'int' } }
+ 
++{ 'type': 'UserDefC',
++  'data': { 'string1': 'str', 'string2': 'str' } }
++
+ { 'union': 'UserDefUnion',
+   'base': 'UserDefZero',
+   'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } }
+@@ -47,6 +50,13 @@
+ # FIXME generated struct UserDefFlatUnion has members for direct base
+ # UserDefOne, but lacks members for indirect base UserDefZero
+ 
++# this variant of UserDefFlatUnion defaults to a union that uses fields with
++# allocated types to test corner cases in the cleanup/dealloc visitor
++{ 'union': 'UserDefFlatUnion2',
++  'base': 'UserDefUnionBase',
++  'discriminator': 'enum1',
++  'data': { 'value1' : 'UserDefC', 'value2' : 'UserDefB', 'value3' : 'UserDefA' } }
++
+ { 'union': 'UserDefAnonUnion',
+   'discriminator': {},
+   'data': { 'uda': 'UserDefA', 's': 'str', 'i': 'int' } }
+diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
+index 95e9899..08d7304 100644
+--- a/tests/qapi-schema/qapi-schema-test.out
++++ b/tests/qapi-schema/qapi-schema-test.out
+@@ -6,9 +6,11 @@
+  OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]),
+  OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
+  OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
++ OrderedDict([('type', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]),
+  OrderedDict([('union', 'UserDefUnion'), ('base', 'UserDefZero'), ('data', OrderedDict([('a', 'UserDefA'), ('b', 'UserDefB')]))]),
+  OrderedDict([('type', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
+  OrderedDict([('union', 'UserDefFlatUnion'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefA'), ('value2', 'UserDefB'), ('value3', 'UserDefB')]))]),
++ OrderedDict([('union', 'UserDefFlatUnion2'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefC'), ('value2', 'UserDefB'), ('value3', 'UserDefA')]))]),
+  OrderedDict([('union', 'UserDefAnonUnion'), ('discriminator', OrderedDict()), ('data', OrderedDict([('uda', 'UserDefA'), ('s', 'str'), ('i', 'int')]))]),
+  OrderedDict([('union', 'UserDefNativeListUnion'), ('data', OrderedDict([('integer', ['int']), ('s8', ['int8']), ('s16', ['int16']), ('s32', ['int32']), ('s64', ['int64']), ('u8', ['uint8']), ('u16', ['uint16']), ('u32', ['uint32']), ('u64', ['uint64']), ('number', ['number']), ('boolean', ['bool']), ('string', ['str'])]))]),
+  OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]),
+@@ -32,6 +34,7 @@
+  OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]),
+  OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
+  OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
++ OrderedDict([('type', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]),
+  OrderedDict([('type', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
+  OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
+  OrderedDict([('type', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))])]
+diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
+index f7c78e7..ad84ac2 100644
+--- a/tests/qemu-iotests/026.out
++++ b/tests/qemu-iotests/026.out
+@@ -14,6 +14,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_update; errno: 5; imm: off; once: off; write 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ 
+ 1 leaked clusters were found on the image.
+@@ -21,6 +23,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_update; errno: 5; imm: off; once: off; write -b
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ 
+ 1 leaked clusters were found on the image.
+@@ -38,6 +42,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_update; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 1 leaked clusters were found on the image.
+@@ -45,6 +51,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_update; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 1 leaked clusters were found on the image.
+@@ -70,7 +78,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+ Event: l2_load; errno: 5; imm: off; once: off; write 
+ wrote 131072/131072 bytes at offset 0
+ 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ read failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -78,7 +90,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+ Event: l2_load; errno: 5; imm: off; once: off; write -b
+ wrote 131072/131072 bytes at offset 0
+ 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ read failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -102,7 +118,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+ Event: l2_load; errno: 28; imm: off; once: off; write 
+ wrote 131072/131072 bytes at offset 0
+ 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ read failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -110,12 +130,17 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+ Event: l2_load; errno: 28; imm: off; once: off; write -b
+ wrote 131072/131072 bytes at offset 0
+ 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ read failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_update; errno: 5; imm: off; once: on; write 
++Failed to flush the L2 table cache: Input/output error
+ write failed: Input/output error
+ 
+ 127 leaked clusters were found on the image.
+@@ -123,6 +148,7 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_update; errno: 5; imm: off; once: on; write -b
++Failed to flush the L2 table cache: Input/output error
+ write failed: Input/output error
+ 
+ 127 leaked clusters were found on the image.
+@@ -130,6 +156,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_update; errno: 5; imm: off; once: off; write 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ 
+ 127 leaked clusters were found on the image.
+@@ -137,6 +165,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_update; errno: 5; imm: off; once: off; write -b
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ 
+ 127 leaked clusters were found on the image.
+@@ -144,6 +174,7 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_update; errno: 28; imm: off; once: on; write 
++Failed to flush the L2 table cache: No space left on device
+ write failed: No space left on device
+ 
+ 127 leaked clusters were found on the image.
+@@ -151,6 +182,7 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_update; errno: 28; imm: off; once: on; write -b
++Failed to flush the L2 table cache: No space left on device
+ write failed: No space left on device
+ 
+ 127 leaked clusters were found on the image.
+@@ -158,6 +190,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_update; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 127 leaked clusters were found on the image.
+@@ -165,6 +199,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_update; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 127 leaked clusters were found on the image.
+@@ -182,11 +218,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_alloc.write; errno: 5; imm: off; once: off; write 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_alloc.write; errno: 5; imm: off; once: off; write -b
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ 
+ 1 leaked clusters were found on the image.
+@@ -204,11 +244,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_alloc.write; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l2_alloc.write; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 1 leaked clusters were found on the image.
+@@ -226,11 +270,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: write_aio; errno: 5; imm: off; once: off; write 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: write_aio; errno: 5; imm: off; once: off; write -b
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -246,11 +294,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: write_aio; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: write_aio; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -266,11 +318,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_load; errno: 5; imm: off; once: off; write 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_load; errno: 5; imm: off; once: off; write -b
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -286,51 +342,67 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_load; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_load; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_update_part; errno: 5; imm: off; once: on; write 
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_update_part; errno: 5; imm: off; once: on; write -b
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_update_part; errno: 5; imm: off; once: off; write 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_update_part; errno: 5; imm: off; once: off; write -b
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_update_part; errno: 28; imm: off; once: on; write 
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_update_part; errno: 28; imm: off; once: on; write -b
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_update_part; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_update_part; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -346,11 +418,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc; errno: 5; imm: off; once: off; write 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc; errno: 5; imm: off; once: off; write -b
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -366,11 +442,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -386,11 +466,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: cluster_alloc; errno: 5; imm: off; once: off; write 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: cluster_alloc; errno: 5; imm: off; once: off; write -b
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -406,11 +490,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: cluster_alloc; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: cluster_alloc; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ 
+@@ -429,6 +517,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 55 leaked clusters were found on the image.
+@@ -436,6 +526,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 251 leaked clusters were found on the image.
+@@ -453,11 +545,15 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.write; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.write; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -473,6 +569,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 11 leaked clusters were found on the image.
+@@ -480,6 +578,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 23 leaked clusters were found on the image.
+@@ -497,6 +597,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 11 leaked clusters were found on the image.
+@@ -504,6 +606,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 23 leaked clusters were found on the image.
+@@ -521,6 +625,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write 
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 11 leaked clusters were found on the image.
+@@ -528,6 +634,8 @@ This means waste of disk space, but no harm to data.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write -b
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 23 leaked clusters were found on the image.
+@@ -543,6 +651,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_grow.alloc_table; errno: 5; imm: off; once: off
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -553,6 +663,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_grow.alloc_table; errno: 28; imm: off; once: off
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -563,6 +675,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_grow.write_table; errno: 5; imm: off; once: off
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -573,6 +687,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_grow.write_table; errno: 28; imm: off; once: off
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+@@ -583,6 +699,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_grow.activate_table; errno: 5; imm: off; once: off
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ write failed: Input/output error
+ 
+ 96 leaked clusters were found on the image.
+@@ -595,6 +713,8 @@ No errors were found on the image.
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+ 
+ Event: l1_grow.activate_table; errno: 28; imm: off; once: off
++Failed to flush the L2 table cache: No space left on device
++Failed to flush the refcount block cache: No space left on device
+ write failed: No space left on device
+ 
+ 96 leaked clusters were found on the image.
+diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
+index 5f840a9..0624581 100644
+--- a/tests/qemu-iotests/071.out
++++ b/tests/qemu-iotests/071.out
+@@ -30,10 +30,14 @@ blkverify: read sector_num=0 nb_sectors=4 contents mismatch in sector 0
+ 
+ === Testing blkdebug through filename ===
+ 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ read failed: Input/output error
+ 
+ === Testing blkdebug through file blockref ===
+ 
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ read failed: Input/output error
+ 
+ === Testing blkdebug on existing block device ===
+@@ -48,6 +52,8 @@ read failed: Input/output error
+ {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+ {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+ {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
++qemu-system-x86_64: Failed to flush the L2 table cache: Input/output error
++qemu-system-x86_64: Failed to flush the refcount block cache: Input/output error
+ 
+ 
+ === Testing blkverify on existing block device ===
+@@ -86,5 +92,7 @@ read failed: Input/output error
+ {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+ {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+ {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
++qemu-system-x86_64: Failed to flush the L2 table cache: Input/output error
++qemu-system-x86_64: Failed to flush the refcount block cache: Input/output error
+ 
+ *** done
+diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
+index 6b3a3e7..b9f9630 100755
+--- a/tests/qemu-iotests/080
++++ b/tests/qemu-iotests/080
+@@ -78,6 +78,8 @@ poke_file "$TEST_IMG" "$offset_backing_file_offset" "\xff\xff\xff\xff\xff\xff\xf
+ poke_file "$TEST_IMG" "$offset_ext_magic" "\x12\x34\x56\x78"
+ poke_file "$TEST_IMG" "$offset_ext_size" "\x7f\xff\xff\xff"
+ { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
++poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x$(printf %x $offset_ext_size)"
++{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+ poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00"
+ { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+ 
+diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
+index f7a943c..33d1f71 100644
+--- a/tests/qemu-iotests/080.out
++++ b/tests/qemu-iotests/080.out
+@@ -13,6 +13,8 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset
+ no file open, try 'help open'
+ qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large
+ no file open, try 'help open'
++qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large
++no file open, try 'help open'
+ 
+ == Huge refcount table size ==
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
+index 82c56b1..d7454d1 100755
+--- a/tests/qemu-iotests/087
++++ b/tests/qemu-iotests/087
+@@ -218,6 +218,23 @@ run_qemu <<EOF
+ { "execute": "quit" }
+ EOF
+ 
++echo
++echo === Missing driver ===
++echo
++
++_make_test_img -o encryption=on $size
++run_qemu -S <<EOF
++{ "execute": "qmp_capabilities" }
++{ "execute": "blockdev-add",
++  "arguments": {
++      "options": {
++        "id": "disk"
++      }
++    }
++  }
++{ "execute": "quit" }
++EOF
++
+ # success, all done
+ echo "*** done"
+ rm -f $seq.full
+diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
+index 7fbee3f..f16bad0 100644
+--- a/tests/qemu-iotests/087.out
++++ b/tests/qemu-iotests/087.out
+@@ -64,4 +64,17 @@ QMP_VERSION
+ {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+ {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+ 
++
++=== Missing driver ===
++
++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on 
++Testing: -S
++QMP_VERSION
++{"return": {}}
++{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'driver', expected: string"}}
++{"return": {}}
++{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
++{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
++{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
++
+ *** done
+diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out
+index 4ca2f88..ab06c55 100644
+--- a/tests/qemu-iotests/089.out
++++ b/tests/qemu-iotests/089.out
+@@ -24,6 +24,8 @@ read 512/512 bytes at offset 0
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+ wrote 512/512 bytes at offset 229376
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++Failed to flush the L2 table cache: Input/output error
++Failed to flush the refcount block cache: Input/output error
+ read failed: Input/output error
+ 
+ === Testing qemu-img info output ===
 diff --git a/tests/qemu-iotests/101 b/tests/qemu-iotests/101
 new file mode 100755
 index 0000000..70fbf25
@@ -1872,15 +5273,372 @@ index 0000000..9a996e8
 +read 512/512 bytes at offset 0
 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 +*** done
+diff --git a/tests/qemu-iotests/113 b/tests/qemu-iotests/113
+new file mode 100755
+index 0000000..a2cd96b
+--- /dev/null
++++ b/tests/qemu-iotests/113
+@@ -0,0 +1,76 @@
++#!/bin/bash
++#
++# Test case for accessing creation options on image formats and
++# protocols not supporting image creation
++#
++# Copyright (C) 2014 Red Hat, Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program 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 General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++#
++
++# creator
++owner=mreitz@redhat.com
++
++seq="$(basename $0)"
++echo "QA output created by $seq"
++
++here="$PWD"
++tmp=/tmp/$$
++status=1	# failure is the default!
++
++_cleanup()
++{
++	_cleanup_test_img
++}
++trap "_cleanup; exit \$status" 0 1 2 3 15
++
++# get standard environment, filters and checks
++. ./common.rc
++. ./common.filter
++
++# We can only test one format here because we need its sample file
++_supported_fmt bochs
++_supported_proto nbd
++_supported_os Linux
++
++echo
++echo '=== Unsupported image creation in qemu-img create ==='
++echo
++
++$QEMU_IMG create -f $IMGFMT nbd://example.com 2>&1 64M | _filter_imgfmt
++
++echo
++echo '=== Unsupported image creation in qemu-img convert ==='
++echo
++
++# We could use any input image format here, but this is a bochs test, so just
++# use the bochs image
++_use_sample_img empty.bochs.bz2
++$QEMU_IMG convert -f $IMGFMT -O $IMGFMT "$TEST_IMG" nbd://example.com 2>&1 \
++    | _filter_imgfmt
++
++echo
++echo '=== Unsupported format in qemu-img amend ==='
++echo
++
++# The protocol does not matter here
++_use_sample_img empty.bochs.bz2
++$QEMU_IMG amend -f $IMGFMT -o foo=bar "$TEST_IMG" 2>&1 | _filter_imgfmt
++
++
++# success, all done
++echo
++echo '*** done'
++rm -f $seq.full
++status=0
+diff --git a/tests/qemu-iotests/113.out b/tests/qemu-iotests/113.out
+new file mode 100644
+index 0000000..00bdfd6
+--- /dev/null
++++ b/tests/qemu-iotests/113.out
+@@ -0,0 +1,15 @@
++QA output created by 113
++
++=== Unsupported image creation in qemu-img create ===
++
++qemu-img: nbd://example.com: Format driver 'IMGFMT' does not support image creation
++
++=== Unsupported image creation in qemu-img convert ===
++
++qemu-img: Format driver 'IMGFMT' does not support image creation
++
++=== Unsupported format in qemu-img amend ===
++
++qemu-img: Format driver 'IMGFMT' does not support any options to amend
++
++*** done
+diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
+new file mode 100755
+index 0000000..d02e7ff
+--- /dev/null
++++ b/tests/qemu-iotests/114
+@@ -0,0 +1,61 @@
++#!/bin/bash
++#
++# Test invalid backing file format in qcow2 images
++#
++# Copyright (C) 2014 Red Hat, Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program 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 General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++#
++
++# creator
++owner=kwolf@redhat.com
++
++seq="$(basename $0)"
++echo "QA output created by $seq"
++
++here="$PWD"
++tmp=/tmp/$$
++status=1	# failure is the default!
++
++_cleanup()
++{
++	_cleanup_test_img
++}
++trap "_cleanup; exit \$status" 0 1 2 3 15
++
++# get standard environment, filters and checks
++. ./common.rc
++. ./common.filter
++
++_supported_fmt qcow2
++_supported_proto generic
++_supported_os Linux
++
++
++TEST_IMG="$TEST_IMG.base" _make_test_img 64M
++_make_test_img -b "$TEST_IMG.base" 64M
++
++# Set an invalid backing file format
++$PYTHON qcow2.py "$TEST_IMG" add-header-ext 0xE2792ACA "foo"
++_img_info
++
++# Try opening the image. Should fail (and not probe) in the first case, but
++# overriding the backing file format should be possible.
++$QEMU_IO -c "open $TEST_IMG" -c "read 0 4k" 2>&1 | _filter_qemu_io | _filter_testdir
++$QEMU_IO -c "open -o backing.driver=$IMGFMT $TEST_IMG" -c "read 0 4k" | _filter_qemu_io
++
++# success, all done
++echo '*** done'
++rm -f $seq.full
++status=0
+diff --git a/tests/qemu-iotests/114.out b/tests/qemu-iotests/114.out
+new file mode 100644
+index 0000000..6c6b210
+--- /dev/null
++++ b/tests/qemu-iotests/114.out
+@@ -0,0 +1,13 @@
++QA output created by 114
++Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 
++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' 
++image: TEST_DIR/t.IMGFMT
++file format: IMGFMT
++virtual size: 64M (67108864 bytes)
++cluster_size: 65536
++backing file: TEST_DIR/t.IMGFMT.base
++backing file format: foo
++qemu-io: can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknown driver 'foo'
++read 4096/4096 bytes at offset 0
++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++*** done
+diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
+index e0ea7e3..e7760a2 100644
+--- a/tests/qemu-iotests/common.rc
++++ b/tests/qemu-iotests/common.rc
+@@ -189,7 +189,9 @@ _cleanup_test_img()
+     case "$IMGPROTO" in
+ 
+         nbd)
+-            kill $QEMU_NBD_PID
++            if [ -n "$QEMU_NBD_PID" ]; then
++                kill $QEMU_NBD_PID
++            fi
+             rm -f "$TEST_IMG_FILE"
+             ;;
+         file)
 diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
-index 6e67f61..e25e992 100644
+index 6e67f61..97026f3 100644
 --- a/tests/qemu-iotests/group
 +++ b/tests/qemu-iotests/group
-@@ -100,3 +100,4 @@
+@@ -100,3 +100,6 @@
  091 rw auto quick
  092 rw auto quick
  095 rw auto quick
 +101 rw auto quick
++113 rw auto quick
++114 rw auto quick
+diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
+index 2058596..9cc4cf7 100755
+--- a/tests/qemu-iotests/qcow2.py
++++ b/tests/qemu-iotests/qcow2.py
+@@ -7,6 +7,10 @@ import string
+ class QcowHeaderExtension:
+ 
+     def __init__(self, magic, length, data):
++        if length % 8 != 0:
++            padding = 8 - (length % 8)
++            data += "\0" * padding
++
+         self.magic  = magic
+         self.length = length
+         self.data   = data
+diff --git a/tests/tcg/xtensa/test_mmu.S b/tests/tcg/xtensa/test_mmu.S
+index 58c5bca..a15316f 100644
+--- a/tests/tcg/xtensa/test_mmu.S
++++ b/tests/tcg/xtensa/test_mmu.S
+@@ -641,7 +641,7 @@ test cross_page_tb
+     witlb   a2, a3
+     wdtlb   a2, a3
+ 
+-    movi    a2, 0x00007ffd
++    movi    a2, 0x00007ffc
+     movi    a3, 20f
+     movi    a4, 21f
+     sub     a4, a4, a3
+@@ -651,7 +651,7 @@ test cross_page_tb
+     addi    a2, a2, 1
+     addi    a3, a3, 1
+ 1:
+-    movi    a2, 0x00007ffd
++    movi    a2, 0x00007ffc
+     movi    a3, 0x00008000
+     /* DTLB: OK, ITLB: OK */
+     jx      a2
+@@ -668,10 +668,10 @@ test cross_page_tb
+     movi    a3, 1
+     assert  eq, a2, a3
+     rsr     a2, epc1
+-    movi    a3, 0x8000
++    movi    a3, 0x7fff
+     assert  eq, a2, a3
+     rsr     a2, excsave1
+-    movi    a3, 0x00007ffd
++    movi    a3, 0x00007ffc
+     assert  ne, a2, a3
+ 
+     reset_ps
+@@ -680,7 +680,7 @@ test cross_page_tb
+     movi    a2, 0x0400000c /* PPN */
+     movi    a3, 0x00008000 /* VPN */
+     wdtlb   a2, a3
+-    movi    a2, 0x00007ffd
++    movi    a2, 0x00007ffc
+     movi    a3, 0x00008000
+     /* DTLB: FAIL, ITLB: OK */
+     jx      a2
+@@ -689,10 +689,10 @@ test cross_page_tb
+     movi    a3, 28
+     assert  eq, a2, a3
+     rsr     a2, epc1
+-    movi    a3, 0x7ffd
++    movi    a3, 0x7ffc
+     assert  eq, a2, a3
+     rsr     a2, excsave1
+-    movi    a3, 0x00007ffd
++    movi    a3, 0x00007ffc
+     assert  eq, a2, a3
+ 
+     reset_ps
+@@ -703,7 +703,7 @@ test cross_page_tb
+     witlb   a2, a3
+     movi    a2, 0x04000003 /* PPN */
+     wdtlb   a2, a3
+-    movi    a2, 0x00007ffd
++    movi    a2, 0x00007ffc
+     movi    a3, 0x00008000
+     /* DTLB: OK, ITLB: FAIL */
+     jx      a2
+@@ -712,10 +712,10 @@ test cross_page_tb
+     movi    a3, 20
+     assert  eq, a2, a3
+     rsr     a2, epc1
+-    movi    a3, 0x8000
++    movi    a3, 0x7fff
+     assert  eq, a2, a3
+     rsr     a2, excsave1
+-    movi    a3, 0x00007ffd
++    movi    a3, 0x00007ffc
+     assert  ne, a2, a3
+ 
+     reset_ps
+@@ -724,7 +724,7 @@ test cross_page_tb
+     movi    a2, 0x0400000c /* PPN */
+     movi    a3, 0x00008000 /* VPN */
+     wdtlb   a2, a3
+-    movi    a2, 0x00007ffd
++    movi    a2, 0x00007ffc
+     movi    a3, 0x00008000
+     /* DTLB: FAIL, ITLB: FAIL */
+     jx      a2
+@@ -733,10 +733,10 @@ test cross_page_tb
+     movi    a3, 28
+     assert  eq, a2, a3
+     rsr     a2, epc1
+-    movi    a3, 0x7ffd
++    movi    a3, 0x7ffc
+     assert  eq, a2, a3
+     rsr     a2, excsave1
+-    movi    a3, 0x00007ffd
++    movi    a3, 0x00007ffc
+     assert  eq, a2, a3
+ test_end
+ 
+diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
+index 0f77003..d5360c6 100644
+--- a/tests/test-qmp-input-strict.c
++++ b/tests/test-qmp-input-strict.c
+@@ -260,6 +260,21 @@ static void test_validate_fail_union_flat(TestInputVisitorData *data,
+     qapi_free_UserDefFlatUnion(tmp);
+ }
+ 
++static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data,
++                                                     const void *unused)
++{
++    UserDefFlatUnion2 *tmp = NULL;
++    Error *err = NULL;
++    Visitor *v;
++
++    /* test situation where discriminator field ('enum1' here) is missing */
++    v = validate_test_init(data, "{ 'string': 'c', 'string1': 'd', 'string2': 'e' }");
++
++    visit_type_UserDefFlatUnion2(v, &tmp, NULL, &err);
++    g_assert(err);
++    qapi_free_UserDefFlatUnion2(tmp);
++}
++
+ static void test_validate_fail_union_anon(TestInputVisitorData *data,
+                                           const void *unused)
+ {
+@@ -310,6 +325,8 @@ int main(int argc, char **argv)
+                        &testdata, test_validate_fail_union);
+     validate_test_add("/visitor/input-strict/fail/union-flat",
+                        &testdata, test_validate_fail_union_flat);
++    validate_test_add("/visitor/input-strict/fail/union-flat-no-discriminator",
++                       &testdata, test_validate_fail_union_flat_no_discrim);
+     validate_test_add("/visitor/input-strict/fail/union-anon",
+                        &testdata, test_validate_fail_union_anon);
+ 
 diff --git a/thread-pool.c b/thread-pool.c
 index dfb699d..23888dc 100644
 --- a/thread-pool.c
@@ -2038,11 +5796,85 @@ index 66e2578..def7b52 100644
      info->n_surfaces = ssd->num_surfaces;
  }
  
+diff --git a/ui/vnc.c b/ui/vnc.c
+index f8d9b7d..87e34ae 100644
+--- a/ui/vnc.c
++++ b/ui/vnc.c
+@@ -2026,6 +2026,16 @@ static void set_pixel_format(VncState *vs,
+         return;
+     }
+ 
++    switch (bits_per_pixel) {
++    case 8:
++    case 16:
++    case 32:
++        break;
++    default:
++        vnc_client_error(vs);
++        return;
++    }
++
+     vs->client_pf.rmax = red_max;
+     vs->client_pf.rbits = hweight_long(red_max);
+     vs->client_pf.rshift = red_shift;
 diff --git a/vl.c b/vl.c
-index fe451aa..7f8bd39 100644
+index fe451aa..653ee2c 100644
 --- a/vl.c
 +++ b/vl.c
-@@ -4009,11 +4009,6 @@ int main(int argc, char **argv, char **envp)
+@@ -1745,9 +1745,7 @@ int qemu_reset_requested_get(void)
+ 
+ static int qemu_shutdown_requested(void)
+ {
+-    int r = shutdown_requested;
+-    shutdown_requested = 0;
+-    return r;
++    return atomic_xchg(&shutdown_requested, 0);
+ }
+ 
+ static void qemu_kill_report(void)
+@@ -3054,9 +3052,6 @@ int main(int argc, char **argv, char **envp)
+                 exit(1);
+             }
+             switch(popt->index) {
+-            case QEMU_OPTION_M:
+-                machine_class = machine_parse(optarg);
+-                break;
+             case QEMU_OPTION_no_kvm_irqchip: {
+                 olist = qemu_find_opts("machine");
+                 qemu_opts_parse(olist, "kernel_irqchip=off", 0);
+@@ -3674,16 +3669,13 @@ int main(int argc, char **argv, char **envp)
+                 olist = qemu_find_opts("machine");
+                 qemu_opts_parse(olist, "accel=kvm", 0);
+                 break;
++            case QEMU_OPTION_M:
+             case QEMU_OPTION_machine:
+                 olist = qemu_find_opts("machine");
+                 opts = qemu_opts_parse(olist, optarg, 1);
+                 if (!opts) {
+                     exit(1);
+                 }
+-                optarg = qemu_opt_get(opts, "type");
+-                if (optarg) {
+-                    machine_class = machine_parse(optarg);
+-                }
+                 break;
+              case QEMU_OPTION_no_kvm:
+                 olist = qemu_find_opts("machine");
+@@ -3966,6 +3958,13 @@ int main(int argc, char **argv, char **envp)
+             }
+         }
+     }
++
++    opts = qemu_get_machine_opts();
++    optarg = qemu_opt_get(opts, "type");
++    if (optarg) {
++        machine_class = machine_parse(optarg);
++    }
++
+     loc_set_none();
+ 
+     os_daemonize();
+@@ -4009,11 +4008,6 @@ int main(int argc, char **argv, char **envp)
          qemu_set_version(machine_class->hw_version);
      }
  
@@ -2054,7 +5886,7 @@ index fe451aa..7f8bd39 100644
      /* Init CPU def lists, based on config
       * - Must be called after all the qemu_read_config_file() calls
       * - Must be called before list_cpus()
-@@ -4225,6 +4220,11 @@ int main(int argc, char **argv, char **envp)
+@@ -4225,6 +4219,11 @@ int main(int argc, char **argv, char **envp)
          exit(0);
      }
  

Attachment: signature.asc
Description: OpenPGP digital signature


Reply to: