diff --git a/SOURCES/kvm-Add-skip_dump-flag-to-ignore-memory-region-during-du.patch b/SOURCES/kvm-Add-skip_dump-flag-to-ignore-memory-region-during-du.patch
new file mode 100644
index 0000000..f1c86ce
--- /dev/null
+++ b/SOURCES/kvm-Add-skip_dump-flag-to-ignore-memory-region-during-du.patch
@@ -0,0 +1,129 @@
+From 0ae4c882404b4590c34bb9b03a86f9389413fd1c Mon Sep 17 00:00:00 2001
+From: Alex Williamson <alex.williamson@redhat.com>
+Date: Wed, 7 Sep 2016 14:09:52 +0200
+Subject: [PATCH 2/2] Add skip_dump flag to ignore memory region during dump
+
+RH-Author: Alex Williamson <alex.williamson@redhat.com>
+Message-id: <20160907140817.21968.47551.stgit@gimli.home>
+Patchwork-id: 72264
+O-Subject: [RHEL7.3 qemu-kvm PATCH v2] Add skip_dump flag to ignore memory region during dump
+Bugzilla: 1373088
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Auger Eric <eric.auger@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+From: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
+
+Bugzilla: 1373088
+Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=11713365
+Upstream: e4dc3f5909ab90520bc1a27b381c3017ff65ed68
+
+The PCI MMIO might be disabled or the device in the reset state.
+Make sure we do not dump these memory regions.
+
+Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
+Acked-by: Alex Williamson <alex.williamson@redhat.com>
+CC: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/misc/vfio.c        |  1 +
+ include/exec/memory.h | 19 +++++++++++++++++++
+ memory.c              | 10 ++++++++++
+ memory_mapping.c      |  3 ++-
+ 4 files changed, 32 insertions(+), 1 deletion(-)
+
+diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
+index 36b9832..4fdc09a 100644
+--- a/hw/misc/vfio.c
++++ b/hw/misc/vfio.c
+@@ -2596,6 +2596,7 @@ static int vfio_mmap_bar(VFIOBAR *bar, MemoryRegion *mem, MemoryRegion *submem,
+         }
+ 
+         memory_region_init_ram_ptr(submem, name, size, *map);
++        memory_region_set_skip_dump(submem);
+     } else {
+ empty_region:
+         /* Create a zero sized sub-region to make cleanup easy. */
+diff --git a/include/exec/memory.h b/include/exec/memory.h
+index 3bbe378..448d501 100644
+--- a/include/exec/memory.h
++++ b/include/exec/memory.h
+@@ -126,6 +126,7 @@ struct MemoryRegion {
+     bool terminates;
+     bool romd_mode;
+     bool ram;
++    bool skip_dump;
+     bool readonly; /* For RAM regions */
+     bool enabled;
+     bool rom_device;
+@@ -353,6 +354,24 @@ uint64_t memory_region_size(MemoryRegion *mr);
+ bool memory_region_is_ram(MemoryRegion *mr);
+ 
+ /**
++ * memory_region_is_skip_dump: check whether a memory region should not be
++ *                             dumped
++ *
++ * Returns %true is a memory region should not be dumped(e.g. VFIO BAR MMAP).
++ *
++ * @mr: the memory region being queried
++ */
++bool memory_region_is_skip_dump(MemoryRegion *mr);
++
++/**
++ * memory_region_set_skip_dump: Set skip_dump flag, dump will ignore this memory
++ *                              region
++ *
++ * @mr: the memory region being queried
++ */
++void memory_region_set_skip_dump(MemoryRegion *mr);
++
++/**
+  * memory_region_is_romd: check whether a memory region is in ROMD mode
+  *
+  * Returns %true if a memory region is a ROM device and currently set to allow
+diff --git a/memory.c b/memory.c
+index a71d096..7bd6e87 100644
+--- a/memory.c
++++ b/memory.c
+@@ -957,6 +957,11 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
+     mr->ram_addr = qemu_ram_alloc_from_ptr(size, ptr, mr);
+ }
+ 
++void memory_region_set_skip_dump(MemoryRegion *mr)
++{
++    mr->skip_dump = true;
++}
++
+ void memory_region_init_alias(MemoryRegion *mr,
+                               const char *name,
+                               MemoryRegion *orig,
+@@ -1047,6 +1052,11 @@ bool memory_region_is_ram(MemoryRegion *mr)
+     return mr->ram;
+ }
+ 
++bool memory_region_is_skip_dump(MemoryRegion *mr)
++{
++    return mr->skip_dump;
++}
++
+ bool memory_region_is_logging(MemoryRegion *mr)
+ {
+     return mr->dirty_log_mask;
+diff --git a/memory_mapping.c b/memory_mapping.c
+index 65082d8..a4d59b7 100644
+--- a/memory_mapping.c
++++ b/memory_mapping.c
+@@ -203,7 +203,8 @@ static void guest_phys_blocks_region_add(MemoryListener *listener,
+     GuestPhysBlock *predecessor;
+ 
+     /* we only care about RAM */
+-    if (!memory_region_is_ram(section->mr)) {
++    if (!memory_region_is_ram(section->mr) ||
++        memory_region_is_skip_dump(section->mr)) {
+         return;
+     }
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-BlockLimits-introduce-max_transfer_length.patch b/SOURCES/kvm-BlockLimits-introduce-max_transfer_length.patch
new file mode 100644
index 0000000..c440c6d
--- /dev/null
+++ b/SOURCES/kvm-BlockLimits-introduce-max_transfer_length.patch
@@ -0,0 +1,66 @@
+From fea907b6897cb3e644dcee3c537ce6e64d7850ed Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 11 Jul 2016 05:33:35 +0200
+Subject: [PATCH 2/7] BlockLimits: introduce max_transfer_length
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1468215219-30793-3-git-send-email-famz@redhat.com>
+Patchwork-id: 71106
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 2/6] BlockLimits: introduce max_transfer_length
+Bugzilla: 1318199
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Peter Lieven <pl@kamp.de>
+
+Signed-off-by: Peter Lieven <pl@kamp.de>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 2647fab57d5d5e38b36f8dbda367d688045e6a2d)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block.c                   | 4 ++++
+ include/block/block_int.h | 3 +++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/block.c b/block.c
+index ecb2b09..ae756aa 100644
+--- a/block.c
++++ b/block.c
+@@ -481,6 +481,7 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
+             return;
+         }
+         bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
++        bs->bl.max_transfer_length = bs->file->bl.max_transfer_length;
+         bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
+     } else {
+         bs->bl.opt_mem_alignment = 512;
+@@ -495,6 +496,9 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
+         bs->bl.opt_transfer_length =
+             MAX(bs->bl.opt_transfer_length,
+                 bs->backing_hd->bl.opt_transfer_length);
++        bs->bl.max_transfer_length =
++            MIN_NON_ZERO(bs->bl.max_transfer_length,
++                         bs->backing_hd->bl.max_transfer_length);
+         bs->bl.opt_mem_alignment =
+             MAX(bs->bl.opt_mem_alignment,
+                 bs->backing_hd->bl.opt_mem_alignment);
+diff --git a/include/block/block_int.h b/include/block/block_int.h
+index 3f86649..28c34d8 100644
+--- a/include/block/block_int.h
++++ b/include/block/block_int.h
+@@ -240,6 +240,9 @@ typedef struct BlockLimits {
+     /* optimal transfer length in sectors */
+     int opt_transfer_length;
+ 
++    /* maximal transfer length in sectors */
++    int max_transfer_length;
++
+     /* memory alignment so that no bounce buffer is needed */
+     size_t opt_mem_alignment;
+ } BlockLimits;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-Fix-backport-of-target-i386-add-feature-flags-for-CP.patch b/SOURCES/kvm-Fix-backport-of-target-i386-add-feature-flags-for-CP.patch
new file mode 100644
index 0000000..0339170
--- /dev/null
+++ b/SOURCES/kvm-Fix-backport-of-target-i386-add-feature-flags-for-CP.patch
@@ -0,0 +1,84 @@
+From 7530a2f3975b76711467226f8b279baf36d92e46 Mon Sep 17 00:00:00 2001
+From: Eduardo Habkost <ehabkost@redhat.com>
+Date: Tue, 6 Sep 2016 21:45:05 +0200
+Subject: [PATCH 1/2] Fix backport of "target-i386: add feature flags for
+ CPUID[EAX=0xd, ECX=1]"
+
+RH-Author: Eduardo Habkost <ehabkost@redhat.com>
+Message-id: <1473198305-8442-1-git-send-email-ehabkost@redhat.com>
+Patchwork-id: 72260
+O-Subject: [RHEL-7.3 qemu-kvm PATCH] Fix backport of "target-i386: add feature flags for CPUID[EAX=0xd, ECX=1]"
+Bugzilla: 1371619
+RH-Acked-by: Bandan Das <bsd@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Upstream status: commit 0bb0b2d2fe7f645ddaf1f0ff40ac669c9feb4aa1
+
+commit 5fcaf5176d7545518c76f3aa8ea7ce6fb063c62d (the backport of
+upstream commit 0bb0b2d2fe7f645ddaf1f0ff40ac669c9feb4aa1) had a
+serious bug: as the qemu-kvm-1.5.3 code doesn't have
+FeatureWordInfo and loops for assigning cpu->features,
+cpu->features[FEAT_XSAVE] was always zero, so that commit
+basically cleared all XSAVE feature bits in all CPU models.
+
+Fix it by handling FEAT_XSAVE everywhere it matters: in the
+plus_features/minus_features handling, in the loading of CPU
+model definition, and kvm_cpu_fill_host().
+
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ target-i386/cpu.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/target-i386/cpu.c b/target-i386/cpu.c
+index 80106ba..1001c47 100644
+--- a/target-i386/cpu.c
++++ b/target-i386/cpu.c
+@@ -1201,6 +1201,8 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
+     } else {
+         x86_cpu_def->features[FEAT_7_0_EBX] = 0;
+     }
++    x86_cpu_def->features[FEAT_XSAVE] =
++                kvm_arch_get_supported_cpuid(s, 0xd, 1, R_EAX);
+ 
+     x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
+     x86_cpu_def->features[FEAT_8000_0001_EDX] =
+@@ -1281,6 +1283,9 @@ static int kvm_check_features_against_host(X86CPU *cpu)
+         {&env->features[FEAT_7_0_EBX],
+             &host_def.features[FEAT_7_0_EBX],
+             FEAT_7_0_EBX },
++        {&env->features[FEAT_XSAVE],
++            &host_def.features[FEAT_XSAVE],
++            FEAT_XSAVE },
+         {&env->features[FEAT_SVM],
+             &host_def.features[FEAT_SVM],
+             FEAT_SVM },
+@@ -1819,6 +1824,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
+     env->features[FEAT_KVM] |= plus_features[FEAT_KVM];
+     env->features[FEAT_SVM] |= plus_features[FEAT_SVM];
+     env->features[FEAT_7_0_EBX] |= plus_features[FEAT_7_0_EBX];
++    env->features[FEAT_XSAVE] |= plus_features[FEAT_XSAVE];
+     env->features[FEAT_1_EDX] &= ~minus_features[FEAT_1_EDX];
+     env->features[FEAT_1_ECX] &= ~minus_features[FEAT_1_ECX];
+     env->features[FEAT_8000_0001_EDX] &= ~minus_features[FEAT_8000_0001_EDX];
+@@ -1827,6 +1833,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
+     env->features[FEAT_KVM] &= ~minus_features[FEAT_KVM];
+     env->features[FEAT_SVM] &= ~minus_features[FEAT_SVM];
+     env->features[FEAT_7_0_EBX] &= ~minus_features[FEAT_7_0_EBX];
++    env->features[FEAT_XSAVE] &= ~minus_features[FEAT_XSAVE];
+ 
+ out:
+     return;
+@@ -1962,6 +1969,7 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
+     env->features[FEAT_SVM] = def->features[FEAT_SVM];
+     env->features[FEAT_C000_0001_EDX] = def->features[FEAT_C000_0001_EDX];
+     env->features[FEAT_7_0_EBX] = def->features[FEAT_7_0_EBX];
++    env->features[FEAT_XSAVE] = def->features[FEAT_XSAVE];
+     env->cpuid_xlevel2 = def->xlevel2;
+ 
+     object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-Make-qemu-io-commands-available-in-HMP.patch b/SOURCES/kvm-Make-qemu-io-commands-available-in-HMP.patch
new file mode 100644
index 0000000..909d57b
--- /dev/null
+++ b/SOURCES/kvm-Make-qemu-io-commands-available-in-HMP.patch
@@ -0,0 +1,132 @@
+From 6b7e23d3e8ff46e638c9dcd769681b2e1b9da08e Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:35 +0100
+Subject: [PATCH 16/27] Make qemu-io commands available in HMP
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-17-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68443
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 16/21] Make qemu-io commands available in HMP
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+It was decided to not make this command available in QMP in order to
+make clear that this is not supposed to be a stable API and should be
+used only for testing and debugging purposes.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 587da2c39c9ace168f4d01fa446a54ae998a2553)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ Makefile        |  2 +-
+ Makefile.objs   |  1 +
+ hmp-commands.hx | 16 ++++++++++++++++
+ hmp.c           | 18 ++++++++++++++++++
+ hmp.h           |  1 +
+ 5 files changed, 37 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index f403057..76eb694 100644
+--- a/Makefile
++++ b/Makefile
+@@ -205,7 +205,7 @@ qemu-img.o: qemu-img-cmds.h
+ 
+ qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
+ qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
+-qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o $(block-obj-y) libqemuutil.a libqemustub.a
++qemu-io$(EXESUF): qemu-io.o $(block-obj-y) libqemuutil.a libqemustub.a
+ 
+ qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
+ 
+diff --git a/Makefile.objs b/Makefile.objs
+index f83a5b2..74f722e 100644
+--- a/Makefile.objs
++++ b/Makefile.objs
+@@ -13,6 +13,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
+ block-obj-$(CONFIG_WIN32) += aio-win32.o
+ block-obj-y += block/
+ block-obj-y += qapi-types.o qapi-visit.o
++block-obj-y += qemu-io-cmds.o
+ 
+ block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
+ block-obj-y += qemu-coroutine-sleep.o
+diff --git a/hmp-commands.hx b/hmp-commands.hx
+index 58498f7..7e1855a 100644
+--- a/hmp-commands.hx
++++ b/hmp-commands.hx
+@@ -1592,6 +1592,22 @@ Removes the chardev @var{id}.
+ ETEXI
+ 
+     {
++        .name       = "qemu-io",
++        .args_type  = "device:B,command:s",
++        .params     = "[device] \"[command]\"",
++        .help       = "run a qemu-io command on a block device",
++        .mhandler.cmd = hmp_qemu_io,
++    },
++
++STEXI
++@item qemu-io @var{device} @var{command}
++@findex qemu-io
++
++Executes a qemu-io command on the given block device.
++
++ETEXI
++
++    {
+         .name       = "info",
+         .args_type  = "item:s?",
+         .params     = "[subcommand]",
+diff --git a/hmp.c b/hmp.c
+index 1805926..e1d92f4 100644
+--- a/hmp.c
++++ b/hmp.c
+@@ -22,6 +22,7 @@
+ #include "qemu/sockets.h"
+ #include "monitor/monitor.h"
+ #include "ui/console.h"
++#include "qemu-io.h"
+ 
+ static void hmp_handle_error(Monitor *mon, Error **errp)
+ {
+@@ -1448,3 +1449,20 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
+     qmp_chardev_remove(qdict_get_str(qdict, "id"), &local_err);
+     hmp_handle_error(mon, &local_err);
+ }
++
++void hmp_qemu_io(Monitor *mon, const QDict *qdict)
++{
++    BlockDriverState *bs;
++    const char* device = qdict_get_str(qdict, "device");
++    const char* command = qdict_get_str(qdict, "command");
++    Error *err = NULL;
++
++    bs = bdrv_find(device);
++    if (bs) {
++        qemuio_command(bs, command);
++    } else {
++        error_set(&err, QERR_DEVICE_NOT_FOUND, device);
++    }
++
++    hmp_handle_error(mon, &err);
++}
+diff --git a/hmp.h b/hmp.h
+index 9b2c9ce..b27ef3d 100644
+--- a/hmp.h
++++ b/hmp.h
+@@ -86,5 +86,6 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
+ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
+ void hmp_chardev_add(Monitor *mon, const QDict *qdict);
+ void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
++void hmp_qemu_io(Monitor *mon, const QDict *qdict);
+ 
+ #endif
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-acpi-add-function-to-extract-oem_id-and-oem_table_id.patch b/SOURCES/kvm-acpi-add-function-to-extract-oem_id-and-oem_table_id.patch
new file mode 100644
index 0000000..4660d3b
--- /dev/null
+++ b/SOURCES/kvm-acpi-add-function-to-extract-oem_id-and-oem_table_id.patch
@@ -0,0 +1,89 @@
+From 5ccdcc1c49246cce9b1536e28a4977c65d72531c Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Wed, 11 May 2016 12:33:47 +0200
+Subject: [PATCH 08/10] acpi: add function to extract oem_id and oem_table_id
+ from the user's SLIC
+
+RH-Author: Laszlo Ersek <lersek@redhat.com>
+Message-id: <1462970028-10959-7-git-send-email-lersek@redhat.com>
+Patchwork-id: 70383
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 6/7] acpi: add function to extract oem_id and oem_table_id from the user's SLIC
+Bugzilla: 1330969
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+The acpi_get_slic_oem() function stores pointers to these fields in the
+(first) SLIC table that the user passes in with the -acpitable switch.
+
+Cc: "Michael S. Tsirkin" <mst@redhat.com> (supporter:ACPI/SMBIOS)
+Cc: Igor Mammedov <imammedo@redhat.com> (supporter:ACPI/SMBIOS)
+Cc: Richard W.M. Jones <rjones@redhat.com>
+Cc: Aleksei Kovura <alex3kov@zoho.com>
+Cc: Michael Tokarev <mjt@tls.msk.ru>
+Cc: Steven Newbury <steve@snewbury.org.uk>
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1248758
+LP: https://bugs.launchpad.net/qemu/+bug/1533848
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Steven Newbury <steve@snewbury.org.uk>
+(cherry picked from commit 88594e4fd1e916b778968b2bdd8d7375ca2fe8d8)
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ include/hw/acpi/acpi.h |  7 +++++++
+ hw/acpi/core.c         | 16 ++++++++++++++++
+ 2 files changed, 23 insertions(+)
+
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/acpi/core.c         | 16 ++++++++++++++++
+ include/hw/acpi/acpi.h |  7 +++++++
+ 2 files changed, 23 insertions(+)
+
+diff --git a/hw/acpi/core.c b/hw/acpi/core.c
+index 88efba7..99c5918 100644
+--- a/hw/acpi/core.c
++++ b/hw/acpi/core.c
+@@ -349,6 +349,22 @@ uint8_t *acpi_table_next(uint8_t *current)
+     }
+ }
+ 
++int acpi_get_slic_oem(AcpiSlicOem *oem)
++{
++    uint8_t *u;
++
++    for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
++        struct acpi_table_header *hdr = (void *)(u - sizeof(hdr->_length));
++
++        if (memcmp(hdr->sig, "SLIC", 4) == 0) {
++            oem->id = hdr->oem_id;
++            oem->table_id = hdr->oem_table_id;
++            return 0;
++        }
++    }
++    return -1;
++}
++
+ static void acpi_notify_wakeup(Notifier *notifier, void *data)
+ {
+     ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup);
+diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
+index bb7136d..1e59ec9 100644
+--- a/include/hw/acpi/acpi.h
++++ b/include/hw/acpi/acpi.h
+@@ -171,4 +171,11 @@ unsigned acpi_table_len(void *current);
+ void acpi_table_add(const QemuOpts *opts, Error **errp);
+ void acpi_table_add_builtin(const QemuOpts *opts, Error **errp);
+ 
++typedef struct AcpiSlicOem AcpiSlicOem;
++struct AcpiSlicOem {
++  char *id;
++  char *table_id;
++};
++int acpi_get_slic_oem(AcpiSlicOem *oem);
++
+ #endif /* !QEMU_HW_ACPI_H */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-acpi-expose-oem_id-and-oem_table_id-in-build_rsdt.patch b/SOURCES/kvm-acpi-expose-oem_id-and-oem_table_id-in-build_rsdt.patch
new file mode 100644
index 0000000..1e8bf05
--- /dev/null
+++ b/SOURCES/kvm-acpi-expose-oem_id-and-oem_table_id-in-build_rsdt.patch
@@ -0,0 +1,92 @@
+From 39f2d80c57f648afd2eab27816e8f93cf48e718d Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Wed, 11 May 2016 12:33:46 +0200
+Subject: [PATCH 07/10] acpi: expose oem_id and oem_table_id in build_rsdt()
+
+RH-Author: Laszlo Ersek <lersek@redhat.com>
+Message-id: <1462970028-10959-6-git-send-email-lersek@redhat.com>
+Patchwork-id: 70382
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 5/7] acpi: expose oem_id and oem_table_id in build_rsdt()
+Bugzilla: 1330969
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+Since build_rsdt() is implemented as common utility code (in
+"hw/acpi/aml-build.c"), it should expose -- and forward -- the oem_id and
+oem_table_id parameters between board code and the generic build_header()
+function.
+
+Cc: "Michael S. Tsirkin" <mst@redhat.com> (supporter:ACPI/SMBIOS)
+Cc: Igor Mammedov <imammedo@redhat.com> (supporter:ACPI/SMBIOS)
+Cc: Shannon Zhao <zhaoshenglong@huawei.com> (maintainer:ARM ACPI Subsystem)
+Cc: Paolo Bonzini <pbonzini@redhat.com> (maintainer:X86)
+Cc: Richard W.M. Jones <rjones@redhat.com>
+Cc: Aleksei Kovura <alex3kov@zoho.com>
+Cc: Michael Tokarev <mjt@tls.msk.ru>
+Cc: Steven Newbury <steve@snewbury.org.uk>
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1248758
+LP: https://bugs.launchpad.net/qemu/+bug/1533848
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>
+(cherry picked from commit 5151355898699eb66fad0a710b8b6011690a0dfc)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	hw/acpi/aml-build.c
+	hw/arm/virt-acpi-build.c
+	hw/i386/acpi-build.c
+	include/hw/acpi/aml-build.h
+
+RHEL-7 backport note: this is actually a manual reimplementation of the
+upstream patch, which is mostly mechanic. A clean cherry-pick would depend
+on a lot of reorganizatorial upstream patches (e.g., 658c27181bf3
+("hw/i386/acpi-build: move generic acpi building helpers into dedictated
+file")), and many new features that overlap with ACPI generation (e.g.,
+the "virt" machtype of the arm/aarch64 targets).
+
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ hw/i386/acpi-build.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+---
+ hw/i386/acpi-build.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index 4839b0e..d9433e6 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -951,7 +951,8 @@ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
+ 
+ /* Build final rsdt table */
+ static void
+-build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
++build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets,
++           const char *oem_id, const char *oem_table_id)
+ {
+     AcpiRsdtDescriptorRev1 *rsdt;
+     size_t rsdt_len;
+@@ -970,7 +971,7 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
+                                        sizeof(uint32_t));
+     }
+     build_header(linker, table_data,
+-                 (void *)rsdt, "RSDT", rsdt_len, 1, NULL, NULL);
++                 (void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id);
+ }
+ 
+ static GArray *
+@@ -1126,7 +1127,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
+ 
+     /* RSDT is pointed to by RSDP */
+     rsdt = tables->table_data->len;
+-    build_rsdt(tables->table_data, tables->linker, table_offsets);
++    build_rsdt(tables->table_data, tables->linker, table_offsets, NULL, NULL);
+ 
+     /* RSDP is in FSEG memory, so allocate it separately */
+     build_rsdp(tables->rsdp, tables->linker, rsdt);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-acpi-fix-endian-ness-for-table-ids.patch b/SOURCES/kvm-acpi-fix-endian-ness-for-table-ids.patch
new file mode 100644
index 0000000..5c998a6
--- /dev/null
+++ b/SOURCES/kvm-acpi-fix-endian-ness-for-table-ids.patch
@@ -0,0 +1,249 @@
+From 87f01cd69488bf39e80c422b92717029fed0bef6 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Wed, 11 May 2016 12:33:43 +0200
+Subject: [PATCH 04/10] acpi: fix endian-ness for table ids
+
+RH-Author: Laszlo Ersek <lersek@redhat.com>
+Message-id: <1462970028-10959-3-git-send-email-lersek@redhat.com>
+Patchwork-id: 70379
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 2/7] acpi: fix endian-ness for table ids
+Bugzilla: 1330969
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+From: "Michael S. Tsirkin" <mst@redhat.com>
+
+when using signature for table ID, we forgot to byte-swap it.
+signatures are really ASCII strings, let's treat them as such.
+While at it, get rid of most of _SIGNATURE macros.
+
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+(cherry picked from commit 821e3227863ea8db057190e578efa0f1f57ed9de)
+
+RHEL-7 backport notes: this patch is being backported only to decrease the
+number of conflicts in the upcoming patches; we only support x86_64 hosts,
+which is unaffected by the endianness issue described in the upstream
+commit message.
+
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ hw/i386/acpi-defs.h  | 14 --------------
+ hw/i386/acpi-build.c | 31 ++++++++++++++++---------------
+ 2 files changed, 16 insertions(+), 29 deletions(-)
+
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/i386/acpi-build.c | 31 ++++++++++++++++---------------
+ hw/i386/acpi-defs.h  | 14 --------------
+ 2 files changed, 16 insertions(+), 29 deletions(-)
+
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index a3a4c3b..be32bc3 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -243,14 +243,14 @@ static void acpi_get_pci_info(PcPciInfo *info)
+ 
+ static void
+ build_header(GArray *linker, GArray *table_data,
+-             AcpiTableHeader *h, uint32_t sig, int len, uint8_t rev)
++             AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
+ {
+-    h->signature = cpu_to_le32(sig);
++    memcpy(&h->signature, sig, 4);
+     h->length = cpu_to_le32(len);
+     h->revision = rev;
+     memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
+     memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
+-    memcpy(h->oem_table_id + 4, (void *)&sig, 4);
++    memcpy(h->oem_table_id + 4, sig, 4);
+     h->oem_revision = cpu_to_le32(1);
+     memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
+     h->asl_compiler_revision = cpu_to_le32(1);
+@@ -463,7 +463,7 @@ static void
+ build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
+ {
+     AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
+-    facs->signature = cpu_to_le32(ACPI_FACS_SIGNATURE);
++    memcpy(&facs->signature, "FACS", 4);
+     facs->length = cpu_to_le32(sizeof(*facs));
+ }
+ 
+@@ -520,7 +520,7 @@ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
+     fadt_setup(fadt, pm);
+ 
+     build_header(linker, table_data,
+-                 (void *)fadt, ACPI_FACP_SIGNATURE, sizeof(*fadt), 1);
++                 (void *)fadt, "FACP", sizeof(*fadt), 1);
+ }
+ 
+ static void
+@@ -589,7 +589,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
+     local_nmi->lint         = 1; /* ACPI_LINT1 */
+ 
+     build_header(linker, table_data,
+-                 (void *)(table_data->data + madt_start), ACPI_APIC_SIGNATURE,
++                 (void *)(table_data->data + madt_start), "APIC",
+                  table_data->len - madt_start, 1);
+ }
+ 
+@@ -782,7 +782,7 @@ build_ssdt(GArray *table_data, GArray *linker,
+ 
+     build_header(linker, table_data,
+                  (void *)(table_data->data + ssdt_start),
+-                 ACPI_SSDT_SIGNATURE, table_data->len - ssdt_start, 1);
++                 "SSDT", table_data->len - ssdt_start, 1);
+ }
+ 
+ static void
+@@ -797,7 +797,7 @@ build_hpet(GArray *table_data, GArray *linker)
+     hpet->timer_block_id = cpu_to_le32(0x8086a201);
+     hpet->addr.address = cpu_to_le64(HPET_BASE);
+     build_header(linker, table_data,
+-                 (void *)hpet, ACPI_HPET_SIGNATURE, sizeof(*hpet), 1);
++                 (void *)hpet, "HPET", sizeof(*hpet), 1);
+ }
+ 
+ static void
+@@ -889,7 +889,7 @@ build_srat(GArray *table_data, GArray *linker,
+ 
+     build_header(linker, table_data,
+                  (void *)(table_data->data + srat_start),
+-                 ACPI_SRAT_SIGNATURE,
++                 "SRAT",
+                  table_data->len - srat_start, 1);
+ }
+ 
+@@ -897,7 +897,7 @@ static void
+ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
+ {
+     AcpiTableMcfg *mcfg;
+-    uint32_t sig;
++    const char *sig;
+     int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
+ 
+     mcfg = acpi_data_push(table_data, len);
+@@ -914,9 +914,10 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
+      * ACPI spec requires OSPMs to ignore such tables.
+      */
+     if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
+-        sig = ACPI_RSRV_SIGNATURE;
++        /* Reserved signature: ignored by OSPM */
++        sig = "QEMU";
+     } else {
+-        sig = ACPI_MCFG_SIGNATURE;
++        sig = "MCFG";
+     }
+     build_header(linker, table_data, (void *)mcfg, sig, len, 1);
+ }
+@@ -932,7 +933,7 @@ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
+     memcpy(dsdt, misc->dsdt_code, misc->dsdt_size);
+ 
+     memset(dsdt, 0, sizeof *dsdt);
+-    build_header(linker, table_data, dsdt, ACPI_DSDT_SIGNATURE,
++    build_header(linker, table_data, dsdt, "DSDT",
+                  misc->dsdt_size, 1);
+ }
+ 
+@@ -957,7 +958,7 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
+                                        sizeof(uint32_t));
+     }
+     build_header(linker, table_data,
+-                 (void *)rsdt, ACPI_RSDT_SIGNATURE, rsdt_len, 1);
++                 (void *)rsdt, "RSDT", rsdt_len, 1);
+ }
+ 
+ static GArray *
+@@ -968,7 +969,7 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
+     bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 1,
+                              true /* fseg memory */);
+ 
+-    rsdp->signature = cpu_to_le64(ACPI_RSDP_SIGNATURE);
++    memcpy(&rsdp->signature, "RSD PTR ", 8);
+     memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
+     rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
+     /* Address to be filled by Guest linker */
+diff --git a/hw/i386/acpi-defs.h b/hw/i386/acpi-defs.h
+index 78ca204..e93babb 100644
+--- a/hw/i386/acpi-defs.h
++++ b/hw/i386/acpi-defs.h
+@@ -52,8 +52,6 @@ struct Acpi20GenericAddress {
+ } QEMU_PACKED;
+ typedef struct Acpi20GenericAddress Acpi20GenericAddress;
+ 
+-#define ACPI_RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
+-
+ struct AcpiRsdpDescriptor {        /* Root System Descriptor Pointer */
+     uint64_t signature;              /* ACPI signature, contains "RSD PTR " */
+     uint8_t  checksum;               /* To make sum of struct == 0 */
+@@ -92,7 +90,6 @@ typedef struct AcpiTableHeader AcpiTableHeader;
+ /*
+  * ACPI 1.0 Fixed ACPI Description Table (FADT)
+  */
+-#define ACPI_FACP_SIGNATURE 0x50434146 // FACP
+ struct AcpiFadtDescriptorRev1
+ {
+     ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
+@@ -141,7 +138,6 @@ typedef struct AcpiFadtDescriptorRev1 AcpiFadtDescriptorRev1;
+ /*
+  * ACPI 1.0 Root System Description Table (RSDT)
+  */
+-#define ACPI_RSDT_SIGNATURE 0x54445352 // RSDT
+ struct AcpiRsdtDescriptorRev1
+ {
+     ACPI_TABLE_HEADER_DEF       /* ACPI common table header */
+@@ -153,7 +149,6 @@ typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1;
+ /*
+  * ACPI 1.0 Firmware ACPI Control Structure (FACS)
+  */
+-#define ACPI_FACS_SIGNATURE 0x53434146 // FACS
+ struct AcpiFacsDescriptorRev1
+ {
+     uint32_t signature;           /* ACPI Signature */
+@@ -169,7 +164,6 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
+ /*
+  * Differentiated System Description Table (DSDT)
+  */
+-#define ACPI_DSDT_SIGNATURE 0x54445344 // DSDT
+ 
+ /*
+  * MADT values and structures
+@@ -182,7 +176,6 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
+ 
+ /* Master MADT */
+ 
+-#define ACPI_APIC_SIGNATURE 0x43495041 // APIC
+ struct AcpiMultipleApicTable
+ {
+     ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
+@@ -253,7 +246,6 @@ typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
+ /*
+  * HPET Description Table
+  */
+-#define ACPI_HPET_SIGNATURE 0x54455048 // HPET
+ struct Acpi20Hpet {
+     ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */
+     uint32_t           timer_block_id;
+@@ -268,7 +260,6 @@ typedef struct Acpi20Hpet Acpi20Hpet;
+  * SRAT (NUMA topology description) table
+  */
+ 
+-#define ACPI_SRAT_SIGNATURE 0x54415253 // SRAT
+ struct AcpiSystemResourceAffinityTable
+ {
+     ACPI_TABLE_HEADER_DEF
+@@ -316,11 +307,6 @@ struct AcpiMcfgAllocation {
+ } QEMU_PACKED;
+ typedef struct AcpiMcfgAllocation AcpiMcfgAllocation;
+ 
+-#define ACPI_MCFG_SIGNATURE 0x4746434d       // MCFG
+-
+-/* Reserved signature: ignored by OSPM */
+-#define ACPI_RSRV_SIGNATURE 0x554d4551       // QEMU
+-
+ struct AcpiTableMcfg {
+     ACPI_TABLE_HEADER_DEF;
+     uint8_t reserved[8];
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-acpi-strip-compiler-info-in-built-in-DSDT.patch b/SOURCES/kvm-acpi-strip-compiler-info-in-built-in-DSDT.patch
new file mode 100644
index 0000000..816c197
--- /dev/null
+++ b/SOURCES/kvm-acpi-strip-compiler-info-in-built-in-DSDT.patch
@@ -0,0 +1,61 @@
+From 464ceecd1e9c070e613624fb896df54b7e4a3e38 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Wed, 11 May 2016 12:33:42 +0200
+Subject: [PATCH 03/10] acpi: strip compiler info in built-in DSDT
+
+RH-Author: Laszlo Ersek <lersek@redhat.com>
+Message-id: <1462970028-10959-2-git-send-email-lersek@redhat.com>
+Patchwork-id: 70378
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 1/7] acpi: strip compiler info in built-in DSDT
+Bugzilla: 1330969
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+From: "Michael S. Tsirkin" <mst@redhat.com>
+
+IASL stores it's revision in each table header it generates.
+That's not nice since guests will see a change each time they move
+between hypervisors.  We generally fill our own info for tables, but we
+(and seabios) forgot to do this for the built-in DSDT.
+
+Modifications in DSDT table:
+ OEM ID:            "BXPC" -> "BOCHS "
+ OEM Table ID:      "BXDSDT" -> "BXPCDSDT"
+ Compiler ID:       "INTL" -> "BXPC"
+ Compiler Version:  0x20130823 -> 0x00000001
+
+Tested-by: Marcel Apfelbaum <marcel.a@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+(cherry picked from commit 53db092ad1c81c30a617f44e83e8fb9e27c001ba)
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/i386/acpi-build.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index 8be1286..a3a4c3b 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -924,10 +924,16 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
+ static void
+ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
+ {
+-    void *dsdt;
++    AcpiTableHeader *dsdt;
++
+     assert(misc->dsdt_code && misc->dsdt_size);
++
+     dsdt = acpi_data_push(table_data, misc->dsdt_size);
+     memcpy(dsdt, misc->dsdt_code, misc->dsdt_size);
++
++    memset(dsdt, 0, sizeof *dsdt);
++    build_header(linker, table_data, dsdt, ACPI_DSDT_SIGNATURE,
++                 misc->dsdt_size, 1);
+ }
+ 
+ /* Build final rsdt table */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-acpi-support-specified-oem-table-id-for-build_header.patch b/SOURCES/kvm-acpi-support-specified-oem-table-id-for-build_header.patch
new file mode 100644
index 0000000..8fd5426
--- /dev/null
+++ b/SOURCES/kvm-acpi-support-specified-oem-table-id-for-build_header.patch
@@ -0,0 +1,154 @@
+From b36e60614f9c4a6eb3f417422c3cb99402b82963 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Wed, 11 May 2016 12:33:44 +0200
+Subject: [PATCH 05/10] acpi: support specified oem table id for build_header
+
+RH-Author: Laszlo Ersek <lersek@redhat.com>
+Message-id: <1462970028-10959-4-git-send-email-lersek@redhat.com>
+Patchwork-id: 70380
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 3/7] acpi: support specified oem table id for build_header
+Bugzilla: 1330969
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+From: Xiao Guangrong <guangrong.xiao@linux.intel.com>
+
+Let build_header() support specified OEM table id so that we can build
+multiple SSDT later
+
+If the oem table id is not specified (aka, NULL), we use the default id
+instead as the previous behavior
+
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+(cherry picked from commit 8870ca0e94f2524644812dd759863c0851ffb870)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	hw/acpi/aml-build.c
+	hw/arm/virt-acpi-build.c
+	hw/i386/acpi-build.c
+	include/hw/acpi/aml-build.h
+
+RHEL-7 backport note: this is actually a manual reimplementation of the
+upstream patch, which is mostly mechanic. A clean cherry-pick would depend
+on a lot of reorganizatorial upstream patches (e.g., 658c27181bf3
+("hw/i386/acpi-build: move generic acpi building helpers into dedictated
+file")), and many new features that overlap with ACPI generation (e.g.,
+the "virt" machtype of the arm/aarch64 targets).
+
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ hw/i386/acpi-build.c | 29 ++++++++++++++++++-----------
+ 1 file changed, 18 insertions(+), 11 deletions(-)
+---
+ hw/i386/acpi-build.c | 29 ++++++++++++++++++-----------
+ 1 file changed, 18 insertions(+), 11 deletions(-)
+
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index be32bc3..a9d9f97 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -243,14 +243,21 @@ static void acpi_get_pci_info(PcPciInfo *info)
+ 
+ static void
+ build_header(GArray *linker, GArray *table_data,
+-             AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
++             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
++             const char *oem_table_id)
+ {
+     memcpy(&h->signature, sig, 4);
+     h->length = cpu_to_le32(len);
+     h->revision = rev;
+     memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
+-    memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
+-    memcpy(h->oem_table_id + 4, sig, 4);
++
++    if (oem_table_id) {
++        strncpy((char *)h->oem_table_id, oem_table_id, sizeof(h->oem_table_id));
++    } else {
++        memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
++        memcpy(h->oem_table_id + 4, sig, 4);
++    }
++
+     h->oem_revision = cpu_to_le32(1);
+     memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
+     h->asl_compiler_revision = cpu_to_le32(1);
+@@ -520,7 +527,7 @@ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
+     fadt_setup(fadt, pm);
+ 
+     build_header(linker, table_data,
+-                 (void *)fadt, "FACP", sizeof(*fadt), 1);
++                 (void *)fadt, "FACP", sizeof(*fadt), 1, NULL);
+ }
+ 
+ static void
+@@ -590,7 +597,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
+ 
+     build_header(linker, table_data,
+                  (void *)(table_data->data + madt_start), "APIC",
+-                 table_data->len - madt_start, 1);
++                 table_data->len - madt_start, 1, NULL);
+ }
+ 
+ /* Encode a hex value */
+@@ -782,7 +789,7 @@ build_ssdt(GArray *table_data, GArray *linker,
+ 
+     build_header(linker, table_data,
+                  (void *)(table_data->data + ssdt_start),
+-                 "SSDT", table_data->len - ssdt_start, 1);
++                 "SSDT", table_data->len - ssdt_start, 1, NULL);
+ }
+ 
+ static void
+@@ -797,7 +804,7 @@ build_hpet(GArray *table_data, GArray *linker)
+     hpet->timer_block_id = cpu_to_le32(0x8086a201);
+     hpet->addr.address = cpu_to_le64(HPET_BASE);
+     build_header(linker, table_data,
+-                 (void *)hpet, "HPET", sizeof(*hpet), 1);
++                 (void *)hpet, "HPET", sizeof(*hpet), 1, NULL);
+ }
+ 
+ static void
+@@ -890,7 +897,7 @@ build_srat(GArray *table_data, GArray *linker,
+     build_header(linker, table_data,
+                  (void *)(table_data->data + srat_start),
+                  "SRAT",
+-                 table_data->len - srat_start, 1);
++                 table_data->len - srat_start, 1, NULL);
+ }
+ 
+ static void
+@@ -919,7 +926,7 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
+     } else {
+         sig = "MCFG";
+     }
+-    build_header(linker, table_data, (void *)mcfg, sig, len, 1);
++    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL);
+ }
+ 
+ static void
+@@ -934,7 +941,7 @@ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
+ 
+     memset(dsdt, 0, sizeof *dsdt);
+     build_header(linker, table_data, dsdt, "DSDT",
+-                 misc->dsdt_size, 1);
++                 misc->dsdt_size, 1, NULL);
+ }
+ 
+ /* Build final rsdt table */
+@@ -958,7 +965,7 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
+                                        sizeof(uint32_t));
+     }
+     build_header(linker, table_data,
+-                 (void *)rsdt, "RSDT", rsdt_len, 1);
++                 (void *)rsdt, "RSDT", rsdt_len, 1, NULL);
+ }
+ 
+ static GArray *
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-acpi-take-oem_id-in-build_header-optionally.patch b/SOURCES/kvm-acpi-take-oem_id-in-build_header-optionally.patch
new file mode 100644
index 0000000..8670c32
--- /dev/null
+++ b/SOURCES/kvm-acpi-take-oem_id-in-build_header-optionally.patch
@@ -0,0 +1,157 @@
+From 0decede8a51451da8f5913b0ad13c8e3bdcef582 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Wed, 11 May 2016 12:33:45 +0200
+Subject: [PATCH 06/10] acpi: take oem_id in build_header(), optionally
+
+RH-Author: Laszlo Ersek <lersek@redhat.com>
+Message-id: <1462970028-10959-5-git-send-email-lersek@redhat.com>
+Patchwork-id: 70381
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 4/7] acpi: take oem_id in build_header(), optionally
+Bugzilla: 1330969
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+This patch is the continuation of commit 8870ca0e94f2 ("acpi: support
+specified oem table id for build_header"). It will allow us to control the
+OEM ID field too in the SDT header.
+
+Cc: "Michael S. Tsirkin" <mst@redhat.com> (supporter:ACPI/SMBIOS)
+Cc: Igor Mammedov <imammedo@redhat.com> (supporter:ACPI/SMBIOS)
+Cc: Xiao Guangrong <guangrong.xiao@linux.intel.com> (maintainer:NVDIMM)
+Cc: Shannon Zhao <zhaoshenglong@huawei.com> (maintainer:ARM ACPI Subsystem)
+Cc: Paolo Bonzini <pbonzini@redhat.com> (maintainer:X86)
+Cc: Richard W.M. Jones <rjones@redhat.com>
+Cc: Aleksei Kovura <alex3kov@zoho.com>
+Cc: Michael Tokarev <mjt@tls.msk.ru>
+Cc: Steven Newbury <steve@snewbury.org.uk>
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1248758
+LP: https://bugs.launchpad.net/qemu/+bug/1533848
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>
+(cherry picked from commit 37ad223c515da2fe9f1c679768cb5ccaa42e57e1)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	hw/acpi/aml-build.c
+	hw/acpi/nvdimm.c
+	hw/arm/virt-acpi-build.c
+	hw/i386/acpi-build.c
+	include/hw/acpi/aml-build.h
+
+RHEL-7 backport note: this is actually a manual reimplementation of the
+upstream patch, which is mostly mechanic. A clean cherry-pick would depend
+on a lot of reorganizatorial upstream patches (e.g., 658c27181bf3
+("hw/i386/acpi-build: move generic acpi building helpers into dedictated
+file")), and many new features that overlap with ACPI generation (e.g.,
+the "virt" machtype of the arm/aarch64 targets).
+
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ hw/i386/acpi-build.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+---
+ hw/i386/acpi-build.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index a9d9f97..4839b0e 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -244,12 +244,17 @@ static void acpi_get_pci_info(PcPciInfo *info)
+ static void
+ build_header(GArray *linker, GArray *table_data,
+              AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
+-             const char *oem_table_id)
++             const char *oem_id, const char *oem_table_id)
+ {
+     memcpy(&h->signature, sig, 4);
+     h->length = cpu_to_le32(len);
+     h->revision = rev;
+-    memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
++
++    if (oem_id) {
++        strncpy((char *)h->oem_id, oem_id, sizeof h->oem_id);
++    } else {
++        memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
++    }
+ 
+     if (oem_table_id) {
+         strncpy((char *)h->oem_table_id, oem_table_id, sizeof(h->oem_table_id));
+@@ -527,7 +532,7 @@ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
+     fadt_setup(fadt, pm);
+ 
+     build_header(linker, table_data,
+-                 (void *)fadt, "FACP", sizeof(*fadt), 1, NULL);
++                 (void *)fadt, "FACP", sizeof(*fadt), 1, NULL, NULL);
+ }
+ 
+ static void
+@@ -597,7 +602,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
+ 
+     build_header(linker, table_data,
+                  (void *)(table_data->data + madt_start), "APIC",
+-                 table_data->len - madt_start, 1, NULL);
++                 table_data->len - madt_start, 1, NULL, NULL);
+ }
+ 
+ /* Encode a hex value */
+@@ -789,7 +794,7 @@ build_ssdt(GArray *table_data, GArray *linker,
+ 
+     build_header(linker, table_data,
+                  (void *)(table_data->data + ssdt_start),
+-                 "SSDT", table_data->len - ssdt_start, 1, NULL);
++                 "SSDT", table_data->len - ssdt_start, 1, NULL, NULL);
+ }
+ 
+ static void
+@@ -804,7 +809,7 @@ build_hpet(GArray *table_data, GArray *linker)
+     hpet->timer_block_id = cpu_to_le32(0x8086a201);
+     hpet->addr.address = cpu_to_le64(HPET_BASE);
+     build_header(linker, table_data,
+-                 (void *)hpet, "HPET", sizeof(*hpet), 1, NULL);
++                 (void *)hpet, "HPET", sizeof(*hpet), 1, NULL, NULL);
+ }
+ 
+ static void
+@@ -897,7 +902,7 @@ build_srat(GArray *table_data, GArray *linker,
+     build_header(linker, table_data,
+                  (void *)(table_data->data + srat_start),
+                  "SRAT",
+-                 table_data->len - srat_start, 1, NULL);
++                 table_data->len - srat_start, 1, NULL, NULL);
+ }
+ 
+ static void
+@@ -926,7 +931,7 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
+     } else {
+         sig = "MCFG";
+     }
+-    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL);
++    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
+ }
+ 
+ static void
+@@ -941,7 +946,7 @@ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
+ 
+     memset(dsdt, 0, sizeof *dsdt);
+     build_header(linker, table_data, dsdt, "DSDT",
+-                 misc->dsdt_size, 1, NULL);
++                 misc->dsdt_size, 1, NULL, NULL);
+ }
+ 
+ /* Build final rsdt table */
+@@ -965,7 +970,7 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
+                                        sizeof(uint32_t));
+     }
+     build_header(linker, table_data,
+-                 (void *)rsdt, "RSDT", rsdt_len, 1, NULL);
++                 (void *)rsdt, "RSDT", rsdt_len, 1, NULL, NULL);
+ }
+ 
+ static GArray *
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-blkdebug-Add-BLKDBG_FLUSH_TO_OS-DISK-events.patch b/SOURCES/kvm-blkdebug-Add-BLKDBG_FLUSH_TO_OS-DISK-events.patch
new file mode 100644
index 0000000..b65b85e
--- /dev/null
+++ b/SOURCES/kvm-blkdebug-Add-BLKDBG_FLUSH_TO_OS-DISK-events.patch
@@ -0,0 +1,100 @@
+From 89f3f5eafd6aed8a79b4570553af711dffc3a1d6 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:36 +0100
+Subject: [PATCH 17/27] blkdebug: Add BLKDBG_FLUSH_TO_OS/DISK events
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-18-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68448
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 17/21] blkdebug: Add BLKDBG_FLUSH_TO_OS/DISK events
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit bf736fe34caba0688c9095c31b9d097ea15c1296)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+  block/blkdebug.c:      debug event ordering
+  include/block/block.h: debug event ordering
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ block.c               | 8 ++++----
+ block/blkdebug.c      | 3 +++
+ include/block/block.h | 3 +++
+ 3 files changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/block.c b/block.c
+index bc6e75c..ecb2b09 100644
+--- a/block.c
++++ b/block.c
+@@ -4026,13 +4026,11 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
+ 
+ void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
+ {
+-    BlockDriver *drv = bs->drv;
+-
+-    if (!drv || !drv->bdrv_debug_event) {
++    if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) {
+         return;
+     }
+ 
+-    drv->bdrv_debug_event(bs, event);
++    bs->drv->bdrv_debug_event(bs, event);
+ }
+ 
+ int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
+@@ -4879,6 +4877,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
+     }
+ 
+     /* Write back cached data to the OS even with cache=unsafe */
++    BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_OS);
+     if (bs->drv->bdrv_co_flush_to_os) {
+         ret = bs->drv->bdrv_co_flush_to_os(bs);
+         if (ret < 0) {
+@@ -4891,6 +4890,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
+         goto flush_parent;
+     }
+ 
++    BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK);
+     if (bs->drv->bdrv_co_flush_to_disk) {
+         ret = bs->drv->bdrv_co_flush_to_disk(bs);
+     } else if (bs->drv->bdrv_aio_flush) {
+diff --git a/block/blkdebug.c b/block/blkdebug.c
+index c61ce52..8e468b2 100644
+--- a/block/blkdebug.c
++++ b/block/blkdebug.c
+@@ -184,6 +184,9 @@ static const char *event_names[BLKDBG_EVENT_MAX] = {
+     [BLKDBG_CLUSTER_ALLOC_BYTES]            = "cluster_alloc_bytes",
+     [BLKDBG_CLUSTER_FREE]                   = "cluster_free",
+ 
++    [BLKDBG_FLUSH_TO_OS]                    = "flush_to_os",
++    [BLKDBG_FLUSH_TO_DISK]                  = "flush_to_disk",
++
+     [BLKDBG_PWRITEV_RMW_HEAD]               = "pwritev_rmw.head",
+     [BLKDBG_PWRITEV_RMW_AFTER_HEAD]         = "pwritev_rmw.after_head",
+     [BLKDBG_PWRITEV_RMW_TAIL]               = "pwritev_rmw.tail",
+diff --git a/include/block/block.h b/include/block/block.h
+index 8339cac..75147b2 100644
+--- a/include/block/block.h
++++ b/include/block/block.h
+@@ -508,6 +508,9 @@ typedef enum {
+     BLKDBG_CLUSTER_ALLOC_BYTES,
+     BLKDBG_CLUSTER_FREE,
+ 
++    BLKDBG_FLUSH_TO_OS,
++    BLKDBG_FLUSH_TO_DISK,
++
+     BLKDBG_PWRITEV_RMW_HEAD,
+     BLKDBG_PWRITEV_RMW_AFTER_HEAD,
+     BLKDBG_PWRITEV_RMW_TAIL,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-block-backend-expose-bs-bl.max_transfer_length.patch b/SOURCES/kvm-block-backend-expose-bs-bl.max_transfer_length.patch
new file mode 100644
index 0000000..587dc00
--- /dev/null
+++ b/SOURCES/kvm-block-backend-expose-bs-bl.max_transfer_length.patch
@@ -0,0 +1,66 @@
+From b9d7b6bbaa64404eb9b4a65d0af841bfae5c9089 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 11 Jul 2016 05:33:36 +0200
+Subject: [PATCH 3/7] block-backend: expose bs->bl.max_transfer_length
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1468215219-30793-4-git-send-email-famz@redhat.com>
+Patchwork-id: 71107
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 3/6] block-backend: expose bs->bl.max_transfer_length
+Bugzilla: 1318199
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Peter Lieven <pl@kamp.de>
+
+Signed-off-by: Peter Lieven <pl@kamp.de>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 454057b7d9b9ad141bd5df8c4075745e56b4870f)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	block/block-backend.c
+	include/sysemu/block-backend.h
+
+Downstream doesn't have BlockBackend yet, so "blk_" -> "bdrv_" and put
+the function in block.c.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+---
+ block.c               | 5 +++++
+ include/block/block.h | 1 +
+ 2 files changed, 6 insertions(+)
+
+diff --git a/block.c b/block.c
+index ae756aa..bdcd741 100644
+--- a/block.c
++++ b/block.c
+@@ -3656,6 +3656,11 @@ int bdrv_get_flags(BlockDriverState *bs)
+     return bs->open_flags;
+ }
+ 
++int bdrv_get_max_transfer_length(BlockDriverState *bs)
++{
++    return bs->bl.max_transfer_length;
++}
++
+ int bdrv_flush_all(void)
+ {
+     BlockDriverState *bs;
+diff --git a/include/block/block.h b/include/block/block.h
+index 75147b2..d29733a 100644
+--- a/include/block/block.h
++++ b/include/block/block.h
+@@ -379,6 +379,7 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
+                          void *opaque);
+ const char *bdrv_get_device_name(BlockDriverState *bs);
+ int bdrv_get_flags(BlockDriverState *bs);
++int bdrv_get_max_transfer_length(BlockDriverState *bs);
+ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
+                           const uint8_t *buf, int nb_sectors);
+ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-block-iscsi-avoid-potential-overflow-of-acb-task-cdb.patch b/SOURCES/kvm-block-iscsi-avoid-potential-overflow-of-acb-task-cdb.patch
index eb8cf75..bd3e9f4 100644
--- a/SOURCES/kvm-block-iscsi-avoid-potential-overflow-of-acb-task-cdb.patch
+++ b/SOURCES/kvm-block-iscsi-avoid-potential-overflow-of-acb-task-cdb.patch
@@ -1,16 +1,16 @@
-From f5596dffdad4014342239c7d3ec85e637969d2de Mon Sep 17 00:00:00 2001
+From d2291657a3d6100be53008fe8206c9e72b37c584 Mon Sep 17 00:00:00 2001
 From: Fam Zheng <famz@redhat.com>
-Date: Fri, 29 Jul 2016 07:54:22 +0200
+Date: Wed, 22 Jun 2016 01:06:15 +0200
 Subject: [PATCH] block/iscsi: avoid potential overflow of acb->task->cdb
 
 RH-Author: Fam Zheng <famz@redhat.com>
-Message-id: <1469778862-32607-1-git-send-email-famz@redhat.com>
-Patchwork-id: 71515
-O-Subject: [RHEL-7.2.z qemu-kvm PATCH] block/iscsi: avoid potential overflow of acb->task->cdb
-Bugzilla: 1358996
-RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
-RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+Message-id: <20160622010615.10307-1-famz@redhat.com>
+Patchwork-id: 70730
+O-Subject: [RHEL-7.3 qemu-kvm PATCH] block/iscsi: avoid potential overflow of acb->task->cdb
+Bugzilla: 1340929
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
 RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
 
 From: Peter Lieven <pl@kamp.de>
 
diff --git a/SOURCES/kvm-block-jobs-qemu-kvm-rhel-differentiation.patch b/SOURCES/kvm-block-jobs-qemu-kvm-rhel-differentiation.patch
new file mode 100644
index 0000000..c3c30e0
--- /dev/null
+++ b/SOURCES/kvm-block-jobs-qemu-kvm-rhel-differentiation.patch
@@ -0,0 +1,141 @@
+From bb8aca64535578520c4b7f5186f9ae5754626694 Mon Sep 17 00:00:00 2001
+From: Jeffrey Cody <jcody@redhat.com>
+Date: Thu, 5 May 2016 19:46:28 +0200
+Subject: [PATCH 10/10] block jobs: qemu-kvm-rhel differentiation
+
+RH-Author: Jeffrey Cody <jcody@redhat.com>
+Message-id: <f2ce1dbde4055f710cb6f83e6edd9e93a498b366.1462477116.git.jcody@redhat.com>
+Patchwork-id: 70344
+O-Subject: [RHEL7.3 qemu-kvm-rhel 1/1] block jobs: qemu-kvm-rhel differentiation
+Bugzilla: 1156635
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+The conditional block job disablement for RHEL left some QAPI / HMP
+commands in place, that are vestigial without any actual block jobs to
+control.
+
+This patch envelopes those block-job related functions in the
+conditional code that is disabled for RHEL:
+
+block-job-set-speed
+block-job-cancel
+block-job-pause
+block-job-resume
+block-job-complete
+
+Signed-off-by: Jeff Cody <jcody@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ blockdev.c       | 2 +-
+ hmp-commands.hx  | 2 +-
+ hmp.c            | 2 +-
+ qapi-schema.json | 2 +-
+ qmp-commands.hx  | 3 ---
+ 5 files changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/blockdev.c b/blockdev.c
+index b5792a2..69e951f 100644
+--- a/blockdev.c
++++ b/blockdev.c
+@@ -1701,7 +1701,6 @@ void qmp_drive_mirror(const char *device, const char *target,
+         return;
+     }
+ }
+-#endif
+ 
+ static BlockJob *find_block_job(const char *device)
+ {
+@@ -1786,6 +1785,7 @@ void qmp_block_job_complete(const char *device, Error **errp)
+     trace_qmp_block_job_complete(job);
+     block_job_complete(job, errp);
+ }
++#endif
+ 
+ void qmp___com_redhat_change_backing_file(const char *device,
+                                           const char *image_node_name,
+diff --git a/hmp-commands.hx b/hmp-commands.hx
+index 7e1855a..dd528d2 100644
+--- a/hmp-commands.hx
++++ b/hmp-commands.hx
+@@ -81,7 +81,6 @@ ETEXI
+         .help       = "copy data from a backing file into a block device",
+         .mhandler.cmd = hmp_block_stream,
+     },
+-#endif
+ 
+ STEXI
+ @item block_stream
+@@ -160,6 +159,7 @@ STEXI
+ @findex block_job_resume
+ Resume a paused block streaming operation.
+ ETEXI
++#endif
+ 
+     {
+         .name       = "eject",
+diff --git a/hmp.c b/hmp.c
+index e1d92f4..fb9b445 100644
+--- a/hmp.c
++++ b/hmp.c
+@@ -1053,7 +1053,6 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
+ 
+     hmp_handle_error(mon, &error);
+ }
+-#endif
+ 
+ void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict)
+ {
+@@ -1106,6 +1105,7 @@ void hmp_block_job_complete(Monitor *mon, const QDict *qdict)
+ 
+     hmp_handle_error(mon, &error);
+ }
++#endif
+ 
+ typedef struct MigrationStatus
+ {
+diff --git a/qapi-schema.json b/qapi-schema.json
+index c8732c1..5138ed9 100644
+--- a/qapi-schema.json
++++ b/qapi-schema.json
+@@ -2326,7 +2326,6 @@
+ { 'command': 'block-stream',
+   'data': { 'device': 'str', '*base': 'str', '*backing-file': 'str',
+             '*speed': 'int', '*on-error': 'BlockdevOnError' } }
+-#_end-rhev-only
+ 
+ ##
+ # @block-job-set-speed:
+@@ -2448,6 +2447,7 @@
+ # Since: 1.3
+ ##
+ { 'command': 'block-job-complete', 'data': { 'device': 'str' } }
++#_end-rhev-only
+ 
+ ##
+ # @ObjectTypeInfo:
+diff --git a/qmp-commands.hx b/qmp-commands.hx
+index 22a09be..9522c44 100644
+--- a/qmp-commands.hx
++++ b/qmp-commands.hx
+@@ -1089,8 +1089,6 @@ Example:
+ 
+ EQMP
+ 
+-#endif
+-
+     {
+         .name       = "block-job-set-speed",
+         .args_type  = "device:B,speed:o",
+@@ -1117,7 +1115,6 @@ EQMP
+         .args_type  = "device:B",
+         .mhandler.cmd_new = qmp_marshal_input_block_job_complete,
+     },
+-#ifdef CONFIG_LIVE_BLOCK_OPS
+     {
+         .name       = "transaction",
+         .args_type  = "actions:q",
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-block-raw-posix-Open-file-descriptor-O_RDWR-to-work-.patch b/SOURCES/kvm-block-raw-posix-Open-file-descriptor-O_RDWR-to-work-.patch
new file mode 100644
index 0000000..fc8ca11
--- /dev/null
+++ b/SOURCES/kvm-block-raw-posix-Open-file-descriptor-O_RDWR-to-work-.patch
@@ -0,0 +1,68 @@
+From 9452583824b50cb6f095c5ec1894b38df7b01175 Mon Sep 17 00:00:00 2001
+Message-Id: <9452583824b50cb6f095c5ec1894b38df7b01175.1464449390.git.jen@redhat.com>
+In-Reply-To: <c7936395ecf322b3de37662c7c6b772e36866cc7.1464449390.git.jen@redhat.com>
+References: <c7936395ecf322b3de37662c7c6b772e36866cc7.1464449390.git.jen@redhat.com>
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Mon, 23 May 2016 11:28:41 -0400
+Subject: [CHANGE 3/3] block/raw-posix: Open file descriptor O_RDWR to work
+ around glibc posix_fallocate emulation issue.
+To: rhvirt-patches@redhat.com,
+    jen@redhat.com
+
+RH-Author: Kevin Wolf <kwolf@redhat.com>
+Message-id: <1464002921-1079-2-git-send-email-kwolf@redhat.com>
+Patchwork-id: 70425
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/1] block/raw-posix: Open file descriptor O_RDWR to work around glibc posix_fallocate emulation issue.
+Bugzilla: 1268345
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Richard Jones <rjones@redhat.com>
+
+From: "Richard W.M. Jones" <rjones@redhat.com>
+
+The following command fails on an NFS mountpoint:
+
+  $ qemu-img create -f qcow2 -o preallocation=falloc disk.img 262144
+  Formatting 'disk.img', fmt=qcow2 size=262144 encryption=off cluster_size=65536 preallocation='falloc' lazy_refcounts=off
+  qemu-img: disk.img: Could not preallocate data for the new file: Bad file descriptor
+
+The reason turns out to be because NFS doesn't support the
+posix_fallocate call.  glibc emulates it instead.  However glibc's
+emulation involves using the pread(2) syscall.  The pread syscall
+fails with EBADF if the file descriptor is opened without the read
+open-flag (ie. open (..., O_WRONLY)).
+
+I contacted glibc upstream about this, and their response is here:
+
+  https://bugzilla.redhat.com/show_bug.cgi?id=1265196#c9
+
+There are two possible fixes: Use Linux fallocate directly, or (this
+fix) work around the problem in qemu by opening the file with O_RDWR
+instead of O_WRONLY.
+
+Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
+Reviewed-by: Jeff Cody <jcody@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 73ba05d936e82fe01b2b2cf987bf3aecb4792af5)
+Signed-off-by: Jeff E. Nelson <jen@redhat.com>
+---
+ block/raw-posix.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/block/raw-posix.c b/block/raw-posix.c
+index 1f5275f..92fcb6c 100644
+--- a/block/raw-posix.c
++++ b/block/raw-posix.c
+@@ -1265,7 +1265,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
+         options++;
+     }
+ 
+-    fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
++    fd = qemu_open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
+                    0644);
+     if (fd < 0) {
+         result = -errno;
+-- 
+2.5.5
+
diff --git a/SOURCES/kvm-block-vmdk-fixed-sizeof-error.patch b/SOURCES/kvm-block-vmdk-fixed-sizeof-error.patch
new file mode 100644
index 0000000..34c517c
--- /dev/null
+++ b/SOURCES/kvm-block-vmdk-fixed-sizeof-error.patch
@@ -0,0 +1,50 @@
+From 37bf9db781d9507501649ee04d23b0dab103a126 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:23 +0100
+Subject: [PATCH 10/18] block: vmdk - fixed sizeof() error
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-11-git-send-email-famz@redhat.com>
+Patchwork-id: 69176
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 10/18] block: vmdk - fixed sizeof() error
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+From: Jeff Cody <jcody@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+The size compared should be PATH_MAX, rather than sizeof(char *).
+
+Reported-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Jeff Cody <jcody@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Message-id: 46d873261433f4527e88885582f96942d61758d6.1423592487.git.jcody@redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit a7be17bee855f26c317e99aa6582e1dc9b8ebd71)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 45ecf02..32b3d4c 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -838,8 +838,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
+         }
+ 
+         extent_path = g_malloc0(PATH_MAX);
+-        path_combine(extent_path, sizeof(extent_path),
+-                desc_file_path, fname);
++        path_combine(extent_path, PATH_MAX, desc_file_path, fname);
+         extent_file = NULL;
+         ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags,
+                              errp);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-block-vmdk-make-ret-variable-usage-clear.patch b/SOURCES/kvm-block-vmdk-make-ret-variable-usage-clear.patch
new file mode 100644
index 0000000..afc092c
--- /dev/null
+++ b/SOURCES/kvm-block-vmdk-make-ret-variable-usage-clear.patch
@@ -0,0 +1,86 @@
+From 931d28d0c1c1015df16fbffb8422895497193a78 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:21 +0100
+Subject: [PATCH 08/18] block: vmdk - make ret variable usage clear
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-9-git-send-email-famz@redhat.com>
+Patchwork-id: 69174
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 08/18] block: vmdk - make ret variable usage clear
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+From: Jeff Cody <jcody@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+Keep the variable 'ret' something that is returned by the function it is
+defined in.  For the return value of 'sscanf', use a more meaningful
+variable name.
+
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Jeff Cody <jcody@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 395a22fae064df64d987d703cf70ae0f57306be8)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 1247ea4..3351782 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -788,6 +788,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
+                               const char *desc_file_path, Error **errp)
+ {
+     int ret;
++    int matches;
+     char access[11];
+     char type[11];
+     char fname[512];
+@@ -799,6 +800,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
+     BDRVVmdkState *s = bs->opaque;
+     VmdkExtent *extent;
+ 
++
+     while (*p) {
+         /* parse extent line in one of below formats:
+          *
+@@ -808,23 +810,23 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
+          * RW [size in sectors] VMFSSPARSE "file-name.vmdk"
+          */
+         flat_offset = -1;
+-        ret = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
+-                access, &sectors, type, fname, &flat_offset);
+-        if (ret < 4 || strcmp(access, "RW")) {
++        matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
++                         access, &sectors, type, fname, &flat_offset);
++        if (matches < 4 || strcmp(access, "RW")) {
+             goto next_line;
+         } else if (!strcmp(type, "FLAT")) {
+-            if (ret != 5 || flat_offset < 0) {
++            if (matches != 5 || flat_offset < 0) {
+                 error_setg(errp, "Invalid extent lines: \n%s", p);
+                 return -EINVAL;
+             }
+         } else if (!strcmp(type, "VMFS")) {
+-            if (ret == 4) {
++            if (matches == 4) {
+                 flat_offset = 0;
+             } else {
+                 error_setg(errp, "Invalid extent lines:\n%s", p);
+                 return -EINVAL;
+             }
+-        } else if (ret != 4) {
++        } else if (matches != 4) {
+             error_setg(errp, "Invalid extent lines:\n%s", p);
+             return -EINVAL;
+         }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-block-vmdk-move-string-allocations-from-stack-to-the.patch b/SOURCES/kvm-block-vmdk-move-string-allocations-from-stack-to-the.patch
new file mode 100644
index 0000000..e1d5c95
--- /dev/null
+++ b/SOURCES/kvm-block-vmdk-move-string-allocations-from-stack-to-the.patch
@@ -0,0 +1,146 @@
+From a767838caf6c761d714a9466d008f8dddaf1a162 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:22 +0100
+Subject: [PATCH 09/18] block: vmdk - move string allocations from stack to the
+ heap
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-10-git-send-email-famz@redhat.com>
+Patchwork-id: 69175
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 09/18] block: vmdk - move string allocations from stack to the heap
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+From: Jeff Cody <jcody@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+Functions 'vmdk_parse_extents' and 'vmdk_create' allocate several
+PATH_MAX sized arrays on the stack.  Make these dynamically allocated.
+
+Signed-off-by: Jeff Cody <jcody@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit fe2065629a9c256f836770ca54449ae77b22d188)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 40 ++++++++++++++++++++++++----------------
+ 1 file changed, 24 insertions(+), 16 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 3351782..45ecf02 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -795,12 +795,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
+     const char *p = desc;
+     int64_t sectors = 0;
+     int64_t flat_offset;
+-    char extent_path[PATH_MAX];
++    char *extent_path;
+     BlockDriverState *extent_file;
+     BDRVVmdkState *s = bs->opaque;
+     VmdkExtent *extent;
+ 
+-
+     while (*p) {
+         /* parse extent line in one of below formats:
+          *
+@@ -838,10 +837,13 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
+             goto next_line;
+         }
+ 
++        extent_path = g_malloc0(PATH_MAX);
+         path_combine(extent_path, sizeof(extent_path),
+                 desc_file_path, fname);
++        extent_file = NULL;
+         ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags,
+                              errp);
++        g_free(extent_path);
+         if (ret) {
+             return ret;
+         }
+@@ -1790,10 +1792,15 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
+     int ret = 0;
+     bool flat, split, compress;
+     GString *ext_desc_lines;
+-    char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
++    char *path = g_malloc0(PATH_MAX);
++    char *prefix = g_malloc0(PATH_MAX);
++    char *postfix = g_malloc0(PATH_MAX);
++    char *desc_line = g_malloc0(BUF_SIZE);
++    char *ext_filename = g_malloc0(PATH_MAX);
++    char *desc_filename = g_malloc0(PATH_MAX);
+     const int64_t split_size = 0x80000000;  /* VMDK has constant split size */
+     const char *desc_extent_line;
+-    char parent_desc_line[BUF_SIZE] = "";
++    char *parent_desc_line = g_malloc0(BUF_SIZE);
+     uint32_t parent_cid = 0xffffffff;
+     uint32_t number_heads = 16;
+     bool zeroed_grain = false;
+@@ -1902,33 +1909,27 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
+         }
+         parent_cid = vmdk_read_cid(bs, 0);
+         bdrv_unref(bs);
+-        snprintf(parent_desc_line, sizeof(parent_desc_line),
++        snprintf(parent_desc_line, BUF_SIZE,
+                 "parentFileNameHint=\"%s\"", backing_file);
+     }
+ 
+     /* Create extents */
+     filesize = total_size;
+     while (filesize > 0) {
+-        char desc_line[BUF_SIZE];
+-        char ext_filename[PATH_MAX];
+-        char desc_filename[PATH_MAX];
+         int64_t size = filesize;
+ 
+         if (split && size > split_size) {
+             size = split_size;
+         }
+         if (split) {
+-            snprintf(desc_filename, sizeof(desc_filename), "%s-%c%03d%s",
++            snprintf(desc_filename, PATH_MAX, "%s-%c%03d%s",
+                     prefix, flat ? 'f' : 's', ++idx, postfix);
+         } else if (flat) {
+-            snprintf(desc_filename, sizeof(desc_filename), "%s-flat%s",
+-                    prefix, postfix);
++            snprintf(desc_filename, PATH_MAX, "%s-flat%s", prefix, postfix);
+         } else {
+-            snprintf(desc_filename, sizeof(desc_filename), "%s%s",
+-                    prefix, postfix);
++            snprintf(desc_filename, PATH_MAX, "%s%s", prefix, postfix);
+         }
+-        snprintf(ext_filename, sizeof(ext_filename), "%s%s",
+-                path, desc_filename);
++        snprintf(ext_filename, PATH_MAX, "%s%s", path, desc_filename);
+ 
+         if (vmdk_create_extent(ext_filename, size,
+                                flat, compress, zeroed_grain, errp)) {
+@@ -1938,7 +1939,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
+         filesize -= size;
+ 
+         /* Format description line */
+-        snprintf(desc_line, sizeof(desc_line),
++        snprintf(desc_line, BUF_SIZE,
+                     desc_extent_line, size / BDRV_SECTOR_SIZE, desc_filename);
+         g_string_append(ext_desc_lines, desc_line);
+     }
+@@ -1988,6 +1989,13 @@ exit:
+         bdrv_unref(new_bs);
+     }
+     g_free(desc);
++    g_free(path);
++    g_free(prefix);
++    g_free(postfix);
++    g_free(desc_line);
++    g_free(ext_filename);
++    g_free(desc_filename);
++    g_free(parent_desc_line);
+     g_string_free(ext_desc_lines, true);
+     return ret;
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-check-qjson-Add-test-for-JSON-nesting-depth-limit.patch b/SOURCES/kvm-check-qjson-Add-test-for-JSON-nesting-depth-limit.patch
new file mode 100644
index 0000000..aac6412
--- /dev/null
+++ b/SOURCES/kvm-check-qjson-Add-test-for-JSON-nesting-depth-limit.patch
@@ -0,0 +1,73 @@
+From 38d4fe12ad2e3bc18842201f437c480120eace2b Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:02 +0200
+Subject: [PATCH 04/16] check-qjson: Add test for JSON nesting depth limit
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-6-git-send-email-armbru@redhat.com>
+Patchwork-id: 71481
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 04/15] check-qjson: Add test for JSON nesting depth limit
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+This would have prevented the regression mentioned in the previous
+commit.
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Message-Id: <1448486613-17634-4-git-send-email-armbru@redhat.com>
+(cherry picked from commit f0ae0304c7a41a42b7d4a6cde450da938d3c2cc7)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ tests/check-qjson.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/tests/check-qjson.c b/tests/check-qjson.c
+index 4e74548..c5dd74d 100644
+--- a/tests/check-qjson.c
++++ b/tests/check-qjson.c
+@@ -1465,6 +1465,30 @@ static void unterminated_literal(void)
+     g_assert(obj == NULL);
+ }
+ 
++static char *make_nest(char *buf, size_t cnt)
++{
++    memset(buf, '[', cnt - 1);
++    buf[cnt - 1] = '{';
++    buf[cnt] = '}';
++    memset(buf + cnt + 1, ']', cnt - 1);
++    buf[2 * cnt] = 0;
++    return buf;
++}
++
++static void limits_nesting(void)
++{
++    enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
++    char buf[2 * (max_nesting + 1) + 1];
++    QObject *obj;
++
++    obj = qobject_from_json(make_nest(buf, max_nesting));
++    g_assert(obj != NULL);
++    qobject_decref(obj);
++
++    obj = qobject_from_json(make_nest(buf, max_nesting + 1));
++    g_assert(obj == NULL);
++}
++
+ int main(int argc, char **argv)
+ {
+     g_test_init(&argc, &argv, NULL);
+@@ -1500,6 +1524,7 @@ int main(int argc, char **argv)
+     g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
+     g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
+     g_test_add_func("/errors/unterminated/literal", unterminated_literal);
++    g_test_add_func("/errors/limits/nesting", limits_nesting);
+ 
+     return g_test_run();
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-cutils-Support-P-and-E-suffixes-in-strtosz.patch b/SOURCES/kvm-cutils-Support-P-and-E-suffixes-in-strtosz.patch
new file mode 100644
index 0000000..d5937c8
--- /dev/null
+++ b/SOURCES/kvm-cutils-Support-P-and-E-suffixes-in-strtosz.patch
@@ -0,0 +1,132 @@
+From b7cea737b24456765a21ed43ebd9b68ebbbf3537 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:21 +0100
+Subject: [PATCH 02/27] cutils: Support 'P' and 'E' suffixes in strtosz()
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-3-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68430
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 02/21] cutils: Support 'P' and 'E' suffixes in strtosz()
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 5e00984aef7c1c317e27c0e8acf66526513c770f)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ include/qemu-common.h      |  2 ++
+ monitor.c                  |  8 ++++----
+ qemu-img.c                 | 10 ++++++----
+ tests/qemu-iotests/049.out |  8 ++++----
+ util/cutils.c              |  4 ++++
+ 5 files changed, 20 insertions(+), 12 deletions(-)
+
+diff --git a/include/qemu-common.h b/include/qemu-common.h
+index aee85e3..67f57c9 100644
+--- a/include/qemu-common.h
++++ b/include/qemu-common.h
+@@ -178,6 +178,8 @@ int parse_uint_full(const char *s, unsigned long long *value, int base);
+  * A-Z, as strtosz() will use qemu_toupper() on the given argument
+  * prior to comparison.
+  */
++#define STRTOSZ_DEFSUFFIX_EB	'E'
++#define STRTOSZ_DEFSUFFIX_PB	'P'
+ #define STRTOSZ_DEFSUFFIX_TB	'T'
+ #define STRTOSZ_DEFSUFFIX_GB	'G'
+ #define STRTOSZ_DEFSUFFIX_MB	'M'
+diff --git a/monitor.c b/monitor.c
+index 6a1d06e..33c5bc8 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -94,10 +94,10 @@
+  * 'M'          Non-negative target long (32 or 64 bit), in user mode the
+  *              value is multiplied by 2^20 (think Mebibyte)
+  * 'o'          octets (aka bytes)
+- *              user mode accepts an optional T, t, G, g, M, m, K, k
+- *              suffix, which multiplies the value by 2^40 for
+- *              suffixes T and t, 2^30 for suffixes G and g, 2^20 for
+- *              M and m, 2^10 for K and k
++ *              user mode accepts an optional E, e, P, p, T, t, G, g, M, m,
++ *              K, k suffix, which multiplies the value by 2^60 for suffixes E
++ *              and e, 2^50 for suffixes P and p, 2^40 for suffixes T and t,
++ *              2^30 for suffixes G and g, 2^20 for M and m, 2^10 for K and k
+  * 'T'          double
+  *              user mode accepts an optional ms, us, ns suffix,
+  *              which divides the value by 1e3, 1e6, 1e9, respectively
+diff --git a/qemu-img.c b/qemu-img.c
+index 9c021e7..eb2d4cb 100644
+--- a/qemu-img.c
++++ b/qemu-img.c
+@@ -87,8 +87,9 @@ static void help(void)
+            "  'src_cache' is the cache mode used to read input disk images, the valid\n"
+            "    options are the same as for the 'cache' option\n"
+            "  'size' is the disk image size in bytes. Optional suffixes\n"
+-           "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
+-           "    and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
++           "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
++           "    'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P)  are\n"
++           "    supported. 'b' is ignored.\n"
+            "  'output_filename' is the destination disk image filename\n"
+            "  'output_fmt' is the destination format\n"
+            "  'options' is a comma separated list of format specific options in a\n"
+@@ -417,8 +418,9 @@ static int img_create(int argc, char **argv)
+                 error_report("Image size must be less than 8 EiB!");
+             } else {
+                 error_report("Invalid image size specified! You may use k, M, "
+-                      "G or T suffixes for ");
+-                error_report("kilobytes, megabytes, gigabytes and terabytes.");
++                      "G, T, P or E suffixes for ");
++                error_report("kilobytes, megabytes, gigabytes, terabytes, "
++                             "petabytes and exabytes.");
+             }
+             goto fail;
+         }
+diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
+index b2fcf0b..3e56772 100644
+--- a/tests/qemu-iotests/049.out
++++ b/tests/qemu-iotests/049.out
+@@ -108,15 +108,15 @@ qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported
+ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off 
+ 
+ qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte
+-qemu-img: Invalid image size specified! You may use k, M, G or T suffixes for 
+-qemu-img: kilobytes, megabytes, gigabytes and terabytes.
++qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for 
++qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
+ 
+ qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2
+ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off 
+ 
+ qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar
+-qemu-img: Invalid image size specified! You may use k, M, G or T suffixes for 
+-qemu-img: kilobytes, megabytes, gigabytes and terabytes.
++qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for 
++qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
+ 
+ qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
+ qemu-img: Parameter 'size' expects a size
+diff --git a/util/cutils.c b/util/cutils.c
+index a165819..8f28896 100644
+--- a/util/cutils.c
++++ b/util/cutils.c
+@@ -267,6 +267,10 @@ static int64_t suffix_mul(char suffix, int64_t unit)
+         return unit * unit * unit;
+     case STRTOSZ_DEFSUFFIX_TB:
+         return unit * unit * unit * unit;
++    case STRTOSZ_DEFSUFFIX_PB:
++        return unit * unit * unit * unit * unit;
++    case STRTOSZ_DEFSUFFIX_EB:
++        return unit * unit * unit * unit * unit * unit;
+     }
+     return -1;
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-e1000-eliminate-infinite-loops-on-out-of-bounds-tran.patch b/SOURCES/kvm-e1000-eliminate-infinite-loops-on-out-of-bounds-tran.patch
new file mode 100644
index 0000000..41398a8
--- /dev/null
+++ b/SOURCES/kvm-e1000-eliminate-infinite-loops-on-out-of-bounds-tran.patch
@@ -0,0 +1,109 @@
+From 4fef3479339001ef3ea529fb0552533fae422240 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Fri, 5 Feb 2016 14:26:18 +0100
+Subject: [PATCH 1/5] e1000: eliminate infinite loops on out-of-bounds transfer
+ start
+
+RH-Author: Laszlo Ersek <lersek@redhat.com>
+Message-id: <1454682378-29144-2-git-send-email-lersek@redhat.com>
+Patchwork-id: 69116
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/1] e1000: eliminate infinite loops on out-of-bounds transfer start
+Bugzilla: 1296044
+RH-Acked-by: Xiao Wang <jasowang@redhat.com>
+RH-Acked-by: P J P <ppandit@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+The start_xmit() and e1000_receive_iov() functions implement DMA transfers
+iterating over a set of descriptors that the guest's e1000 driver
+prepares:
+
+- the TDLEN and RDLEN registers store the total size of the descriptor
+  area,
+
+- while the TDH and RDH registers store the offset (in whole tx / rx
+  descriptors) into the area where the transfer is supposed to start.
+
+Each time a descriptor is processed, the TDH and RDH register is bumped
+(as appropriate for the transfer direction).
+
+QEMU already contains logic to deal with bogus transfers submitted by the
+guest:
+
+- Normally, the transmit case wants to increase TDH from its initial value
+  to TDT. (TDT is allowed to be numerically smaller than the initial TDH
+  value; wrapping at or above TDLEN bytes to zero is normal.) The failsafe
+  that QEMU currently has here is a check against reaching the original
+  TDH value again -- a complete wraparound, which should never happen.
+
+- In the receive case RDH is increased from its initial value until
+  "total_size" bytes have been received; preferably in a single step, or
+  in "s->rxbuf_size" byte steps, if the latter is smaller. However, null
+  RX descriptors are skipped without receiving data, while RDH is
+  incremented just the same. QEMU tries to prevent an infinite loop
+  (processing only null RX descriptors) by detecting whether RDH assumes
+  its original value during the loop. (Again, wrapping from RDLEN to 0 is
+  normal.)
+
+What both directions miss is that the guest could program TDLEN and RDLEN
+so low, and the initial TDH and RDH so high, that these registers will
+immediately be truncated to zero, and then never reassume their initial
+values in the loop -- a full wraparound will never occur.
+
+The condition that expresses this is:
+
+  xdh_start >= s->mac_reg[XDLEN] / sizeof(desc)
+
+i.e., TDH or RDH start out after the last whole rx or tx descriptor that
+fits into the TDLEN or RDLEN sized area.
+
+This condition could be checked before we enter the loops, but
+pci_dma_read() / pci_dma_write() knows how to fill in buffers safely for
+bogus DMA addresses, so we just extend the existing failsafes with the
+above condition.
+
+This is CVE-2016-1981.
+
+Cc: "Michael S. Tsirkin" <mst@redhat.com>
+Cc: Petr Matousek <pmatouse@redhat.com>
+Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Cc: Prasad Pandit <ppandit@redhat.com>
+Cc: Michael Roth <mdroth@linux.vnet.ibm.com>
+Cc: Jason Wang <jasowang@redhat.com>
+Cc: qemu-stable@nongnu.org
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1296044
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Reviewed-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+(cherry picked from commit dd793a74882477ca38d49e191110c17dfee51dcc)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/net/e1000.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/hw/net/e1000.c b/hw/net/e1000.c
+index 87a84a7..2cd38bc 100644
+--- a/hw/net/e1000.c
++++ b/hw/net/e1000.c
+@@ -697,7 +697,8 @@ start_xmit(E1000State *s)
+          * bogus values to TDT/TDLEN.
+          * there's nothing too intelligent we could do about this.
+          */
+-        if (s->mac_reg[TDH] == tdh_start) {
++        if (s->mac_reg[TDH] == tdh_start ||
++            tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) {
+             DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",
+                    tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);
+             break;
+@@ -902,7 +903,8 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
+             s->mac_reg[RDH] = 0;
+         /* see comment in start_xmit; same here */
+-        if (s->mac_reg[RDH] == rdh_start) {
++        if (s->mac_reg[RDH] == rdh_start ||
++            rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) {
+             DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
+                    rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
+             set_ics(s, 0, E1000_ICS_RXO);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-ehci-clear-suspend-bit-on-detach.patch b/SOURCES/kvm-ehci-clear-suspend-bit-on-detach.patch
new file mode 100644
index 0000000..9a38ccd
--- /dev/null
+++ b/SOURCES/kvm-ehci-clear-suspend-bit-on-detach.patch
@@ -0,0 +1,48 @@
+From ad3f6b5b188c572bd07cc5929e844138c2d95915 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 13 Nov 2015 13:32:34 +0100
+Subject: [PATCH 1/6] ehci: clear suspend bit on detach
+
+Message-id: <1447421554-28366-2-git-send-email-kraxel@redhat.com>
+Patchwork-id: 68349
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/1] ehci: clear suspend bit on detach
+Bugzilla: 1268879
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+When a device is detached, clear the suspend bit (PORTSC_SUSPEND)
+in the port status register.
+
+The specs are not *that* clear what is supposed to happen in case
+a suspended device is unplugged.  But the enable bit (PORTSC_PED)
+is cleared, and the specs mention setting suspend with enable being
+unset is undefined behavior.  So clearing them both looks reasonable,
+and it actually fixes the reported bug.
+
+Cc: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Message-id: 1445413462-18004-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit cbf82fa01e6fd4ecb234b235b10ffce548154a95)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/usb/hcd-ehci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index 02d2ab7..3429c77 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -802,7 +802,7 @@ static void ehci_detach(USBPort *port)
+     ehci_queues_rip_device(s, port->dev, 0);
+     ehci_queues_rip_device(s, port->dev, 1);
+ 
+-    *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
++    *portsc &= ~(PORTSC_CONNECT|PORTSC_PED|PORTSC_SUSPEND);
+     *portsc |= PORTSC_CSC;
+ 
+     ehci_raise_irq(s, USBSTS_PCD);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-fw_cfg-add-check-to-validate-current-entry-value-CVE.patch b/SOURCES/kvm-fw_cfg-add-check-to-validate-current-entry-value-CVE.patch
index e1eb3b2..ac3c08f 100644
--- a/SOURCES/kvm-fw_cfg-add-check-to-validate-current-entry-value-CVE.patch
+++ b/SOURCES/kvm-fw_cfg-add-check-to-validate-current-entry-value-CVE.patch
@@ -1,16 +1,17 @@
-From 5d12c17191e042a57e02749cedc55104a8251ac3 Mon Sep 17 00:00:00 2001
+From ba24567fd90702ea40ff320a79bc921b38510f22 Mon Sep 17 00:00:00 2001
 From: Miroslav Rezanina <mrezanin@redhat.com>
 Date: Thu, 21 Jan 2016 07:17:43 +0100
-Subject: [PATCH] fw_cfg: add check to validate current entry value
+Subject: [PATCH 2/2] fw_cfg: add check to validate current entry value
  (CVE-2016-1714)
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
 
+RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
 Message-id: <1453360663-5066-1-git-send-email-mrezanin@redhat.com>
 Patchwork-id: 68834
 O-Subject: [RHEL-7.2.z/RHEL-7.3 qemu-kvm PATCH] fw_cfg: add check to validate current entry value (CVE-2016-1714)
-Bugzilla: 1298047
+Bugzilla: 1298048
 RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
 RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
 RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/SOURCES/kvm-hw-input-hid.c-Fix-capslock-hid-code.patch b/SOURCES/kvm-hw-input-hid.c-Fix-capslock-hid-code.patch
new file mode 100644
index 0000000..4a15536
--- /dev/null
+++ b/SOURCES/kvm-hw-input-hid.c-Fix-capslock-hid-code.patch
@@ -0,0 +1,50 @@
+From 61ecb3c995018bc9ec901d376004c1d092d166ff Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Wed, 1 Jun 2016 12:24:01 +0200
+Subject: [PATCH 1/3] hw/input/hid.c Fix capslock hid code
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1464783841-27701-2-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70522
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/1] hw/input/hid.c Fix capslock hid code
+Bugzilla: 1256741
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+From: Dinar Valeev <dvaleev@suse.com>
+
+When ever USB keyboard is used, e.g. '-usbdevice keyboard' pressing
+caps lock key send 0x32 hid code, which is treated as backslash.
+Instead it should be 0x39 code. This affects sending uppercase keys,
+as they typed whith caps lock active.
+
+While on x86 this can be workarounded by using ps/2 protocol. On
+Power it is crusial as we don't have anything else than USB.
+
+This is fixes guest automation tasts over vnc.
+
+Signed-off-by: Dinar Valeev <dvaleev@suse.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+(cherry picked from commit 0ee4de5840ccc1072459ec68062bfb63c888a94d)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/input/hid.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/input/hid.c b/hw/input/hid.c
+index 14b3125..db45c89 100644
+--- a/hw/input/hid.c
++++ b/hw/input/hid.c
+@@ -41,7 +41,7 @@ static const uint8_t hid_usage_keys[0x100] = {
+     0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
+     0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
+     0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
+-    0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
++    0xe2, 0x2c, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+     0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
+     0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
+     0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-ide-test-fix-failure-for-test_flush.patch b/SOURCES/kvm-ide-test-fix-failure-for-test_flush.patch
new file mode 100644
index 0000000..d7e4c96
--- /dev/null
+++ b/SOURCES/kvm-ide-test-fix-failure-for-test_flush.patch
@@ -0,0 +1,113 @@
+From 31ce74359a069be69af0f6ba2f7867ed2083317a Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Tue, 8 Dec 2015 20:30:59 +0100
+Subject: [PATCH 21/27] ide-test: fix failure for test_flush
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1449606659-23710-1-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68521
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v3 21/21] ide-test: fix failure for test_flush
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+This patch is a combination of two patches:
+
+(1) Revert "qtest/ide-test: disable flush-test"
+(2) ide-test: fix failure for test_flush
+
+First, the downstream-only revert:
+This reverts commit 228e49fabffa644ab7a6a03e98205f293115dc89.
+
+Second, the backported fix:
+
+bd07684aacfb61668ae2c25b7dd00b64f3d7c7f3 added a test to ensure BSY
+flag is set when a flush request is in flight. It does this by setting
+a blkdebug breakpoint on flush_to_os before issuing a CMD_FLUSH_CACHE.
+It then resumes CMD_FLUSH_CACHE operation and checks that BSY is unset.
+
+The actual unsetting of BSY does not occur until ide_flush_cb gets
+called in a bh, however, so in some cases this check will race with
+the actual completion.
+
+Fix this by polling the ide status register until BSY flag gets unset
+before we do our final sanity checks. According to
+f68ec8379e88502b4841a110c070e9b118d3151c this is in line with how a guest
+would determine whether or not the device is still busy.
+
+Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
+Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
+(cherry picked from commit 22bfa16ed3d4c9d534dcfe6f2381a654f32296b9)
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ tests/ide-test.c | 41 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ tests/ide-test.c | 41 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+diff --git a/tests/ide-test.c b/tests/ide-test.c
+index 43b7fd6..92dd0e5 100644
+--- a/tests/ide-test.c
++++ b/tests/ide-test.c
+@@ -425,6 +425,46 @@ static void test_identify(void)
+     ide_test_quit();
+ }
+ 
++static void test_flush(void)
++{
++    uint8_t data;
++
++    ide_test_start(
++        "-vnc none "
++        "-drive file=blkdebug::%s,if=ide,cache=writeback",
++        tmp_path);
++
++    /* Delay the completion of the flush request until we explicitly do it */
++    qmp("{'execute':'human-monitor-command', 'arguments': { "
++        "'command-line': 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }");
++
++    /* FLUSH CACHE command on device 0*/
++    outb(IDE_BASE + reg_device, 0);
++    outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE);
++
++    /* Check status while request is in flight*/
++    data = inb(IDE_BASE + reg_status);
++    assert_bit_set(data, BSY | DRDY);
++    assert_bit_clear(data, DF | ERR | DRQ);
++
++    /* Complete the command */
++    qmp("{'execute':'human-monitor-command', 'arguments': { "
++        "'command-line': 'qemu-io ide0-hd0 \"resume A\"'} }");
++
++    /* Check registers */
++    data = inb(IDE_BASE + reg_device);
++    g_assert_cmpint(data & DEV, ==, 0);
++
++    do {
++        data = inb(IDE_BASE + reg_status);
++    } while (data & BSY);
++
++    assert_bit_set(data, DRDY);
++    assert_bit_clear(data, BSY | DF | ERR | DRQ);
++
++    ide_test_quit();
++}
++
+ static void test_flush_nodev(void)
+ {
+     ide_test_start("");
+@@ -468,6 +508,7 @@ int main(int argc, char **argv)
+     qtest_add_func("/ide/bmdma/long_prdt", test_bmdma_long_prdt);
+     qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown);
+ 
++    qtest_add_func("/ide/flush", test_flush);
+     qtest_add_func("/ide/flush_nodev", test_flush_nodev);
+ 
+     ret = g_test_run();
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-json-parser-drop-superfluous-assignment-for-token-va.patch b/SOURCES/kvm-json-parser-drop-superfluous-assignment-for-token-va.patch
new file mode 100644
index 0000000..3e6503f
--- /dev/null
+++ b/SOURCES/kvm-json-parser-drop-superfluous-assignment-for-token-va.patch
@@ -0,0 +1,97 @@
+From 110f5902133db4e8a46c9cc18ed0d4ed2e99aec2 Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:34:59 +0200
+Subject: [PATCH 01/16] json-parser: drop superfluous assignment for token
+ variable
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-3-git-send-email-armbru@redhat.com>
+Patchwork-id: 71470
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 01/15] json-parser: drop superfluous assignment for token variable
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Gonglei <arei.gonglei@huawei.com>
+
+Signed-off-by: ChenLiang <chenliang88@huawei.com>
+Signed-off-by: Gonglei <arei.gonglei@huawei.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
+(cherry picked from commit a491af471bf8f1188b2665f54d109065d4591e45)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qobject/json-parser.c | 15 ++-------------
+ 1 file changed, 2 insertions(+), 13 deletions(-)
+
+diff --git a/qobject/json-parser.c b/qobject/json-parser.c
+index e7947b3..fa09769 100644
+--- a/qobject/json-parser.c
++++ b/qobject/json-parser.c
+@@ -423,7 +423,6 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+     if (!token_is_operator(token, '{')) {
+         goto out;
+     }
+-    token = NULL;
+ 
+     dict = qdict_new();
+ 
+@@ -449,7 +448,6 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+                 parse_error(ctxt, token, "expected separator in dict");
+                 goto out;
+             }
+-            token = NULL;
+ 
+             if (parse_pair(ctxt, dict, ap) == -1) {
+                 goto out;
+@@ -461,10 +459,8 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+                 goto out;
+             }
+         }
+-        token = NULL;
+     } else {
+-        token = parser_context_pop_token(ctxt);
+-        token = NULL;
++        (void)parser_context_pop_token(ctxt);
+     }
+ 
+     return QOBJECT(dict);
+@@ -487,10 +483,8 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+     }
+ 
+     if (!token_is_operator(token, '[')) {
+-        token = NULL;
+         goto out;
+     }
+-    token = NULL;
+ 
+     list = qlist_new();
+ 
+@@ -523,8 +517,6 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+                 goto out;
+             }
+ 
+-            token = NULL;
+-
+             obj = parse_value(ctxt, ap);
+             if (obj == NULL) {
+                 parse_error(ctxt, token, "expecting value");
+@@ -539,11 +531,8 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+                 goto out;
+             }
+         }
+-
+-        token = NULL;
+     } else {
+-        token = parser_context_pop_token(ctxt);
+-        token = NULL;
++        (void)parser_context_pop_token(ctxt);
+     }
+ 
+     return QOBJECT(list);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-json-streamer-Don-t-leak-tokens-on-incomplete-parse.patch b/SOURCES/kvm-json-streamer-Don-t-leak-tokens-on-incomplete-parse.patch
new file mode 100644
index 0000000..73a78fd
--- /dev/null
+++ b/SOURCES/kvm-json-streamer-Don-t-leak-tokens-on-incomplete-parse.patch
@@ -0,0 +1,65 @@
+From b3e87d63aec8631b853cb86a0736af41954769a4 Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:12 +0200
+Subject: [PATCH 14/16] json-streamer: Don't leak tokens on incomplete parse
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-16-git-send-email-armbru@redhat.com>
+Patchwork-id: 71477
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 14/15] json-streamer: Don't leak tokens on incomplete parse
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Eric Blake <eblake@redhat.com>
+
+Valgrind complained about a number of leaks in
+tests/check-qobject-json:
+
+==12657==    definitely lost: 17,247 bytes in 1,234 blocks
+
+All of which had the same root cause: on an incomplete parse,
+we were abandoning the token queue without cleaning up the
+allocated data within each queue element.  Introduced in
+commit 95385fe, when we switched from QList (which recursively
+frees contents) to g_queue (which does not).
+
+We don't yet require glib 2.32 with its g_queue_free_full(),
+so open-code it instead.
+
+CC: qemu-stable@nongnu.org
+Signed-off-by: Eric Blake <eblake@redhat.com>
+Message-Id: <1463608012-12760-1-git-send-email-eblake@redhat.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+(cherry picked from commit ba4dba54347d5062436a8553f527dbbed6dcf069)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qobject/json-streamer.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index a4db4b8..3c7d6be 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -19,9 +19,15 @@
+ #define MAX_TOKEN_COUNT (2ULL << 20)
+ #define MAX_NESTING (1ULL << 10)
+ 
++static void json_message_free_token(void *token, void *opaque)
++{
++    g_free(token);
++}
++
+ static void json_message_free_tokens(JSONMessageParser *parser)
+ {
+     if (parser->tokens) {
++        g_queue_foreach(parser->tokens, json_message_free_token, NULL);
+         g_queue_free(parser->tokens);
+         parser->tokens = NULL;
+     }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-json-streamer-fix-double-free-on-exiting-during-a-pa.patch b/SOURCES/kvm-json-streamer-fix-double-free-on-exiting-during-a-pa.patch
new file mode 100644
index 0000000..602f1a7
--- /dev/null
+++ b/SOURCES/kvm-json-streamer-fix-double-free-on-exiting-during-a-pa.patch
@@ -0,0 +1,64 @@
+From a781053c1b5084ba32b86229b98b9601c990722c Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:13 +0200
+Subject: [PATCH 15/16] json-streamer: fix double-free on exiting during a
+ parse
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-17-git-send-email-armbru@redhat.com>
+Patchwork-id: 71484
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 15/15] json-streamer: fix double-free on exiting during a parse
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+Now that json-streamer tries not to leak tokens on incomplete parse,
+the tokens can be freed twice if QEMU destroys the json-streamer
+object during the parser->emit call.  To fix this, create the new
+empty GQueue earlier, so that it is already in place when the old
+one is passed to parser->emit.
+
+Reported-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Message-Id: <1467636059-12557-1-git-send-email-pbonzini@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit a942d8fa01f65279cdc135f4294db611bbc088ef)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qobject/json-streamer.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index 3c7d6be..7d041e1 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -38,6 +38,7 @@ static void json_message_process_token(JSONLexer *lexer, GString *input,
+ {
+     JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
+     JSONToken *token;
++    GQueue *tokens;
+ 
+     switch (type) {
+     case JSON_LCURLY:
+@@ -95,9 +96,12 @@ out_emit:
+     /* send current list of tokens to parser and reset tokenizer */
+     parser->brace_count = 0;
+     parser->bracket_count = 0;
+-    /* parser->emit takes ownership of parser->tokens.  */
+-    parser->emit(parser, parser->tokens);
++    /* parser->emit takes ownership of parser->tokens.  Remove our own
++     * reference to parser->tokens before handing it out to parser->emit.
++     */
++    tokens = parser->tokens;
+     parser->tokens = g_queue_new();
++    parser->emit(parser, tokens);
+     parser->token_size = 0;
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-nbd-Always-call-close_fn-in-nbd_client_new.patch b/SOURCES/kvm-nbd-Always-call-close_fn-in-nbd_client_new.patch
new file mode 100644
index 0000000..60dacb5
--- /dev/null
+++ b/SOURCES/kvm-nbd-Always-call-close_fn-in-nbd_client_new.patch
@@ -0,0 +1,112 @@
+From 2efca7904a7a71d44bdf715208899e3bb29711df Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Thu, 10 Mar 2016 04:00:51 +0100
+Subject: [PATCH 2/5] nbd: Always call "close_fn" in nbd_client_new
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1457582453-13835-2-git-send-email-famz@redhat.com>
+Patchwork-id: 69757
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 1/3] nbd: Always call "close_fn" in nbd_client_new
+Bugzilla: 1285453
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+
+Rename the parameter "close" to "close_fn" to disambiguous with
+close(2).
+
+This unifies error handling paths of NBDClient allocation:
+nbd_client_new will shutdown the socket and call the "close_fn" callback
+if negotiation failed, so the caller don't need a different path than
+the normal close.
+
+The returned pointer is never used, make it void in preparation for the
+next patch.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Message-Id: <1452760863-25350-2-git-send-email-famz@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit ee7d7aabdaea4484e069cb99c9fc54e8cb24b56f)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+    include/block/nbd.h
+    nbd.c
+    qemu-nbd.c
+* nbd_update_server_fd_handler not in downstream;
+* Context around the changed line is different.
+---
+ include/block/nbd.h |  3 +--
+ nbd.c               | 11 +++++------
+ qemu-nbd.c          |  4 ++--
+ 3 files changed, 8 insertions(+), 10 deletions(-)
+
+diff --git a/include/block/nbd.h b/include/block/nbd.h
+index c90f5e4..92e360e 100644
+--- a/include/block/nbd.h
++++ b/include/block/nbd.h
+@@ -92,8 +92,7 @@ NBDExport *nbd_export_find(const char *name);
+ void nbd_export_set_name(NBDExport *exp, const char *name);
+ void nbd_export_close_all(void);
+ 
+-NBDClient *nbd_client_new(NBDExport *exp, int csock,
+-                          void (*close)(NBDClient *));
++void nbd_client_new(NBDExport *exp, int csock, void (*close_fn)(NBDClient *));
+ void nbd_client_close(NBDClient *client);
+ void nbd_client_get(NBDClient *client);
+ void nbd_client_put(NBDClient *client);
+diff --git a/nbd.c b/nbd.c
+index f258cdd..ba97270 100644
+--- a/nbd.c
++++ b/nbd.c
+@@ -1232,8 +1232,7 @@ static void nbd_restart_write(void *opaque)
+     qemu_coroutine_enter(client->send_coroutine, NULL);
+ }
+ 
+-NBDClient *nbd_client_new(NBDExport *exp, int csock,
+-                          void (*close)(NBDClient *))
++void nbd_client_new(NBDExport *exp, int csock, void (*close_fn)(NBDClient *))
+ {
+     NBDClient *client;
+     client = g_malloc0(sizeof(NBDClient));
+@@ -1241,10 +1240,11 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock,
+     client->exp = exp;
+     client->sock = csock;
+     if (nbd_send_negotiate(client) < 0) {
+-        g_free(client);
+-        return NULL;
++        shutdown(client->sock, 2);
++        close_fn(client);
++        return;
+     }
+-    client->close = close;
++    client->close = close_fn;
+     qemu_co_mutex_init(&client->send_lock);
+     qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client);
+ 
+@@ -1252,5 +1252,4 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock,
+         QTAILQ_INSERT_TAIL(&exp->clients, client, next);
+         nbd_export_get(exp);
+     }
+-    return client;
+ }
+diff --git a/qemu-nbd.c b/qemu-nbd.c
+index ff792ef..047dd49 100644
+--- a/qemu-nbd.c
++++ b/qemu-nbd.c
+@@ -297,9 +297,9 @@ static void nbd_accept(void *opaque)
+         close(fd);
+         return;
+     }
+-
+-    if (fd >= 0 && nbd_client_new(exp, fd, nbd_client_closed)) {
++    if (fd >= 0) {
+         nb_fds++;
++        nbd_client_new(exp, fd, nbd_client_closed);
+     }
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-nbd-client_close-on-error-in-nbd_co_client_start.patch b/SOURCES/kvm-nbd-client_close-on-error-in-nbd_co_client_start.patch
new file mode 100644
index 0000000..9479ecd
--- /dev/null
+++ b/SOURCES/kvm-nbd-client_close-on-error-in-nbd_co_client_start.patch
@@ -0,0 +1,50 @@
+From c62e0877b191e5fba9b678bbd518a57c8fdf7099 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Thu, 10 Mar 2016 04:00:53 +0100
+Subject: [PATCH 4/5] nbd: client_close on error in nbd_co_client_start
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1457582453-13835-4-git-send-email-famz@redhat.com>
+Patchwork-id: 69759
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 3/3] nbd: client_close on error in nbd_co_client_start
+Bugzilla: 1285453
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+
+From: Max Reitz <mreitz@redhat.com>
+
+Use client_close() if an error in nbd_co_client_start() occurs instead
+of manually inlining parts of it. This fixes an assertion error on the
+server side if nbd_negotiate() fails.
+
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit d3780c2dce2c452759ee9d94f9d824cf14cc3ab8)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+
+Downstream: client_close -> nbd_client_close.
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ nbd.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/nbd.c b/nbd.c
+index 97aeecb..c20e57e 100644
+--- a/nbd.c
++++ b/nbd.c
+@@ -1282,8 +1282,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
+         nbd_export_get(exp);
+     }
+     if (nbd_negotiate(data)) {
+-        shutdown(client->sock, 2);
+-        client->close(client);
++        nbd_client_close(client);
+         goto out;
+     }
+     qemu_co_mutex_init(&client->send_lock);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-nbd-server-Coroutine-based-negotiation.patch b/SOURCES/kvm-nbd-server-Coroutine-based-negotiation.patch
new file mode 100644
index 0000000..9083ba7
--- /dev/null
+++ b/SOURCES/kvm-nbd-server-Coroutine-based-negotiation.patch
@@ -0,0 +1,262 @@
+From 2a68d801c63137c3d1fe9fa96f0193eb2d1576f5 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Thu, 10 Mar 2016 04:00:52 +0100
+Subject: [PATCH 3/5] nbd-server: Coroutine based negotiation
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1457582453-13835-3-git-send-email-famz@redhat.com>
+Patchwork-id: 69758
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 2/3] nbd-server: Coroutine based negotiation
+Bugzilla: 1285453
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+
+Create a coroutine in nbd_client_new, so that nbd_send_negotiate doesn't
+need qemu_set_block().
+
+Handlers need to be set temporarily for csock fd in case the coroutine
+yields during I/O.
+
+With this, if the other end disappears in the middle of the negotiation,
+we don't block the whole event loop.
+
+To make the code clearer, unify all function names that belong to
+negotiate, so they are less likely to be misused. This is important
+because we rely on negotiation staying in main loop, as commented in
+nbd_negotiate_read/write().
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Message-Id: <1452760863-25350-4-git-send-email-famz@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 1a6245a5b0b4e8d822c739b403fc67c8a7bc8d12)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	nbd.c
+Downstream doesn't have new style protocol, and the code is not split.
+The patch is redone.
+---
+ nbd.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 82 insertions(+), 24 deletions(-)
+
+diff --git a/nbd.c b/nbd.c
+index ba97270..97aeecb 100644
+--- a/nbd.c
++++ b/nbd.c
+@@ -167,6 +167,41 @@ ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
+     return offset;
+ }
+ 
++static void nbd_negotiate_continue(void *opaque)
++{
++    qemu_coroutine_enter(opaque, NULL);
++}
++
++static ssize_t read_sync(int fd, void *buffer, size_t size);
++static ssize_t write_sync(int fd, void *buffer, size_t size);
++
++static ssize_t nbd_negotiate_read(int fd, void *buffer, size_t size)
++{
++    ssize_t ret;
++
++    assert(qemu_in_coroutine());
++    /* Negotiation are always in main loop. */
++    qemu_set_fd_handler(fd, nbd_negotiate_continue, NULL,
++                        qemu_coroutine_self());
++    ret = read_sync(fd, buffer, size);
++    qemu_set_fd_handler(fd, NULL, NULL, NULL);
++    return ret;
++
++}
++
++static ssize_t nbd_negotiate_write(int fd, void *buffer, size_t size)
++{
++    ssize_t ret;
++
++    assert(qemu_in_coroutine());
++    /* Negotiation are always in main loop. */
++    qemu_set_fd_handler(fd, NULL, nbd_negotiate_continue,
++                        qemu_coroutine_self());
++    ret = write_sync(fd, buffer, size);
++    qemu_set_fd_handler(fd, NULL, NULL, NULL);
++    return ret;
++}
++
+ static ssize_t read_sync(int fd, void *buffer, size_t size)
+ {
+     /* Sockets are kept in blocking mode in the negotiation phase.  After
+@@ -280,7 +315,7 @@ int unix_socket_outgoing(const char *path)
+ 
+ */
+ 
+-static int nbd_receive_options(NBDClient *client)
++static coroutine_fn int nbd_negotiate_receive_options(NBDClient *client)
+ {
+     int csock = client->sock;
+     char name[256];
+@@ -297,7 +332,7 @@ static int nbd_receive_options(NBDClient *client)
+      */
+ 
+     rc = -EINVAL;
+-    if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
++    if (nbd_negotiate_read(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
+         LOG("read failed");
+         goto fail;
+     }
+@@ -307,7 +342,7 @@ static int nbd_receive_options(NBDClient *client)
+         goto fail;
+     }
+ 
+-    if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
++    if (nbd_negotiate_read(csock, &magic, sizeof(magic)) != sizeof(magic)) {
+         LOG("read failed");
+         goto fail;
+     }
+@@ -317,7 +352,7 @@ static int nbd_receive_options(NBDClient *client)
+         goto fail;
+     }
+ 
+-    if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
++    if (nbd_negotiate_read(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
+         LOG("read failed");
+         goto fail;
+     }
+@@ -327,7 +362,7 @@ static int nbd_receive_options(NBDClient *client)
+         goto fail;
+     }
+ 
+-    if (read_sync(csock, &length, sizeof(length)) != sizeof(length)) {
++    if (nbd_negotiate_read(csock, &length, sizeof(length)) != sizeof(length)) {
+         LOG("read failed");
+         goto fail;
+     }
+@@ -337,7 +372,7 @@ static int nbd_receive_options(NBDClient *client)
+         LOG("Bad length received");
+         goto fail;
+     }
+-    if (read_sync(csock, name, length) != length) {
++    if (nbd_negotiate_read(csock, name, length) != length) {
+         LOG("read failed");
+         goto fail;
+     }
+@@ -358,8 +393,14 @@ fail:
+     return rc;
+ }
+ 
+-static int nbd_send_negotiate(NBDClient *client)
++typedef struct {
++    NBDClient *client;
++    Coroutine *co;
++} NBDClientNewData;
++
++static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
+ {
++    NBDClient *client = data->client;
+     int csock = client->sock;
+     char buf[8 + 8 + 8 + 128];
+     int rc;
+@@ -385,7 +426,6 @@ static int nbd_send_negotiate(NBDClient *client)
+         [28 .. 151]   reserved     (0)
+      */
+ 
+-    qemu_set_block(csock);
+     rc = -EINVAL;
+ 
+     TRACE("Beginning negotiation.");
+@@ -401,16 +441,16 @@ static int nbd_send_negotiate(NBDClient *client)
+     }
+ 
+     if (client->exp) {
+-        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
++        if (nbd_negotiate_write(csock, buf, sizeof(buf)) != sizeof(buf)) {
+             LOG("write failed");
+             goto fail;
+         }
+     } else {
+-        if (write_sync(csock, buf, 18) != 18) {
++        if (nbd_negotiate_write(csock, buf, 18) != 18) {
+             LOG("write failed");
+             goto fail;
+         }
+-        rc = nbd_receive_options(client);
++        rc = nbd_negotiate_receive_options(client);
+         if (rc < 0) {
+             LOG("option negotiation failed");
+             goto fail;
+@@ -419,7 +459,8 @@ static int nbd_send_negotiate(NBDClient *client)
+         assert ((client->exp->nbdflags & ~65535) == 0);
+         cpu_to_be64w((uint64_t*)(buf + 18), client->exp->size);
+         cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags);
+-        if (write_sync(csock, buf + 18, sizeof(buf) - 18) != sizeof(buf) - 18) {
++        if (nbd_negotiate_write(csock, buf + 18,
++                                sizeof(buf) - 18) != sizeof(buf) - 18) {
+             LOG("write failed");
+             goto fail;
+         }
+@@ -428,7 +469,6 @@ static int nbd_send_negotiate(NBDClient *client)
+     TRACE("Negotiation succeeded.");
+     rc = 0;
+ fail:
+-    qemu_set_nonblock(csock);
+     return rc;
+ }
+ 
+@@ -1232,24 +1272,42 @@ static void nbd_restart_write(void *opaque)
+     qemu_coroutine_enter(client->send_coroutine, NULL);
+ }
+ 
++static coroutine_fn void nbd_co_client_start(void *opaque)
++{
++    NBDClientNewData *data = opaque;
++    NBDClient *client = data->client;
++    NBDExport *exp = client->exp;
++
++    if (exp) {
++        nbd_export_get(exp);
++    }
++    if (nbd_negotiate(data)) {
++        shutdown(client->sock, 2);
++        client->close(client);
++        goto out;
++    }
++    qemu_co_mutex_init(&client->send_lock);
++    qemu_set_fd_handler2(client->sock, nbd_can_read, nbd_read, NULL, client);
++
++    if (exp) {
++        QTAILQ_INSERT_TAIL(&exp->clients, client, next);
++    }
++out:
++    g_free(data);
++}
++
+ void nbd_client_new(NBDExport *exp, int csock, void (*close_fn)(NBDClient *))
+ {
+     NBDClient *client;
++    NBDClientNewData *data = g_new(NBDClientNewData, 1);
++
+     client = g_malloc0(sizeof(NBDClient));
+     client->refcount = 1;
+     client->exp = exp;
+     client->sock = csock;
+-    if (nbd_send_negotiate(client) < 0) {
+-        shutdown(client->sock, 2);
+-        close_fn(client);
+-        return;
+-    }
+     client->close = close_fn;
+-    qemu_co_mutex_init(&client->send_lock);
+-    qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client);
+ 
+-    if (exp) {
+-        QTAILQ_INSERT_TAIL(&exp->clients, client, next);
+-        nbd_export_get(exp);
+-    }
++    data->client = client;
++    data->co = qemu_coroutine_create(nbd_co_client_start);
++    qemu_coroutine_enter(data->co, data);
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-nbd-server-Set-O_NONBLOCK-on-client-fd.patch b/SOURCES/kvm-nbd-server-Set-O_NONBLOCK-on-client-fd.patch
new file mode 100644
index 0000000..6b9b473
--- /dev/null
+++ b/SOURCES/kvm-nbd-server-Set-O_NONBLOCK-on-client-fd.patch
@@ -0,0 +1,44 @@
+From e36a5a8613df42339773ebf48e07d063ad7484e8 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 5 Sep 2016 01:18:15 +0200
+Subject: [PATCH] nbd-server: Set O_NONBLOCK on client fd
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1473038295-7193-1-git-send-email-famz@redhat.com>
+Patchwork-id: 72141
+O-Subject: [RHEL-7.3 qemu-kvm PATCH] nbd-server: Set O_NONBLOCK on client fd
+Bugzilla: 1285453
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+Upstream: upstream uses IO channels that is not present in downstream.
+Backporting that deserves a separate and deliberate justification BZ,
+for 7.4.
+
+Even with 2a68d80 (nbd-server: Coroutine based negotiation), QEMU still
+hangs when client hangs, because recvmsg the socket fd is blocking. Set
+the O_NONBLOCK to fix this.
+
+Analyzed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ nbd.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/nbd.c b/nbd.c
+index c20e57e..8a32e18 100644
+--- a/nbd.c
++++ b/nbd.c
+@@ -1281,6 +1281,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
+     if (exp) {
+         nbd_export_get(exp);
+     }
++    qemu_set_nonblock(client->sock);
+     if (nbd_negotiate(data)) {
+         nbd_client_close(client);
+         goto out;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-net-Make-qmp_query_rx_filter-with-name-argument-more.patch b/SOURCES/kvm-net-Make-qmp_query_rx_filter-with-name-argument-more.patch
new file mode 100644
index 0000000..28e945b
--- /dev/null
+++ b/SOURCES/kvm-net-Make-qmp_query_rx_filter-with-name-argument-more.patch
@@ -0,0 +1,47 @@
+From 9c2a6798c053cec989e02935e810a0d239fb493c Mon Sep 17 00:00:00 2001
+From: Vlad Yasevich <vyasevic@redhat.com>
+Date: Wed, 16 Dec 2015 02:59:35 +0100
+Subject: [PATCH 1/2] net: Make qmp_query_rx_filter() with name argument more
+ obvious
+
+RH-Author: Vlad Yasevich <vyasevic@redhat.com>
+Message-id: <1450234776-7779-2-git-send-email-vyasevic@redhat.com>
+Patchwork-id: 68620
+O-Subject: [RHEL7.3 qemu-kvm PATCH 1/2] net: Make qmp_query_rx_filter() with name argument more obvious
+Bugzilla: 1269738
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+
+From: Markus Armbruster <armbru@redhat.com>
+
+With a client name, the QMP command is specified to return a list of
+one element.  This isn't locally obvious in the code.  Make it so.
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 638fb14169ad96cf9bc0dd5f61460daaecee5bb1)
+Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ net/net.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/net.c b/net/net.c
+index a8c49fc..0be50a0 100644
+--- a/net/net.c
++++ b/net/net.c
+@@ -1000,6 +1000,10 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
+                        " rx-filter querying", name);
+             break;
+         }
++
++        if (has_name) {
++            break;
++        }
+     }
+ 
+     if (filter_list == NULL && !error_is_set(errp) && has_name) {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-pc-set-the-OEM-fields-in-the-RSDT-and-the-FADT-from-.patch b/SOURCES/kvm-pc-set-the-OEM-fields-in-the-RSDT-and-the-FADT-from-.patch
new file mode 100644
index 0000000..f1d5ebf
--- /dev/null
+++ b/SOURCES/kvm-pc-set-the-OEM-fields-in-the-RSDT-and-the-FADT-from-.patch
@@ -0,0 +1,133 @@
+From 607904cf94b1dee91c74522aedebda308ffba93d Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Wed, 11 May 2016 12:33:48 +0200
+Subject: [PATCH 09/10] pc: set the OEM fields in the RSDT and the FADT from
+ the SLIC
+
+RH-Author: Laszlo Ersek <lersek@redhat.com>
+Message-id: <1462970028-10959-8-git-send-email-lersek@redhat.com>
+Patchwork-id: 70384
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 7/7] pc: set the OEM fields in the RSDT and the FADT from the SLIC
+Bugzilla: 1330969
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+The Microsoft spec about the SLIC and MSDM ACPI tables at
+<http://go.microsoft.com/fwlink/p/?LinkId=234834> requires the OEM ID and
+OEM Table ID fields to be consistent between the SLIC and the RSDT/XSDT.
+That further affects the FADT, because a similar match between the FADT
+and the RSDT/XSDT is required by the ACPI spec in general.
+
+This patch wires up the previous three patches.
+
+Cc: "Michael S. Tsirkin" <mst@redhat.com> (supporter:ACPI/SMBIOS)
+Cc: Igor Mammedov <imammedo@redhat.com> (supporter:ACPI/SMBIOS)
+Cc: Paolo Bonzini <pbonzini@redhat.com> (maintainer:X86)
+Cc: Richard W.M. Jones <rjones@redhat.com>
+Cc: Aleksei Kovura <alex3kov@zoho.com>
+Cc: Michael Tokarev <mjt@tls.msk.ru>
+Cc: Steven Newbury <steve@snewbury.org.uk>
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1248758
+LP: https://bugs.launchpad.net/qemu/+bug/1533848
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Steven Newbury <steve@snewbury.org.uk>
+(cherry picked from commit ae12374951f07157f7a52c8d848b90f8eec722fb)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	hw/i386/acpi-build.c
+
+RHEL-7 backport note: conflict due to downstream lacking 7c2c1fa5f428
+("pc: acpi: use local var for accessing ACPI tables blob in
+acpi_build()").
+
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ hw/i386/acpi-build.c | 13 +++++++++----
+ qemu-options.hx      |  4 ++++
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+---
+ hw/i386/acpi-build.c | 13 +++++++++----
+ qemu-options.hx      |  4 ++++
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index d9433e6..85291f5 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -511,7 +511,8 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm)
+ /* FADT */
+ static void
+ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
+-           unsigned facs, unsigned dsdt)
++           unsigned facs, unsigned dsdt,
++           const char *oem_id, const char *oem_table_id)
+ {
+     AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
+ 
+@@ -532,7 +533,7 @@ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
+     fadt_setup(fadt, pm);
+ 
+     build_header(linker, table_data,
+-                 (void *)fadt, "FACP", sizeof(*fadt), 1, NULL, NULL);
++                 (void *)fadt, "FACP", sizeof(*fadt), 1, oem_id, oem_table_id);
+ }
+ 
+ static void
+@@ -1065,6 +1066,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
+     AcpiMcfgInfo mcfg;
+     PcPciInfo pci;
+     uint8_t *u;
++    AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
+ 
+     acpi_get_cpu_info(&cpu);
+     acpi_get_pm_info(&pm);
+@@ -1072,6 +1074,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
+     acpi_get_hotplug_info(&misc);
+     acpi_get_misc_info(&misc);
+     acpi_get_pci_info(&pci);
++    acpi_get_slic_oem(&slic_oem);
+ 
+     table_offsets = g_array_new(false, true /* clear */,
+                                         sizeof(uint32_t));
+@@ -1095,7 +1098,8 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
+ 
+     /* ACPI tables pointed to by RSDT */
+     acpi_add_table(table_offsets, tables->table_data);
+-    build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt);
++    build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt,
++               slic_oem.id, slic_oem.table_id);
+ 
+     acpi_add_table(table_offsets, tables->table_data);
+     build_ssdt(tables->table_data, tables->linker, &cpu, &pm, &misc, &pci,
+@@ -1127,7 +1131,8 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
+ 
+     /* RSDT is pointed to by RSDP */
+     rsdt = tables->table_data->len;
+-    build_rsdt(tables->table_data, tables->linker, table_offsets, NULL, NULL);
++    build_rsdt(tables->table_data, tables->linker, table_offsets,
++               slic_oem.id, slic_oem.table_id);
+ 
+     /* RSDP is in FSEG memory, so allocate it separately */
+     build_rsdp(tables->rsdp, tables->linker, rsdt);
+diff --git a/qemu-options.hx b/qemu-options.hx
+index 62c3e06..24ffab6 100644
+--- a/qemu-options.hx
++++ b/qemu-options.hx
+@@ -1295,6 +1295,10 @@ ACPI headers (possible overridden by other options).
+ For data=, only data
+ portion of the table is used, all header information is specified in the
+ command line.
++If a SLIC table is supplied to QEMU, then the SLIC's oem_id and oem_table_id
++fields will override the same in the RSDT and the FADT (a.k.a. FACP), in order
++to ensure the field matches required by the Microsoft SLIC spec and the ACPI
++spec.
+ ETEXI
+ 
+ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Check-for-trailing-chars.patch b/SOURCES/kvm-qemu-io-Check-for-trailing-chars.patch
new file mode 100644
index 0000000..d4d0f7f
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Check-for-trailing-chars.patch
@@ -0,0 +1,59 @@
+From 362faad8e8f4c2c2c875df12f6bbae7964c0146d Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:38 +0100
+Subject: [PATCH 19/27] qemu-io: Check for trailing chars
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-20-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68449
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 19/21] qemu-io: Check for trailing chars
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+Make sure there's not trailing garbage, e.g.
+"64k-whatever-i-want-here"
+
+Reported-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: John Snow <jsnow@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit ef5a788527b2038d742b057a415ab4d0e735e98f)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+  qemu-io-cmds.c:
+    - Downstream still uses strtosz_suffix, not
+      qemu_strtosz_suffix.
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ qemu-io-cmds.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+index 95345fe..6ea027d 100644
+--- a/qemu-io-cmds.c
++++ b/qemu-io-cmds.c
+@@ -124,7 +124,14 @@ static char **breakline(char *input, int *count)
+ static int64_t cvtnum(const char *s)
+ {
+     char *end;
+-    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
++    int64_t ret;
++
++    ret = strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
++    if (*end != '\0') {
++        /* Detritus at the end of the string */
++        return -EINVAL;
++    }
++    return ret;
+ }
+ 
+ #define EXABYTES(x)     ((long long)(x) << 60)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Correct-error-messages.patch b/SOURCES/kvm-qemu-io-Correct-error-messages.patch
new file mode 100644
index 0000000..07f3345
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Correct-error-messages.patch
@@ -0,0 +1,218 @@
+From 8adbd2914ccd44e0b1766690b514bda213b88740 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:39 +0100
+Subject: [PATCH 20/27] qemu-io: Correct error messages
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-21-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68446
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 20/21] qemu-io: Correct error messages
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+Reported-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: John Snow <jsnow@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit a9ecfa004f2dd83df612daac4a87dfc3a0feba28)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+  qemu-io-cmds.c:
+    - Fixes to sigraise are not backported.
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ qemu-io-cmds.c | 51 +++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 33 insertions(+), 18 deletions(-)
+
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+index 6ea027d..b41d6ee 100644
+--- a/qemu-io-cmds.c
++++ b/qemu-io-cmds.c
+@@ -134,6 +134,21 @@ static int64_t cvtnum(const char *s)
+     return ret;
+ }
+ 
++static void print_cvtnum_err(int64_t rc, const char *arg)
++{
++    switch (rc) {
++    case -EINVAL:
++        printf("Parsing error: non-numeric argument,"
++               " or extraneous/unrecognized suffix -- %s\n", arg);
++        break;
++    case -ERANGE:
++        printf("Parsing error: argument too large -- %s\n", arg);
++        break;
++    default:
++        printf("Parsing error: %s\n", arg);
++    }
++}
++
+ #define EXABYTES(x)     ((long long)(x) << 60)
+ #define PETABYTES(x)    ((long long)(x) << 50)
+ #define TERABYTES(x)    ((long long)(x) << 40)
+@@ -355,13 +370,13 @@ create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
+ 
+         len = cvtnum(arg);
+         if (len < 0) {
+-            printf("non-numeric length argument -- %s\n", arg);
++            print_cvtnum_err(len, arg);
+             goto fail;
+         }
+ 
+         /* should be SIZE_T_MAX, but that doesn't exist */
+         if (len > INT_MAX) {
+-            printf("too large length argument -- %s\n", arg);
++            printf("Argument '%s' exceeds maximum size %d\n", arg, INT_MAX);
+             goto fail;
+         }
+ 
+@@ -688,7 +703,7 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+             lflag = 1;
+             pattern_count = cvtnum(optarg);
+             if (pattern_count < 0) {
+-                printf("non-numeric length argument -- %s\n", optarg);
++                print_cvtnum_err(pattern_count, optarg);
+                 return 0;
+             }
+             break;
+@@ -709,7 +724,7 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+             sflag = 1;
+             pattern_offset = cvtnum(optarg);
+             if (pattern_offset < 0) {
+-                printf("non-numeric length argument -- %s\n", optarg);
++                print_cvtnum_err(pattern_offset, optarg);
+                 return 0;
+             }
+             break;
+@@ -732,14 +747,14 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     offset = cvtnum(argv[optind]);
+     if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(offset, argv[optind]);
+         return 0;
+     }
+ 
+     optind++;
+     count = cvtnum(argv[optind]);
+     if (count < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(count, argv[optind]);
+         return 0;
+     } else if (count > SIZE_MAX) {
+         printf("length cannot exceed %" PRIu64 ", given %s\n",
+@@ -894,7 +909,7 @@ static int readv_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     offset = cvtnum(argv[optind]);
+     if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(offset, argv[optind]);
+         return 0;
+     }
+     optind++;
+@@ -1043,14 +1058,14 @@ static int write_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     offset = cvtnum(argv[optind]);
+     if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(offset, argv[optind]);
+         return 0;
+     }
+ 
+     optind++;
+     count = cvtnum(argv[optind]);
+     if (count < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(count, argv[optind]);
+         return 0;
+     } else if (count > SIZE_MAX) {
+         printf("length cannot exceed %" PRIu64 ", given %s\n",
+@@ -1179,7 +1194,7 @@ static int writev_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     offset = cvtnum(argv[optind]);
+     if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(offset, argv[optind]);
+         return 0;
+     }
+     optind++;
+@@ -1306,7 +1321,7 @@ static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
+         /* Read the offset of the request */
+         offset = cvtnum(argv[optind]);
+         if (offset < 0) {
+-            printf("non-numeric offset argument -- %s\n", argv[optind]);
++            print_cvtnum_err(offset, argv[optind]);
+             goto out;
+         }
+         optind++;
+@@ -1526,7 +1541,7 @@ static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     ctx->offset = cvtnum(argv[optind]);
+     if (ctx->offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(ctx->offset, argv[optind]);
+         g_free(ctx);
+         return 0;
+     }
+@@ -1618,7 +1633,7 @@ static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     ctx->offset = cvtnum(argv[optind]);
+     if (ctx->offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(ctx->offset, argv[optind]);
+         g_free(ctx);
+         return 0;
+     }
+@@ -1676,7 +1691,7 @@ static int truncate_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     offset = cvtnum(argv[1]);
+     if (offset < 0) {
+-        printf("non-numeric truncate argument -- %s\n", argv[1]);
++        print_cvtnum_err(offset, argv[1]);
+         return 0;
+     }
+ 
+@@ -1822,14 +1837,14 @@ static int discard_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     offset = cvtnum(argv[optind]);
+     if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(offset, argv[optind]);
+         return 0;
+     }
+ 
+     optind++;
+     count = cvtnum(argv[optind]);
+     if (count < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
++        print_cvtnum_err(count, argv[optind]);
+         return 0;
+     } else if (count >> BDRV_SECTOR_BITS > INT_MAX) {
+         printf("length cannot exceed %"PRIu64", given %s\n",
+@@ -1867,7 +1882,7 @@ static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     offset = cvtnum(argv[1]);
+     if (offset < 0) {
+-        printf("non-numeric offset argument -- %s\n", argv[1]);
++        print_cvtnum_err(offset, argv[1]);
+         return 0;
+     } else if (offset & 0x1ff) {
+         printf("offset %" PRId64 " is not sector aligned\n",
+@@ -1878,7 +1893,7 @@ static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+     if (argc == 3) {
+         nb_sectors = cvtnum(argv[2]);
+         if (nb_sectors < 0) {
+-            printf("non-numeric length argument -- %s\n", argv[2]);
++            print_cvtnum_err(nb_sectors, argv[2]);
+             return 0;
+         } else if (nb_sectors > INT_MAX) {
+             printf("length argument cannot exceed %d, given %s\n",
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Don-t-use-global-bs-in-command-implementatio.patch b/SOURCES/kvm-qemu-io-Don-t-use-global-bs-in-command-implementatio.patch
new file mode 100644
index 0000000..7a8bd97
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Don-t-use-global-bs-in-command-implementatio.patch
@@ -0,0 +1,737 @@
+From 2653e21a25d8fb99479337c785e81b07f755acda Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:24 +0100
+Subject: [PATCH 05/27] qemu-io: Don't use global bs in command implementations
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-6-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68433
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 05/21] qemu-io: Don't use global bs in command implementations
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Pass in the BlockDriverState to the command handlers instead of using
+the global variable. This is an important step to make the commands
+usable outside of qemu-io.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 734c3b85cb72d264ad2b38a87f30304e05de2cb1)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+  qemu-io.c
+    Number of arguments to bdrv_co_write_zeroes
+    bdrv_unref used downstream instead of bdrv_delete
+    downstream, local_err used for bdrv_open
+    downstream, error_abort used for bdrv_new
+    map_is_allocated was never backported from a00e81e98f71
+    sleep_f was backported, adjust its signature
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ cmd.c     |   6 ++-
+ cmd.h     |   8 ++-
+ qemu-io.c | 164 ++++++++++++++++++++++++++++++++++----------------------------
+ 3 files changed, 99 insertions(+), 79 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index 214c6f7..d501aab 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -57,7 +57,7 @@ check_command(
+ 	const cmdinfo_t	*ci)
+ {
+ 	if (check_func)
+-		return check_func(ci);
++		return check_func(qemuio_bs, ci);
+ 	return 1;
+ }
+ 
+@@ -103,7 +103,7 @@ command(
+ 		return 0;
+ 	}
+ 	optind = 0;
+-	return ct->cfunc(argc, argv);
++	return ct->cfunc(qemuio_bs, argc, argv);
+ }
+ 
+ const cmdinfo_t *
+@@ -452,6 +452,7 @@ static cmdinfo_t quit_cmd;
+ /* ARGSUSED */
+ static int
+ quit_f(
++    BlockDriverState *bs,
+ 	int	argc,
+ 	char	**argv)
+ {
+@@ -490,6 +491,7 @@ help_all(void)
+ 
+ static int
+ help_f(
++    BlockDriverState *bs,
+ 	int		argc,
+ 	char		**argv)
+ {
+diff --git a/cmd.h b/cmd.h
+index 4dcfe88..ccf6336 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -17,9 +17,13 @@
+ #ifndef __COMMAND_H__
+ #define __COMMAND_H__
+ 
++#include "qemu-common.h"
++
+ #define CMD_FLAG_GLOBAL	((int)0x80000000)	/* don't iterate "args" */
+ 
+-typedef int (*cfunc_t)(int argc, char **argv);
++extern BlockDriverState *qemuio_bs;
++
++typedef int (*cfunc_t)(BlockDriverState *bs, int argc, char **argv);
+ typedef void (*helpfunc_t)(void);
+ 
+ typedef struct cmdinfo {
+@@ -41,7 +45,7 @@ extern int		ncmds;
+ void help_init(void);
+ void quit_init(void);
+ 
+-typedef int (*checkfunc_t)(const cmdinfo_t *ci);
++typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
+ 
+ void add_command(const cmdinfo_t *ci);
+ void add_user_command(char *optarg);
+diff --git a/qemu-io.c b/qemu-io.c
+index e4fa2fc..c3cc4f3 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -29,8 +29,8 @@
+ #define CMD_NOFILE_OK   0x01
+ 
+ char *progname;
+-static BlockDriverState *bs;
+ 
++BlockDriverState *qemuio_bs;
+ static int misalign;
+ 
+ static int64_t cvtnum(const char *s)
+@@ -67,7 +67,7 @@ static int parse_pattern(const char *arg)
+  */
+ 
+ #define MISALIGN_OFFSET     16
+-static void *qemu_io_alloc(size_t len, int pattern)
++static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
+ {
+     void *buf;
+ 
+@@ -140,7 +140,8 @@ static void print_report(const char *op, struct timeval *t, int64_t offset,
+  * vector matching it.
+  */
+ static void *
+-create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
++create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
++             int pattern)
+ {
+     size_t *sizes = g_new0(size_t, nr_iov);
+     size_t count = 0;
+@@ -176,7 +177,7 @@ create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
+ 
+     qemu_iovec_init(qiov, nr_iov);
+ 
+-    buf = p = qemu_io_alloc(count, pattern);
++    buf = p = qemu_io_alloc(bs, count, pattern);
+ 
+     for (i = 0; i < nr_iov; i++) {
+         qemu_iovec_add(qiov, p, sizes[i]);
+@@ -188,7 +189,8 @@ fail:
+     return buf;
+ }
+ 
+-static int do_read(char *buf, int64_t offset, int count, int *total)
++static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
++                   int *total)
+ {
+     int ret;
+ 
+@@ -200,7 +202,8 @@ static int do_read(char *buf, int64_t offset, int count, int *total)
+     return 1;
+ }
+ 
+-static int do_write(char *buf, int64_t offset, int count, int *total)
++static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
++                    int *total)
+ {
+     int ret;
+ 
+@@ -212,7 +215,8 @@ static int do_write(char *buf, int64_t offset, int count, int *total)
+     return 1;
+ }
+ 
+-static int do_pread(char *buf, int64_t offset, int count, int *total)
++static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
++                    int *total)
+ {
+     *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
+     if (*total < 0) {
+@@ -221,7 +225,8 @@ static int do_pread(char *buf, int64_t offset, int count, int *total)
+     return 1;
+ }
+ 
+-static int do_pwrite(char *buf, int64_t offset, int count, int *total)
++static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
++                     int *total)
+ {
+     *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
+     if (*total < 0) {
+@@ -231,6 +236,7 @@ static int do_pwrite(char *buf, int64_t offset, int count, int *total)
+ }
+ 
+ typedef struct {
++    BlockDriverState *bs;
+     int64_t offset;
+     int count;
+     int *total;
+@@ -242,7 +248,7 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque)
+ {
+     CoWriteZeroes *data = opaque;
+ 
+-    data->ret = bdrv_co_write_zeroes(bs, data->offset / BDRV_SECTOR_SIZE,
++    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
+                                      data->count / BDRV_SECTOR_SIZE, 0);
+     data->done = true;
+     if (data->ret < 0) {
+@@ -253,10 +259,12 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque)
+     *data->total = data->count;
+ }
+ 
+-static int do_co_write_zeroes(int64_t offset, int count, int *total)
++static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
++                              int *total)
+ {
+     Coroutine *co;
+     CoWriteZeroes data = {
++        .bs     = bs,
+         .offset = offset,
+         .count  = count,
+         .total  = total,
+@@ -275,7 +283,8 @@ static int do_co_write_zeroes(int64_t offset, int count, int *total)
+     }
+ }
+ 
+-static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
++static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
++                               int count, int *total)
+ {
+     int ret;
+ 
+@@ -287,7 +296,8 @@ static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
+     return 1;
+ }
+ 
+-static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
++static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
++                           int count, int *total)
+ {
+     *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
+     if (*total < 0) {
+@@ -296,7 +306,8 @@ static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
+     return 1;
+ }
+ 
+-static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
++static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
++                           int count, int *total)
+ {
+     *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
+     if (*total < 0) {
+@@ -311,7 +322,8 @@ static void aio_rw_done(void *opaque, int ret)
+     *(int *)opaque = ret;
+ }
+ 
+-static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
++static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
++                        int64_t offset, int *total)
+ {
+     int async_ret = NOT_DONE;
+ 
+@@ -325,7 +337,8 @@ static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
+     return async_ret < 0 ? async_ret : 1;
+ }
+ 
+-static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
++static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
++                         int64_t offset, int *total)
+ {
+     int async_ret = NOT_DONE;
+ 
+@@ -354,7 +367,8 @@ static void multiwrite_cb(void *opaque, int ret)
+     }
+ }
+ 
+-static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
++static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
++                             int num_reqs, int *total)
+ {
+     int i, ret;
+     struct multiwrite_async_ret async_ret = {
+@@ -403,7 +417,7 @@ static void read_help(void)
+ "\n");
+ }
+ 
+-static int read_f(int argc, char **argv);
++static int read_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t read_cmd = {
+     .name       = "read",
+@@ -416,7 +430,7 @@ static const cmdinfo_t read_cmd = {
+     .help       = read_help,
+ };
+ 
+-static int read_f(int argc, char **argv)
++static int read_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     struct timeval t1, t2;
+     int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
+@@ -522,15 +536,15 @@ static int read_f(int argc, char **argv)
+         }
+     }
+ 
+-    buf = qemu_io_alloc(count, 0xab);
++    buf = qemu_io_alloc(bs, count, 0xab);
+ 
+     gettimeofday(&t1, NULL);
+     if (pflag) {
+-        cnt = do_pread(buf, offset, count, &total);
++        cnt = do_pread(bs, buf, offset, count, &total);
+     } else if (bflag) {
+-        cnt = do_load_vmstate(buf, offset, count, &total);
++        cnt = do_load_vmstate(bs, buf, offset, count, &total);
+     } else {
+-        cnt = do_read(buf, offset, count, &total);
++        cnt = do_read(bs, buf, offset, count, &total);
+     }
+     gettimeofday(&t2, NULL);
+ 
+@@ -587,7 +601,7 @@ static void readv_help(void)
+ "\n");
+ }
+ 
+-static int readv_f(int argc, char **argv);
++static int readv_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t readv_cmd = {
+     .name       = "readv",
+@@ -599,7 +613,7 @@ static const cmdinfo_t readv_cmd = {
+     .help       = readv_help,
+ };
+ 
+-static int readv_f(int argc, char **argv)
++static int readv_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     struct timeval t1, t2;
+     int Cflag = 0, qflag = 0, vflag = 0;
+@@ -655,13 +669,13 @@ static int readv_f(int argc, char **argv)
+     }
+ 
+     nr_iov = argc - optind;
+-    buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
++    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
+     if (buf == NULL) {
+         return 0;
+     }
+ 
+     gettimeofday(&t1, NULL);
+-    cnt = do_aio_readv(&qiov, offset, &total);
++    cnt = do_aio_readv(bs, &qiov, offset, &total);
+     gettimeofday(&t2, NULL);
+ 
+     if (cnt < 0) {
+@@ -718,7 +732,7 @@ static void write_help(void)
+ "\n");
+ }
+ 
+-static int write_f(int argc, char **argv);
++static int write_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t write_cmd = {
+     .name       = "write",
+@@ -731,7 +745,7 @@ static const cmdinfo_t write_cmd = {
+     .help       = write_help,
+ };
+ 
+-static int write_f(int argc, char **argv)
++static int write_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     struct timeval t1, t2;
+     int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
+@@ -818,20 +832,20 @@ static int write_f(int argc, char **argv)
+     }
+ 
+     if (!zflag) {
+-        buf = qemu_io_alloc(count, pattern);
++        buf = qemu_io_alloc(bs, count, pattern);
+     }
+ 
+     gettimeofday(&t1, NULL);
+     if (pflag) {
+-        cnt = do_pwrite(buf, offset, count, &total);
++        cnt = do_pwrite(bs, buf, offset, count, &total);
+     } else if (bflag) {
+-        cnt = do_save_vmstate(buf, offset, count, &total);
++        cnt = do_save_vmstate(bs, buf, offset, count, &total);
+     } else if (zflag) {
+-        cnt = do_co_write_zeroes(offset, count, &total);
++        cnt = do_co_write_zeroes(bs, offset, count, &total);
+     } else if (cflag) {
+-        cnt = do_write_compressed(buf, offset, count, &total);
++        cnt = do_write_compressed(bs, buf, offset, count, &total);
+     } else {
+-        cnt = do_write(buf, offset, count, &total);
++        cnt = do_write(bs, buf, offset, count, &total);
+     }
+     gettimeofday(&t2, NULL);
+ 
+@@ -874,7 +888,7 @@ writev_help(void)
+ "\n");
+ }
+ 
+-static int writev_f(int argc, char **argv);
++static int writev_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t writev_cmd = {
+     .name       = "writev",
+@@ -886,7 +900,7 @@ static const cmdinfo_t writev_cmd = {
+     .help       = writev_help,
+ };
+ 
+-static int writev_f(int argc, char **argv)
++static int writev_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     struct timeval t1, t2;
+     int Cflag = 0, qflag = 0;
+@@ -936,13 +950,13 @@ static int writev_f(int argc, char **argv)
+     }
+ 
+     nr_iov = argc - optind;
+-    buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
++    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
+     if (buf == NULL) {
+         return 0;
+     }
+ 
+     gettimeofday(&t1, NULL);
+-    cnt = do_aio_writev(&qiov, offset, &total);
++    cnt = do_aio_writev(bs, &qiov, offset, &total);
+     gettimeofday(&t2, NULL);
+ 
+     if (cnt < 0) {
+@@ -983,7 +997,7 @@ static void multiwrite_help(void)
+ "\n");
+ }
+ 
+-static int multiwrite_f(int argc, char **argv);
++static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t multiwrite_cmd = {
+     .name       = "multiwrite",
+@@ -995,7 +1009,7 @@ static const cmdinfo_t multiwrite_cmd = {
+     .help       = multiwrite_help,
+ };
+ 
+-static int multiwrite_f(int argc, char **argv)
++static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     struct timeval t1, t2;
+     int Cflag = 0, qflag = 0;
+@@ -1076,7 +1090,7 @@ static int multiwrite_f(int argc, char **argv)
+         nr_iov = j - optind;
+ 
+         /* Build request */
+-        buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern);
++        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
+         if (buf[i] == NULL) {
+             goto out;
+         }
+@@ -1094,7 +1108,7 @@ static int multiwrite_f(int argc, char **argv)
+     nr_reqs = i;
+ 
+     gettimeofday(&t1, NULL);
+-    cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
++    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
+     gettimeofday(&t2, NULL);
+ 
+     if (cnt < 0) {
+@@ -1222,7 +1236,7 @@ static void aio_read_help(void)
+ "\n");
+ }
+ 
+-static int aio_read_f(int argc, char **argv);
++static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t aio_read_cmd = {
+     .name       = "aio_read",
+@@ -1234,7 +1248,7 @@ static const cmdinfo_t aio_read_cmd = {
+     .help       = aio_read_help,
+ };
+ 
+-static int aio_read_f(int argc, char **argv)
++static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int nr_iov, c;
+     struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
+@@ -1285,7 +1299,7 @@ static int aio_read_f(int argc, char **argv)
+     }
+ 
+     nr_iov = argc - optind;
+-    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
++    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
+     if (ctx->buf == NULL) {
+         g_free(ctx);
+         return 0;
+@@ -1317,7 +1331,7 @@ static void aio_write_help(void)
+ "\n");
+ }
+ 
+-static int aio_write_f(int argc, char **argv);
++static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t aio_write_cmd = {
+     .name       = "aio_write",
+@@ -1329,7 +1343,7 @@ static const cmdinfo_t aio_write_cmd = {
+     .help       = aio_write_help,
+ };
+ 
+-static int aio_write_f(int argc, char **argv)
++static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int nr_iov, c;
+     int pattern = 0xcd;
+@@ -1377,7 +1391,7 @@ static int aio_write_f(int argc, char **argv)
+     }
+ 
+     nr_iov = argc - optind;
+-    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
++    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
+     if (ctx->buf == NULL) {
+         g_free(ctx);
+         return 0;
+@@ -1389,7 +1403,7 @@ static int aio_write_f(int argc, char **argv)
+     return 0;
+ }
+ 
+-static int aio_flush_f(int argc, char **argv)
++static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     bdrv_drain_all();
+     return 0;
+@@ -1401,7 +1415,7 @@ static const cmdinfo_t aio_flush_cmd = {
+     .oneline    = "completes all outstanding aio requests"
+ };
+ 
+-static int flush_f(int argc, char **argv)
++static int flush_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     bdrv_flush(bs);
+     return 0;
+@@ -1414,7 +1428,7 @@ static const cmdinfo_t flush_cmd = {
+     .oneline    = "flush all in-core file state to disk",
+ };
+ 
+-static int truncate_f(int argc, char **argv)
++static int truncate_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int64_t offset;
+     int ret;
+@@ -1444,7 +1458,7 @@ static const cmdinfo_t truncate_cmd = {
+     .oneline    = "truncates the current file at the given offset",
+ };
+ 
+-static int length_f(int argc, char **argv)
++static int length_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int64_t size;
+     char s1[64];
+@@ -1469,7 +1483,7 @@ static const cmdinfo_t length_cmd = {
+ };
+ 
+ 
+-static int info_f(int argc, char **argv)
++static int info_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     BlockDriverInfo bdi;
+     ImageInfoSpecific *spec_info;
+@@ -1528,7 +1542,7 @@ static void discard_help(void)
+ "\n");
+ }
+ 
+-static int discard_f(int argc, char **argv);
++static int discard_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t discard_cmd = {
+     .name       = "discard",
+@@ -1541,7 +1555,7 @@ static const cmdinfo_t discard_cmd = {
+     .help       = discard_help,
+ };
+ 
+-static int discard_f(int argc, char **argv)
++static int discard_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     struct timeval t1, t2;
+     int Cflag = 0, qflag = 0;
+@@ -1599,7 +1613,7 @@ out:
+     return 0;
+ }
+ 
+-static int alloc_f(int argc, char **argv)
++static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int64_t offset, sector_num;
+     int nb_sectors, remaining;
+@@ -1664,7 +1678,7 @@ static const cmdinfo_t alloc_cmd = {
+     .oneline    = "checks if a sector is present in the file",
+ };
+ 
+-static int map_f(int argc, char **argv)
++static int map_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int64_t offset;
+     int64_t nb_sectors;
+@@ -1700,7 +1714,7 @@ static const cmdinfo_t map_cmd = {
+        .oneline        = "prints the allocated areas of a file",
+ };
+ 
+-static int break_f(int argc, char **argv)
++static int break_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int ret;
+ 
+@@ -1722,7 +1736,7 @@ static const cmdinfo_t break_cmd = {
+                          "request as tag",
+ };
+ 
+-static int resume_f(int argc, char **argv)
++static int resume_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int ret;
+ 
+@@ -1743,7 +1757,7 @@ static const cmdinfo_t resume_cmd = {
+        .oneline        = "resumes the request tagged as tag",
+ };
+ 
+-static int wait_break_f(int argc, char **argv)
++static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     while (!bdrv_debug_is_suspended(bs, argv[1])) {
+         qemu_aio_wait();
+@@ -1761,7 +1775,7 @@ static const cmdinfo_t wait_break_cmd = {
+        .oneline        = "waits for the suspension of a request",
+ };
+ 
+-static int abort_f(int argc, char **argv)
++static int abort_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     abort();
+ }
+@@ -1773,10 +1787,10 @@ static const cmdinfo_t abort_cmd = {
+        .oneline        = "simulate a program crash using abort(3)",
+ };
+ 
+-static int close_f(int argc, char **argv)
++static int close_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     bdrv_unref(bs);
+-    bs = NULL;
++    qemuio_bs = NULL;
+     return 0;
+ }
+ 
+@@ -1793,7 +1807,7 @@ static void sleep_cb(void *opaque)
+     *expired = true;
+ }
+ 
+-static int sleep_f(int argc, char **argv)
++static int sleep_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     char *endptr;
+     long ms;
+@@ -1831,27 +1845,27 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
+ {
+     Error *local_err = NULL;
+ 
+-    if (bs) {
++    if (qemuio_bs) {
+         fprintf(stderr, "file open already, try 'help close'\n");
+         return 1;
+     }
+ 
+     if (growable) {
+-        if (bdrv_file_open(&bs, name, opts, flags, &local_err)) {
++        if (bdrv_file_open(&qemuio_bs, name, opts, flags, &local_err)) {
+             fprintf(stderr, "%s: can't open device %s: %s\n", progname, name,
+                     error_get_pretty(local_err));
+             error_free(local_err);
+             return 1;
+         }
+     } else {
+-        bs = bdrv_new("hda", &error_abort);
++        qemuio_bs = bdrv_new("hda", &error_abort);
+ 
+-        if (bdrv_open(bs, name, opts, flags, NULL, &local_err) < 0) {
++        if (bdrv_open(qemuio_bs, name, opts, flags, NULL, &local_err) < 0) {
+             fprintf(stderr, "%s: can't open device %s: %s\n", progname, name,
+                     error_get_pretty(local_err));
+             error_free(local_err);
+-            bdrv_unref(bs);
+-            bs = NULL;
++            bdrv_unref(qemuio_bs);
++            qemuio_bs = NULL;
+             return 1;
+         }
+     }
+@@ -1877,7 +1891,7 @@ static void open_help(void)
+ "\n");
+ }
+ 
+-static int open_f(int argc, char **argv);
++static int open_f(BlockDriverState *bs, int argc, char **argv);
+ 
+ static const cmdinfo_t open_cmd = {
+     .name       = "open",
+@@ -1900,7 +1914,7 @@ static QemuOptsList empty_opts = {
+     },
+ };
+ 
+-static int open_f(int argc, char **argv)
++static int open_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     int flags = 0;
+     int readonly = 0;
+@@ -1948,7 +1962,7 @@ static int open_f(int argc, char **argv)
+     return openfile(argv[optind], flags, growable, opts);
+ }
+ 
+-static int init_check_command(const cmdinfo_t *ct)
++static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+ {
+     if (ct->flags & CMD_FLAG_GLOBAL) {
+         return 1;
+@@ -2117,8 +2131,8 @@ int main(int argc, char **argv)
+      */
+     bdrv_drain_all();
+ 
+-    if (bs) {
+-        bdrv_unref(bs);
++    if (qemuio_bs) {
++        bdrv_unref(qemuio_bs);
+     }
+     return 0;
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Factor-out-qemuio_command.patch b/SOURCES/kvm-qemu-io-Factor-out-qemuio_command.patch
new file mode 100644
index 0000000..8e3dfa0
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Factor-out-qemuio_command.patch
@@ -0,0 +1,163 @@
+From c73b87743086200c3f9ad485dcd4e71bdee27881 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:26 +0100
+Subject: [PATCH 07/27] qemu-io: Factor out qemuio_command
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-8-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68438
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 07/21] qemu-io: Factor out qemuio_command
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+It's duplicated code. Move it to qemu-io-cmds.c because it's not
+dependent on any static data of the qemu-io tool.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit dd5832967ac3fe96bd5bf9f199639176998ead69)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ cmd.c          | 43 +++++--------------------------------------
+ cmd.h          |  3 ++-
+ qemu-io-cmds.c | 24 ++++++++++++++++++++++++
+ 3 files changed, 31 insertions(+), 39 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index d501aab..7ae978f 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -138,28 +138,11 @@ static char *get_prompt(void);
+ 
+ void command_loop(void)
+ {
+-    int c, i, done = 0, fetchable = 0, prompted = 0;
++    int i, done = 0, fetchable = 0, prompted = 0;
+     char *input;
+-    char **v;
+-    const cmdinfo_t *ct;
+ 
+     for (i = 0; !done && i < ncmdline; i++) {
+-        input = strdup(cmdline[i]);
+-        if (!input) {
+-            fprintf(stderr, _("cannot strdup command '%s': %s\n"),
+-                    cmdline[i], strerror(errno));
+-            exit(1);
+-        }
+-        v = breakline(input, &c);
+-        if (c) {
+-            ct = find_command(v[0]);
+-            if (ct) {
+-                done = command(ct, c, v);
+-            } else {
+-                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
+-            }
+-	}
+-        doneline(input, v);
++        done = qemuio_command(cmdline[i]);
+     }
+     if (cmdline) {
+         g_free(cmdline);
+@@ -179,20 +162,13 @@ void command_loop(void)
+         if (!fetchable) {
+             continue;
+         }
++
+         input = fetchline();
+         if (input == NULL) {
+             break;
+         }
+-        v = breakline(input, &c);
+-        if (c) {
+-            ct = find_command(v[0]);
+-            if (ct) {
+-                done = command(ct, c, v);
+-            } else {
+-                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
+-            }
+-        }
+-        doneline(input, v);
++        done = qemuio_command(input);
++        free(input);
+ 
+         prompted = 0;
+         fetchable = 0;
+@@ -328,15 +304,6 @@ char **breakline(char *input, int *count)
+     return rval;
+ }
+ 
+-void
+-doneline(
+-	char	*input,
+-	char	**vec)
+-{
+-	free(input);
+-	free(vec);
+-}
+-
+ #define EXABYTES(x)	((long long)(x) << 60)
+ #define PETABYTES(x)	((long long)(x) << 50)
+ #define TERABYTES(x)	((long long)(x) << 40)
+diff --git a/cmd.h b/cmd.h
+index ccf6336..d676408 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -59,7 +59,6 @@ int command(const cmdinfo_t *ci, int argc, char **argv);
+ 
+ /* from input.h */
+ char **breakline(char *input, int *count);
+-void doneline(char *input, char **vec);
+ char *fetchline(void);
+ 
+ void cvtstr(double value, char *str, size_t sz);
+@@ -77,4 +76,6 @@ void timestr(struct timeval *tv, char *str, size_t sz, int flags);
+ 
+ extern char *progname;
+ 
++bool qemuio_command(const char *cmd);
++
+ #endif	/* __COMMAND_H__ */
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+index efa6070..09e4099 100644
+--- a/qemu-io-cmds.c
++++ b/qemu-io-cmds.c
+@@ -1824,6 +1824,30 @@ static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+     return 1;
+ }
+ 
++bool qemuio_command(const char *cmd)
++{
++    char *input;
++    const cmdinfo_t *ct;
++    char **v;
++    int c;
++    bool done = false;
++
++    input = g_strdup(cmd);
++    v = breakline(input, &c);
++    if (c) {
++        ct = find_command(v[0]);
++        if (ct) {
++            done = command(ct, c, v);
++        } else {
++            fprintf(stderr, "command \"%s\" not found\n", v[0]);
++        }
++    }
++    g_free(input);
++    g_free(v);
++
++    return done;
++}
++
+ static void __attribute((constructor)) init_qemuio_commands(void)
+ {
+     /* initialize commands */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Handle-cvtnum-errors-in-alloc.patch b/SOURCES/kvm-qemu-io-Handle-cvtnum-errors-in-alloc.patch
new file mode 100644
index 0000000..f3e78e1
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Handle-cvtnum-errors-in-alloc.patch
@@ -0,0 +1,56 @@
+From 862f45e0ad5a70d10bffa435d5331c444874e4d2 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:23 +0100
+Subject: [PATCH 04/27] qemu-io: Handle cvtnum() errors in 'alloc'
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-5-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68431
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 04/21] qemu-io: Handle cvtnum() errors in 'alloc'
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit cf49a6a00c19cabf4006d4f82bef26345043e7b5)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qemu-io.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/qemu-io.c b/qemu-io.c
+index 3b5890e..e4fa2fc 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -1608,7 +1608,10 @@ static int alloc_f(int argc, char **argv)
+     int ret;
+ 
+     offset = cvtnum(argv[1]);
+-    if (offset & 0x1ff) {
++    if (offset < 0) {
++        printf("non-numeric offset argument -- %s\n", argv[1]);
++        return 0;
++    } else if (offset & 0x1ff) {
+         printf("offset %" PRId64 " is not sector aligned\n",
+                offset);
+         return 0;
+@@ -1616,6 +1619,10 @@ static int alloc_f(int argc, char **argv)
+ 
+     if (argc == 3) {
+         nb_sectors = cvtnum(argv[2]);
++        if (nb_sectors < 0) {
++            printf("non-numeric length argument -- %s\n", argv[2]);
++            return 0;
++        }
+     } else {
+         nb_sectors = 1;
+     }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Interface-cleanup.patch b/SOURCES/kvm-qemu-io-Interface-cleanup.patch
new file mode 100644
index 0000000..68430eb
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Interface-cleanup.patch
@@ -0,0 +1,240 @@
+From 0dfb1b6f831f5b2a1fdf5e77330db3c95db2e464 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:33 +0100
+Subject: [PATCH 14/27] qemu-io: Interface cleanup
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-15-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68444
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 14/21] qemu-io: Interface cleanup
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 3d21994f9c511cb63220fef5abea164b83fbb997)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+  qemu-io-cmds.c: include block/qapi.h context
+  qemu-io.c       include block/qapi.h context
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ cmd.h             | 48 ------------------------------------------------
+ include/qemu-io.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ qemu-io-cmds.c    | 14 +++++++-------
+ qemu-io.c         |  7 +++----
+ 4 files changed, 56 insertions(+), 59 deletions(-)
+ delete mode 100644 cmd.h
+ create mode 100644 include/qemu-io.h
+
+diff --git a/cmd.h b/cmd.h
+deleted file mode 100644
+index 9907795..0000000
+--- a/cmd.h
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/*
+- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+- * All Rights Reserved.
+- *
+- * 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.
+- *
+- * This program is distributed in the hope that it would 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/>.
+- */
+-#ifndef __COMMAND_H__
+-#define __COMMAND_H__
+-
+-#include "qemu-common.h"
+-
+-#define CMD_FLAG_GLOBAL	((int)0x80000000)	/* don't iterate "args" */
+-
+-extern BlockDriverState *qemuio_bs;
+-
+-typedef int (*cfunc_t)(BlockDriverState *bs, int argc, char **argv);
+-typedef void (*helpfunc_t)(void);
+-
+-typedef struct cmdinfo {
+-	const char	*name;
+-	const char	*altname;
+-	cfunc_t		cfunc;
+-	int		argmin;
+-	int		argmax;
+-	int		canpush;
+-	int		flags;
+-	const char	*args;
+-	const char	*oneline;
+-	helpfunc_t      help;
+-} cmdinfo_t;
+-
+-void qemuio_add_command(const cmdinfo_t *ci);
+-
+-int qemuio_command_usage(const cmdinfo_t *ci);
+-
+-bool qemuio_command(const char *cmd);
+-
+-#endif	/* __COMMAND_H__ */
+diff --git a/include/qemu-io.h b/include/qemu-io.h
+new file mode 100644
+index 0000000..a418b46
+--- /dev/null
++++ b/include/qemu-io.h
+@@ -0,0 +1,46 @@
++/*
++ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
++ * All Rights Reserved.
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it would 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/>.
++ */
++
++#ifndef QEMU_IO_H
++#define QEMU_IO_H
++
++#include "qemu-common.h"
++
++#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
++
++typedef int (*cfunc_t)(BlockDriverState *bs, int argc, char **argv);
++typedef void (*helpfunc_t)(void);
++
++typedef struct cmdinfo {
++    const char* name;
++    const char* altname;
++    cfunc_t     cfunc;
++    int         argmin;
++    int         argmax;
++    int         canpush;
++    int         flags;
++    const char  *args;
++    const char  *oneline;
++    helpfunc_t  help;
++} cmdinfo_t;
++
++bool qemuio_command(BlockDriverState *bs, const char *cmd);
++
++void qemuio_add_command(const cmdinfo_t *ci);
++int qemuio_command_usage(const cmdinfo_t *ci);
++
++#endif /* QEMU_IO_H */
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+index 1db7fb9..1f21ce9 100644
+--- a/qemu-io-cmds.c
++++ b/qemu-io-cmds.c
+@@ -8,10 +8,9 @@
+  * See the COPYING file in the top-level directory.
+  */
+ 
+-#include "qemu-common.h"
++#include "qemu-io.h"
+ #include "block/block_int.h"
+ #include "block/qapi.h"
+-#include "cmd.h"
+ 
+ #define CMD_NOFILE_OK   0x01
+ 
+@@ -51,11 +50,12 @@ static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+     return 1;
+ }
+ 
+-static int command(const cmdinfo_t *ct, int argc, char **argv)
++static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
++                   char **argv)
+ {
+     char *cmd = argv[0];
+ 
+-    if (!init_check_command(qemuio_bs, ct)) {
++    if (!init_check_command(bs, ct)) {
+         return 0;
+     }
+ 
+@@ -76,7 +76,7 @@ static int command(const cmdinfo_t *ct, int argc, char **argv)
+         return 0;
+     }
+     optind = 0;
+-    return ct->cfunc(qemuio_bs, argc, argv);
++    return ct->cfunc(bs, argc, argv);
+ }
+ 
+ static const cmdinfo_t *find_command(const char *cmd)
+@@ -2084,7 +2084,7 @@ static const cmdinfo_t help_cmd = {
+     .oneline    = "help for one or all commands",
+ };
+ 
+-bool qemuio_command(const char *cmd)
++bool qemuio_command(BlockDriverState *bs, const char *cmd)
+ {
+     char *input;
+     const cmdinfo_t *ct;
+@@ -2097,7 +2097,7 @@ bool qemuio_command(const char *cmd)
+     if (c) {
+         ct = find_command(v[0]);
+         if (ct) {
+-            done = command(ct, c, v);
++            done = command(bs, ct, c, v);
+         } else {
+             fprintf(stderr, "command \"%s\" not found\n", v[0]);
+         }
+diff --git a/qemu-io.c b/qemu-io.c
+index da9944e..e685808 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -14,13 +14,12 @@
+ #include <getopt.h>
+ #include <libgen.h>
+ 
+-#include "qemu-common.h"
++#include "qemu-io.h"
+ #include "qemu/main-loop.h"
+ #include "qemu/option.h"
+ #include "qemu/config-file.h"
+ #include "block/block_int.h"
+ #include "block/qapi.h"
+-#include "cmd.h"
+ #include "trace/control.h"
+ #include "qemu/timer.h"
+ 
+@@ -306,7 +305,7 @@ static void command_loop(void)
+     char *input;
+ 
+     for (i = 0; !done && i < ncmdline; i++) {
+-        done = qemuio_command(cmdline[i]);
++        done = qemuio_command(qemuio_bs, cmdline[i]);
+     }
+     if (cmdline) {
+         g_free(cmdline);
+@@ -331,7 +330,7 @@ static void command_loop(void)
+         if (input == NULL) {
+             break;
+         }
+-        done = qemuio_command(input);
++        done = qemuio_command(qemuio_bs, input);
+         g_free(input);
+ 
+         prompted = 0;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Make-cvtnum-a-wrapper-around-strtosz_suffix.patch b/SOURCES/kvm-qemu-io-Make-cvtnum-a-wrapper-around-strtosz_suffix.patch
new file mode 100644
index 0000000..2b4fbc7
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Make-cvtnum-a-wrapper-around-strtosz_suffix.patch
@@ -0,0 +1,112 @@
+From 94787daf53d6eb2936704f7d9089b26cc5803699 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:22 +0100
+Subject: [PATCH 03/27] qemu-io: Make cvtnum() a wrapper around
+ strtosz_suffix()
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-4-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68432
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 03/21] qemu-io: Make cvtnum() a wrapper around strtosz_suffix()
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+No reason to implement the same thing multiple times. A nice side effect
+is that fractional numbers like 0.5M can be used in qemu-io now.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit b6e356aa25c81d928e1c463292048d29cf25f04e)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ cmd.c     | 37 -------------------------------------
+ cmd.h     |  1 -
+ qemu-io.c |  6 ++++++
+ 3 files changed, 6 insertions(+), 38 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index 4e7579b..214c6f7 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -344,43 +344,6 @@ doneline(
+ #define MEGABYTES(x)	((long long)(x) << 20)
+ #define KILOBYTES(x)	((long long)(x) << 10)
+ 
+-long long
+-cvtnum(
+-	char		*s)
+-{
+-	long long	i;
+-	char		*sp;
+-	int		c;
+-
+-	i = strtoll(s, &sp, 0);
+-	if (i == 0 && sp == s)
+-		return -1LL;
+-	if (*sp == '\0')
+-		return i;
+-
+-	if (sp[1] != '\0')
+-		return -1LL;
+-
+-	c = qemu_tolower(*sp);
+-	switch (c) {
+-	default:
+-		return i;
+-	case 'k':
+-		return KILOBYTES(i);
+-	case 'm':
+-		return MEGABYTES(i);
+-	case 'g':
+-		return GIGABYTES(i);
+-	case 't':
+-		return TERABYTES(i);
+-	case 'p':
+-		return PETABYTES(i);
+-	case 'e':
+-		return  EXABYTES(i);
+-	}
+-	return -1LL;
+-}
+-
+ #define TO_EXABYTES(x)	((x) / EXABYTES(1))
+ #define TO_PETABYTES(x)	((x) / PETABYTES(1))
+ #define TO_TERABYTES(x)	((x) / TERABYTES(1))
+diff --git a/cmd.h b/cmd.h
+index 8e6f753..4dcfe88 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -58,7 +58,6 @@ char **breakline(char *input, int *count);
+ void doneline(char *input, char **vec);
+ char *fetchline(void);
+ 
+-long long cvtnum(char *s);
+ void cvtstr(double value, char *str, size_t sz);
+ 
+ struct timeval tsub(struct timeval t1, struct timeval t2);
+diff --git a/qemu-io.c b/qemu-io.c
+index 9f66a78..3b5890e 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -33,6 +33,12 @@ static BlockDriverState *bs;
+ 
+ static int misalign;
+ 
++static int64_t cvtnum(const char *s)
++{
++    char *end;
++    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
++}
++
+ /*
+  * Parse the pattern argument to various sub-commands.
+  *
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Move-command_loop-and-friends.patch b/SOURCES/kvm-qemu-io-Move-command_loop-and-friends.patch
new file mode 100644
index 0000000..2ba730c
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Move-command_loop-and-friends.patch
@@ -0,0 +1,369 @@
+From 828d09abacc6ae7f0643957301cc3ddee269d7a0 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:31 +0100
+Subject: [PATCH 12/27] qemu-io: Move command_loop() and friends
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-13-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68441
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 12/21] qemu-io: Move command_loop() and friends
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit d1174f13e78e2f43f7ae33d59b62b0b94468c8db)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ cmd.c     | 139 --------------------------------------------------------------
+ cmd.h     |   9 ----
+ qemu-io.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 139 insertions(+), 148 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index 6616d61..26d38a8 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -31,145 +31,6 @@
+ 
+ /* from libxcmd/command.c */
+ 
+-static int		ncmdline;
+-static char		**cmdline;
+-
+-
+-void add_user_command(char *optarg)
+-{
+-    cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
+-    cmdline[ncmdline-1] = optarg;
+-}
+-
+-static void prep_fetchline(void *opaque)
+-{
+-    int *fetchable = opaque;
+-
+-    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
+-    *fetchable= 1;
+-}
+-
+-static char *get_prompt(void);
+-
+-void command_loop(void)
+-{
+-    int i, done = 0, fetchable = 0, prompted = 0;
+-    char *input;
+-
+-    for (i = 0; !done && i < ncmdline; i++) {
+-        done = qemuio_command(cmdline[i]);
+-    }
+-    if (cmdline) {
+-        g_free(cmdline);
+-        return;
+-    }
+-
+-    while (!done) {
+-        if (!prompted) {
+-            printf("%s", get_prompt());
+-            fflush(stdout);
+-            qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable);
+-            prompted = 1;
+-        }
+-
+-        main_loop_wait(false);
+-
+-        if (!fetchable) {
+-            continue;
+-        }
+-
+-        input = fetchline();
+-        if (input == NULL) {
+-            break;
+-        }
+-        done = qemuio_command(input);
+-        free(input);
+-
+-        prompted = 0;
+-        fetchable = 0;
+-    }
+-    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
+-}
+-
+-/* from libxcmd/input.c */
+-
+-#if defined(ENABLE_READLINE)
+-# include <readline/history.h>
+-# include <readline/readline.h>
+-#elif defined(ENABLE_EDITLINE)
+-# include <histedit.h>
+-#endif
+-
+-static char *
+-get_prompt(void)
+-{
+-	static char	prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
+-
+-	if (!prompt[0])
+-		snprintf(prompt, sizeof(prompt), "%s> ", progname);
+-	return prompt;
+-}
+-
+-#if defined(ENABLE_READLINE)
+-char *
+-fetchline(void)
+-{
+-	char	*line;
+-
+-	line = readline(get_prompt());
+-	if (line && *line)
+-		add_history(line);
+-	return line;
+-}
+-#elif defined(ENABLE_EDITLINE)
+-static char *el_get_prompt(EditLine *e) { return get_prompt(); }
+-char *
+-fetchline(void)
+-{
+-	static EditLine	*el;
+-	static History	*hist;
+-	HistEvent	hevent;
+-	char		*line;
+-	int		count;
+-
+-	if (!el) {
+-		hist = history_init();
+-		history(hist, &hevent, H_SETSIZE, 100);
+-		el = el_init(progname, stdin, stdout, stderr);
+-		el_source(el, NULL);
+-		el_set(el, EL_SIGNAL, 1);
+-		el_set(el, EL_PROMPT, el_get_prompt);
+-		el_set(el, EL_HIST, history, (const char *)hist);
+-	}
+-	line = strdup(el_gets(el, &count));
+-	if (line) {
+-		if (count > 0)
+-			line[count-1] = '\0';
+-		if (*line)
+-			history(hist, &hevent, H_ENTER, line);
+-	}
+-	return line;
+-}
+-#else
+-# define MAXREADLINESZ	1024
+-char *
+-fetchline(void)
+-{
+-	char	*p, *line = malloc(MAXREADLINESZ);
+-
+-	if (!line)
+-		return NULL;
+-	if (!fgets(line, MAXREADLINESZ, stdin)) {
+-		free(line);
+-		return NULL;
+-	}
+-	p = line + strlen(line);
+-	if (p != line && p[-1] == '\n')
+-		p[-1] = '\0';
+-	return line;
+-}
+-#endif
+-
+ #define EXABYTES(x)	((long long)(x) << 60)
+ #define PETABYTES(x)	((long long)(x) << 50)
+ #define TERABYTES(x)	((long long)(x) << 40)
+diff --git a/cmd.h b/cmd.h
+index 0d01a33..da0c7cf 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -39,18 +39,11 @@ typedef struct cmdinfo {
+ 	helpfunc_t      help;
+ } cmdinfo_t;
+ 
+-typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
+-
+ void qemuio_add_command(const cmdinfo_t *ci);
+-void add_user_command(char *optarg);
+-void add_check_command(checkfunc_t cf);
+ 
+-void command_loop(void);
+ int qemuio_command_usage(const cmdinfo_t *ci);
+ 
+ /* from input.h */
+-char *fetchline(void);
+-
+ void cvtstr(double value, char *str, size_t sz);
+ 
+ struct timeval tsub(struct timeval t1, struct timeval t2);
+@@ -64,8 +57,6 @@ enum {
+ 
+ void timestr(struct timeval *tv, char *str, size_t sz, int flags);
+ 
+-extern char *progname;
+-
+ bool qemuio_command(const char *cmd);
+ 
+ #endif	/* __COMMAND_H__ */
+diff --git a/qemu-io.c b/qemu-io.c
+index 97af39e..da9944e 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -34,6 +34,10 @@ BlockDriverState *qemuio_bs;
+ 
+ extern int qemuio_misalign;
+ 
++/* qemu-io commands passed using -c */
++static int ncmdline;
++static char **cmdline;
++
+ static int close_f(BlockDriverState *bs, int argc, char **argv)
+ {
+     bdrv_unref(bs);
+@@ -207,6 +211,141 @@ static void usage(const char *name)
+ }
+ 
+ 
++#if defined(ENABLE_READLINE)
++# include <readline/history.h>
++# include <readline/readline.h>
++#elif defined(ENABLE_EDITLINE)
++# include <histedit.h>
++#endif
++
++static char *get_prompt(void)
++{
++    static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
++
++    if (!prompt[0]) {
++        snprintf(prompt, sizeof(prompt), "%s> ", progname);
++    }
++
++    return prompt;
++}
++
++#if defined(ENABLE_READLINE)
++static char *fetchline(void)
++{
++    char *line = readline(get_prompt());
++    if (line && *line) {
++        add_history(line);
++    }
++    return line;
++}
++#elif defined(ENABLE_EDITLINE)
++static char *el_get_prompt(EditLine *e)
++{
++    return get_prompt();
++}
++
++static char *fetchline(void)
++{
++    static EditLine *el;
++    static History *hist;
++    HistEvent hevent;
++    char *line;
++    int count;
++
++    if (!el) {
++        hist = history_init();
++        history(hist, &hevent, H_SETSIZE, 100);
++        el = el_init(progname, stdin, stdout, stderr);
++        el_source(el, NULL);
++        el_set(el, EL_SIGNAL, 1);
++        el_set(el, EL_PROMPT, el_get_prompt);
++        el_set(el, EL_HIST, history, (const char *)hist);
++    }
++    line = strdup(el_gets(el, &count));
++    if (line) {
++        if (count > 0) {
++            line[count-1] = '\0';
++        }
++        if (*line) {
++            history(hist, &hevent, H_ENTER, line);
++        }
++    }
++    return line;
++}
++#else
++# define MAXREADLINESZ 1024
++static char *fetchline(void)
++{
++    char *p, *line = g_malloc(MAXREADLINESZ);
++
++    if (!fgets(line, MAXREADLINESZ, stdin)) {
++        g_free(line);
++        return NULL;
++    }
++
++    p = line + strlen(line);
++    if (p != line && p[-1] == '\n') {
++        p[-1] = '\0';
++    }
++
++    return line;
++}
++#endif
++
++static void prep_fetchline(void *opaque)
++{
++    int *fetchable = opaque;
++
++    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
++    *fetchable= 1;
++}
++
++static void command_loop(void)
++{
++    int i, done = 0, fetchable = 0, prompted = 0;
++    char *input;
++
++    for (i = 0; !done && i < ncmdline; i++) {
++        done = qemuio_command(cmdline[i]);
++    }
++    if (cmdline) {
++        g_free(cmdline);
++        return;
++    }
++
++    while (!done) {
++        if (!prompted) {
++            printf("%s", get_prompt());
++            fflush(stdout);
++            qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable);
++            prompted = 1;
++        }
++
++        main_loop_wait(false);
++
++        if (!fetchable) {
++            continue;
++        }
++
++        input = fetchline();
++        if (input == NULL) {
++            break;
++        }
++        done = qemuio_command(input);
++        g_free(input);
++
++        prompted = 0;
++        fetchable = 0;
++    }
++    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
++}
++
++static void add_user_command(char *optarg)
++{
++    cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
++    cmdline[ncmdline-1] = optarg;
++}
++
+ int main(int argc, char **argv)
+ {
+     int readonly = 0;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Move-functions-for-registering-and-running-c.patch b/SOURCES/kvm-qemu-io-Move-functions-for-registering-and-running-c.patch
new file mode 100644
index 0000000..0284767
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Move-functions-for-registering-and-running-c.patch
@@ -0,0 +1,551 @@
+From df682d833654f2f42595d6156341439644a8848d Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:30 +0100
+Subject: [PATCH 11/27] qemu-io: Move functions for registering and running
+ commands
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-12-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68439
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 11/21] qemu-io: Move functions for registering and running commands
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit c2cdf5c5892165cbe7d3567bff5930521bc52669)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+    qemu-io-cmds.c: Conflicts over sleep_f, again.
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ cmd.c          | 113 ---------------------------------
+ cmd.h          |  11 +---
+ qemu-io-cmds.c | 194 +++++++++++++++++++++++++++++++++++++++++----------------
+ qemu-io.c      |  10 +--
+ 4 files changed, 149 insertions(+), 179 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index f6bf2c5..6616d61 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -31,94 +31,9 @@
+ 
+ /* from libxcmd/command.c */
+ 
+-cmdinfo_t	*cmdtab;
+-int		ncmds;
+-
+-static checkfunc_t	check_func;
+ static int		ncmdline;
+ static char		**cmdline;
+ 
+-static int
+-compare(const void *a, const void *b)
+-{
+-	return strcmp(((const cmdinfo_t *)a)->name,
+-		      ((const cmdinfo_t *)b)->name);
+-}
+-
+-void add_command(const cmdinfo_t *ci)
+-{
+-    cmdtab = g_realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
+-    cmdtab[ncmds - 1] = *ci;
+-    qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
+-}
+-
+-static int
+-check_command(
+-	const cmdinfo_t	*ci)
+-{
+-	if (check_func)
+-		return check_func(qemuio_bs, ci);
+-	return 1;
+-}
+-
+-void
+-add_check_command(
+-	checkfunc_t	cf)
+-{
+-	check_func = cf;
+-}
+-
+-int
+-command_usage(
+-	const cmdinfo_t *ci)
+-{
+-	printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
+-	return 0;
+-}
+-
+-int
+-command(
+-	const cmdinfo_t	*ct,
+-	int		argc,
+-	char		**argv)
+-{
+-	char		*cmd = argv[0];
+-
+-	if (!check_command(ct))
+-		return 0;
+-
+-	if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
+-		if (ct->argmax == -1)
+-			fprintf(stderr,
+-	_("bad argument count %d to %s, expected at least %d arguments\n"),
+-				argc-1, cmd, ct->argmin);
+-		else if (ct->argmin == ct->argmax)
+-			fprintf(stderr,
+-	_("bad argument count %d to %s, expected %d arguments\n"),
+-				argc-1, cmd, ct->argmin);
+-		else
+-			fprintf(stderr,
+-	_("bad argument count %d to %s, expected between %d and %d arguments\n"),
+-			argc-1, cmd, ct->argmin, ct->argmax);
+-		return 0;
+-	}
+-	optind = 0;
+-	return ct->cfunc(qemuio_bs, argc, argv);
+-}
+-
+-const cmdinfo_t *
+-find_command(
+-	const char	*cmd)
+-{
+-	cmdinfo_t	*ct;
+-
+-	for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
+-		if (strcmp(ct->name, cmd) == 0 ||
+-		    (ct->altname && strcmp(ct->altname, cmd) == 0))
+-			return (const cmdinfo_t *)ct;
+-	}
+-	return NULL;
+-}
+ 
+ void add_user_command(char *optarg)
+ {
+@@ -255,34 +170,6 @@ fetchline(void)
+ }
+ #endif
+ 
+-char **breakline(char *input, int *count)
+-{
+-    int c = 0;
+-    char *p;
+-    char **rval = calloc(sizeof(char *), 1);
+-    char **tmp;
+-
+-    while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
+-        if (!*p) {
+-            continue;
+-        }
+-        c++;
+-        tmp = realloc(rval, sizeof(*rval) * (c + 1));
+-        if (!tmp) {
+-            free(rval);
+-            rval = NULL;
+-            c = 0;
+-            break;
+-        } else {
+-            rval = tmp;
+-        }
+-        rval[c - 1] = p;
+-        rval[c] = NULL;
+-    }
+-    *count = c;
+-    return rval;
+-}
+-
+ #define EXABYTES(x)	((long long)(x) << 60)
+ #define PETABYTES(x)	((long long)(x) << 50)
+ #define TERABYTES(x)	((long long)(x) << 40)
+diff --git a/cmd.h b/cmd.h
+index 5b6f61b..0d01a33 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -39,23 +39,16 @@ typedef struct cmdinfo {
+ 	helpfunc_t      help;
+ } cmdinfo_t;
+ 
+-extern cmdinfo_t	*cmdtab;
+-extern int		ncmds;
+-
+ typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
+ 
+-void add_command(const cmdinfo_t *ci);
++void qemuio_add_command(const cmdinfo_t *ci);
+ void add_user_command(char *optarg);
+ void add_check_command(checkfunc_t cf);
+ 
+-const cmdinfo_t *find_command(const char *cmd);
+-
+ void command_loop(void);
+-int command_usage(const cmdinfo_t *ci);
+-int command(const cmdinfo_t *ci, int argc, char **argv);
++int qemuio_command_usage(const cmdinfo_t *ci);
+ 
+ /* from input.h */
+-char **breakline(char *input, int *count);
+ char *fetchline(void);
+ 
+ void cvtstr(double value, char *str, size_t sz);
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+index a8e891a..27a903f 100644
+--- a/qemu-io-cmds.c
++++ b/qemu-io-cmds.c
+@@ -17,6 +17,110 @@
+ 
+ int qemuio_misalign;
+ 
++static cmdinfo_t *cmdtab;
++static int ncmds;
++
++static int compare_cmdname(const void *a, const void *b)
++{
++    return strcmp(((const cmdinfo_t *)a)->name,
++                  ((const cmdinfo_t *)b)->name);
++}
++
++void qemuio_add_command(const cmdinfo_t *ci)
++{
++    cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
++    cmdtab[ncmds - 1] = *ci;
++    qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
++}
++
++int qemuio_command_usage(const cmdinfo_t *ci)
++{
++    printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
++    return 0;
++}
++
++static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
++{
++    if (ct->flags & CMD_FLAG_GLOBAL) {
++        return 1;
++    }
++    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
++        fprintf(stderr, "no file open, try 'help open'\n");
++        return 0;
++    }
++    return 1;
++}
++
++static int command(const cmdinfo_t *ct, int argc, char **argv)
++{
++    char *cmd = argv[0];
++
++    if (!init_check_command(qemuio_bs, ct)) {
++        return 0;
++    }
++
++    if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
++        if (ct->argmax == -1) {
++            fprintf(stderr,
++                    "bad argument count %d to %s, expected at least %d arguments\n",
++                    argc-1, cmd, ct->argmin);
++        } else if (ct->argmin == ct->argmax) {
++            fprintf(stderr,
++                    "bad argument count %d to %s, expected %d arguments\n",
++                    argc-1, cmd, ct->argmin);
++        } else {
++            fprintf(stderr,
++                    "bad argument count %d to %s, expected between %d and %d arguments\n",
++                    argc-1, cmd, ct->argmin, ct->argmax);
++        }
++        return 0;
++    }
++    optind = 0;
++    return ct->cfunc(qemuio_bs, argc, argv);
++}
++
++static const cmdinfo_t *find_command(const char *cmd)
++{
++    cmdinfo_t *ct;
++
++    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
++        if (strcmp(ct->name, cmd) == 0 ||
++            (ct->altname && strcmp(ct->altname, cmd) == 0))
++        {
++            return (const cmdinfo_t *)ct;
++        }
++    }
++    return NULL;
++}
++
++static char **breakline(char *input, int *count)
++{
++    int c = 0;
++    char *p;
++    char **rval = g_malloc0(sizeof(char *));
++    char **tmp;
++
++    while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
++        if (!*p) {
++            continue;
++        }
++        c++;
++        tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
++        if (!tmp) {
++            g_free(rval);
++            rval = NULL;
++            c = 0;
++            break;
++        } else {
++            rval = tmp;
++        }
++        rval[c - 1] = p;
++        rval[c] = NULL;
++    }
++    *count = c;
++    return rval;
++}
++
+ static int64_t cvtnum(const char *s)
+ {
+     char *end;
+@@ -468,12 +572,12 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+             vflag = 1;
+             break;
+         default:
+-            return command_usage(&read_cmd);
++            return qemuio_command_usage(&read_cmd);
+         }
+     }
+ 
+     if (optind != argc - 2) {
+-        return command_usage(&read_cmd);
++        return qemuio_command_usage(&read_cmd);
+     }
+ 
+     if (bflag && pflag) {
+@@ -495,7 +599,7 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+     }
+ 
+     if (!Pflag && (lflag || sflag)) {
+-        return command_usage(&read_cmd);
++        return qemuio_command_usage(&read_cmd);
+     }
+ 
+     if (!lflag) {
+@@ -630,12 +734,12 @@ static int readv_f(BlockDriverState *bs, int argc, char **argv)
+             vflag = 1;
+             break;
+         default:
+-            return command_usage(&readv_cmd);
++            return qemuio_command_usage(&readv_cmd);
+         }
+     }
+ 
+     if (optind > argc - 2) {
+-        return command_usage(&readv_cmd);
++        return qemuio_command_usage(&readv_cmd);
+     }
+ 
+ 
+@@ -770,12 +874,12 @@ static int write_f(BlockDriverState *bs, int argc, char **argv)
+             zflag = 1;
+             break;
+         default:
+-            return command_usage(&write_cmd);
++            return qemuio_command_usage(&write_cmd);
+         }
+     }
+ 
+     if (optind != argc - 2) {
+-        return command_usage(&write_cmd);
++        return qemuio_command_usage(&write_cmd);
+     }
+ 
+     if (bflag + pflag + zflag > 1) {
+@@ -912,12 +1016,12 @@ static int writev_f(BlockDriverState *bs, int argc, char **argv)
+             }
+             break;
+         default:
+-            return command_usage(&writev_cmd);
++            return qemuio_command_usage(&writev_cmd);
+         }
+     }
+ 
+     if (optind > argc - 2) {
+-        return command_usage(&writev_cmd);
++        return qemuio_command_usage(&writev_cmd);
+     }
+ 
+     offset = cvtnum(argv[optind]);
+@@ -1024,12 +1128,12 @@ static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
+             }
+             break;
+         default:
+-            return command_usage(&writev_cmd);
++            return qemuio_command_usage(&writev_cmd);
+         }
+     }
+ 
+     if (optind > argc - 2) {
+-        return command_usage(&writev_cmd);
++        return qemuio_command_usage(&writev_cmd);
+     }
+ 
+     nr_reqs = 1;
+@@ -1258,13 +1362,13 @@ static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
+             break;
+         default:
+             g_free(ctx);
+-            return command_usage(&aio_read_cmd);
++            return qemuio_command_usage(&aio_read_cmd);
+         }
+     }
+ 
+     if (optind > argc - 2) {
+         g_free(ctx);
+-        return command_usage(&aio_read_cmd);
++        return qemuio_command_usage(&aio_read_cmd);
+     }
+ 
+     ctx->offset = cvtnum(argv[optind]);
+@@ -1350,13 +1454,13 @@ static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
+             break;
+         default:
+             g_free(ctx);
+-            return command_usage(&aio_write_cmd);
++            return qemuio_command_usage(&aio_write_cmd);
+         }
+     }
+ 
+     if (optind > argc - 2) {
+         g_free(ctx);
+-        return command_usage(&aio_write_cmd);
++        return qemuio_command_usage(&aio_write_cmd);
+     }
+ 
+     ctx->offset = cvtnum(argv[optind]);
+@@ -1556,12 +1660,12 @@ static int discard_f(BlockDriverState *bs, int argc, char **argv)
+             qflag = 1;
+             break;
+         default:
+-            return command_usage(&discard_cmd);
++            return qemuio_command_usage(&discard_cmd);
+         }
+     }
+ 
+     if (optind != argc - 2) {
+-        return command_usage(&discard_cmd);
++        return qemuio_command_usage(&discard_cmd);
+     }
+ 
+     offset = cvtnum(argv[optind]);
+@@ -1876,18 +1980,6 @@ static const cmdinfo_t help_cmd = {
+     .oneline    = "help for one or all commands",
+ };
+ 
+-static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+-{
+-    if (ct->flags & CMD_FLAG_GLOBAL) {
+-        return 1;
+-    }
+-    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
+-        fprintf(stderr, "no file open, try 'help open'\n");
+-        return 0;
+-    }
+-    return 1;
+-}
+-
+ bool qemuio_command(const char *cmd)
+ {
+     char *input;
+@@ -1915,27 +2007,25 @@ bool qemuio_command(const char *cmd)
+ static void __attribute((constructor)) init_qemuio_commands(void)
+ {
+     /* initialize commands */
+-    add_command(&help_cmd);
+-    add_command(&read_cmd);
+-    add_command(&readv_cmd);
+-    add_command(&write_cmd);
+-    add_command(&writev_cmd);
+-    add_command(&multiwrite_cmd);
+-    add_command(&aio_read_cmd);
+-    add_command(&aio_write_cmd);
+-    add_command(&aio_flush_cmd);
+-    add_command(&flush_cmd);
+-    add_command(&truncate_cmd);
+-    add_command(&length_cmd);
+-    add_command(&info_cmd);
+-    add_command(&discard_cmd);
+-    add_command(&alloc_cmd);
+-    add_command(&map_cmd);
+-    add_command(&break_cmd);
+-    add_command(&resume_cmd);
+-    add_command(&wait_break_cmd);
+-    add_command(&abort_cmd);
+-    add_command(&sleep_cmd);
+-
+-    add_check_command(init_check_command);
++    qemuio_add_command(&help_cmd);
++    qemuio_add_command(&read_cmd);
++    qemuio_add_command(&readv_cmd);
++    qemuio_add_command(&write_cmd);
++    qemuio_add_command(&writev_cmd);
++    qemuio_add_command(&multiwrite_cmd);
++    qemuio_add_command(&aio_read_cmd);
++    qemuio_add_command(&aio_write_cmd);
++    qemuio_add_command(&aio_flush_cmd);
++    qemuio_add_command(&flush_cmd);
++    qemuio_add_command(&truncate_cmd);
++    qemuio_add_command(&length_cmd);
++    qemuio_add_command(&info_cmd);
++    qemuio_add_command(&discard_cmd);
++    qemuio_add_command(&alloc_cmd);
++    qemuio_add_command(&map_cmd);
++    qemuio_add_command(&break_cmd);
++    qemuio_add_command(&resume_cmd);
++    qemuio_add_command(&wait_break_cmd);
++    qemuio_add_command(&abort_cmd);
++    qemuio_add_command(&sleep_cmd);
+ }
+diff --git a/qemu-io.c b/qemu-io.c
+index b86bfbf..97af39e 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -155,7 +155,7 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
+             qemu_opts_del(qopts);
+             break;
+         default:
+-            return command_usage(&open_cmd);
++            return qemuio_command_usage(&open_cmd);
+         }
+     }
+ 
+@@ -164,7 +164,7 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
+     }
+ 
+     if (optind != argc - 1) {
+-        return command_usage(&open_cmd);
++        return qemuio_command_usage(&open_cmd);
+     }
+ 
+     return openfile(argv[optind], flags, growable, opts);
+@@ -300,9 +300,9 @@ int main(int argc, char **argv)
+     bdrv_init();
+ 
+     /* initialize commands */
+-    add_command(&quit_cmd);
+-    add_command(&open_cmd);
+-    add_command(&close_cmd);
++    qemuio_add_command(&quit_cmd);
++    qemuio_add_command(&open_cmd);
++    qemuio_add_command(&close_cmd);
+ 
+     /* open the device */
+     if (!readonly) {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Move-help-function.patch b/SOURCES/kvm-qemu-io-Move-help-function.patch
new file mode 100644
index 0000000..42daa19
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Move-help-function.patch
@@ -0,0 +1,223 @@
+From 8d6f59c923b536461df1aea18045535b090984fb Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:27 +0100
+Subject: [PATCH 08/27] qemu-io: Move 'help' function
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-9-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68435
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 08/21] qemu-io: Move 'help' function
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+No reason to treat it different from other commands. Move it to
+qemu-io-cmds.c, adapt the coding style and register it like any other
+command.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit f18a834a92f0b490cefeb71410f3f25b969d336f)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+  qemu-io-cmds:  patch context (from sleep_f)
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ cmd.c          | 79 ----------------------------------------------------------
+ cmd.h          |  1 -
+ qemu-io-cmds.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 65 insertions(+), 81 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index 7ae978f..2941ad3 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -439,82 +439,3 @@ quit_init(void)
+ 
+ 	add_command(&quit_cmd);
+ }
+-
+-/* from libxcmd/help.c */
+-
+-static cmdinfo_t help_cmd;
+-static void help_onecmd(const char *cmd, const cmdinfo_t *ct);
+-static void help_oneline(const char *cmd, const cmdinfo_t *ct);
+-
+-static void
+-help_all(void)
+-{
+-	const cmdinfo_t	*ct;
+-
+-	for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
+-		help_oneline(ct->name, ct);
+-	printf(_("\nUse 'help commandname' for extended help.\n"));
+-}
+-
+-static int
+-help_f(
+-    BlockDriverState *bs,
+-	int		argc,
+-	char		**argv)
+-{
+-	const cmdinfo_t	*ct;
+-
+-	if (argc == 1) {
+-		help_all();
+-		return 0;
+-	}
+-	ct = find_command(argv[1]);
+-	if (ct == NULL) {
+-		printf(_("command %s not found\n"), argv[1]);
+-		return 0;
+-	}
+-	help_onecmd(argv[1], ct);
+-	return 0;
+-}
+-
+-static void
+-help_onecmd(
+-	const char	*cmd,
+-	const cmdinfo_t	*ct)
+-{
+-	help_oneline(cmd, ct);
+-	if (ct->help)
+-		ct->help();
+-}
+-
+-static void
+-help_oneline(
+-	const char	*cmd,
+-	const cmdinfo_t	*ct)
+-{
+-	if (cmd)
+-		printf("%s ", cmd);
+-	else {
+-		printf("%s ", ct->name);
+-		if (ct->altname)
+-			printf("(or %s) ", ct->altname);
+-	}
+-	if (ct->args)
+-		printf("%s ", ct->args);
+-	printf("-- %s\n", ct->oneline);
+-}
+-
+-void
+-help_init(void)
+-{
+-	help_cmd.name = _("help");
+-	help_cmd.altname = _("?");
+-	help_cmd.cfunc = help_f;
+-	help_cmd.argmin = 0;
+-	help_cmd.argmax = 1;
+-	help_cmd.flags = CMD_FLAG_GLOBAL;
+-	help_cmd.args = _("[command]");
+-	help_cmd.oneline = _("help for one or all commands");
+-
+-	add_command(&help_cmd);
+-}
+diff --git a/cmd.h b/cmd.h
+index d676408..89e7c6e 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -42,7 +42,6 @@ typedef struct cmdinfo {
+ extern cmdinfo_t	*cmdtab;
+ extern int		ncmds;
+ 
+-void help_init(void);
+ void quit_init(void);
+ 
+ typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+index 09e4099..a8e891a 100644
+--- a/qemu-io-cmds.c
++++ b/qemu-io-cmds.c
+@@ -1811,6 +1811,70 @@ static const cmdinfo_t sleep_cmd = {
+        .oneline        = "waits for the given value in milliseconds",
+ };
+ 
++static void help_oneline(const char *cmd, const cmdinfo_t *ct)
++{
++    if (cmd) {
++        printf("%s ", cmd);
++    } else {
++        printf("%s ", ct->name);
++        if (ct->altname) {
++            printf("(or %s) ", ct->altname);
++        }
++    }
++
++    if (ct->args) {
++        printf("%s ", ct->args);
++    }
++    printf("-- %s\n", ct->oneline);
++}
++
++static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
++{
++    help_oneline(cmd, ct);
++    if (ct->help) {
++        ct->help();
++    }
++}
++
++static void help_all(void)
++{
++    const cmdinfo_t *ct;
++
++    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
++        help_oneline(ct->name, ct);
++    }
++    printf("\nUse 'help commandname' for extended help.\n");
++}
++
++static int help_f(BlockDriverState *bs, int argc, char **argv)
++{
++    const cmdinfo_t *ct;
++
++    if (argc == 1) {
++        help_all();
++        return 0;
++    }
++
++    ct = find_command(argv[1]);
++    if (ct == NULL) {
++        printf("command %s not found\n", argv[1]);
++        return 0;
++    }
++
++    help_onecmd(argv[1], ct);
++    return 0;
++}
++
++static const cmdinfo_t help_cmd = {
++    .name       = "help",
++    .altname    = "?",
++    .cfunc      = help_f,
++    .argmin     = 0,
++    .argmax     = 1,
++    .flags      = CMD_FLAG_GLOBAL,
++    .args       = "[command]",
++    .oneline    = "help for one or all commands",
++};
+ 
+ static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+ {
+@@ -1851,7 +1915,7 @@ bool qemuio_command(const char *cmd)
+ static void __attribute((constructor)) init_qemuio_commands(void)
+ {
+     /* initialize commands */
+-    help_init();
++    add_command(&help_cmd);
+     add_command(&read_cmd);
+     add_command(&readv_cmd);
+     add_command(&write_cmd);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Move-qemu_strsep-to-cutils.c.patch b/SOURCES/kvm-qemu-io-Move-qemu_strsep-to-cutils.c.patch
new file mode 100644
index 0000000..743967c
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Move-qemu_strsep-to-cutils.c.patch
@@ -0,0 +1,107 @@
+From 4ab2a72fcfc65bd78cf60e6e5a29e2189fddf877 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:29 +0100
+Subject: [PATCH 10/27] qemu-io: Move qemu_strsep() to cutils.c
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-11-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68440
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 10/21] qemu-io: Move qemu_strsep() to cutils.c
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit a38ed811474e953371f848233208c2026c2d1195)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ cmd.c                 | 21 ---------------------
+ include/qemu-common.h |  1 +
+ util/cutils.c         | 21 +++++++++++++++++++++
+ 3 files changed, 22 insertions(+), 21 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index 8496e74..f6bf2c5 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -255,27 +255,6 @@ fetchline(void)
+ }
+ #endif
+ 
+-static char *qemu_strsep(char **input, const char *delim)
+-{
+-    char *result = *input;
+-    if (result != NULL) {
+-        char *p;
+-
+-        for (p = result; *p != '\0'; p++) {
+-            if (strchr(delim, *p)) {
+-                break;
+-            }
+-        }
+-        if (*p == '\0') {
+-            *input = NULL;
+-        } else {
+-            *p = '\0';
+-            *input = p + 1;
+-        }
+-    }
+-    return result;
+-}
+-
+ char **breakline(char *input, int *count)
+ {
+     int c = 0;
+diff --git a/include/qemu-common.h b/include/qemu-common.h
+index 67f57c9..8c1132c 100644
+--- a/include/qemu-common.h
++++ b/include/qemu-common.h
+@@ -161,6 +161,7 @@ char *pstrcat(char *buf, int buf_size, const char *s);
+ int strstart(const char *str, const char *val, const char **ptr);
+ int stristart(const char *str, const char *val, const char **ptr);
+ int qemu_strnlen(const char *s, int max_len);
++char *qemu_strsep(char **input, const char *delim);
+ time_t mktimegm(struct tm *tm);
+ int qemu_fls(int i);
+ int qemu_fdatasync(int fd);
+diff --git a/util/cutils.c b/util/cutils.c
+index 8f28896..0116fcd 100644
+--- a/util/cutils.c
++++ b/util/cutils.c
+@@ -107,6 +107,27 @@ int qemu_strnlen(const char *s, int max_len)
+     return i;
+ }
+ 
++char *qemu_strsep(char **input, const char *delim)
++{
++    char *result = *input;
++    if (result != NULL) {
++        char *p;
++
++        for (p = result; *p != '\0'; p++) {
++            if (strchr(delim, *p)) {
++                break;
++            }
++        }
++        if (*p == '\0') {
++            *input = NULL;
++        } else {
++            *p = '\0';
++            *input = p + 1;
++        }
++    }
++    return result;
++}
++
+ time_t mktimegm(struct tm *tm)
+ {
+     time_t t;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Move-quit-function.patch b/SOURCES/kvm-qemu-io-Move-quit-function.patch
new file mode 100644
index 0000000..e6442be
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Move-quit-function.patch
@@ -0,0 +1,119 @@
+From 6ea43a1599b4abdfe480d6e963dbbafa9339601a Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:28 +0100
+Subject: [PATCH 09/27] qemu-io: Move 'quit' function
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-10-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68436
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 09/21] qemu-io: Move 'quit' function
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+This one only makes sense in the context of the qemu-io tool, so move it
+to qemu-io.c. Adapt coding style and register it like other commands.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit e681be7eca0143fe7259ce8233fe5dd8898d072f)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ cmd.c     | 29 -----------------------------
+ cmd.h     |  2 --
+ qemu-io.c | 17 ++++++++++++++++-
+ 3 files changed, 16 insertions(+), 32 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index 2941ad3..8496e74 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -410,32 +410,3 @@ timestr(
+ 		snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
+ 	}
+ }
+-
+-
+-/* from libxcmd/quit.c */
+-
+-static cmdinfo_t quit_cmd;
+-
+-/* ARGSUSED */
+-static int
+-quit_f(
+-    BlockDriverState *bs,
+-	int	argc,
+-	char	**argv)
+-{
+-	return 1;
+-}
+-
+-void
+-quit_init(void)
+-{
+-	quit_cmd.name = _("quit");
+-	quit_cmd.altname = _("q");
+-	quit_cmd.cfunc = quit_f;
+-	quit_cmd.argmin = -1;
+-	quit_cmd.argmax = -1;
+-	quit_cmd.flags = CMD_FLAG_GLOBAL;
+-	quit_cmd.oneline = _("exit the program");
+-
+-	add_command(&quit_cmd);
+-}
+diff --git a/cmd.h b/cmd.h
+index 89e7c6e..5b6f61b 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -42,8 +42,6 @@ typedef struct cmdinfo {
+ extern cmdinfo_t	*cmdtab;
+ extern int		ncmds;
+ 
+-void quit_init(void);
+-
+ typedef int (*checkfunc_t)(BlockDriverState *bs, const cmdinfo_t *ci);
+ 
+ void add_command(const cmdinfo_t *ci);
+diff --git a/qemu-io.c b/qemu-io.c
+index 4f1c808..b86bfbf 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -170,6 +170,21 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
+     return openfile(argv[optind], flags, growable, opts);
+ }
+ 
++static int quit_f(BlockDriverState *bs, int argc, char **argv)
++{
++    return 1;
++}
++
++static const cmdinfo_t quit_cmd = {
++    .name       = "quit",
++    .altname    = "q",
++    .cfunc      = quit_f,
++    .argmin     = -1,
++    .argmax     = -1,
++    .flags      = CMD_FLAG_GLOBAL,
++    .oneline    = "exit the program",
++};
++
+ static void usage(const char *name)
+ {
+     printf(
+@@ -285,7 +300,7 @@ int main(int argc, char **argv)
+     bdrv_init();
+ 
+     /* initialize commands */
+-    quit_init();
++    add_command(&quit_cmd);
+     add_command(&open_cmd);
+     add_command(&close_cmd);
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Move-remaining-helpers-from-cmd.c.patch b/SOURCES/kvm-qemu-io-Move-remaining-helpers-from-cmd.c.patch
new file mode 100644
index 0000000..89354b4
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Move-remaining-helpers-from-cmd.c.patch
@@ -0,0 +1,330 @@
+From f0e4ec43a0a3af6f1e385fae17527ed76cdb00e4 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:32 +0100
+Subject: [PATCH 13/27] qemu-io: Move remaining helpers from cmd.c
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-14-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68437
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 13/21] qemu-io: Move remaining helpers from cmd.c
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 0b613881ae8fc59359b3d91e666fea6c9b1e731b)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ Makefile       |   2 +-
+ cmd.c          | 139 ---------------------------------------------------------
+ cmd.h          |  14 ------
+ qemu-io-cmds.c | 104 ++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 105 insertions(+), 154 deletions(-)
+ delete mode 100644 cmd.c
+
+diff --git a/Makefile b/Makefile
+index f28ce29..f403057 100644
+--- a/Makefile
++++ b/Makefile
+@@ -205,7 +205,7 @@ qemu-img.o: qemu-img-cmds.h
+ 
+ qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
+ qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
+-qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
++qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o $(block-obj-y) libqemuutil.a libqemustub.a
+ 
+ qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
+ 
+diff --git a/cmd.c b/cmd.c
+deleted file mode 100644
+index 26d38a8..0000000
+--- a/cmd.c
++++ /dev/null
+@@ -1,139 +0,0 @@
+-/*
+- * Copyright (c) 2003-2005 Silicon Graphics, Inc.
+- * All Rights Reserved.
+- *
+- * 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.
+- *
+- * This program is distributed in the hope that it would 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/>.
+- */
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <ctype.h>
+-#include <errno.h>
+-#include <sys/time.h>
+-#include <getopt.h>
+-
+-#include "cmd.h"
+-#include "block/aio.h"
+-#include "qemu/main-loop.h"
+-
+-#define _(x)	x	/* not gettext support yet */
+-
+-/* from libxcmd/command.c */
+-
+-#define EXABYTES(x)	((long long)(x) << 60)
+-#define PETABYTES(x)	((long long)(x) << 50)
+-#define TERABYTES(x)	((long long)(x) << 40)
+-#define GIGABYTES(x)	((long long)(x) << 30)
+-#define MEGABYTES(x)	((long long)(x) << 20)
+-#define KILOBYTES(x)	((long long)(x) << 10)
+-
+-#define TO_EXABYTES(x)	((x) / EXABYTES(1))
+-#define TO_PETABYTES(x)	((x) / PETABYTES(1))
+-#define TO_TERABYTES(x)	((x) / TERABYTES(1))
+-#define TO_GIGABYTES(x)	((x) / GIGABYTES(1))
+-#define TO_MEGABYTES(x)	((x) / MEGABYTES(1))
+-#define TO_KILOBYTES(x)	((x) / KILOBYTES(1))
+-
+-void
+-cvtstr(
+-	double		value,
+-	char		*str,
+-	size_t		size)
+-{
+-	char		*trim;
+-	const char	*suffix;
+-
+-	if (value >= EXABYTES(1)) {
+-		suffix = " EiB";
+-		snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
+-	} else if (value >= PETABYTES(1)) {
+-		suffix = " PiB";
+-		snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
+-	} else if (value >= TERABYTES(1)) {
+-		suffix = " TiB";
+-		snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
+-	} else if (value >= GIGABYTES(1)) {
+-		suffix = " GiB";
+-		snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
+-	} else if (value >= MEGABYTES(1)) {
+-		suffix = " MiB";
+-		snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
+-	} else if (value >= KILOBYTES(1)) {
+-		suffix = " KiB";
+-		snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
+-	} else {
+-		suffix = " bytes";
+-		snprintf(str, size - 6, "%f", value);
+-	}
+-
+-	trim = strstr(str, ".000");
+-	if (trim) {
+-		strcpy(trim, suffix);
+-	} else {
+-		strcat(str, suffix);
+-	}
+-}
+-
+-struct timeval
+-tsub(struct timeval t1, struct timeval t2)
+-{
+-	t1.tv_usec -= t2.tv_usec;
+-	if (t1.tv_usec < 0) {
+-		t1.tv_usec += 1000000;
+-		t1.tv_sec--;
+-	}
+-	t1.tv_sec -= t2.tv_sec;
+-	return t1;
+-}
+-
+-double
+-tdiv(double value, struct timeval tv)
+-{
+-	return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
+-}
+-
+-#define HOURS(sec)	((sec) / (60 * 60))
+-#define MINUTES(sec)	(((sec) % (60 * 60)) / 60)
+-#define SECONDS(sec)	((sec) % 60)
+-
+-void
+-timestr(
+-	struct timeval	*tv,
+-	char		*ts,
+-	size_t		size,
+-	int		format)
+-{
+-	double		usec = (double)tv->tv_usec / 1000000.0;
+-
+-	if (format & TERSE_FIXED_TIME) {
+-		if (!HOURS(tv->tv_sec)) {
+-			snprintf(ts, size, "%u:%02u.%02u",
+-				(unsigned int) MINUTES(tv->tv_sec),
+-				(unsigned int) SECONDS(tv->tv_sec),
+-				(unsigned int) (usec * 100));
+-			return;
+-		}
+-		format |= VERBOSE_FIXED_TIME;	/* fallback if hours needed */
+-	}
+-
+-	if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
+-		snprintf(ts, size, "%u:%02u:%02u.%02u",
+-			(unsigned int) HOURS(tv->tv_sec),
+-			(unsigned int) MINUTES(tv->tv_sec),
+-			(unsigned int) SECONDS(tv->tv_sec),
+-			(unsigned int) (usec * 100));
+-	} else {
+-		snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
+-	}
+-}
+diff --git a/cmd.h b/cmd.h
+index da0c7cf..9907795 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -43,20 +43,6 @@ void qemuio_add_command(const cmdinfo_t *ci);
+ 
+ int qemuio_command_usage(const cmdinfo_t *ci);
+ 
+-/* from input.h */
+-void cvtstr(double value, char *str, size_t sz);
+-
+-struct timeval tsub(struct timeval t1, struct timeval t2);
+-double tdiv(double value, struct timeval tv);
+-
+-enum {
+-	DEFAULT_TIME		= 0x0,
+-	TERSE_FIXED_TIME	= 0x1,
+-	VERBOSE_FIXED_TIME	= 0x2
+-};
+-
+-void timestr(struct timeval *tv, char *str, size_t sz, int flags);
+-
+ bool qemuio_command(const char *cmd);
+ 
+ #endif	/* __COMMAND_H__ */
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+index 27a903f..1db7fb9 100644
+--- a/qemu-io-cmds.c
++++ b/qemu-io-cmds.c
+@@ -127,6 +127,110 @@ static int64_t cvtnum(const char *s)
+     return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
+ }
+ 
++#define EXABYTES(x)     ((long long)(x) << 60)
++#define PETABYTES(x)    ((long long)(x) << 50)
++#define TERABYTES(x)    ((long long)(x) << 40)
++#define GIGABYTES(x)    ((long long)(x) << 30)
++#define MEGABYTES(x)    ((long long)(x) << 20)
++#define KILOBYTES(x)    ((long long)(x) << 10)
++
++#define TO_EXABYTES(x)  ((x) / EXABYTES(1))
++#define TO_PETABYTES(x) ((x) / PETABYTES(1))
++#define TO_TERABYTES(x) ((x) / TERABYTES(1))
++#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
++#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
++#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
++
++static void cvtstr(double value, char *str, size_t size)
++{
++    char *trim;
++    const char *suffix;
++
++    if (value >= EXABYTES(1)) {
++        suffix = " EiB";
++        snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
++    } else if (value >= PETABYTES(1)) {
++        suffix = " PiB";
++        snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
++    } else if (value >= TERABYTES(1)) {
++        suffix = " TiB";
++        snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
++    } else if (value >= GIGABYTES(1)) {
++        suffix = " GiB";
++        snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
++    } else if (value >= MEGABYTES(1)) {
++        suffix = " MiB";
++        snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
++    } else if (value >= KILOBYTES(1)) {
++        suffix = " KiB";
++        snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
++    } else {
++        suffix = " bytes";
++        snprintf(str, size - 6, "%f", value);
++    }
++
++    trim = strstr(str, ".000");
++    if (trim) {
++        strcpy(trim, suffix);
++    } else {
++        strcat(str, suffix);
++    }
++}
++
++
++
++static struct timeval tsub(struct timeval t1, struct timeval t2)
++{
++    t1.tv_usec -= t2.tv_usec;
++    if (t1.tv_usec < 0) {
++        t1.tv_usec += 1000000;
++        t1.tv_sec--;
++    }
++    t1.tv_sec -= t2.tv_sec;
++    return t1;
++}
++
++static double tdiv(double value, struct timeval tv)
++{
++    return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
++}
++
++#define HOURS(sec)      ((sec) / (60 * 60))
++#define MINUTES(sec)    (((sec) % (60 * 60)) / 60)
++#define SECONDS(sec)    ((sec) % 60)
++
++enum {
++    DEFAULT_TIME        = 0x0,
++    TERSE_FIXED_TIME    = 0x1,
++    VERBOSE_FIXED_TIME  = 0x2,
++};
++
++static void timestr(struct timeval *tv, char *ts, size_t size, int format)
++{
++    double usec = (double)tv->tv_usec / 1000000.0;
++
++    if (format & TERSE_FIXED_TIME) {
++        if (!HOURS(tv->tv_sec)) {
++            snprintf(ts, size, "%u:%02u.%02u",
++                    (unsigned int) MINUTES(tv->tv_sec),
++                    (unsigned int) SECONDS(tv->tv_sec),
++                    (unsigned int) (usec * 100));
++            return;
++        }
++        format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
++    }
++
++    if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
++        snprintf(ts, size, "%u:%02u:%02u.%02u",
++                (unsigned int) HOURS(tv->tv_sec),
++                (unsigned int) MINUTES(tv->tv_sec),
++                (unsigned int) SECONDS(tv->tv_sec),
++                (unsigned int) (usec * 100));
++    } else {
++        snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
++    }
++}
++
+ /*
+  * Parse the pattern argument to various sub-commands.
+  *
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Remove-unused-args_command.patch b/SOURCES/kvm-qemu-io-Remove-unused-args_command.patch
new file mode 100644
index 0000000..a005944
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Remove-unused-args_command.patch
@@ -0,0 +1,141 @@
+From d16c34d6dc39a159326efda97101aed3c1481812 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:20 +0100
+Subject: [PATCH 01/27] qemu-io: Remove unused args_command
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-2-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68429
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 01/21] qemu-io: Remove unused args_command
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+The original intention seems to be something with handling multiple
+images at once, but this has never been implemented and the only
+function ever registered is implemented to make everything behave like a
+"global" command. Just do that unconditionally now.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit a23818f4ff3d7981f49453b739f589e4205930b5)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ cmd.c     | 28 ++--------------------------
+ cmd.h     |  2 --
+ qemu-io.c | 10 ----------
+ 3 files changed, 2 insertions(+), 38 deletions(-)
+
+diff --git a/cmd.c b/cmd.c
+index 10a8688..4e7579b 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -34,7 +34,6 @@
+ cmdinfo_t	*cmdtab;
+ int		ncmds;
+ 
+-static argsfunc_t	args_func;
+ static checkfunc_t	check_func;
+ static int		ncmdline;
+ static char		**cmdline;
+@@ -127,22 +126,6 @@ void add_user_command(char *optarg)
+     cmdline[ncmdline-1] = optarg;
+ }
+ 
+-static int
+-args_command(
+-	int	index)
+-{
+-	if (args_func)
+-		return args_func(index);
+-	return 0;
+-}
+-
+-void
+-add_args_command(
+-	argsfunc_t	af)
+-{
+-	args_func = af;
+-}
+-
+ static void prep_fetchline(void *opaque)
+ {
+     int *fetchable = opaque;
+@@ -155,7 +138,7 @@ static char *get_prompt(void);
+ 
+ void command_loop(void)
+ {
+-    int c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
++    int c, i, done = 0, fetchable = 0, prompted = 0;
+     char *input;
+     char **v;
+     const cmdinfo_t *ct;
+@@ -171,14 +154,7 @@ void command_loop(void)
+         if (c) {
+             ct = find_command(v[0]);
+             if (ct) {
+-                if (ct->flags & CMD_FLAG_GLOBAL) {
+-                    done = command(ct, c, v);
+-                } else {
+-                    j = 0;
+-                    while (!done && (j = args_command(j))) {
+-                        done = command(ct, c, v);
+-                    }
+-                }
++                done = command(ct, c, v);
+             } else {
+                 fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
+             }
+diff --git a/cmd.h b/cmd.h
+index b763b19..8e6f753 100644
+--- a/cmd.h
++++ b/cmd.h
+@@ -41,12 +41,10 @@ extern int		ncmds;
+ void help_init(void);
+ void quit_init(void);
+ 
+-typedef int (*argsfunc_t)(int index);
+ typedef int (*checkfunc_t)(const cmdinfo_t *ci);
+ 
+ void add_command(const cmdinfo_t *ci);
+ void add_user_command(char *optarg);
+-void add_args_command(argsfunc_t af);
+ void add_check_command(checkfunc_t cf);
+ 
+ const cmdinfo_t *find_command(const char *cmd);
+diff --git a/qemu-io.c b/qemu-io.c
+index cc89947..9f66a78 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -1935,15 +1935,6 @@ static int open_f(int argc, char **argv)
+     return openfile(argv[optind], flags, growable, opts);
+ }
+ 
+-static int init_args_command(int index)
+-{
+-    /* only one device allowed so far */
+-    if (index >= 1) {
+-        return 0;
+-    }
+-    return ++index;
+-}
+-
+ static int init_check_command(const cmdinfo_t *ct)
+ {
+     if (ct->flags & CMD_FLAG_GLOBAL) {
+@@ -2096,7 +2087,6 @@ int main(int argc, char **argv)
+     add_command(&abort_cmd);
+     add_command(&sleep_cmd);
+ 
+-    add_args_command(init_args_command);
+     add_check_command(init_check_command);
+ 
+     /* open the device */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Split-off-commands-to-qemu-io-cmds.c.patch b/SOURCES/kvm-qemu-io-Split-off-commands-to-qemu-io-cmds.c.patch
new file mode 100644
index 0000000..957b8c7
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Split-off-commands-to-qemu-io-cmds.c.patch
@@ -0,0 +1,3789 @@
+From 9bd448e0f256ac9327363a0f370b9616d967e986 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:25 +0100
+Subject: [PATCH 06/27] qemu-io: Split off commands to qemu-io-cmds.c
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-7-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68434
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 06/21] qemu-io: Split off commands to qemu-io-cmds.c
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+This is the implementation of all qemu-io commands that make sense to be
+called from the qemu monitor, i.e. everything except open, close and
+quit.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 797ac58cb2093ab9192d8998a1fef85d87cc8661)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+  qemu-io.c: Minor differences, but as this is code motion,
+             The code motion had to be re-done to preserve
+             any backported changes.
+  qemu-io-cmds.c: re-created from downstream qemu-io.c.
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ Makefile       |    2 +-
+ qemu-io-cmds.c | 1853 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ qemu-io.c      | 1831 +------------------------------------------------------
+ 3 files changed, 1856 insertions(+), 1830 deletions(-)
+ create mode 100644 qemu-io-cmds.c
+
+diff --git a/Makefile b/Makefile
+index 8407945..f28ce29 100644
+--- a/Makefile
++++ b/Makefile
+@@ -205,7 +205,7 @@ qemu-img.o: qemu-img-cmds.h
+ 
+ qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
+ qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
+-qemu-io$(EXESUF): qemu-io.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
++qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
+ 
+ qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
+ 
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+new file mode 100644
+index 0000000..efa6070
+--- /dev/null
++++ b/qemu-io-cmds.c
+@@ -0,0 +1,1853 @@
++/*
++ * Command line utility to exercise the QEMU I/O path.
++ *
++ * Copyright (C) 2009 Red Hat, Inc.
++ * Copyright (c) 2003-2005 Silicon Graphics, Inc.
++ *
++ * This work is licensed under the terms of the GNU GPL, version 2 or later.
++ * See the COPYING file in the top-level directory.
++ */
++
++#include "qemu-common.h"
++#include "block/block_int.h"
++#include "block/qapi.h"
++#include "cmd.h"
++
++#define CMD_NOFILE_OK   0x01
++
++int qemuio_misalign;
++
++static int64_t cvtnum(const char *s)
++{
++    char *end;
++    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
++}
++
++/*
++ * Parse the pattern argument to various sub-commands.
++ *
++ * Because the pattern is used as an argument to memset it must evaluate
++ * to an unsigned integer that fits into a single byte.
++ */
++static int parse_pattern(const char *arg)
++{
++    char *endptr = NULL;
++    long pattern;
++
++    pattern = strtol(arg, &endptr, 0);
++    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
++        printf("%s is not a valid pattern byte\n", arg);
++        return -1;
++    }
++
++    return pattern;
++}
++
++/*
++ * Memory allocation helpers.
++ *
++ * Make sure memory is aligned by default, or purposefully misaligned if
++ * that is specified on the command line.
++ */
++
++#define MISALIGN_OFFSET     16
++static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
++{
++    void *buf;
++
++    if (qemuio_misalign) {
++        len += MISALIGN_OFFSET;
++    }
++    buf = qemu_blockalign(bs, len);
++    memset(buf, pattern, len);
++    if (qemuio_misalign) {
++        buf += MISALIGN_OFFSET;
++    }
++    return buf;
++}
++
++static void qemu_io_free(void *p)
++{
++    if (qemuio_misalign) {
++        p -= MISALIGN_OFFSET;
++    }
++    qemu_vfree(p);
++}
++
++static void dump_buffer(const void *buffer, int64_t offset, int len)
++{
++    int i, j;
++    const uint8_t *p;
++
++    for (i = 0, p = buffer; i < len; i += 16) {
++        const uint8_t *s = p;
++
++        printf("%08" PRIx64 ":  ", offset + i);
++        for (j = 0; j < 16 && i + j < len; j++, p++) {
++            printf("%02x ", *p);
++        }
++        printf(" ");
++        for (j = 0; j < 16 && i + j < len; j++, s++) {
++            if (isalnum(*s)) {
++                printf("%c", *s);
++            } else {
++                printf(".");
++            }
++        }
++        printf("\n");
++    }
++}
++
++static void print_report(const char *op, struct timeval *t, int64_t offset,
++                         int count, int total, int cnt, int Cflag)
++{
++    char s1[64], s2[64], ts[64];
++
++    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
++    if (!Cflag) {
++        cvtstr((double)total, s1, sizeof(s1));
++        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
++        printf("%s %d/%d bytes at offset %" PRId64 "\n",
++               op, total, count, offset);
++        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
++               s1, cnt, ts, s2, tdiv((double)cnt, *t));
++    } else {/* bytes,ops,time,bytes/sec,ops/sec */
++        printf("%d,%d,%s,%.3f,%.3f\n",
++            total, cnt, ts,
++            tdiv((double)total, *t),
++            tdiv((double)cnt, *t));
++    }
++}
++
++/*
++ * Parse multiple length statements for vectored I/O, and construct an I/O
++ * vector matching it.
++ */
++static void *
++create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
++             int pattern)
++{
++    size_t *sizes = g_new0(size_t, nr_iov);
++    size_t count = 0;
++    void *buf = NULL;
++    void *p;
++    int i;
++
++    for (i = 0; i < nr_iov; i++) {
++        char *arg = argv[i];
++        int64_t len;
++
++        len = cvtnum(arg);
++        if (len < 0) {
++            printf("non-numeric length argument -- %s\n", arg);
++            goto fail;
++        }
++
++        /* should be SIZE_T_MAX, but that doesn't exist */
++        if (len > INT_MAX) {
++            printf("too large length argument -- %s\n", arg);
++            goto fail;
++        }
++
++        if (len & 0x1ff) {
++            printf("length argument %" PRId64
++                   " is not sector aligned\n", len);
++            goto fail;
++        }
++
++        sizes[i] = len;
++        count += len;
++    }
++
++    qemu_iovec_init(qiov, nr_iov);
++
++    buf = p = qemu_io_alloc(bs, count, pattern);
++
++    for (i = 0; i < nr_iov; i++) {
++        qemu_iovec_add(qiov, p, sizes[i]);
++        p += sizes[i];
++    }
++
++fail:
++    g_free(sizes);
++    return buf;
++}
++
++static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
++                   int *total)
++{
++    int ret;
++
++    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
++    if (ret < 0) {
++        return ret;
++    }
++    *total = count;
++    return 1;
++}
++
++static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
++                    int *total)
++{
++    int ret;
++
++    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
++    if (ret < 0) {
++        return ret;
++    }
++    *total = count;
++    return 1;
++}
++
++static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
++                    int *total)
++{
++    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
++    if (*total < 0) {
++        return *total;
++    }
++    return 1;
++}
++
++static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
++                     int *total)
++{
++    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
++    if (*total < 0) {
++        return *total;
++    }
++    return 1;
++}
++
++typedef struct {
++    BlockDriverState *bs;
++    int64_t offset;
++    int count;
++    int *total;
++    int ret;
++    bool done;
++} CoWriteZeroes;
++
++static void coroutine_fn co_write_zeroes_entry(void *opaque)
++{
++    CoWriteZeroes *data = opaque;
++
++    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
++                                     data->count / BDRV_SECTOR_SIZE, 0);
++    data->done = true;
++    if (data->ret < 0) {
++        *data->total = data->ret;
++        return;
++    }
++
++    *data->total = data->count;
++}
++
++static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
++                              int *total)
++{
++    Coroutine *co;
++    CoWriteZeroes data = {
++        .bs     = bs,
++        .offset = offset,
++        .count  = count,
++        .total  = total,
++        .done   = false,
++    };
++
++    co = qemu_coroutine_create(co_write_zeroes_entry);
++    qemu_coroutine_enter(co, &data);
++    while (!data.done) {
++        qemu_aio_wait();
++    }
++    if (data.ret < 0) {
++        return data.ret;
++    } else {
++        return 1;
++    }
++}
++
++static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
++                               int count, int *total)
++{
++    int ret;
++
++    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
++    if (ret < 0) {
++        return ret;
++    }
++    *total = count;
++    return 1;
++}
++
++static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
++                           int count, int *total)
++{
++    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
++    if (*total < 0) {
++        return *total;
++    }
++    return 1;
++}
++
++static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
++                           int count, int *total)
++{
++    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
++    if (*total < 0) {
++        return *total;
++    }
++    return 1;
++}
++
++#define NOT_DONE 0x7fffffff
++static void aio_rw_done(void *opaque, int ret)
++{
++    *(int *)opaque = ret;
++}
++
++static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
++                        int64_t offset, int *total)
++{
++    int async_ret = NOT_DONE;
++
++    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
++                   aio_rw_done, &async_ret);
++    while (async_ret == NOT_DONE) {
++        main_loop_wait(false);
++    }
++
++    *total = qiov->size;
++    return async_ret < 0 ? async_ret : 1;
++}
++
++static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
++                         int64_t offset, int *total)
++{
++    int async_ret = NOT_DONE;
++
++    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
++                    aio_rw_done, &async_ret);
++    while (async_ret == NOT_DONE) {
++        main_loop_wait(false);
++    }
++
++    *total = qiov->size;
++    return async_ret < 0 ? async_ret : 1;
++}
++
++struct multiwrite_async_ret {
++    int num_done;
++    int error;
++};
++
++static void multiwrite_cb(void *opaque, int ret)
++{
++    struct multiwrite_async_ret *async_ret = opaque;
++
++    async_ret->num_done++;
++    if (ret < 0) {
++        async_ret->error = ret;
++    }
++}
++
++static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
++                             int num_reqs, int *total)
++{
++    int i, ret;
++    struct multiwrite_async_ret async_ret = {
++        .num_done = 0,
++        .error = 0,
++    };
++
++    *total = 0;
++    for (i = 0; i < num_reqs; i++) {
++        reqs[i].cb = multiwrite_cb;
++        reqs[i].opaque = &async_ret;
++        *total += reqs[i].qiov->size;
++    }
++
++    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
++    if (ret < 0) {
++        return ret;
++    }
++
++    while (async_ret.num_done < num_reqs) {
++        main_loop_wait(false);
++    }
++
++    return async_ret.error < 0 ? async_ret.error : 1;
++}
++
++static void read_help(void)
++{
++    printf(
++"\n"
++" reads a range of bytes from the given offset\n"
++"\n"
++" Example:\n"
++" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
++"\n"
++" Reads a segment of the currently open file, optionally dumping it to the\n"
++" standard output stream (with -v option) for subsequent inspection.\n"
++" -b, -- read from the VM state rather than the virtual disk\n"
++" -C, -- report statistics in a machine parsable format\n"
++" -l, -- length for pattern verification (only with -P)\n"
++" -p, -- use bdrv_pread to read the file\n"
++" -P, -- use a pattern to verify read data\n"
++" -q, -- quiet mode, do not show I/O statistics\n"
++" -s, -- start offset for pattern verification (only with -P)\n"
++" -v, -- dump buffer to standard output\n"
++"\n");
++}
++
++static int read_f(BlockDriverState *bs, int argc, char **argv);
++
++static const cmdinfo_t read_cmd = {
++    .name       = "read",
++    .altname    = "r",
++    .cfunc      = read_f,
++    .argmin     = 2,
++    .argmax     = -1,
++    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
++    .oneline    = "reads a number of bytes at a specified offset",
++    .help       = read_help,
++};
++
++static int read_f(BlockDriverState *bs, int argc, char **argv)
++{
++    struct timeval t1, t2;
++    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
++    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
++    int c, cnt;
++    char *buf;
++    int64_t offset;
++    int count;
++    /* Some compilers get confused and warn if this is not initialized.  */
++    int total = 0;
++    int pattern = 0, pattern_offset = 0, pattern_count = 0;
++
++    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
++        switch (c) {
++        case 'b':
++            bflag = 1;
++            break;
++        case 'C':
++            Cflag = 1;
++            break;
++        case 'l':
++            lflag = 1;
++            pattern_count = cvtnum(optarg);
++            if (pattern_count < 0) {
++                printf("non-numeric length argument -- %s\n", optarg);
++                return 0;
++            }
++            break;
++        case 'p':
++            pflag = 1;
++            break;
++        case 'P':
++            Pflag = 1;
++            pattern = parse_pattern(optarg);
++            if (pattern < 0) {
++                return 0;
++            }
++            break;
++        case 'q':
++            qflag = 1;
++            break;
++        case 's':
++            sflag = 1;
++            pattern_offset = cvtnum(optarg);
++            if (pattern_offset < 0) {
++                printf("non-numeric length argument -- %s\n", optarg);
++                return 0;
++            }
++            break;
++        case 'v':
++            vflag = 1;
++            break;
++        default:
++            return command_usage(&read_cmd);
++        }
++    }
++
++    if (optind != argc - 2) {
++        return command_usage(&read_cmd);
++    }
++
++    if (bflag && pflag) {
++        printf("-b and -p cannot be specified at the same time\n");
++        return 0;
++    }
++
++    offset = cvtnum(argv[optind]);
++    if (offset < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        return 0;
++    }
++
++    optind++;
++    count = cvtnum(argv[optind]);
++    if (count < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        return 0;
++    }
++
++    if (!Pflag && (lflag || sflag)) {
++        return command_usage(&read_cmd);
++    }
++
++    if (!lflag) {
++        pattern_count = count - pattern_offset;
++    }
++
++    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
++        printf("pattern verification range exceeds end of read data\n");
++        return 0;
++    }
++
++    if (!pflag) {
++        if (offset & 0x1ff) {
++            printf("offset %" PRId64 " is not sector aligned\n",
++                   offset);
++            return 0;
++        }
++        if (count & 0x1ff) {
++            printf("count %d is not sector aligned\n",
++                   count);
++            return 0;
++        }
++    }
++
++    buf = qemu_io_alloc(bs, count, 0xab);
++
++    gettimeofday(&t1, NULL);
++    if (pflag) {
++        cnt = do_pread(bs, buf, offset, count, &total);
++    } else if (bflag) {
++        cnt = do_load_vmstate(bs, buf, offset, count, &total);
++    } else {
++        cnt = do_read(bs, buf, offset, count, &total);
++    }
++    gettimeofday(&t2, NULL);
++
++    if (cnt < 0) {
++        printf("read failed: %s\n", strerror(-cnt));
++        goto out;
++    }
++
++    if (Pflag) {
++        void *cmp_buf = g_malloc(pattern_count);
++        memset(cmp_buf, pattern, pattern_count);
++        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
++            printf("Pattern verification failed at offset %"
++                   PRId64 ", %d bytes\n",
++                   offset + pattern_offset, pattern_count);
++        }
++        g_free(cmp_buf);
++    }
++
++    if (qflag) {
++        goto out;
++    }
++
++    if (vflag) {
++        dump_buffer(buf, offset, count);
++    }
++
++    /* Finally, report back -- -C gives a parsable format */
++    t2 = tsub(t2, t1);
++    print_report("read", &t2, offset, count, total, cnt, Cflag);
++
++out:
++    qemu_io_free(buf);
++
++    return 0;
++}
++
++static void readv_help(void)
++{
++    printf(
++"\n"
++" reads a range of bytes from the given offset into multiple buffers\n"
++"\n"
++" Example:\n"
++" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
++"\n"
++" Reads a segment of the currently open file, optionally dumping it to the\n"
++" standard output stream (with -v option) for subsequent inspection.\n"
++" Uses multiple iovec buffers if more than one byte range is specified.\n"
++" -C, -- report statistics in a machine parsable format\n"
++" -P, -- use a pattern to verify read data\n"
++" -v, -- dump buffer to standard output\n"
++" -q, -- quiet mode, do not show I/O statistics\n"
++"\n");
++}
++
++static int readv_f(BlockDriverState *bs, int argc, char **argv);
++
++static const cmdinfo_t readv_cmd = {
++    .name       = "readv",
++    .cfunc      = readv_f,
++    .argmin     = 2,
++    .argmax     = -1,
++    .args       = "[-Cqv] [-P pattern ] off len [len..]",
++    .oneline    = "reads a number of bytes at a specified offset",
++    .help       = readv_help,
++};
++
++static int readv_f(BlockDriverState *bs, int argc, char **argv)
++{
++    struct timeval t1, t2;
++    int Cflag = 0, qflag = 0, vflag = 0;
++    int c, cnt;
++    char *buf;
++    int64_t offset;
++    /* Some compilers get confused and warn if this is not initialized.  */
++    int total = 0;
++    int nr_iov;
++    QEMUIOVector qiov;
++    int pattern = 0;
++    int Pflag = 0;
++
++    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
++        switch (c) {
++        case 'C':
++            Cflag = 1;
++            break;
++        case 'P':
++            Pflag = 1;
++            pattern = parse_pattern(optarg);
++            if (pattern < 0) {
++                return 0;
++            }
++            break;
++        case 'q':
++            qflag = 1;
++            break;
++        case 'v':
++            vflag = 1;
++            break;
++        default:
++            return command_usage(&readv_cmd);
++        }
++    }
++
++    if (optind > argc - 2) {
++        return command_usage(&readv_cmd);
++    }
++
++
++    offset = cvtnum(argv[optind]);
++    if (offset < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        return 0;
++    }
++    optind++;
++
++    if (offset & 0x1ff) {
++        printf("offset %" PRId64 " is not sector aligned\n",
++               offset);
++        return 0;
++    }
++
++    nr_iov = argc - optind;
++    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
++    if (buf == NULL) {
++        return 0;
++    }
++
++    gettimeofday(&t1, NULL);
++    cnt = do_aio_readv(bs, &qiov, offset, &total);
++    gettimeofday(&t2, NULL);
++
++    if (cnt < 0) {
++        printf("readv failed: %s\n", strerror(-cnt));
++        goto out;
++    }
++
++    if (Pflag) {
++        void *cmp_buf = g_malloc(qiov.size);
++        memset(cmp_buf, pattern, qiov.size);
++        if (memcmp(buf, cmp_buf, qiov.size)) {
++            printf("Pattern verification failed at offset %"
++                   PRId64 ", %zd bytes\n", offset, qiov.size);
++        }
++        g_free(cmp_buf);
++    }
++
++    if (qflag) {
++        goto out;
++    }
++
++    if (vflag) {
++        dump_buffer(buf, offset, qiov.size);
++    }
++
++    /* Finally, report back -- -C gives a parsable format */
++    t2 = tsub(t2, t1);
++    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
++
++out:
++    qemu_iovec_destroy(&qiov);
++    qemu_io_free(buf);
++    return 0;
++}
++
++static void write_help(void)
++{
++    printf(
++"\n"
++" writes a range of bytes from the given offset\n"
++"\n"
++" Example:\n"
++" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
++"\n"
++" Writes into a segment of the currently open file, using a buffer\n"
++" filled with a set pattern (0xcdcdcdcd).\n"
++" -b, -- write to the VM state rather than the virtual disk\n"
++" -c, -- write compressed data with bdrv_write_compressed\n"
++" -p, -- use bdrv_pwrite to write the file\n"
++" -P, -- use different pattern to fill file\n"
++" -C, -- report statistics in a machine parsable format\n"
++" -q, -- quiet mode, do not show I/O statistics\n"
++" -z, -- write zeroes using bdrv_co_write_zeroes\n"
++"\n");
++}
++
++static int write_f(BlockDriverState *bs, int argc, char **argv);
++
++static const cmdinfo_t write_cmd = {
++    .name       = "write",
++    .altname    = "w",
++    .cfunc      = write_f,
++    .argmin     = 2,
++    .argmax     = -1,
++    .args       = "[-bcCpqz] [-P pattern ] off len",
++    .oneline    = "writes a number of bytes at a specified offset",
++    .help       = write_help,
++};
++
++static int write_f(BlockDriverState *bs, int argc, char **argv)
++{
++    struct timeval t1, t2;
++    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
++    int cflag = 0;
++    int c, cnt;
++    char *buf = NULL;
++    int64_t offset;
++    int count;
++    /* Some compilers get confused and warn if this is not initialized.  */
++    int total = 0;
++    int pattern = 0xcd;
++
++    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
++        switch (c) {
++        case 'b':
++            bflag = 1;
++            break;
++        case 'c':
++            cflag = 1;
++            break;
++        case 'C':
++            Cflag = 1;
++            break;
++        case 'p':
++            pflag = 1;
++            break;
++        case 'P':
++            Pflag = 1;
++            pattern = parse_pattern(optarg);
++            if (pattern < 0) {
++                return 0;
++            }
++            break;
++        case 'q':
++            qflag = 1;
++            break;
++        case 'z':
++            zflag = 1;
++            break;
++        default:
++            return command_usage(&write_cmd);
++        }
++    }
++
++    if (optind != argc - 2) {
++        return command_usage(&write_cmd);
++    }
++
++    if (bflag + pflag + zflag > 1) {
++        printf("-b, -p, or -z cannot be specified at the same time\n");
++        return 0;
++    }
++
++    if (zflag && Pflag) {
++        printf("-z and -P cannot be specified at the same time\n");
++        return 0;
++    }
++
++    offset = cvtnum(argv[optind]);
++    if (offset < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        return 0;
++    }
++
++    optind++;
++    count = cvtnum(argv[optind]);
++    if (count < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        return 0;
++    }
++
++    if (!pflag) {
++        if (offset & 0x1ff) {
++            printf("offset %" PRId64 " is not sector aligned\n",
++                   offset);
++            return 0;
++        }
++
++        if (count & 0x1ff) {
++            printf("count %d is not sector aligned\n",
++                   count);
++            return 0;
++        }
++    }
++
++    if (!zflag) {
++        buf = qemu_io_alloc(bs, count, pattern);
++    }
++
++    gettimeofday(&t1, NULL);
++    if (pflag) {
++        cnt = do_pwrite(bs, buf, offset, count, &total);
++    } else if (bflag) {
++        cnt = do_save_vmstate(bs, buf, offset, count, &total);
++    } else if (zflag) {
++        cnt = do_co_write_zeroes(bs, offset, count, &total);
++    } else if (cflag) {
++        cnt = do_write_compressed(bs, buf, offset, count, &total);
++    } else {
++        cnt = do_write(bs, buf, offset, count, &total);
++    }
++    gettimeofday(&t2, NULL);
++
++    if (cnt < 0) {
++        printf("write failed: %s\n", strerror(-cnt));
++        goto out;
++    }
++
++    if (qflag) {
++        goto out;
++    }
++
++    /* Finally, report back -- -C gives a parsable format */
++    t2 = tsub(t2, t1);
++    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
++
++out:
++    if (!zflag) {
++        qemu_io_free(buf);
++    }
++
++    return 0;
++}
++
++static void
++writev_help(void)
++{
++    printf(
++"\n"
++" writes a range of bytes from the given offset source from multiple buffers\n"
++"\n"
++" Example:\n"
++" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
++"\n"
++" Writes into a segment of the currently open file, using a buffer\n"
++" filled with a set pattern (0xcdcdcdcd).\n"
++" -P, -- use different pattern to fill file\n"
++" -C, -- report statistics in a machine parsable format\n"
++" -q, -- quiet mode, do not show I/O statistics\n"
++"\n");
++}
++
++static int writev_f(BlockDriverState *bs, int argc, char **argv);
++
++static const cmdinfo_t writev_cmd = {
++    .name       = "writev",
++    .cfunc      = writev_f,
++    .argmin     = 2,
++    .argmax     = -1,
++    .args       = "[-Cq] [-P pattern ] off len [len..]",
++    .oneline    = "writes a number of bytes at a specified offset",
++    .help       = writev_help,
++};
++
++static int writev_f(BlockDriverState *bs, int argc, char **argv)
++{
++    struct timeval t1, t2;
++    int Cflag = 0, qflag = 0;
++    int c, cnt;
++    char *buf;
++    int64_t offset;
++    /* Some compilers get confused and warn if this is not initialized.  */
++    int total = 0;
++    int nr_iov;
++    int pattern = 0xcd;
++    QEMUIOVector qiov;
++
++    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
++        switch (c) {
++        case 'C':
++            Cflag = 1;
++            break;
++        case 'q':
++            qflag = 1;
++            break;
++        case 'P':
++            pattern = parse_pattern(optarg);
++            if (pattern < 0) {
++                return 0;
++            }
++            break;
++        default:
++            return command_usage(&writev_cmd);
++        }
++    }
++
++    if (optind > argc - 2) {
++        return command_usage(&writev_cmd);
++    }
++
++    offset = cvtnum(argv[optind]);
++    if (offset < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        return 0;
++    }
++    optind++;
++
++    if (offset & 0x1ff) {
++        printf("offset %" PRId64 " is not sector aligned\n",
++               offset);
++        return 0;
++    }
++
++    nr_iov = argc - optind;
++    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
++    if (buf == NULL) {
++        return 0;
++    }
++
++    gettimeofday(&t1, NULL);
++    cnt = do_aio_writev(bs, &qiov, offset, &total);
++    gettimeofday(&t2, NULL);
++
++    if (cnt < 0) {
++        printf("writev failed: %s\n", strerror(-cnt));
++        goto out;
++    }
++
++    if (qflag) {
++        goto out;
++    }
++
++    /* Finally, report back -- -C gives a parsable format */
++    t2 = tsub(t2, t1);
++    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
++out:
++    qemu_iovec_destroy(&qiov);
++    qemu_io_free(buf);
++    return 0;
++}
++
++static void multiwrite_help(void)
++{
++    printf(
++"\n"
++" writes a range of bytes from the given offset source from multiple buffers,\n"
++" in a batch of requests that may be merged by qemu\n"
++"\n"
++" Example:\n"
++" 'multiwrite 512 1k 1k ; 4k 1k'\n"
++"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
++"\n"
++" Writes into a segment of the currently open file, using a buffer\n"
++" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
++" by one for each request contained in the multiwrite command.\n"
++" -P, -- use different pattern to fill file\n"
++" -C, -- report statistics in a machine parsable format\n"
++" -q, -- quiet mode, do not show I/O statistics\n"
++"\n");
++}
++
++static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
++
++static const cmdinfo_t multiwrite_cmd = {
++    .name       = "multiwrite",
++    .cfunc      = multiwrite_f,
++    .argmin     = 2,
++    .argmax     = -1,
++    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
++    .oneline    = "issues multiple write requests at once",
++    .help       = multiwrite_help,
++};
++
++static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
++{
++    struct timeval t1, t2;
++    int Cflag = 0, qflag = 0;
++    int c, cnt;
++    char **buf;
++    int64_t offset, first_offset = 0;
++    /* Some compilers get confused and warn if this is not initialized.  */
++    int total = 0;
++    int nr_iov;
++    int nr_reqs;
++    int pattern = 0xcd;
++    QEMUIOVector *qiovs;
++    int i;
++    BlockRequest *reqs;
++
++    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
++        switch (c) {
++        case 'C':
++            Cflag = 1;
++            break;
++        case 'q':
++            qflag = 1;
++            break;
++        case 'P':
++            pattern = parse_pattern(optarg);
++            if (pattern < 0) {
++                return 0;
++            }
++            break;
++        default:
++            return command_usage(&writev_cmd);
++        }
++    }
++
++    if (optind > argc - 2) {
++        return command_usage(&writev_cmd);
++    }
++
++    nr_reqs = 1;
++    for (i = optind; i < argc; i++) {
++        if (!strcmp(argv[i], ";")) {
++            nr_reqs++;
++        }
++    }
++
++    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
++    buf = g_malloc0(nr_reqs * sizeof(*buf));
++    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
++
++    for (i = 0; i < nr_reqs && optind < argc; i++) {
++        int j;
++
++        /* Read the offset of the request */
++        offset = cvtnum(argv[optind]);
++        if (offset < 0) {
++            printf("non-numeric offset argument -- %s\n", argv[optind]);
++            goto out;
++        }
++        optind++;
++
++        if (offset & 0x1ff) {
++            printf("offset %lld is not sector aligned\n",
++                   (long long)offset);
++            goto out;
++        }
++
++        if (i == 0) {
++            first_offset = offset;
++        }
++
++        /* Read lengths for qiov entries */
++        for (j = optind; j < argc; j++) {
++            if (!strcmp(argv[j], ";")) {
++                break;
++            }
++        }
++
++        nr_iov = j - optind;
++
++        /* Build request */
++        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
++        if (buf[i] == NULL) {
++            goto out;
++        }
++
++        reqs[i].qiov = &qiovs[i];
++        reqs[i].sector = offset >> 9;
++        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
++
++        optind = j + 1;
++
++        pattern++;
++    }
++
++    /* If there were empty requests at the end, ignore them */
++    nr_reqs = i;
++
++    gettimeofday(&t1, NULL);
++    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
++    gettimeofday(&t2, NULL);
++
++    if (cnt < 0) {
++        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
++        goto out;
++    }
++
++    if (qflag) {
++        goto out;
++    }
++
++    /* Finally, report back -- -C gives a parsable format */
++    t2 = tsub(t2, t1);
++    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
++out:
++    for (i = 0; i < nr_reqs; i++) {
++        qemu_io_free(buf[i]);
++        if (reqs[i].qiov != NULL) {
++            qemu_iovec_destroy(&qiovs[i]);
++        }
++    }
++    g_free(buf);
++    g_free(reqs);
++    g_free(qiovs);
++    return 0;
++}
++
++struct aio_ctx {
++    QEMUIOVector qiov;
++    int64_t offset;
++    char *buf;
++    int qflag;
++    int vflag;
++    int Cflag;
++    int Pflag;
++    int pattern;
++    struct timeval t1;
++};
++
++static void aio_write_done(void *opaque, int ret)
++{
++    struct aio_ctx *ctx = opaque;
++    struct timeval t2;
++
++    gettimeofday(&t2, NULL);
++
++
++    if (ret < 0) {
++        printf("aio_write failed: %s\n", strerror(-ret));
++        goto out;
++    }
++
++    if (ctx->qflag) {
++        goto out;
++    }
++
++    /* Finally, report back -- -C gives a parsable format */
++    t2 = tsub(t2, ctx->t1);
++    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
++                 ctx->qiov.size, 1, ctx->Cflag);
++out:
++    qemu_io_free(ctx->buf);
++    qemu_iovec_destroy(&ctx->qiov);
++    g_free(ctx);
++}
++
++static void aio_read_done(void *opaque, int ret)
++{
++    struct aio_ctx *ctx = opaque;
++    struct timeval t2;
++
++    gettimeofday(&t2, NULL);
++
++    if (ret < 0) {
++        printf("readv failed: %s\n", strerror(-ret));
++        goto out;
++    }
++
++    if (ctx->Pflag) {
++        void *cmp_buf = g_malloc(ctx->qiov.size);
++
++        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
++        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
++            printf("Pattern verification failed at offset %"
++                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
++        }
++        g_free(cmp_buf);
++    }
++
++    if (ctx->qflag) {
++        goto out;
++    }
++
++    if (ctx->vflag) {
++        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
++    }
++
++    /* Finally, report back -- -C gives a parsable format */
++    t2 = tsub(t2, ctx->t1);
++    print_report("read", &t2, ctx->offset, ctx->qiov.size,
++                 ctx->qiov.size, 1, ctx->Cflag);
++out:
++    qemu_io_free(ctx->buf);
++    qemu_iovec_destroy(&ctx->qiov);
++    g_free(ctx);
++}
++
++static void aio_read_help(void)
++{
++    printf(
++"\n"
++" asynchronously reads a range of bytes from the given offset\n"
++"\n"
++" Example:\n"
++" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
++"\n"
++" Reads a segment of the currently open file, optionally dumping it to the\n"
++" standard output stream (with -v option) for subsequent inspection.\n"
++" The read is performed asynchronously and the aio_flush command must be\n"
++" used to ensure all outstanding aio requests have been completed.\n"
++" -C, -- report statistics in a machine parsable format\n"
++" -P, -- use a pattern to verify read data\n"
++" -v, -- dump buffer to standard output\n"
++" -q, -- quiet mode, do not show I/O statistics\n"
++"\n");
++}
++
++static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
++
++static const cmdinfo_t aio_read_cmd = {
++    .name       = "aio_read",
++    .cfunc      = aio_read_f,
++    .argmin     = 2,
++    .argmax     = -1,
++    .args       = "[-Cqv] [-P pattern ] off len [len..]",
++    .oneline    = "asynchronously reads a number of bytes",
++    .help       = aio_read_help,
++};
++
++static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
++{
++    int nr_iov, c;
++    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
++
++    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
++        switch (c) {
++        case 'C':
++            ctx->Cflag = 1;
++            break;
++        case 'P':
++            ctx->Pflag = 1;
++            ctx->pattern = parse_pattern(optarg);
++            if (ctx->pattern < 0) {
++                g_free(ctx);
++                return 0;
++            }
++            break;
++        case 'q':
++            ctx->qflag = 1;
++            break;
++        case 'v':
++            ctx->vflag = 1;
++            break;
++        default:
++            g_free(ctx);
++            return command_usage(&aio_read_cmd);
++        }
++    }
++
++    if (optind > argc - 2) {
++        g_free(ctx);
++        return command_usage(&aio_read_cmd);
++    }
++
++    ctx->offset = cvtnum(argv[optind]);
++    if (ctx->offset < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        g_free(ctx);
++        return 0;
++    }
++    optind++;
++
++    if (ctx->offset & 0x1ff) {
++        printf("offset %" PRId64 " is not sector aligned\n",
++               ctx->offset);
++        g_free(ctx);
++        return 0;
++    }
++
++    nr_iov = argc - optind;
++    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
++    if (ctx->buf == NULL) {
++        g_free(ctx);
++        return 0;
++    }
++
++    gettimeofday(&ctx->t1, NULL);
++    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
++                   ctx->qiov.size >> 9, aio_read_done, ctx);
++    return 0;
++}
++
++static void aio_write_help(void)
++{
++    printf(
++"\n"
++" asynchronously writes a range of bytes from the given offset source\n"
++" from multiple buffers\n"
++"\n"
++" Example:\n"
++" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
++"\n"
++" Writes into a segment of the currently open file, using a buffer\n"
++" filled with a set pattern (0xcdcdcdcd).\n"
++" The write is performed asynchronously and the aio_flush command must be\n"
++" used to ensure all outstanding aio requests have been completed.\n"
++" -P, -- use different pattern to fill file\n"
++" -C, -- report statistics in a machine parsable format\n"
++" -q, -- quiet mode, do not show I/O statistics\n"
++"\n");
++}
++
++static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
++
++static const cmdinfo_t aio_write_cmd = {
++    .name       = "aio_write",
++    .cfunc      = aio_write_f,
++    .argmin     = 2,
++    .argmax     = -1,
++    .args       = "[-Cq] [-P pattern ] off len [len..]",
++    .oneline    = "asynchronously writes a number of bytes",
++    .help       = aio_write_help,
++};
++
++static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
++{
++    int nr_iov, c;
++    int pattern = 0xcd;
++    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
++
++    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
++        switch (c) {
++        case 'C':
++            ctx->Cflag = 1;
++            break;
++        case 'q':
++            ctx->qflag = 1;
++            break;
++        case 'P':
++            pattern = parse_pattern(optarg);
++            if (pattern < 0) {
++                g_free(ctx);
++                return 0;
++            }
++            break;
++        default:
++            g_free(ctx);
++            return command_usage(&aio_write_cmd);
++        }
++    }
++
++    if (optind > argc - 2) {
++        g_free(ctx);
++        return command_usage(&aio_write_cmd);
++    }
++
++    ctx->offset = cvtnum(argv[optind]);
++    if (ctx->offset < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        g_free(ctx);
++        return 0;
++    }
++    optind++;
++
++    if (ctx->offset & 0x1ff) {
++        printf("offset %" PRId64 " is not sector aligned\n",
++               ctx->offset);
++        g_free(ctx);
++        return 0;
++    }
++
++    nr_iov = argc - optind;
++    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
++    if (ctx->buf == NULL) {
++        g_free(ctx);
++        return 0;
++    }
++
++    gettimeofday(&ctx->t1, NULL);
++    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
++                    ctx->qiov.size >> 9, aio_write_done, ctx);
++    return 0;
++}
++
++static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
++{
++    bdrv_drain_all();
++    return 0;
++}
++
++static const cmdinfo_t aio_flush_cmd = {
++    .name       = "aio_flush",
++    .cfunc      = aio_flush_f,
++    .oneline    = "completes all outstanding aio requests"
++};
++
++static int flush_f(BlockDriverState *bs, int argc, char **argv)
++{
++    bdrv_flush(bs);
++    return 0;
++}
++
++static const cmdinfo_t flush_cmd = {
++    .name       = "flush",
++    .altname    = "f",
++    .cfunc      = flush_f,
++    .oneline    = "flush all in-core file state to disk",
++};
++
++static int truncate_f(BlockDriverState *bs, int argc, char **argv)
++{
++    int64_t offset;
++    int ret;
++
++    offset = cvtnum(argv[1]);
++    if (offset < 0) {
++        printf("non-numeric truncate argument -- %s\n", argv[1]);
++        return 0;
++    }
++
++    ret = bdrv_truncate(bs, offset);
++    if (ret < 0) {
++        printf("truncate: %s\n", strerror(-ret));
++        return 0;
++    }
++
++    return 0;
++}
++
++static const cmdinfo_t truncate_cmd = {
++    .name       = "truncate",
++    .altname    = "t",
++    .cfunc      = truncate_f,
++    .argmin     = 1,
++    .argmax     = 1,
++    .args       = "off",
++    .oneline    = "truncates the current file at the given offset",
++};
++
++static int length_f(BlockDriverState *bs, int argc, char **argv)
++{
++    int64_t size;
++    char s1[64];
++
++    size = bdrv_getlength(bs);
++    if (size < 0) {
++        printf("getlength: %s\n", strerror(-size));
++        return 0;
++    }
++
++    cvtstr(size, s1, sizeof(s1));
++    printf("%s\n", s1);
++    return 0;
++}
++
++
++static const cmdinfo_t length_cmd = {
++    .name   = "length",
++    .altname    = "l",
++    .cfunc      = length_f,
++    .oneline    = "gets the length of the current file",
++};
++
++
++static int info_f(BlockDriverState *bs, int argc, char **argv)
++{
++    BlockDriverInfo bdi;
++    ImageInfoSpecific *spec_info;
++    char s1[64], s2[64];
++    int ret;
++
++    if (bs->drv && bs->drv->format_name) {
++        printf("format name: %s\n", bs->drv->format_name);
++    }
++    if (bs->drv && bs->drv->protocol_name) {
++        printf("format name: %s\n", bs->drv->protocol_name);
++    }
++
++    ret = bdrv_get_info(bs, &bdi);
++    if (ret) {
++        return 0;
++    }
++
++    cvtstr(bdi.cluster_size, s1, sizeof(s1));
++    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
++
++    printf("cluster size: %s\n", s1);
++    printf("vm state offset: %s\n", s2);
++
++    spec_info = bdrv_get_specific_info(bs);
++    if (spec_info) {
++        printf("Format specific information:\n");
++        bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
++        qapi_free_ImageInfoSpecific(spec_info);
++    }
++
++    return 0;
++}
++
++
++
++static const cmdinfo_t info_cmd = {
++    .name       = "info",
++    .altname    = "i",
++    .cfunc      = info_f,
++    .oneline    = "prints information about the current file",
++};
++
++static void discard_help(void)
++{
++    printf(
++"\n"
++" discards a range of bytes from the given offset\n"
++"\n"
++" Example:\n"
++" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
++"\n"
++" Discards a segment of the currently open file.\n"
++" -C, -- report statistics in a machine parsable format\n"
++" -q, -- quiet mode, do not show I/O statistics\n"
++"\n");
++}
++
++static int discard_f(BlockDriverState *bs, int argc, char **argv);
++
++static const cmdinfo_t discard_cmd = {
++    .name       = "discard",
++    .altname    = "d",
++    .cfunc      = discard_f,
++    .argmin     = 2,
++    .argmax     = -1,
++    .args       = "[-Cq] off len",
++    .oneline    = "discards a number of bytes at a specified offset",
++    .help       = discard_help,
++};
++
++static int discard_f(BlockDriverState *bs, int argc, char **argv)
++{
++    struct timeval t1, t2;
++    int Cflag = 0, qflag = 0;
++    int c, ret;
++    int64_t offset;
++    int count;
++
++    while ((c = getopt(argc, argv, "Cq")) != EOF) {
++        switch (c) {
++        case 'C':
++            Cflag = 1;
++            break;
++        case 'q':
++            qflag = 1;
++            break;
++        default:
++            return command_usage(&discard_cmd);
++        }
++    }
++
++    if (optind != argc - 2) {
++        return command_usage(&discard_cmd);
++    }
++
++    offset = cvtnum(argv[optind]);
++    if (offset < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        return 0;
++    }
++
++    optind++;
++    count = cvtnum(argv[optind]);
++    if (count < 0) {
++        printf("non-numeric length argument -- %s\n", argv[optind]);
++        return 0;
++    }
++
++    gettimeofday(&t1, NULL);
++    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
++                       count >> BDRV_SECTOR_BITS);
++    gettimeofday(&t2, NULL);
++
++    if (ret < 0) {
++        printf("discard failed: %s\n", strerror(-ret));
++        goto out;
++    }
++
++    /* Finally, report back -- -C gives a parsable format */
++    if (!qflag) {
++        t2 = tsub(t2, t1);
++        print_report("discard", &t2, offset, count, count, 1, Cflag);
++    }
++
++out:
++    return 0;
++}
++
++static int alloc_f(BlockDriverState *bs, int argc, char **argv)
++{
++    int64_t offset, sector_num;
++    int nb_sectors, remaining;
++    char s1[64];
++    int num, sum_alloc;
++    int ret;
++
++    offset = cvtnum(argv[1]);
++    if (offset < 0) {
++        printf("non-numeric offset argument -- %s\n", argv[1]);
++        return 0;
++    } else if (offset & 0x1ff) {
++        printf("offset %" PRId64 " is not sector aligned\n",
++               offset);
++        return 0;
++    }
++
++    if (argc == 3) {
++        nb_sectors = cvtnum(argv[2]);
++        if (nb_sectors < 0) {
++            printf("non-numeric length argument -- %s\n", argv[2]);
++            return 0;
++        }
++    } else {
++        nb_sectors = 1;
++    }
++
++    remaining = nb_sectors;
++    sum_alloc = 0;
++    sector_num = offset >> 9;
++    while (remaining) {
++        ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
++        if (ret < 0) {
++            printf("is_allocated failed: %s\n", strerror(-ret));
++            return 0;
++        }
++        sector_num += num;
++        remaining -= num;
++        if (ret) {
++            sum_alloc += num;
++        }
++        if (num == 0) {
++            nb_sectors -= remaining;
++            remaining = 0;
++        }
++    }
++
++    cvtstr(offset, s1, sizeof(s1));
++
++    printf("%d/%d sectors allocated at offset %s\n",
++           sum_alloc, nb_sectors, s1);
++    return 0;
++}
++
++static const cmdinfo_t alloc_cmd = {
++    .name       = "alloc",
++    .altname    = "a",
++    .argmin     = 1,
++    .argmax     = 2,
++    .cfunc      = alloc_f,
++    .args       = "off [sectors]",
++    .oneline    = "checks if a sector is present in the file",
++};
++
++static int map_f(BlockDriverState *bs, int argc, char **argv)
++{
++    int64_t offset;
++    int64_t nb_sectors;
++    char s1[64];
++    int num, num_checked;
++    int ret;
++    const char *retstr;
++
++    offset = 0;
++    nb_sectors = bs->total_sectors;
++
++    do {
++        num_checked = MIN(nb_sectors, INT_MAX);
++        ret = bdrv_is_allocated(bs, offset, num_checked, &num);
++        retstr = ret ? "    allocated" : "not allocated";
++        cvtstr(offset << 9ULL, s1, sizeof(s1));
++        printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
++               offset << 9ULL, num, num_checked, retstr, s1, ret);
++
++        offset += num;
++        nb_sectors -= num;
++    } while (offset < bs->total_sectors);
++
++    return 0;
++}
++
++static const cmdinfo_t map_cmd = {
++       .name           = "map",
++       .argmin         = 0,
++       .argmax         = 0,
++       .cfunc          = map_f,
++       .args           = "",
++       .oneline        = "prints the allocated areas of a file",
++};
++
++static int break_f(BlockDriverState *bs, int argc, char **argv)
++{
++    int ret;
++
++    ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
++    if (ret < 0) {
++        printf("Could not set breakpoint: %s\n", strerror(-ret));
++    }
++
++    return 0;
++}
++
++static const cmdinfo_t break_cmd = {
++       .name           = "break",
++       .argmin         = 2,
++       .argmax         = 2,
++       .cfunc          = break_f,
++       .args           = "event tag",
++       .oneline        = "sets a breakpoint on event and tags the stopped "
++                         "request as tag",
++};
++
++static int resume_f(BlockDriverState *bs, int argc, char **argv)
++{
++    int ret;
++
++    ret = bdrv_debug_resume(bs, argv[1]);
++    if (ret < 0) {
++        printf("Could not resume request: %s\n", strerror(-ret));
++    }
++
++    return 0;
++}
++
++static const cmdinfo_t resume_cmd = {
++       .name           = "resume",
++       .argmin         = 1,
++       .argmax         = 1,
++       .cfunc          = resume_f,
++       .args           = "tag",
++       .oneline        = "resumes the request tagged as tag",
++};
++
++static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
++{
++    while (!bdrv_debug_is_suspended(bs, argv[1])) {
++        qemu_aio_wait();
++    }
++
++    return 0;
++}
++
++static const cmdinfo_t wait_break_cmd = {
++       .name           = "wait_break",
++       .argmin         = 1,
++       .argmax         = 1,
++       .cfunc          = wait_break_f,
++       .args           = "tag",
++       .oneline        = "waits for the suspension of a request",
++};
++
++static int abort_f(BlockDriverState *bs, int argc, char **argv)
++{
++    abort();
++}
++
++static const cmdinfo_t abort_cmd = {
++       .name           = "abort",
++       .cfunc          = abort_f,
++       .flags          = CMD_NOFILE_OK,
++       .oneline        = "simulate a program crash using abort(3)",
++};
++
++static void sleep_cb(void *opaque)
++{
++    bool *expired = opaque;
++    *expired = true;
++}
++
++static int sleep_f(BlockDriverState *bs, int argc, char **argv)
++{
++    char *endptr;
++    long ms;
++    struct QEMUTimer *timer;
++    bool expired = false;
++
++    ms = strtol(argv[1], &endptr, 0);
++    if (ms < 0 || *endptr != '\0') {
++        printf("%s is not a valid number\n", argv[1]);
++        return 0;
++    }
++
++    timer = qemu_new_timer_ns(host_clock, sleep_cb, &expired);
++    qemu_mod_timer(timer, qemu_get_clock_ns(host_clock) + SCALE_MS * ms);
++
++    while (!expired) {
++        main_loop_wait(false);
++    }
++
++    qemu_free_timer(timer);
++
++    return 0;
++}
++
++static const cmdinfo_t sleep_cmd = {
++       .name           = "sleep",
++       .argmin         = 1,
++       .argmax         = 1,
++       .cfunc          = sleep_f,
++       .flags          = CMD_NOFILE_OK,
++       .oneline        = "waits for the given value in milliseconds",
++};
++
++
++static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
++{
++    if (ct->flags & CMD_FLAG_GLOBAL) {
++        return 1;
++    }
++    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
++        fprintf(stderr, "no file open, try 'help open'\n");
++        return 0;
++    }
++    return 1;
++}
++
++static void __attribute((constructor)) init_qemuio_commands(void)
++{
++    /* initialize commands */
++    help_init();
++    add_command(&read_cmd);
++    add_command(&readv_cmd);
++    add_command(&write_cmd);
++    add_command(&writev_cmd);
++    add_command(&multiwrite_cmd);
++    add_command(&aio_read_cmd);
++    add_command(&aio_write_cmd);
++    add_command(&aio_flush_cmd);
++    add_command(&flush_cmd);
++    add_command(&truncate_cmd);
++    add_command(&length_cmd);
++    add_command(&info_cmd);
++    add_command(&discard_cmd);
++    add_command(&alloc_cmd);
++    add_command(&map_cmd);
++    add_command(&break_cmd);
++    add_command(&resume_cmd);
++    add_command(&wait_break_cmd);
++    add_command(&abort_cmd);
++    add_command(&sleep_cmd);
++
++    add_check_command(init_check_command);
++}
+diff --git a/qemu-io.c b/qemu-io.c
+index c3cc4f3..4f1c808 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -31,1761 +31,8 @@
+ char *progname;
+ 
+ BlockDriverState *qemuio_bs;
+-static int misalign;
+ 
+-static int64_t cvtnum(const char *s)
+-{
+-    char *end;
+-    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
+-}
+-
+-/*
+- * Parse the pattern argument to various sub-commands.
+- *
+- * Because the pattern is used as an argument to memset it must evaluate
+- * to an unsigned integer that fits into a single byte.
+- */
+-static int parse_pattern(const char *arg)
+-{
+-    char *endptr = NULL;
+-    long pattern;
+-
+-    pattern = strtol(arg, &endptr, 0);
+-    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
+-        printf("%s is not a valid pattern byte\n", arg);
+-        return -1;
+-    }
+-
+-    return pattern;
+-}
+-
+-/*
+- * Memory allocation helpers.
+- *
+- * Make sure memory is aligned by default, or purposefully misaligned if
+- * that is specified on the command line.
+- */
+-
+-#define MISALIGN_OFFSET     16
+-static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
+-{
+-    void *buf;
+-
+-    if (misalign) {
+-        len += MISALIGN_OFFSET;
+-    }
+-    buf = qemu_blockalign(bs, len);
+-    memset(buf, pattern, len);
+-    if (misalign) {
+-        buf += MISALIGN_OFFSET;
+-    }
+-    return buf;
+-}
+-
+-static void qemu_io_free(void *p)
+-{
+-    if (misalign) {
+-        p -= MISALIGN_OFFSET;
+-    }
+-    qemu_vfree(p);
+-}
+-
+-static void dump_buffer(const void *buffer, int64_t offset, int len)
+-{
+-    int i, j;
+-    const uint8_t *p;
+-
+-    for (i = 0, p = buffer; i < len; i += 16) {
+-        const uint8_t *s = p;
+-
+-        printf("%08" PRIx64 ":  ", offset + i);
+-        for (j = 0; j < 16 && i + j < len; j++, p++) {
+-            printf("%02x ", *p);
+-        }
+-        printf(" ");
+-        for (j = 0; j < 16 && i + j < len; j++, s++) {
+-            if (isalnum(*s)) {
+-                printf("%c", *s);
+-            } else {
+-                printf(".");
+-            }
+-        }
+-        printf("\n");
+-    }
+-}
+-
+-static void print_report(const char *op, struct timeval *t, int64_t offset,
+-                         int count, int total, int cnt, int Cflag)
+-{
+-    char s1[64], s2[64], ts[64];
+-
+-    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
+-    if (!Cflag) {
+-        cvtstr((double)total, s1, sizeof(s1));
+-        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
+-        printf("%s %d/%d bytes at offset %" PRId64 "\n",
+-               op, total, count, offset);
+-        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
+-               s1, cnt, ts, s2, tdiv((double)cnt, *t));
+-    } else {/* bytes,ops,time,bytes/sec,ops/sec */
+-        printf("%d,%d,%s,%.3f,%.3f\n",
+-            total, cnt, ts,
+-            tdiv((double)total, *t),
+-            tdiv((double)cnt, *t));
+-    }
+-}
+-
+-/*
+- * Parse multiple length statements for vectored I/O, and construct an I/O
+- * vector matching it.
+- */
+-static void *
+-create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
+-             int pattern)
+-{
+-    size_t *sizes = g_new0(size_t, nr_iov);
+-    size_t count = 0;
+-    void *buf = NULL;
+-    void *p;
+-    int i;
+-
+-    for (i = 0; i < nr_iov; i++) {
+-        char *arg = argv[i];
+-        int64_t len;
+-
+-        len = cvtnum(arg);
+-        if (len < 0) {
+-            printf("non-numeric length argument -- %s\n", arg);
+-            goto fail;
+-        }
+-
+-        /* should be SIZE_T_MAX, but that doesn't exist */
+-        if (len > INT_MAX) {
+-            printf("too large length argument -- %s\n", arg);
+-            goto fail;
+-        }
+-
+-        if (len & 0x1ff) {
+-            printf("length argument %" PRId64
+-                   " is not sector aligned\n", len);
+-            goto fail;
+-        }
+-
+-        sizes[i] = len;
+-        count += len;
+-    }
+-
+-    qemu_iovec_init(qiov, nr_iov);
+-
+-    buf = p = qemu_io_alloc(bs, count, pattern);
+-
+-    for (i = 0; i < nr_iov; i++) {
+-        qemu_iovec_add(qiov, p, sizes[i]);
+-        p += sizes[i];
+-    }
+-
+-fail:
+-    g_free(sizes);
+-    return buf;
+-}
+-
+-static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
+-                   int *total)
+-{
+-    int ret;
+-
+-    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+-    if (ret < 0) {
+-        return ret;
+-    }
+-    *total = count;
+-    return 1;
+-}
+-
+-static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
+-                    int *total)
+-{
+-    int ret;
+-
+-    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+-    if (ret < 0) {
+-        return ret;
+-    }
+-    *total = count;
+-    return 1;
+-}
+-
+-static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
+-                    int *total)
+-{
+-    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
+-    if (*total < 0) {
+-        return *total;
+-    }
+-    return 1;
+-}
+-
+-static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
+-                     int *total)
+-{
+-    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
+-    if (*total < 0) {
+-        return *total;
+-    }
+-    return 1;
+-}
+-
+-typedef struct {
+-    BlockDriverState *bs;
+-    int64_t offset;
+-    int count;
+-    int *total;
+-    int ret;
+-    bool done;
+-} CoWriteZeroes;
+-
+-static void coroutine_fn co_write_zeroes_entry(void *opaque)
+-{
+-    CoWriteZeroes *data = opaque;
+-
+-    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
+-                                     data->count / BDRV_SECTOR_SIZE, 0);
+-    data->done = true;
+-    if (data->ret < 0) {
+-        *data->total = data->ret;
+-        return;
+-    }
+-
+-    *data->total = data->count;
+-}
+-
+-static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
+-                              int *total)
+-{
+-    Coroutine *co;
+-    CoWriteZeroes data = {
+-        .bs     = bs,
+-        .offset = offset,
+-        .count  = count,
+-        .total  = total,
+-        .done   = false,
+-    };
+-
+-    co = qemu_coroutine_create(co_write_zeroes_entry);
+-    qemu_coroutine_enter(co, &data);
+-    while (!data.done) {
+-        qemu_aio_wait();
+-    }
+-    if (data.ret < 0) {
+-        return data.ret;
+-    } else {
+-        return 1;
+-    }
+-}
+-
+-static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
+-                               int count, int *total)
+-{
+-    int ret;
+-
+-    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+-    if (ret < 0) {
+-        return ret;
+-    }
+-    *total = count;
+-    return 1;
+-}
+-
+-static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+-                           int count, int *total)
+-{
+-    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
+-    if (*total < 0) {
+-        return *total;
+-    }
+-    return 1;
+-}
+-
+-static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+-                           int count, int *total)
+-{
+-    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
+-    if (*total < 0) {
+-        return *total;
+-    }
+-    return 1;
+-}
+-
+-#define NOT_DONE 0x7fffffff
+-static void aio_rw_done(void *opaque, int ret)
+-{
+-    *(int *)opaque = ret;
+-}
+-
+-static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
+-                        int64_t offset, int *total)
+-{
+-    int async_ret = NOT_DONE;
+-
+-    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
+-                   aio_rw_done, &async_ret);
+-    while (async_ret == NOT_DONE) {
+-        main_loop_wait(false);
+-    }
+-
+-    *total = qiov->size;
+-    return async_ret < 0 ? async_ret : 1;
+-}
+-
+-static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
+-                         int64_t offset, int *total)
+-{
+-    int async_ret = NOT_DONE;
+-
+-    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
+-                    aio_rw_done, &async_ret);
+-    while (async_ret == NOT_DONE) {
+-        main_loop_wait(false);
+-    }
+-
+-    *total = qiov->size;
+-    return async_ret < 0 ? async_ret : 1;
+-}
+-
+-struct multiwrite_async_ret {
+-    int num_done;
+-    int error;
+-};
+-
+-static void multiwrite_cb(void *opaque, int ret)
+-{
+-    struct multiwrite_async_ret *async_ret = opaque;
+-
+-    async_ret->num_done++;
+-    if (ret < 0) {
+-        async_ret->error = ret;
+-    }
+-}
+-
+-static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
+-                             int num_reqs, int *total)
+-{
+-    int i, ret;
+-    struct multiwrite_async_ret async_ret = {
+-        .num_done = 0,
+-        .error = 0,
+-    };
+-
+-    *total = 0;
+-    for (i = 0; i < num_reqs; i++) {
+-        reqs[i].cb = multiwrite_cb;
+-        reqs[i].opaque = &async_ret;
+-        *total += reqs[i].qiov->size;
+-    }
+-
+-    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
+-    if (ret < 0) {
+-        return ret;
+-    }
+-
+-    while (async_ret.num_done < num_reqs) {
+-        main_loop_wait(false);
+-    }
+-
+-    return async_ret.error < 0 ? async_ret.error : 1;
+-}
+-
+-static void read_help(void)
+-{
+-    printf(
+-"\n"
+-" reads a range of bytes from the given offset\n"
+-"\n"
+-" Example:\n"
+-" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
+-"\n"
+-" Reads a segment of the currently open file, optionally dumping it to the\n"
+-" standard output stream (with -v option) for subsequent inspection.\n"
+-" -b, -- read from the VM state rather than the virtual disk\n"
+-" -C, -- report statistics in a machine parsable format\n"
+-" -l, -- length for pattern verification (only with -P)\n"
+-" -p, -- use bdrv_pread to read the file\n"
+-" -P, -- use a pattern to verify read data\n"
+-" -q, -- quiet mode, do not show I/O statistics\n"
+-" -s, -- start offset for pattern verification (only with -P)\n"
+-" -v, -- dump buffer to standard output\n"
+-"\n");
+-}
+-
+-static int read_f(BlockDriverState *bs, int argc, char **argv);
+-
+-static const cmdinfo_t read_cmd = {
+-    .name       = "read",
+-    .altname    = "r",
+-    .cfunc      = read_f,
+-    .argmin     = 2,
+-    .argmax     = -1,
+-    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
+-    .oneline    = "reads a number of bytes at a specified offset",
+-    .help       = read_help,
+-};
+-
+-static int read_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    struct timeval t1, t2;
+-    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
+-    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
+-    int c, cnt;
+-    char *buf;
+-    int64_t offset;
+-    int count;
+-    /* Some compilers get confused and warn if this is not initialized.  */
+-    int total = 0;
+-    int pattern = 0, pattern_offset = 0, pattern_count = 0;
+-
+-    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
+-        switch (c) {
+-        case 'b':
+-            bflag = 1;
+-            break;
+-        case 'C':
+-            Cflag = 1;
+-            break;
+-        case 'l':
+-            lflag = 1;
+-            pattern_count = cvtnum(optarg);
+-            if (pattern_count < 0) {
+-                printf("non-numeric length argument -- %s\n", optarg);
+-                return 0;
+-            }
+-            break;
+-        case 'p':
+-            pflag = 1;
+-            break;
+-        case 'P':
+-            Pflag = 1;
+-            pattern = parse_pattern(optarg);
+-            if (pattern < 0) {
+-                return 0;
+-            }
+-            break;
+-        case 'q':
+-            qflag = 1;
+-            break;
+-        case 's':
+-            sflag = 1;
+-            pattern_offset = cvtnum(optarg);
+-            if (pattern_offset < 0) {
+-                printf("non-numeric length argument -- %s\n", optarg);
+-                return 0;
+-            }
+-            break;
+-        case 'v':
+-            vflag = 1;
+-            break;
+-        default:
+-            return command_usage(&read_cmd);
+-        }
+-    }
+-
+-    if (optind != argc - 2) {
+-        return command_usage(&read_cmd);
+-    }
+-
+-    if (bflag && pflag) {
+-        printf("-b and -p cannot be specified at the same time\n");
+-        return 0;
+-    }
+-
+-    offset = cvtnum(argv[optind]);
+-    if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        return 0;
+-    }
+-
+-    optind++;
+-    count = cvtnum(argv[optind]);
+-    if (count < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        return 0;
+-    }
+-
+-    if (!Pflag && (lflag || sflag)) {
+-        return command_usage(&read_cmd);
+-    }
+-
+-    if (!lflag) {
+-        pattern_count = count - pattern_offset;
+-    }
+-
+-    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
+-        printf("pattern verification range exceeds end of read data\n");
+-        return 0;
+-    }
+-
+-    if (!pflag) {
+-        if (offset & 0x1ff) {
+-            printf("offset %" PRId64 " is not sector aligned\n",
+-                   offset);
+-            return 0;
+-        }
+-        if (count & 0x1ff) {
+-            printf("count %d is not sector aligned\n",
+-                   count);
+-            return 0;
+-        }
+-    }
+-
+-    buf = qemu_io_alloc(bs, count, 0xab);
+-
+-    gettimeofday(&t1, NULL);
+-    if (pflag) {
+-        cnt = do_pread(bs, buf, offset, count, &total);
+-    } else if (bflag) {
+-        cnt = do_load_vmstate(bs, buf, offset, count, &total);
+-    } else {
+-        cnt = do_read(bs, buf, offset, count, &total);
+-    }
+-    gettimeofday(&t2, NULL);
+-
+-    if (cnt < 0) {
+-        printf("read failed: %s\n", strerror(-cnt));
+-        goto out;
+-    }
+-
+-    if (Pflag) {
+-        void *cmp_buf = g_malloc(pattern_count);
+-        memset(cmp_buf, pattern, pattern_count);
+-        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
+-            printf("Pattern verification failed at offset %"
+-                   PRId64 ", %d bytes\n",
+-                   offset + pattern_offset, pattern_count);
+-        }
+-        g_free(cmp_buf);
+-    }
+-
+-    if (qflag) {
+-        goto out;
+-    }
+-
+-    if (vflag) {
+-        dump_buffer(buf, offset, count);
+-    }
+-
+-    /* Finally, report back -- -C gives a parsable format */
+-    t2 = tsub(t2, t1);
+-    print_report("read", &t2, offset, count, total, cnt, Cflag);
+-
+-out:
+-    qemu_io_free(buf);
+-
+-    return 0;
+-}
+-
+-static void readv_help(void)
+-{
+-    printf(
+-"\n"
+-" reads a range of bytes from the given offset into multiple buffers\n"
+-"\n"
+-" Example:\n"
+-" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
+-"\n"
+-" Reads a segment of the currently open file, optionally dumping it to the\n"
+-" standard output stream (with -v option) for subsequent inspection.\n"
+-" Uses multiple iovec buffers if more than one byte range is specified.\n"
+-" -C, -- report statistics in a machine parsable format\n"
+-" -P, -- use a pattern to verify read data\n"
+-" -v, -- dump buffer to standard output\n"
+-" -q, -- quiet mode, do not show I/O statistics\n"
+-"\n");
+-}
+-
+-static int readv_f(BlockDriverState *bs, int argc, char **argv);
+-
+-static const cmdinfo_t readv_cmd = {
+-    .name       = "readv",
+-    .cfunc      = readv_f,
+-    .argmin     = 2,
+-    .argmax     = -1,
+-    .args       = "[-Cqv] [-P pattern ] off len [len..]",
+-    .oneline    = "reads a number of bytes at a specified offset",
+-    .help       = readv_help,
+-};
+-
+-static int readv_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    struct timeval t1, t2;
+-    int Cflag = 0, qflag = 0, vflag = 0;
+-    int c, cnt;
+-    char *buf;
+-    int64_t offset;
+-    /* Some compilers get confused and warn if this is not initialized.  */
+-    int total = 0;
+-    int nr_iov;
+-    QEMUIOVector qiov;
+-    int pattern = 0;
+-    int Pflag = 0;
+-
+-    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
+-        switch (c) {
+-        case 'C':
+-            Cflag = 1;
+-            break;
+-        case 'P':
+-            Pflag = 1;
+-            pattern = parse_pattern(optarg);
+-            if (pattern < 0) {
+-                return 0;
+-            }
+-            break;
+-        case 'q':
+-            qflag = 1;
+-            break;
+-        case 'v':
+-            vflag = 1;
+-            break;
+-        default:
+-            return command_usage(&readv_cmd);
+-        }
+-    }
+-
+-    if (optind > argc - 2) {
+-        return command_usage(&readv_cmd);
+-    }
+-
+-
+-    offset = cvtnum(argv[optind]);
+-    if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        return 0;
+-    }
+-    optind++;
+-
+-    if (offset & 0x1ff) {
+-        printf("offset %" PRId64 " is not sector aligned\n",
+-               offset);
+-        return 0;
+-    }
+-
+-    nr_iov = argc - optind;
+-    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
+-    if (buf == NULL) {
+-        return 0;
+-    }
+-
+-    gettimeofday(&t1, NULL);
+-    cnt = do_aio_readv(bs, &qiov, offset, &total);
+-    gettimeofday(&t2, NULL);
+-
+-    if (cnt < 0) {
+-        printf("readv failed: %s\n", strerror(-cnt));
+-        goto out;
+-    }
+-
+-    if (Pflag) {
+-        void *cmp_buf = g_malloc(qiov.size);
+-        memset(cmp_buf, pattern, qiov.size);
+-        if (memcmp(buf, cmp_buf, qiov.size)) {
+-            printf("Pattern verification failed at offset %"
+-                   PRId64 ", %zd bytes\n", offset, qiov.size);
+-        }
+-        g_free(cmp_buf);
+-    }
+-
+-    if (qflag) {
+-        goto out;
+-    }
+-
+-    if (vflag) {
+-        dump_buffer(buf, offset, qiov.size);
+-    }
+-
+-    /* Finally, report back -- -C gives a parsable format */
+-    t2 = tsub(t2, t1);
+-    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
+-
+-out:
+-    qemu_iovec_destroy(&qiov);
+-    qemu_io_free(buf);
+-    return 0;
+-}
+-
+-static void write_help(void)
+-{
+-    printf(
+-"\n"
+-" writes a range of bytes from the given offset\n"
+-"\n"
+-" Example:\n"
+-" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
+-"\n"
+-" Writes into a segment of the currently open file, using a buffer\n"
+-" filled with a set pattern (0xcdcdcdcd).\n"
+-" -b, -- write to the VM state rather than the virtual disk\n"
+-" -c, -- write compressed data with bdrv_write_compressed\n"
+-" -p, -- use bdrv_pwrite to write the file\n"
+-" -P, -- use different pattern to fill file\n"
+-" -C, -- report statistics in a machine parsable format\n"
+-" -q, -- quiet mode, do not show I/O statistics\n"
+-" -z, -- write zeroes using bdrv_co_write_zeroes\n"
+-"\n");
+-}
+-
+-static int write_f(BlockDriverState *bs, int argc, char **argv);
+-
+-static const cmdinfo_t write_cmd = {
+-    .name       = "write",
+-    .altname    = "w",
+-    .cfunc      = write_f,
+-    .argmin     = 2,
+-    .argmax     = -1,
+-    .args       = "[-bcCpqz] [-P pattern ] off len",
+-    .oneline    = "writes a number of bytes at a specified offset",
+-    .help       = write_help,
+-};
+-
+-static int write_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    struct timeval t1, t2;
+-    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
+-    int cflag = 0;
+-    int c, cnt;
+-    char *buf = NULL;
+-    int64_t offset;
+-    int count;
+-    /* Some compilers get confused and warn if this is not initialized.  */
+-    int total = 0;
+-    int pattern = 0xcd;
+-
+-    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
+-        switch (c) {
+-        case 'b':
+-            bflag = 1;
+-            break;
+-        case 'c':
+-            cflag = 1;
+-            break;
+-        case 'C':
+-            Cflag = 1;
+-            break;
+-        case 'p':
+-            pflag = 1;
+-            break;
+-        case 'P':
+-            Pflag = 1;
+-            pattern = parse_pattern(optarg);
+-            if (pattern < 0) {
+-                return 0;
+-            }
+-            break;
+-        case 'q':
+-            qflag = 1;
+-            break;
+-        case 'z':
+-            zflag = 1;
+-            break;
+-        default:
+-            return command_usage(&write_cmd);
+-        }
+-    }
+-
+-    if (optind != argc - 2) {
+-        return command_usage(&write_cmd);
+-    }
+-
+-    if (bflag + pflag + zflag > 1) {
+-        printf("-b, -p, or -z cannot be specified at the same time\n");
+-        return 0;
+-    }
+-
+-    if (zflag && Pflag) {
+-        printf("-z and -P cannot be specified at the same time\n");
+-        return 0;
+-    }
+-
+-    offset = cvtnum(argv[optind]);
+-    if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        return 0;
+-    }
+-
+-    optind++;
+-    count = cvtnum(argv[optind]);
+-    if (count < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        return 0;
+-    }
+-
+-    if (!pflag) {
+-        if (offset & 0x1ff) {
+-            printf("offset %" PRId64 " is not sector aligned\n",
+-                   offset);
+-            return 0;
+-        }
+-
+-        if (count & 0x1ff) {
+-            printf("count %d is not sector aligned\n",
+-                   count);
+-            return 0;
+-        }
+-    }
+-
+-    if (!zflag) {
+-        buf = qemu_io_alloc(bs, count, pattern);
+-    }
+-
+-    gettimeofday(&t1, NULL);
+-    if (pflag) {
+-        cnt = do_pwrite(bs, buf, offset, count, &total);
+-    } else if (bflag) {
+-        cnt = do_save_vmstate(bs, buf, offset, count, &total);
+-    } else if (zflag) {
+-        cnt = do_co_write_zeroes(bs, offset, count, &total);
+-    } else if (cflag) {
+-        cnt = do_write_compressed(bs, buf, offset, count, &total);
+-    } else {
+-        cnt = do_write(bs, buf, offset, count, &total);
+-    }
+-    gettimeofday(&t2, NULL);
+-
+-    if (cnt < 0) {
+-        printf("write failed: %s\n", strerror(-cnt));
+-        goto out;
+-    }
+-
+-    if (qflag) {
+-        goto out;
+-    }
+-
+-    /* Finally, report back -- -C gives a parsable format */
+-    t2 = tsub(t2, t1);
+-    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
+-
+-out:
+-    if (!zflag) {
+-        qemu_io_free(buf);
+-    }
+-
+-    return 0;
+-}
+-
+-static void
+-writev_help(void)
+-{
+-    printf(
+-"\n"
+-" writes a range of bytes from the given offset source from multiple buffers\n"
+-"\n"
+-" Example:\n"
+-" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
+-"\n"
+-" Writes into a segment of the currently open file, using a buffer\n"
+-" filled with a set pattern (0xcdcdcdcd).\n"
+-" -P, -- use different pattern to fill file\n"
+-" -C, -- report statistics in a machine parsable format\n"
+-" -q, -- quiet mode, do not show I/O statistics\n"
+-"\n");
+-}
+-
+-static int writev_f(BlockDriverState *bs, int argc, char **argv);
+-
+-static const cmdinfo_t writev_cmd = {
+-    .name       = "writev",
+-    .cfunc      = writev_f,
+-    .argmin     = 2,
+-    .argmax     = -1,
+-    .args       = "[-Cq] [-P pattern ] off len [len..]",
+-    .oneline    = "writes a number of bytes at a specified offset",
+-    .help       = writev_help,
+-};
+-
+-static int writev_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    struct timeval t1, t2;
+-    int Cflag = 0, qflag = 0;
+-    int c, cnt;
+-    char *buf;
+-    int64_t offset;
+-    /* Some compilers get confused and warn if this is not initialized.  */
+-    int total = 0;
+-    int nr_iov;
+-    int pattern = 0xcd;
+-    QEMUIOVector qiov;
+-
+-    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+-        switch (c) {
+-        case 'C':
+-            Cflag = 1;
+-            break;
+-        case 'q':
+-            qflag = 1;
+-            break;
+-        case 'P':
+-            pattern = parse_pattern(optarg);
+-            if (pattern < 0) {
+-                return 0;
+-            }
+-            break;
+-        default:
+-            return command_usage(&writev_cmd);
+-        }
+-    }
+-
+-    if (optind > argc - 2) {
+-        return command_usage(&writev_cmd);
+-    }
+-
+-    offset = cvtnum(argv[optind]);
+-    if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        return 0;
+-    }
+-    optind++;
+-
+-    if (offset & 0x1ff) {
+-        printf("offset %" PRId64 " is not sector aligned\n",
+-               offset);
+-        return 0;
+-    }
+-
+-    nr_iov = argc - optind;
+-    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
+-    if (buf == NULL) {
+-        return 0;
+-    }
+-
+-    gettimeofday(&t1, NULL);
+-    cnt = do_aio_writev(bs, &qiov, offset, &total);
+-    gettimeofday(&t2, NULL);
+-
+-    if (cnt < 0) {
+-        printf("writev failed: %s\n", strerror(-cnt));
+-        goto out;
+-    }
+-
+-    if (qflag) {
+-        goto out;
+-    }
+-
+-    /* Finally, report back -- -C gives a parsable format */
+-    t2 = tsub(t2, t1);
+-    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
+-out:
+-    qemu_iovec_destroy(&qiov);
+-    qemu_io_free(buf);
+-    return 0;
+-}
+-
+-static void multiwrite_help(void)
+-{
+-    printf(
+-"\n"
+-" writes a range of bytes from the given offset source from multiple buffers,\n"
+-" in a batch of requests that may be merged by qemu\n"
+-"\n"
+-" Example:\n"
+-" 'multiwrite 512 1k 1k ; 4k 1k'\n"
+-"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
+-"\n"
+-" Writes into a segment of the currently open file, using a buffer\n"
+-" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
+-" by one for each request contained in the multiwrite command.\n"
+-" -P, -- use different pattern to fill file\n"
+-" -C, -- report statistics in a machine parsable format\n"
+-" -q, -- quiet mode, do not show I/O statistics\n"
+-"\n");
+-}
+-
+-static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
+-
+-static const cmdinfo_t multiwrite_cmd = {
+-    .name       = "multiwrite",
+-    .cfunc      = multiwrite_f,
+-    .argmin     = 2,
+-    .argmax     = -1,
+-    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
+-    .oneline    = "issues multiple write requests at once",
+-    .help       = multiwrite_help,
+-};
+-
+-static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    struct timeval t1, t2;
+-    int Cflag = 0, qflag = 0;
+-    int c, cnt;
+-    char **buf;
+-    int64_t offset, first_offset = 0;
+-    /* Some compilers get confused and warn if this is not initialized.  */
+-    int total = 0;
+-    int nr_iov;
+-    int nr_reqs;
+-    int pattern = 0xcd;
+-    QEMUIOVector *qiovs;
+-    int i;
+-    BlockRequest *reqs;
+-
+-    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+-        switch (c) {
+-        case 'C':
+-            Cflag = 1;
+-            break;
+-        case 'q':
+-            qflag = 1;
+-            break;
+-        case 'P':
+-            pattern = parse_pattern(optarg);
+-            if (pattern < 0) {
+-                return 0;
+-            }
+-            break;
+-        default:
+-            return command_usage(&writev_cmd);
+-        }
+-    }
+-
+-    if (optind > argc - 2) {
+-        return command_usage(&writev_cmd);
+-    }
+-
+-    nr_reqs = 1;
+-    for (i = optind; i < argc; i++) {
+-        if (!strcmp(argv[i], ";")) {
+-            nr_reqs++;
+-        }
+-    }
+-
+-    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
+-    buf = g_malloc0(nr_reqs * sizeof(*buf));
+-    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
+-
+-    for (i = 0; i < nr_reqs && optind < argc; i++) {
+-        int j;
+-
+-        /* Read the offset of the request */
+-        offset = cvtnum(argv[optind]);
+-        if (offset < 0) {
+-            printf("non-numeric offset argument -- %s\n", argv[optind]);
+-            goto out;
+-        }
+-        optind++;
+-
+-        if (offset & 0x1ff) {
+-            printf("offset %lld is not sector aligned\n",
+-                   (long long)offset);
+-            goto out;
+-        }
+-
+-        if (i == 0) {
+-            first_offset = offset;
+-        }
+-
+-        /* Read lengths for qiov entries */
+-        for (j = optind; j < argc; j++) {
+-            if (!strcmp(argv[j], ";")) {
+-                break;
+-            }
+-        }
+-
+-        nr_iov = j - optind;
+-
+-        /* Build request */
+-        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
+-        if (buf[i] == NULL) {
+-            goto out;
+-        }
+-
+-        reqs[i].qiov = &qiovs[i];
+-        reqs[i].sector = offset >> 9;
+-        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
+-
+-        optind = j + 1;
+-
+-        pattern++;
+-    }
+-
+-    /* If there were empty requests at the end, ignore them */
+-    nr_reqs = i;
+-
+-    gettimeofday(&t1, NULL);
+-    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
+-    gettimeofday(&t2, NULL);
+-
+-    if (cnt < 0) {
+-        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
+-        goto out;
+-    }
+-
+-    if (qflag) {
+-        goto out;
+-    }
+-
+-    /* Finally, report back -- -C gives a parsable format */
+-    t2 = tsub(t2, t1);
+-    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
+-out:
+-    for (i = 0; i < nr_reqs; i++) {
+-        qemu_io_free(buf[i]);
+-        if (reqs[i].qiov != NULL) {
+-            qemu_iovec_destroy(&qiovs[i]);
+-        }
+-    }
+-    g_free(buf);
+-    g_free(reqs);
+-    g_free(qiovs);
+-    return 0;
+-}
+-
+-struct aio_ctx {
+-    QEMUIOVector qiov;
+-    int64_t offset;
+-    char *buf;
+-    int qflag;
+-    int vflag;
+-    int Cflag;
+-    int Pflag;
+-    int pattern;
+-    struct timeval t1;
+-};
+-
+-static void aio_write_done(void *opaque, int ret)
+-{
+-    struct aio_ctx *ctx = opaque;
+-    struct timeval t2;
+-
+-    gettimeofday(&t2, NULL);
+-
+-
+-    if (ret < 0) {
+-        printf("aio_write failed: %s\n", strerror(-ret));
+-        goto out;
+-    }
+-
+-    if (ctx->qflag) {
+-        goto out;
+-    }
+-
+-    /* Finally, report back -- -C gives a parsable format */
+-    t2 = tsub(t2, ctx->t1);
+-    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
+-                 ctx->qiov.size, 1, ctx->Cflag);
+-out:
+-    qemu_io_free(ctx->buf);
+-    qemu_iovec_destroy(&ctx->qiov);
+-    g_free(ctx);
+-}
+-
+-static void aio_read_done(void *opaque, int ret)
+-{
+-    struct aio_ctx *ctx = opaque;
+-    struct timeval t2;
+-
+-    gettimeofday(&t2, NULL);
+-
+-    if (ret < 0) {
+-        printf("readv failed: %s\n", strerror(-ret));
+-        goto out;
+-    }
+-
+-    if (ctx->Pflag) {
+-        void *cmp_buf = g_malloc(ctx->qiov.size);
+-
+-        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
+-        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
+-            printf("Pattern verification failed at offset %"
+-                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
+-        }
+-        g_free(cmp_buf);
+-    }
+-
+-    if (ctx->qflag) {
+-        goto out;
+-    }
+-
+-    if (ctx->vflag) {
+-        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
+-    }
+-
+-    /* Finally, report back -- -C gives a parsable format */
+-    t2 = tsub(t2, ctx->t1);
+-    print_report("read", &t2, ctx->offset, ctx->qiov.size,
+-                 ctx->qiov.size, 1, ctx->Cflag);
+-out:
+-    qemu_io_free(ctx->buf);
+-    qemu_iovec_destroy(&ctx->qiov);
+-    g_free(ctx);
+-}
+-
+-static void aio_read_help(void)
+-{
+-    printf(
+-"\n"
+-" asynchronously reads a range of bytes from the given offset\n"
+-"\n"
+-" Example:\n"
+-" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
+-"\n"
+-" Reads a segment of the currently open file, optionally dumping it to the\n"
+-" standard output stream (with -v option) for subsequent inspection.\n"
+-" The read is performed asynchronously and the aio_flush command must be\n"
+-" used to ensure all outstanding aio requests have been completed.\n"
+-" -C, -- report statistics in a machine parsable format\n"
+-" -P, -- use a pattern to verify read data\n"
+-" -v, -- dump buffer to standard output\n"
+-" -q, -- quiet mode, do not show I/O statistics\n"
+-"\n");
+-}
+-
+-static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
+-
+-static const cmdinfo_t aio_read_cmd = {
+-    .name       = "aio_read",
+-    .cfunc      = aio_read_f,
+-    .argmin     = 2,
+-    .argmax     = -1,
+-    .args       = "[-Cqv] [-P pattern ] off len [len..]",
+-    .oneline    = "asynchronously reads a number of bytes",
+-    .help       = aio_read_help,
+-};
+-
+-static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    int nr_iov, c;
+-    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
+-
+-    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
+-        switch (c) {
+-        case 'C':
+-            ctx->Cflag = 1;
+-            break;
+-        case 'P':
+-            ctx->Pflag = 1;
+-            ctx->pattern = parse_pattern(optarg);
+-            if (ctx->pattern < 0) {
+-                g_free(ctx);
+-                return 0;
+-            }
+-            break;
+-        case 'q':
+-            ctx->qflag = 1;
+-            break;
+-        case 'v':
+-            ctx->vflag = 1;
+-            break;
+-        default:
+-            g_free(ctx);
+-            return command_usage(&aio_read_cmd);
+-        }
+-    }
+-
+-    if (optind > argc - 2) {
+-        g_free(ctx);
+-        return command_usage(&aio_read_cmd);
+-    }
+-
+-    ctx->offset = cvtnum(argv[optind]);
+-    if (ctx->offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        g_free(ctx);
+-        return 0;
+-    }
+-    optind++;
+-
+-    if (ctx->offset & 0x1ff) {
+-        printf("offset %" PRId64 " is not sector aligned\n",
+-               ctx->offset);
+-        g_free(ctx);
+-        return 0;
+-    }
+-
+-    nr_iov = argc - optind;
+-    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
+-    if (ctx->buf == NULL) {
+-        g_free(ctx);
+-        return 0;
+-    }
+-
+-    gettimeofday(&ctx->t1, NULL);
+-    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
+-                   ctx->qiov.size >> 9, aio_read_done, ctx);
+-    return 0;
+-}
+-
+-static void aio_write_help(void)
+-{
+-    printf(
+-"\n"
+-" asynchronously writes a range of bytes from the given offset source\n"
+-" from multiple buffers\n"
+-"\n"
+-" Example:\n"
+-" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
+-"\n"
+-" Writes into a segment of the currently open file, using a buffer\n"
+-" filled with a set pattern (0xcdcdcdcd).\n"
+-" The write is performed asynchronously and the aio_flush command must be\n"
+-" used to ensure all outstanding aio requests have been completed.\n"
+-" -P, -- use different pattern to fill file\n"
+-" -C, -- report statistics in a machine parsable format\n"
+-" -q, -- quiet mode, do not show I/O statistics\n"
+-"\n");
+-}
+-
+-static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
+-
+-static const cmdinfo_t aio_write_cmd = {
+-    .name       = "aio_write",
+-    .cfunc      = aio_write_f,
+-    .argmin     = 2,
+-    .argmax     = -1,
+-    .args       = "[-Cq] [-P pattern ] off len [len..]",
+-    .oneline    = "asynchronously writes a number of bytes",
+-    .help       = aio_write_help,
+-};
+-
+-static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    int nr_iov, c;
+-    int pattern = 0xcd;
+-    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
+-
+-    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+-        switch (c) {
+-        case 'C':
+-            ctx->Cflag = 1;
+-            break;
+-        case 'q':
+-            ctx->qflag = 1;
+-            break;
+-        case 'P':
+-            pattern = parse_pattern(optarg);
+-            if (pattern < 0) {
+-                g_free(ctx);
+-                return 0;
+-            }
+-            break;
+-        default:
+-            g_free(ctx);
+-            return command_usage(&aio_write_cmd);
+-        }
+-    }
+-
+-    if (optind > argc - 2) {
+-        g_free(ctx);
+-        return command_usage(&aio_write_cmd);
+-    }
+-
+-    ctx->offset = cvtnum(argv[optind]);
+-    if (ctx->offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        g_free(ctx);
+-        return 0;
+-    }
+-    optind++;
+-
+-    if (ctx->offset & 0x1ff) {
+-        printf("offset %" PRId64 " is not sector aligned\n",
+-               ctx->offset);
+-        g_free(ctx);
+-        return 0;
+-    }
+-
+-    nr_iov = argc - optind;
+-    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
+-    if (ctx->buf == NULL) {
+-        g_free(ctx);
+-        return 0;
+-    }
+-
+-    gettimeofday(&ctx->t1, NULL);
+-    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
+-                    ctx->qiov.size >> 9, aio_write_done, ctx);
+-    return 0;
+-}
+-
+-static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    bdrv_drain_all();
+-    return 0;
+-}
+-
+-static const cmdinfo_t aio_flush_cmd = {
+-    .name       = "aio_flush",
+-    .cfunc      = aio_flush_f,
+-    .oneline    = "completes all outstanding aio requests"
+-};
+-
+-static int flush_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    bdrv_flush(bs);
+-    return 0;
+-}
+-
+-static const cmdinfo_t flush_cmd = {
+-    .name       = "flush",
+-    .altname    = "f",
+-    .cfunc      = flush_f,
+-    .oneline    = "flush all in-core file state to disk",
+-};
+-
+-static int truncate_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    int64_t offset;
+-    int ret;
+-
+-    offset = cvtnum(argv[1]);
+-    if (offset < 0) {
+-        printf("non-numeric truncate argument -- %s\n", argv[1]);
+-        return 0;
+-    }
+-
+-    ret = bdrv_truncate(bs, offset);
+-    if (ret < 0) {
+-        printf("truncate: %s\n", strerror(-ret));
+-        return 0;
+-    }
+-
+-    return 0;
+-}
+-
+-static const cmdinfo_t truncate_cmd = {
+-    .name       = "truncate",
+-    .altname    = "t",
+-    .cfunc      = truncate_f,
+-    .argmin     = 1,
+-    .argmax     = 1,
+-    .args       = "off",
+-    .oneline    = "truncates the current file at the given offset",
+-};
+-
+-static int length_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    int64_t size;
+-    char s1[64];
+-
+-    size = bdrv_getlength(bs);
+-    if (size < 0) {
+-        printf("getlength: %s\n", strerror(-size));
+-        return 0;
+-    }
+-
+-    cvtstr(size, s1, sizeof(s1));
+-    printf("%s\n", s1);
+-    return 0;
+-}
+-
+-
+-static const cmdinfo_t length_cmd = {
+-    .name   = "length",
+-    .altname    = "l",
+-    .cfunc      = length_f,
+-    .oneline    = "gets the length of the current file",
+-};
+-
+-
+-static int info_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    BlockDriverInfo bdi;
+-    ImageInfoSpecific *spec_info;
+-    char s1[64], s2[64];
+-    int ret;
+-
+-    if (bs->drv && bs->drv->format_name) {
+-        printf("format name: %s\n", bs->drv->format_name);
+-    }
+-    if (bs->drv && bs->drv->protocol_name) {
+-        printf("format name: %s\n", bs->drv->protocol_name);
+-    }
+-
+-    ret = bdrv_get_info(bs, &bdi);
+-    if (ret) {
+-        return 0;
+-    }
+-
+-    cvtstr(bdi.cluster_size, s1, sizeof(s1));
+-    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
+-
+-    printf("cluster size: %s\n", s1);
+-    printf("vm state offset: %s\n", s2);
+-
+-    spec_info = bdrv_get_specific_info(bs);
+-    if (spec_info) {
+-        printf("Format specific information:\n");
+-        bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
+-        qapi_free_ImageInfoSpecific(spec_info);
+-    }
+-
+-    return 0;
+-}
+-
+-
+-
+-static const cmdinfo_t info_cmd = {
+-    .name       = "info",
+-    .altname    = "i",
+-    .cfunc      = info_f,
+-    .oneline    = "prints information about the current file",
+-};
+-
+-static void discard_help(void)
+-{
+-    printf(
+-"\n"
+-" discards a range of bytes from the given offset\n"
+-"\n"
+-" Example:\n"
+-" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
+-"\n"
+-" Discards a segment of the currently open file.\n"
+-" -C, -- report statistics in a machine parsable format\n"
+-" -q, -- quiet mode, do not show I/O statistics\n"
+-"\n");
+-}
+-
+-static int discard_f(BlockDriverState *bs, int argc, char **argv);
+-
+-static const cmdinfo_t discard_cmd = {
+-    .name       = "discard",
+-    .altname    = "d",
+-    .cfunc      = discard_f,
+-    .argmin     = 2,
+-    .argmax     = -1,
+-    .args       = "[-Cq] off len",
+-    .oneline    = "discards a number of bytes at a specified offset",
+-    .help       = discard_help,
+-};
+-
+-static int discard_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    struct timeval t1, t2;
+-    int Cflag = 0, qflag = 0;
+-    int c, ret;
+-    int64_t offset;
+-    int count;
+-
+-    while ((c = getopt(argc, argv, "Cq")) != EOF) {
+-        switch (c) {
+-        case 'C':
+-            Cflag = 1;
+-            break;
+-        case 'q':
+-            qflag = 1;
+-            break;
+-        default:
+-            return command_usage(&discard_cmd);
+-        }
+-    }
+-
+-    if (optind != argc - 2) {
+-        return command_usage(&discard_cmd);
+-    }
+-
+-    offset = cvtnum(argv[optind]);
+-    if (offset < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        return 0;
+-    }
+-
+-    optind++;
+-    count = cvtnum(argv[optind]);
+-    if (count < 0) {
+-        printf("non-numeric length argument -- %s\n", argv[optind]);
+-        return 0;
+-    }
+-
+-    gettimeofday(&t1, NULL);
+-    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
+-                       count >> BDRV_SECTOR_BITS);
+-    gettimeofday(&t2, NULL);
+-
+-    if (ret < 0) {
+-        printf("discard failed: %s\n", strerror(-ret));
+-        goto out;
+-    }
+-
+-    /* Finally, report back -- -C gives a parsable format */
+-    if (!qflag) {
+-        t2 = tsub(t2, t1);
+-        print_report("discard", &t2, offset, count, count, 1, Cflag);
+-    }
+-
+-out:
+-    return 0;
+-}
+-
+-static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    int64_t offset, sector_num;
+-    int nb_sectors, remaining;
+-    char s1[64];
+-    int num, sum_alloc;
+-    int ret;
+-
+-    offset = cvtnum(argv[1]);
+-    if (offset < 0) {
+-        printf("non-numeric offset argument -- %s\n", argv[1]);
+-        return 0;
+-    } else if (offset & 0x1ff) {
+-        printf("offset %" PRId64 " is not sector aligned\n",
+-               offset);
+-        return 0;
+-    }
+-
+-    if (argc == 3) {
+-        nb_sectors = cvtnum(argv[2]);
+-        if (nb_sectors < 0) {
+-            printf("non-numeric length argument -- %s\n", argv[2]);
+-            return 0;
+-        }
+-    } else {
+-        nb_sectors = 1;
+-    }
+-
+-    remaining = nb_sectors;
+-    sum_alloc = 0;
+-    sector_num = offset >> 9;
+-    while (remaining) {
+-        ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
+-        if (ret < 0) {
+-            printf("is_allocated failed: %s\n", strerror(-ret));
+-            return 0;
+-        }
+-        sector_num += num;
+-        remaining -= num;
+-        if (ret) {
+-            sum_alloc += num;
+-        }
+-        if (num == 0) {
+-            nb_sectors -= remaining;
+-            remaining = 0;
+-        }
+-    }
+-
+-    cvtstr(offset, s1, sizeof(s1));
+-
+-    printf("%d/%d sectors allocated at offset %s\n",
+-           sum_alloc, nb_sectors, s1);
+-    return 0;
+-}
+-
+-static const cmdinfo_t alloc_cmd = {
+-    .name       = "alloc",
+-    .altname    = "a",
+-    .argmin     = 1,
+-    .argmax     = 2,
+-    .cfunc      = alloc_f,
+-    .args       = "off [sectors]",
+-    .oneline    = "checks if a sector is present in the file",
+-};
+-
+-static int map_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    int64_t offset;
+-    int64_t nb_sectors;
+-    char s1[64];
+-    int num, num_checked;
+-    int ret;
+-    const char *retstr;
+-
+-    offset = 0;
+-    nb_sectors = bs->total_sectors;
+-
+-    do {
+-        num_checked = MIN(nb_sectors, INT_MAX);
+-        ret = bdrv_is_allocated(bs, offset, num_checked, &num);
+-        retstr = ret ? "    allocated" : "not allocated";
+-        cvtstr(offset << 9ULL, s1, sizeof(s1));
+-        printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
+-               offset << 9ULL, num, num_checked, retstr, s1, ret);
+-
+-        offset += num;
+-        nb_sectors -= num;
+-    } while (offset < bs->total_sectors);
+-
+-    return 0;
+-}
+-
+-static const cmdinfo_t map_cmd = {
+-       .name           = "map",
+-       .argmin         = 0,
+-       .argmax         = 0,
+-       .cfunc          = map_f,
+-       .args           = "",
+-       .oneline        = "prints the allocated areas of a file",
+-};
+-
+-static int break_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    int ret;
+-
+-    ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
+-    if (ret < 0) {
+-        printf("Could not set breakpoint: %s\n", strerror(-ret));
+-    }
+-
+-    return 0;
+-}
+-
+-static const cmdinfo_t break_cmd = {
+-       .name           = "break",
+-       .argmin         = 2,
+-       .argmax         = 2,
+-       .cfunc          = break_f,
+-       .args           = "event tag",
+-       .oneline        = "sets a breakpoint on event and tags the stopped "
+-                         "request as tag",
+-};
+-
+-static int resume_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    int ret;
+-
+-    ret = bdrv_debug_resume(bs, argv[1]);
+-    if (ret < 0) {
+-        printf("Could not resume request: %s\n", strerror(-ret));
+-    }
+-
+-    return 0;
+-}
+-
+-static const cmdinfo_t resume_cmd = {
+-       .name           = "resume",
+-       .argmin         = 1,
+-       .argmax         = 1,
+-       .cfunc          = resume_f,
+-       .args           = "tag",
+-       .oneline        = "resumes the request tagged as tag",
+-};
+-
+-static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    while (!bdrv_debug_is_suspended(bs, argv[1])) {
+-        qemu_aio_wait();
+-    }
+-
+-    return 0;
+-}
+-
+-static const cmdinfo_t wait_break_cmd = {
+-       .name           = "wait_break",
+-       .argmin         = 1,
+-       .argmax         = 1,
+-       .cfunc          = wait_break_f,
+-       .args           = "tag",
+-       .oneline        = "waits for the suspension of a request",
+-};
+-
+-static int abort_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    abort();
+-}
+-
+-static const cmdinfo_t abort_cmd = {
+-       .name           = "abort",
+-       .cfunc          = abort_f,
+-       .flags          = CMD_NOFILE_OK,
+-       .oneline        = "simulate a program crash using abort(3)",
+-};
++extern int qemuio_misalign;
+ 
+ static int close_f(BlockDriverState *bs, int argc, char **argv)
+ {
+@@ -1801,45 +48,6 @@ static const cmdinfo_t close_cmd = {
+     .oneline    = "close the current open file",
+ };
+ 
+-static void sleep_cb(void *opaque)
+-{
+-    bool *expired = opaque;
+-    *expired = true;
+-}
+-
+-static int sleep_f(BlockDriverState *bs, int argc, char **argv)
+-{
+-    char *endptr;
+-    long ms;
+-    struct QEMUTimer *timer;
+-    bool expired = false;
+-
+-    ms = strtol(argv[1], &endptr, 0);
+-    if (ms < 0 || *endptr != '\0') {
+-        printf("%s is not a valid number\n", argv[1]);
+-        return 0;
+-    }
+-
+-    timer = qemu_new_timer_ns(host_clock, sleep_cb, &expired);
+-    qemu_mod_timer(timer, qemu_get_clock_ns(host_clock) + SCALE_MS * ms);
+-
+-    while (!expired) {
+-        main_loop_wait(false);
+-    }
+-
+-    qemu_free_timer(timer);
+-
+-    return 0;
+-}
+-
+-static const cmdinfo_t sleep_cmd = {
+-       .name           = "sleep",
+-       .argmin         = 1,
+-       .argmax         = 1,
+-       .cfunc          = sleep_f,
+-       .flags          = CMD_NOFILE_OK,
+-       .oneline        = "waits for the given value in milliseconds",
+-};
+ 
+ static int openfile(char *name, int flags, int growable, QDict *opts)
+ {
+@@ -1962,18 +170,6 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
+     return openfile(argv[optind], flags, growable, opts);
+ }
+ 
+-static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
+-{
+-    if (ct->flags & CMD_FLAG_GLOBAL) {
+-        return 1;
+-    }
+-    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
+-        fprintf(stderr, "no file open, try 'help open'\n");
+-        return 0;
+-    }
+-    return 1;
+-}
+-
+ static void usage(const char *name)
+ {
+     printf(
+@@ -2049,7 +245,7 @@ int main(int argc, char **argv)
+             readonly = 1;
+             break;
+         case 'm':
+-            misalign = 1;
++            qemuio_misalign = 1;
+             break;
+         case 'g':
+             growable = 1;
+@@ -2090,31 +286,8 @@ int main(int argc, char **argv)
+ 
+     /* initialize commands */
+     quit_init();
+-    help_init();
+     add_command(&open_cmd);
+     add_command(&close_cmd);
+-    add_command(&read_cmd);
+-    add_command(&readv_cmd);
+-    add_command(&write_cmd);
+-    add_command(&writev_cmd);
+-    add_command(&multiwrite_cmd);
+-    add_command(&aio_read_cmd);
+-    add_command(&aio_write_cmd);
+-    add_command(&aio_flush_cmd);
+-    add_command(&flush_cmd);
+-    add_command(&truncate_cmd);
+-    add_command(&length_cmd);
+-    add_command(&info_cmd);
+-    add_command(&discard_cmd);
+-    add_command(&alloc_cmd);
+-    add_command(&map_cmd);
+-    add_command(&break_cmd);
+-    add_command(&resume_cmd);
+-    add_command(&wait_break_cmd);
+-    add_command(&abort_cmd);
+-    add_command(&sleep_cmd);
+-
+-    add_check_command(init_check_command);
+ 
+     /* open the device */
+     if (!readonly) {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-Use-the-qemu-version-for-V.patch b/SOURCES/kvm-qemu-io-Use-the-qemu-version-for-V.patch
new file mode 100644
index 0000000..a2622d6
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-Use-the-qemu-version-for-V.patch
@@ -0,0 +1,54 @@
+From 883449501b5d87002bb01c2a060cf650acf45d9a Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:34 +0100
+Subject: [PATCH 15/27] qemu-io: Use the qemu version for -V
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-16-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68442
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 15/21] qemu-io: Use the qemu version for -V
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+From: Kevin Wolf <kwolf@redhat.com>
+
+Always printing 0.0.1 and never updating the version number wasn't very
+useful. qemu-io is released with qemu, so using the same version number
+makes most sense.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 02da386a2d7a020e80b0aed64769efa9dd42072a)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qemu-io.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/qemu-io.c b/qemu-io.c
+index e685808..16b2d8a 100644
+--- a/qemu-io.c
++++ b/qemu-io.c
+@@ -23,8 +23,6 @@
+ #include "trace/control.h"
+ #include "qemu/timer.h"
+ 
+-#define VERSION	"0.0.1"
+-
+ #define CMD_NOFILE_OK   0x01
+ 
+ char *progname;
+@@ -418,7 +416,7 @@ int main(int argc, char **argv)
+             }
+             break;
+         case 'V':
+-            printf("%s version %s\n", progname, VERSION);
++            printf("%s version %s\n", progname, QEMU_VERSION);
+             exit(0);
+         case 'h':
+             usage(progname);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qemu-io-fix-cvtnum-lval-types.patch b/SOURCES/kvm-qemu-io-fix-cvtnum-lval-types.patch
new file mode 100644
index 0000000..9372946
--- /dev/null
+++ b/SOURCES/kvm-qemu-io-fix-cvtnum-lval-types.patch
@@ -0,0 +1,360 @@
+From a5226789eaaedf06f50f2faf14b506c17deb5435 Mon Sep 17 00:00:00 2001
+From: John Snow <jsnow@redhat.com>
+Date: Mon, 23 Nov 2015 17:38:37 +0100
+Subject: [PATCH 18/27] qemu-io: fix cvtnum lval types
+
+RH-Author: John Snow <jsnow@redhat.com>
+Message-id: <1448300320-7772-19-git-send-email-jsnow@redhat.com>
+Patchwork-id: 68445
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 18/21] qemu-io: fix cvtnum lval types
+Bugzilla: 1272523
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+
+cvtnum() returns int64_t: we should not be storing this
+result inside of an int.
+
+In a few cases, we need an extra sprinkling of error handling
+where we expect to pass this number on towards a function that
+expects something smaller than int64_t.
+
+Reported-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 9b0beaf3de1396a23d5c287283e6f36c4b5d4385)
+Signed-off-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+  qemu-io-cmds.c:
+    - Upstream uses blk_xxx commands, while downstream uses bdrv_xxx
+    - Fixes to sigraise are not backported.
+
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ qemu-io-cmds.c | 119 ++++++++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 84 insertions(+), 35 deletions(-)
+
+diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
+index 1f21ce9..95345fe 100644
+--- a/qemu-io-cmds.c
++++ b/qemu-io-cmds.c
+@@ -282,9 +282,10 @@ static void qemu_io_free(void *p)
+     qemu_vfree(p);
+ }
+ 
+-static void dump_buffer(const void *buffer, int64_t offset, int len)
++static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
+ {
+-    int i, j;
++    uint64_t i;
++    int j;
+     const uint8_t *p;
+ 
+     for (i = 0, p = buffer; i < len; i += 16) {
+@@ -307,7 +308,7 @@ static void dump_buffer(const void *buffer, int64_t offset, int len)
+ }
+ 
+ static void print_report(const char *op, struct timeval *t, int64_t offset,
+-                         int count, int total, int cnt, int Cflag)
++                         int64_t count, int64_t total, int cnt, int Cflag)
+ {
+     char s1[64], s2[64], ts[64];
+ 
+@@ -315,12 +316,12 @@ static void print_report(const char *op, struct timeval *t, int64_t offset,
+     if (!Cflag) {
+         cvtstr((double)total, s1, sizeof(s1));
+         cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
+-        printf("%s %d/%d bytes at offset %" PRId64 "\n",
++        printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n",
+                op, total, count, offset);
+         printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
+                s1, cnt, ts, s2, tdiv((double)cnt, *t));
+     } else {/* bytes,ops,time,bytes/sec,ops/sec */
+-        printf("%d,%d,%s,%.3f,%.3f\n",
++        printf("%"PRId64",%d,%s,%.3f,%.3f\n",
+             total, cnt, ts,
+             tdiv((double)total, *t),
+             tdiv((double)cnt, *t));
+@@ -381,11 +382,15 @@ fail:
+     return buf;
+ }
+ 
+-static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
+-                   int *total)
++static int do_read(BlockDriverState *bs, char *buf, int64_t offset,
++                   int64_t count, int64_t *total)
+ {
+     int ret;
+ 
++    if (count >> 9 > INT_MAX) {
++        return -ERANGE;
++    }
++
+     ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+     if (ret < 0) {
+         return ret;
+@@ -394,11 +399,15 @@ static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
+     return 1;
+ }
+ 
+-static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
+-                    int *total)
++static int do_write(BlockDriverState *bs, char *buf, int64_t offset,
++                    int64_t count, int64_t *total)
+ {
+     int ret;
+ 
++    if (count >> 9 > INT_MAX) {
++        return -ERANGE;
++    }
++
+     ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+     if (ret < 0) {
+         return ret;
+@@ -407,9 +416,13 @@ static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
+     return 1;
+ }
+ 
+-static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
+-                    int *total)
++static int do_pread(BlockDriverState *bs, char *buf, int64_t offset,
++                    int64_t count, int64_t *total)
+ {
++    if (count > INT_MAX) {
++        return -ERANGE;
++    }
++
+     *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
+     if (*total < 0) {
+         return *total;
+@@ -417,9 +430,13 @@ static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
+     return 1;
+ }
+ 
+-static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
+-                     int *total)
++static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset,
++                     int64_t count, int64_t *total)
+ {
++    if (count > INT_MAX) {
++        return -ERANGE;
++    }
++
+     *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
+     if (*total < 0) {
+         return *total;
+@@ -430,8 +447,8 @@ static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
+ typedef struct {
+     BlockDriverState *bs;
+     int64_t offset;
+-    int count;
+-    int *total;
++    int64_t count;
++    int64_t *total;
+     int ret;
+     bool done;
+ } CoWriteZeroes;
+@@ -451,8 +468,8 @@ static void coroutine_fn co_write_zeroes_entry(void *opaque)
+     *data->total = data->count;
+ }
+ 
+-static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
+-                              int *total)
++static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset,
++                              int64_t count, int64_t *total)
+ {
+     Coroutine *co;
+     CoWriteZeroes data = {
+@@ -463,6 +480,10 @@ static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
+         .done   = false,
+     };
+ 
++    if (count >> BDRV_SECTOR_BITS > INT_MAX) {
++        return -ERANGE;
++    }
++
+     co = qemu_coroutine_create(co_write_zeroes_entry);
+     qemu_coroutine_enter(co, &data);
+     while (!data.done) {
+@@ -476,10 +497,14 @@ static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
+ }
+ 
+ static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
+-                               int count, int *total)
++                               int64_t count, int64_t *total)
+ {
+     int ret;
+ 
++    if (count >> 9 > INT_MAX) {
++        return -ERANGE;
++    }
++
+     ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
+     if (ret < 0) {
+         return ret;
+@@ -489,8 +514,12 @@ static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
+ }
+ 
+ static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+-                           int count, int *total)
++                           int64_t count, int64_t *total)
+ {
++    if (count > INT_MAX) {
++        return -ERANGE;
++    }
++
+     *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
+     if (*total < 0) {
+         return *total;
+@@ -499,8 +528,12 @@ static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+ }
+ 
+ static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
+-                           int count, int *total)
++                           int64_t count, int64_t *total)
+ {
++    if (count > INT_MAX) {
++        return -ERANGE;
++    }
++
+     *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
+     if (*total < 0) {
+         return *total;
+@@ -630,10 +663,11 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+     int c, cnt;
+     char *buf;
+     int64_t offset;
+-    int count;
++    int64_t count;
+     /* Some compilers get confused and warn if this is not initialized.  */
+-    int total = 0;
+-    int pattern = 0, pattern_offset = 0, pattern_count = 0;
++    int64_t total = 0;
++    int pattern = 0;
++    int64_t pattern_offset = 0, pattern_count = 0;
+ 
+     while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
+         switch (c) {
+@@ -700,6 +734,10 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+     if (count < 0) {
+         printf("non-numeric length argument -- %s\n", argv[optind]);
+         return 0;
++    } else if (count > SIZE_MAX) {
++        printf("length cannot exceed %" PRIu64 ", given %s\n",
++               (uint64_t) SIZE_MAX, argv[optind]);
++        return 0;
+     }
+ 
+     if (!Pflag && (lflag || sflag)) {
+@@ -722,7 +760,7 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+             return 0;
+         }
+         if (count & 0x1ff) {
+-            printf("count %d is not sector aligned\n",
++            printf("count %"PRId64" is not sector aligned\n",
+                    count);
+             return 0;
+         }
+@@ -750,7 +788,7 @@ static int read_f(BlockDriverState *bs, int argc, char **argv)
+         memset(cmp_buf, pattern, pattern_count);
+         if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
+             printf("Pattern verification failed at offset %"
+-                   PRId64 ", %d bytes\n",
++                   PRId64 ", %"PRId64" bytes\n",
+                    offset + pattern_offset, pattern_count);
+         }
+         g_free(cmp_buf);
+@@ -945,9 +983,9 @@ static int write_f(BlockDriverState *bs, int argc, char **argv)
+     int c, cnt;
+     char *buf = NULL;
+     int64_t offset;
+-    int count;
++    int64_t count;
+     /* Some compilers get confused and warn if this is not initialized.  */
+-    int total = 0;
++    int64_t total = 0;
+     int pattern = 0xcd;
+ 
+     while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
+@@ -1007,6 +1045,10 @@ static int write_f(BlockDriverState *bs, int argc, char **argv)
+     if (count < 0) {
+         printf("non-numeric length argument -- %s\n", argv[optind]);
+         return 0;
++    } else if (count > SIZE_MAX) {
++        printf("length cannot exceed %" PRIu64 ", given %s\n",
++               (uint64_t) SIZE_MAX, argv[optind]);
++        return 0;
+     }
+ 
+     if (!pflag) {
+@@ -1017,7 +1059,7 @@ static int write_f(BlockDriverState *bs, int argc, char **argv)
+         }
+ 
+         if (count & 0x1ff) {
+-            printf("count %d is not sector aligned\n",
++            printf("count %"PRId64" is not sector aligned\n",
+                    count);
+             return 0;
+         }
+@@ -1752,8 +1794,7 @@ static int discard_f(BlockDriverState *bs, int argc, char **argv)
+     struct timeval t1, t2;
+     int Cflag = 0, qflag = 0;
+     int c, ret;
+-    int64_t offset;
+-    int count;
++    int64_t offset, count;
+ 
+     while ((c = getopt(argc, argv, "Cq")) != EOF) {
+         switch (c) {
+@@ -1783,6 +1824,11 @@ static int discard_f(BlockDriverState *bs, int argc, char **argv)
+     if (count < 0) {
+         printf("non-numeric length argument -- %s\n", argv[optind]);
+         return 0;
++    } else if (count >> BDRV_SECTOR_BITS > INT_MAX) {
++        printf("length cannot exceed %"PRIu64", given %s\n",
++               (uint64_t)INT_MAX << BDRV_SECTOR_BITS,
++               argv[optind]);
++        return 0;
+     }
+ 
+     gettimeofday(&t1, NULL);
+@@ -1807,11 +1853,10 @@ out:
+ 
+ static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+ {
+-    int64_t offset, sector_num;
+-    int nb_sectors, remaining;
++    int64_t offset, sector_num, nb_sectors, remaining;
+     char s1[64];
+-    int num, sum_alloc;
+-    int ret;
++    int num, ret;
++    int64_t sum_alloc;
+ 
+     offset = cvtnum(argv[1]);
+     if (offset < 0) {
+@@ -1828,6 +1873,10 @@ static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+         if (nb_sectors < 0) {
+             printf("non-numeric length argument -- %s\n", argv[2]);
+             return 0;
++        } else if (nb_sectors > INT_MAX) {
++            printf("length argument cannot exceed %d, given %s\n",
++                   INT_MAX, argv[2]);
++            return 0;
+         }
+     } else {
+         nb_sectors = 1;
+@@ -1855,7 +1904,7 @@ static int alloc_f(BlockDriverState *bs, int argc, char **argv)
+ 
+     cvtstr(offset, s1, sizeof(s1));
+ 
+-    printf("%d/%d sectors allocated at offset %s\n",
++    printf("%"PRId64"/%"PRId64" sectors allocated at offset %s\n",
+            sum_alloc, nb_sectors, s1);
+     return 0;
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-Apply-nesting-limit-more-sanely.patch b/SOURCES/kvm-qjson-Apply-nesting-limit-more-sanely.patch
new file mode 100644
index 0000000..061218c
--- /dev/null
+++ b/SOURCES/kvm-qjson-Apply-nesting-limit-more-sanely.patch
@@ -0,0 +1,46 @@
+From 1f08301adf98c235ccc4e978f809c3f60833452c Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:00 +0200
+Subject: [PATCH 02/16] qjson: Apply nesting limit more sanely
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-4-git-send-email-armbru@redhat.com>
+Patchwork-id: 71468
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 02/15] qjson: Apply nesting limit more sanely
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+The nesting limit from commit 29c75dd "json-streamer: limit the
+maximum recursion depth and maximum token count" applies separately to
+braces and brackets.  This makes no sense.  Apply it to their sum,
+because that's actually a measure of recursion depth.
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Message-Id: <1448486613-17634-2-git-send-email-armbru@redhat.com>
+(cherry picked from commit 4f2d31fbc0bfdf41feea7d1be49f4f7ffa005534)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qobject/json-streamer.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index 1b2f9b1..dced2c7 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -64,8 +64,7 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
+          parser->bracket_count == 0)) {
+         goto out_emit;
+     } else if (parser->token_size > MAX_TOKEN_SIZE ||
+-               parser->bracket_count > MAX_NESTING ||
+-               parser->brace_count > MAX_NESTING) {
++               parser->bracket_count + parser->brace_count > MAX_NESTING) {
+         /* Security consideration, we limit total memory allocated per object
+          * and the maximum recursion depth that a message can force.
+          */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-Convert-to-parser-to-recursive-descent.patch b/SOURCES/kvm-qjson-Convert-to-parser-to-recursive-descent.patch
new file mode 100644
index 0000000..2da74a2
--- /dev/null
+++ b/SOURCES/kvm-qjson-Convert-to-parser-to-recursive-descent.patch
@@ -0,0 +1,328 @@
+From 2975abb487a54b49246646db9aa40ee6d1beaa97 Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:08 +0200
+Subject: [PATCH 10/16] qjson: Convert to parser to recursive descent
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-12-git-send-email-armbru@redhat.com>
+Patchwork-id: 71474
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 10/15] qjson: Convert to parser to recursive descent
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+We backtrack in parse_value(), even though JSON is LL(1) and thus can
+be parsed by straightforward recursive descent.  Do exactly that.
+
+Based on an almost-correct patch from Paolo Bonzini.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Message-Id: <1448486613-17634-10-git-send-email-armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit d538b25543f4db026bb435066e2403a542522c40)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	qobject/json-parser.c
+
+Straighforward conflicts because lacking commit fc48ffc "qobject: Use
+'bool' for qbool", we still use qbool_from_int(), and we lack commit
+e549e71 "json-parser: Accept 'null' in QMP".
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+---
+ qobject/json-parser.c | 163 ++++++++++++++------------------------------------
+ 1 file changed, 46 insertions(+), 117 deletions(-)
+
+diff --git a/qobject/json-parser.c b/qobject/json-parser.c
+index 79f4173..b242fba 100644
+--- a/qobject/json-parser.c
++++ b/qobject/json-parser.c
+@@ -266,23 +266,6 @@ static QObject *parser_context_peek_token(JSONParserContext *ctxt)
+     return token;
+ }
+ 
+-static JSONParserContext parser_context_save(JSONParserContext *ctxt)
+-{
+-    JSONParserContext saved_ctxt = {0};
+-    saved_ctxt.tokens.pos = ctxt->tokens.pos;
+-    saved_ctxt.tokens.count = ctxt->tokens.count;
+-    saved_ctxt.tokens.buf = ctxt->tokens.buf;
+-    return saved_ctxt;
+-}
+-
+-static void parser_context_restore(JSONParserContext *ctxt,
+-                                   JSONParserContext saved_ctxt)
+-{
+-    ctxt->tokens.pos = saved_ctxt.tokens.pos;
+-    ctxt->tokens.count = saved_ctxt.tokens.count;
+-    ctxt->tokens.buf = saved_ctxt.tokens.buf;
+-}
+-
+ static void tokens_append_from_iter(QObject *obj, void *opaque)
+ {
+     JSONParserContext *ctxt = opaque;
+@@ -334,7 +317,6 @@ static void parser_context_free(JSONParserContext *ctxt)
+ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
+ {
+     QObject *key = NULL, *token = NULL, *value, *peek;
+-    JSONParserContext saved_ctxt = parser_context_save(ctxt);
+ 
+     peek = parser_context_peek_token(ctxt);
+     if (peek == NULL) {
+@@ -372,7 +354,6 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
+     return 0;
+ 
+ out:
+-    parser_context_restore(ctxt, saved_ctxt);
+     qobject_decref(key);
+ 
+     return -1;
+@@ -382,16 +363,9 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+ {
+     QDict *dict = NULL;
+     QObject *token, *peek;
+-    JSONParserContext saved_ctxt = parser_context_save(ctxt);
+ 
+     token = parser_context_pop_token(ctxt);
+-    if (token == NULL) {
+-        goto out;
+-    }
+-
+-    if (token_get_type(token) != JSON_LCURLY) {
+-        goto out;
+-    }
++    assert(token && token_get_type(token) == JSON_LCURLY);
+ 
+     dict = qdict_new();
+ 
+@@ -435,7 +409,6 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+     return QOBJECT(dict);
+ 
+ out:
+-    parser_context_restore(ctxt, saved_ctxt);
+     QDECREF(dict);
+     return NULL;
+ }
+@@ -444,16 +417,9 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+ {
+     QList *list = NULL;
+     QObject *token, *peek;
+-    JSONParserContext saved_ctxt = parser_context_save(ctxt);
+ 
+     token = parser_context_pop_token(ctxt);
+-    if (token == NULL) {
+-        goto out;
+-    }
+-
+-    if (token_get_type(token) != JSON_LSQUARE) {
+-        goto out;
+-    }
++    assert(token && token_get_type(token) == JSON_LSQUARE);
+ 
+     list = qlist_new();
+ 
+@@ -507,107 +473,70 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+     return QOBJECT(list);
+ 
+ out:
+-    parser_context_restore(ctxt, saved_ctxt);
+     QDECREF(list);
+     return NULL;
+ }
+ 
+ static QObject *parse_keyword(JSONParserContext *ctxt)
+ {
+-    QObject *token, *ret;
+-    JSONParserContext saved_ctxt = parser_context_save(ctxt);
++    QObject *token;
+     const char *val;
+ 
+     token = parser_context_pop_token(ctxt);
+-    if (token == NULL) {
+-        goto out;
+-    }
+-
+-    if (token_get_type(token) != JSON_KEYWORD) {
+-        goto out;
+-    }
+-
++    assert(token && token_get_type(token) == JSON_KEYWORD);
+     val = token_get_value(token);
+ 
+     if (!strcmp(val, "true")) {
+-        ret = QOBJECT(qbool_from_int(true));
++        return QOBJECT(qbool_from_int(true));
+     } else if (!strcmp(val, "false")) {
+-        ret = QOBJECT(qbool_from_int(false));
+-    } else {
+-        parse_error(ctxt, token, "invalid keyword '%s'", val);
+-        goto out;
++        return QOBJECT(qbool_from_int(false));
+     }
+-
+-    return ret;
+-
+-out: 
+-    parser_context_restore(ctxt, saved_ctxt);
+-
++    parse_error(ctxt, token, "invalid keyword '%s'", val);
+     return NULL;
+ }
+ 
+ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
+ {
+-    QObject *token = NULL, *obj;
+-    JSONParserContext saved_ctxt = parser_context_save(ctxt);
++    QObject *token;
+     const char *val;
+ 
+     if (ap == NULL) {
+-        goto out;
++        return NULL;
+     }
+ 
+     token = parser_context_pop_token(ctxt);
+-    if (token == NULL) {
+-        goto out;
+-    }
+-
+-    if (token_get_type(token) != JSON_ESCAPE) {
+-        goto out;
+-    }
+-
++    assert(token && token_get_type(token) == JSON_ESCAPE);
+     val = token_get_value(token);
+ 
+     if (!strcmp(val, "%p")) {
+-        obj = va_arg(*ap, QObject *);
++        return va_arg(*ap, QObject *);
+     } else if (!strcmp(val, "%i")) {
+-        obj = QOBJECT(qbool_from_int(va_arg(*ap, int)));
++        return QOBJECT(qbool_from_int(va_arg(*ap, int)));
+     } else if (!strcmp(val, "%d")) {
+-        obj = QOBJECT(qint_from_int(va_arg(*ap, int)));
++        return QOBJECT(qint_from_int(va_arg(*ap, int)));
+     } else if (!strcmp(val, "%ld")) {
+-        obj = QOBJECT(qint_from_int(va_arg(*ap, long)));
++        return QOBJECT(qint_from_int(va_arg(*ap, long)));
+     } else if (!strcmp(val, "%lld") ||
+                !strcmp(val, "%I64d")) {
+-        obj = QOBJECT(qint_from_int(va_arg(*ap, long long)));
++        return QOBJECT(qint_from_int(va_arg(*ap, long long)));
+     } else if (!strcmp(val, "%s")) {
+-        obj = QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
++        return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
+     } else if (!strcmp(val, "%f")) {
+-        obj = QOBJECT(qfloat_from_double(va_arg(*ap, double)));
+-    } else {
+-        goto out;
++        return QOBJECT(qfloat_from_double(va_arg(*ap, double)));
+     }
+-
+-    return obj;
+-
+-out:
+-    parser_context_restore(ctxt, saved_ctxt);
+-
+     return NULL;
+ }
+ 
+ static QObject *parse_literal(JSONParserContext *ctxt)
+ {
+-    QObject *token, *obj;
+-    JSONParserContext saved_ctxt = parser_context_save(ctxt);
++    QObject *token;
+ 
+     token = parser_context_pop_token(ctxt);
+-    if (token == NULL) {
+-        goto out;
+-    }
++    assert(token);
+ 
+     switch (token_get_type(token)) {
+     case JSON_STRING:
+-        obj = QOBJECT(qstring_from_escaped_str(ctxt, token));
+-        break;
++        return QOBJECT(qstring_from_escaped_str(ctxt, token));
+     case JSON_INTEGER: {
+         /* A possibility exists that this is a whole-valued float where the
+          * fractional part was left out due to being 0 (.0). It's not a big
+@@ -626,46 +555,46 @@ static QObject *parse_literal(JSONParserContext *ctxt)
+         errno = 0; /* strtoll doesn't set errno on success */
+         value = strtoll(token_get_value(token), NULL, 10);
+         if (errno != ERANGE) {
+-            obj = QOBJECT(qint_from_int(value));
+-            break;
++            return QOBJECT(qint_from_int(value));
+         }
+         /* fall through to JSON_FLOAT */
+     }
+     case JSON_FLOAT:
+         /* FIXME dependent on locale */
+-        obj = QOBJECT(qfloat_from_double(strtod(token_get_value(token), NULL)));
+-        break;
++        return QOBJECT(qfloat_from_double(strtod(token_get_value(token),
++                                                 NULL)));
+     default:
+-        goto out;
++        abort();
+     }
+-
+-    return obj;
+-
+-out:
+-    parser_context_restore(ctxt, saved_ctxt);
+-
+-    return NULL;
+ }
+ 
+ static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
+ {
+-    QObject *obj;
++    QObject *token;
+ 
+-    obj = parse_object(ctxt, ap);
+-    if (obj == NULL) {
+-        obj = parse_array(ctxt, ap);
+-    }
+-    if (obj == NULL) {
+-        obj = parse_escape(ctxt, ap);
+-    }
+-    if (obj == NULL) {
+-        obj = parse_keyword(ctxt);
+-    } 
+-    if (obj == NULL) {
+-        obj = parse_literal(ctxt);
++    token = parser_context_peek_token(ctxt);
++    if (token == NULL) {
++        parse_error(ctxt, NULL, "premature EOI");
++        return NULL;
+     }
+ 
+-    return obj;
++    switch (token_get_type(token)) {
++    case JSON_LCURLY:
++        return parse_object(ctxt, ap);
++    case JSON_LSQUARE:
++        return parse_array(ctxt, ap);
++    case JSON_ESCAPE:
++        return parse_escape(ctxt, ap);
++    case JSON_INTEGER:
++    case JSON_FLOAT:
++    case JSON_STRING:
++        return parse_literal(ctxt);
++    case JSON_KEYWORD:
++        return parse_keyword(ctxt);
++    default:
++        parse_error(ctxt, token, "expecting value");
++        return NULL;
++    }
+ }
+ 
+ QObject *json_parser_parse(QList *tokens, va_list *ap)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-Don-t-crash-when-input-exceeds-nesting-limit.patch b/SOURCES/kvm-qjson-Don-t-crash-when-input-exceeds-nesting-limit.patch
new file mode 100644
index 0000000..e8ac2fa
--- /dev/null
+++ b/SOURCES/kvm-qjson-Don-t-crash-when-input-exceeds-nesting-limit.patch
@@ -0,0 +1,62 @@
+From ba9229d280e035872ac2258873c1b9f34cc8c4a9 Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:01 +0200
+Subject: [PATCH 03/16] qjson: Don't crash when input exceeds nesting limit
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-5-git-send-email-armbru@redhat.com>
+Patchwork-id: 71472
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 03/15] qjson: Don't crash when input exceeds nesting limit
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+We limit nesting depth and input size to defend against input
+triggering excessive heap or stack memory use (commit 29c75dd
+json-streamer: limit the maximum recursion depth and maximum token
+count).  However, when the nesting limit is exceeded,
+parser_context_peek_token()'s assertion fails.
+
+Broken in commit 65c0f1e "json-parser: don't replicate tokens at each
+level of recursion".
+
+To reproduce stuff 1025 open braces or brackets into QMP.
+
+Fix by taking the error exit instead of the normal one.
+
+Reported-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Message-Id: <1448486613-17634-3-git-send-email-armbru@redhat.com>
+(cherry picked from commit 0753113a26bb8c77f951b1ea91fd4f36d099c37a)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qobject/json-streamer.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index dced2c7..2bd22a7 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -68,13 +68,14 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
+         /* Security consideration, we limit total memory allocated per object
+          * and the maximum recursion depth that a message can force.
+          */
+-        goto out_emit;
++        goto out_emit_bad;
+     }
+ 
+     return;
+ 
+ out_emit_bad:
+-    /* clear out token list and tell the parser to emit and error
++    /*
++     * Clear out token list and tell the parser to emit an error
+      * indication by passing it a NULL list
+      */
+     QDECREF(parser->tokens);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-Give-each-of-the-six-structural-chars-its-own-.patch b/SOURCES/kvm-qjson-Give-each-of-the-six-structural-chars-its-own-.patch
new file mode 100644
index 0000000..a007310
--- /dev/null
+++ b/SOURCES/kvm-qjson-Give-each-of-the-six-structural-chars-its-own-.patch
@@ -0,0 +1,222 @@
+From 95aeff93da762bf7f69317eb674d3eccce672038 Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:04 +0200
+Subject: [PATCH 06/16] qjson: Give each of the six structural chars its own
+ token type
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-8-git-send-email-armbru@redhat.com>
+Patchwork-id: 71482
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 06/15] qjson: Give each of the six structural chars its own token type
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+Simplifies things, because we always check for a specific one.
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Message-Id: <1448486613-17634-6-git-send-email-armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit c54616608af442edf4cfb7397a1909c2653efba0)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ include/qapi/qmp/json-lexer.h |  7 ++++++-
+ qobject/json-lexer.c          | 19 ++++++++++++-------
+ qobject/json-parser.c         | 31 +++++++++----------------------
+ qobject/json-streamer.c       | 32 +++++++++++++++-----------------
+ 4 files changed, 42 insertions(+), 47 deletions(-)
+
+diff --git a/include/qapi/qmp/json-lexer.h b/include/qapi/qmp/json-lexer.h
+index 61a143f..f3e8dc7 100644
+--- a/include/qapi/qmp/json-lexer.h
++++ b/include/qapi/qmp/json-lexer.h
+@@ -19,7 +19,12 @@
+ 
+ typedef enum json_token_type {
+     JSON_MIN = 100,
+-    JSON_OPERATOR = JSON_MIN,
++    JSON_LCURLY = JSON_MIN,
++    JSON_RCURLY,
++    JSON_LSQUARE,
++    JSON_RSQUARE,
++    JSON_COLON,
++    JSON_COMMA,
+     JSON_INTEGER,
+     JSON_FLOAT,
+     JSON_KEYWORD,
+diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
+index f106ffb..1bfff02 100644
+--- a/qobject/json-lexer.c
++++ b/qobject/json-lexer.c
+@@ -257,12 +257,12 @@ static const uint8_t json_lexer[][256] =  {
+         ['0'] = IN_ZERO,
+         ['1' ... '9'] = IN_NONZERO_NUMBER,
+         ['-'] = IN_NEG_NONZERO_NUMBER,
+-        ['{'] = JSON_OPERATOR,
+-        ['}'] = JSON_OPERATOR,
+-        ['['] = JSON_OPERATOR,
+-        [']'] = JSON_OPERATOR,
+-        [','] = JSON_OPERATOR,
+-        [':'] = JSON_OPERATOR,
++        ['{'] = JSON_LCURLY,
++        ['}'] = JSON_RCURLY,
++        ['['] = JSON_LSQUARE,
++        [']'] = JSON_RSQUARE,
++        [','] = JSON_COMMA,
++        [':'] = JSON_COLON,
+         ['a' ... 'z'] = IN_KEYWORD,
+         ['%'] = IN_ESCAPE,
+         [' '] = IN_WHITESPACE,
+@@ -299,7 +299,12 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
+         }
+ 
+         switch (new_state) {
+-        case JSON_OPERATOR:
++        case JSON_LCURLY:
++        case JSON_RCURLY:
++        case JSON_LSQUARE:
++        case JSON_RSQUARE:
++        case JSON_COLON:
++        case JSON_COMMA:
+         case JSON_ESCAPE:
+         case JSON_INTEGER:
+         case JSON_FLOAT:
+diff --git a/qobject/json-parser.c b/qobject/json-parser.c
+index fa09769..50bf30c 100644
+--- a/qobject/json-parser.c
++++ b/qobject/json-parser.c
+@@ -64,19 +64,6 @@ static JSONTokenType token_get_type(QObject *obj)
+     return qdict_get_int(qobject_to_qdict(obj), "type");
+ }
+ 
+-static int token_is_operator(QObject *obj, char op)
+-{
+-    const char *val;
+-
+-    if (token_get_type(obj) != JSON_OPERATOR) {
+-        return 0;
+-    }
+-
+-    val = token_get_value(obj);
+-
+-    return (val[0] == op) && (val[1] == 0);
+-}
+-
+ static int token_is_keyword(QObject *obj, const char *value)
+ {
+     if (token_get_type(obj) != JSON_KEYWORD) {
+@@ -385,7 +372,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
+         goto out;
+     }
+ 
+-    if (!token_is_operator(token, ':')) {
++    if (token_get_type(token) != JSON_COLON) {
+         parse_error(ctxt, token, "missing : in object pair");
+         goto out;
+     }
+@@ -420,7 +407,7 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+         goto out;
+     }
+ 
+-    if (!token_is_operator(token, '{')) {
++    if (token_get_type(token) != JSON_LCURLY) {
+         goto out;
+     }
+ 
+@@ -432,7 +419,7 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+         goto out;
+     }
+ 
+-    if (!token_is_operator(peek, '}')) {
++    if (token_get_type(peek) != JSON_RCURLY) {
+         if (parse_pair(ctxt, dict, ap) == -1) {
+             goto out;
+         }
+@@ -443,8 +430,8 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+             goto out;
+         }
+ 
+-        while (!token_is_operator(token, '}')) {
+-            if (!token_is_operator(token, ',')) {
++        while (token_get_type(token) != JSON_RCURLY) {
++            if (token_get_type(token) != JSON_COMMA) {
+                 parse_error(ctxt, token, "expected separator in dict");
+                 goto out;
+             }
+@@ -482,7 +469,7 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+         goto out;
+     }
+ 
+-    if (!token_is_operator(token, '[')) {
++    if (token_get_type(token) != JSON_LSQUARE) {
+         goto out;
+     }
+ 
+@@ -494,7 +481,7 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+         goto out;
+     }
+ 
+-    if (!token_is_operator(peek, ']')) {
++    if (token_get_type(peek) != JSON_RSQUARE) {
+         QObject *obj;
+ 
+         obj = parse_value(ctxt, ap);
+@@ -511,8 +498,8 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+             goto out;
+         }
+ 
+-        while (!token_is_operator(token, ']')) {
+-            if (!token_is_operator(token, ',')) {
++        while (token_get_type(token) != JSON_RSQUARE) {
++            if (token_get_type(token) != JSON_COMMA) {
+                 parse_error(ctxt, token, "expected separator in list");
+                 goto out;
+             }
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index 2bd22a7..4a161a1 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -26,23 +26,21 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
+     JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
+     QDict *dict;
+ 
+-    if (type == JSON_OPERATOR) {
+-        switch (qstring_get_str(token)[0]) {
+-        case '{':
+-            parser->brace_count++;
+-            break;
+-        case '}':
+-            parser->brace_count--;
+-            break;
+-        case '[':
+-            parser->bracket_count++;
+-            break;
+-        case ']':
+-            parser->bracket_count--;
+-            break;
+-        default:
+-            break;
+-        }
++    switch (type) {
++    case JSON_LCURLY:
++        parser->brace_count++;
++        break;
++    case JSON_RCURLY:
++        parser->brace_count--;
++        break;
++    case JSON_LSQUARE:
++        parser->bracket_count++;
++        break;
++    case JSON_RSQUARE:
++        parser->bracket_count--;
++        break;
++    default:
++        break;
+     }
+ 
+     dict = qdict_new();
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-Inline-token_is_escape-and-simplify.patch b/SOURCES/kvm-qjson-Inline-token_is_escape-and-simplify.patch
new file mode 100644
index 0000000..8ed2c95
--- /dev/null
+++ b/SOURCES/kvm-qjson-Inline-token_is_escape-and-simplify.patch
@@ -0,0 +1,97 @@
+From 225cb3d48dd4dcbc7bf845c0b4b06a90030874f3 Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:06 +0200
+Subject: [PATCH 08/16] qjson: Inline token_is_escape() and simplify
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-10-git-send-email-armbru@redhat.com>
+Patchwork-id: 71479
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 08/15] qjson: Inline token_is_escape() and simplify
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Message-Id: <1448486613-17634-8-git-send-email-armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 6b9606f68ec589def27bd2a9cea97ec63cffd581)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	qobject/json-parser.c
+
+Straighforward conflict because lacking commit fc48ffc "qobject: Use
+'bool' for qbool", we still use qbool_from_int().
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+---
+ qobject/json-parser.c | 32 +++++++++++++++-----------------
+ 1 file changed, 15 insertions(+), 17 deletions(-)
+
+diff --git a/qobject/json-parser.c b/qobject/json-parser.c
+index e3690de..79f4173 100644
+--- a/qobject/json-parser.c
++++ b/qobject/json-parser.c
+@@ -64,15 +64,6 @@ static JSONTokenType token_get_type(QObject *obj)
+     return qdict_get_int(qobject_to_qdict(obj), "type");
+ }
+ 
+-static int token_is_escape(QObject *obj, const char *value)
+-{
+-    if (token_get_type(obj) != JSON_ESCAPE) {
+-        return 0;
+-    }
+-
+-    return (strcmp(token_get_value(obj), value) == 0);
+-}
+-
+ /**
+  * Error handler
+  */
+@@ -559,6 +550,7 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
+ {
+     QObject *token = NULL, *obj;
+     JSONParserContext saved_ctxt = parser_context_save(ctxt);
++    const char *val;
+ 
+     if (ap == NULL) {
+         goto out;
+@@ -569,20 +561,26 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
+         goto out;
+     }
+ 
+-    if (token_is_escape(token, "%p")) {
++    if (token_get_type(token) != JSON_ESCAPE) {
++        goto out;
++    }
++
++    val = token_get_value(token);
++
++    if (!strcmp(val, "%p")) {
+         obj = va_arg(*ap, QObject *);
+-    } else if (token_is_escape(token, "%i")) {
++    } else if (!strcmp(val, "%i")) {
+         obj = QOBJECT(qbool_from_int(va_arg(*ap, int)));
+-    } else if (token_is_escape(token, "%d")) {
++    } else if (!strcmp(val, "%d")) {
+         obj = QOBJECT(qint_from_int(va_arg(*ap, int)));
+-    } else if (token_is_escape(token, "%ld")) {
++    } else if (!strcmp(val, "%ld")) {
+         obj = QOBJECT(qint_from_int(va_arg(*ap, long)));
+-    } else if (token_is_escape(token, "%lld") ||
+-               token_is_escape(token, "%I64d")) {
++    } else if (!strcmp(val, "%lld") ||
++               !strcmp(val, "%I64d")) {
+         obj = QOBJECT(qint_from_int(va_arg(*ap, long long)));
+-    } else if (token_is_escape(token, "%s")) {
++    } else if (!strcmp(val, "%s")) {
+         obj = QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
+-    } else if (token_is_escape(token, "%f")) {
++    } else if (!strcmp(val, "%f")) {
+         obj = QOBJECT(qfloat_from_double(va_arg(*ap, double)));
+     } else {
+         goto out;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-Inline-token_is_keyword-and-simplify.patch b/SOURCES/kvm-qjson-Inline-token_is_keyword-and-simplify.patch
new file mode 100644
index 0000000..f885b32
--- /dev/null
+++ b/SOURCES/kvm-qjson-Inline-token_is_keyword-and-simplify.patch
@@ -0,0 +1,81 @@
+From 3cf8ec8ff0ad3920ce23166b2576655bcd886c5a Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:05 +0200
+Subject: [PATCH 07/16] qjson: Inline token_is_keyword() and simplify
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-9-git-send-email-armbru@redhat.com>
+Patchwork-id: 71483
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 07/15] qjson: Inline token_is_keyword() and simplify
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Message-Id: <1448486613-17634-7-git-send-email-armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 50e2a467f5315fa36c547fb6330659ba45f6bb83)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	qobject/json-parser.c
+
+Straighforward conflict because lacking commit fc48ffc "qobject: Use
+'bool' for qbool", we still use qbool_from_int(), and we lack commit
+e549e71 "json-parser: Accept 'null' in QMP".
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+---
+ qobject/json-parser.c | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+diff --git a/qobject/json-parser.c b/qobject/json-parser.c
+index 50bf30c..e3690de 100644
+--- a/qobject/json-parser.c
++++ b/qobject/json-parser.c
+@@ -64,15 +64,6 @@ static JSONTokenType token_get_type(QObject *obj)
+     return qdict_get_int(qobject_to_qdict(obj), "type");
+ }
+ 
+-static int token_is_keyword(QObject *obj, const char *value)
+-{
+-    if (token_get_type(obj) != JSON_KEYWORD) {
+-        return 0;
+-    }
+-
+-    return strcmp(token_get_value(obj), value) == 0;
+-}
+-
+ static int token_is_escape(QObject *obj, const char *value)
+ {
+     if (token_get_type(obj) != JSON_ESCAPE) {
+@@ -534,6 +525,7 @@ static QObject *parse_keyword(JSONParserContext *ctxt)
+ {
+     QObject *token, *ret;
+     JSONParserContext saved_ctxt = parser_context_save(ctxt);
++    const char *val;
+ 
+     token = parser_context_pop_token(ctxt);
+     if (token == NULL) {
+@@ -544,12 +536,14 @@ static QObject *parse_keyword(JSONParserContext *ctxt)
+         goto out;
+     }
+ 
+-    if (token_is_keyword(token, "true")) {
++    val = token_get_value(token);
++
++    if (!strcmp(val, "true")) {
+         ret = QOBJECT(qbool_from_int(true));
+-    } else if (token_is_keyword(token, "false")) {
++    } else if (!strcmp(val, "false")) {
+         ret = QOBJECT(qbool_from_int(false));
+     } else {
+-        parse_error(ctxt, token, "invalid keyword `%s'", token_get_value(token));
++        parse_error(ctxt, token, "invalid keyword '%s'", val);
+         goto out;
+     }
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-Limit-number-of-tokens-in-addition-to-total-si.patch b/SOURCES/kvm-qjson-Limit-number-of-tokens-in-addition-to-total-si.patch
new file mode 100644
index 0000000..94ec4c4
--- /dev/null
+++ b/SOURCES/kvm-qjson-Limit-number-of-tokens-in-addition-to-total-si.patch
@@ -0,0 +1,59 @@
+From 60ad1bad25ea99c538b745ff95e6e0a877d37d1f Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:11 +0200
+Subject: [PATCH 13/16] qjson: Limit number of tokens in addition to total size
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-15-git-send-email-armbru@redhat.com>
+Patchwork-id: 71476
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 13/15] qjson: Limit number of tokens in addition to total size
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+Commit 29c75dd "json-streamer: limit the maximum recursion depth and
+maximum token count" attempts to guard against excessive heap usage by
+limiting total token size (it says "token count", but that's a lie).
+
+Total token size is a rather imprecise predictor of heap usage: many
+small tokens use more space than few large tokens with the same input
+size, because there's a constant per-token overhead: 37 bytes on my
+system.
+
+Tighten this up: limit the token count to 2Mi.  Chosen to roughly
+match the 64MiB total token size limit.
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Message-Id: <1448486613-17634-13-git-send-email-armbru@redhat.com>
+(cherry picked from commit df649835fe48f635a93316fdefe96ced7189316e)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qobject/json-streamer.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index e87230d..a4db4b8 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -16,6 +16,7 @@
+ #include "qapi/qmp/json-streamer.h"
+ 
+ #define MAX_TOKEN_SIZE (64ULL << 20)
++#define MAX_TOKEN_COUNT (2ULL << 20)
+ #define MAX_NESTING (1ULL << 10)
+ 
+ static void json_message_free_tokens(JSONMessageParser *parser)
+@@ -68,6 +69,7 @@ static void json_message_process_token(JSONLexer *lexer, GString *input,
+          parser->bracket_count == 0)) {
+         goto out_emit;
+     } else if (parser->token_size > MAX_TOKEN_SIZE ||
++               g_queue_get_length(parser->tokens) > MAX_TOKEN_COUNT ||
+                parser->bracket_count + parser->brace_count > MAX_NESTING) {
+         /* Security consideration, we limit total memory allocated per object
+          * and the maximum recursion depth that a message can force.
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-Spell-out-some-silent-assumptions.patch b/SOURCES/kvm-qjson-Spell-out-some-silent-assumptions.patch
new file mode 100644
index 0000000..6015054
--- /dev/null
+++ b/SOURCES/kvm-qjson-Spell-out-some-silent-assumptions.patch
@@ -0,0 +1,81 @@
+From c4c2e01b3fa861de40f809785a0643d56e2b311e Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:03 +0200
+Subject: [PATCH 05/16] qjson: Spell out some silent assumptions
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-7-git-send-email-armbru@redhat.com>
+Patchwork-id: 71473
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 05/15] qjson: Spell out some silent assumptions
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Message-Id: <1448486613-17634-5-git-send-email-armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit b8d3b1da3cdbb02e180618d6be346c564723015d)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ include/qapi/qmp/json-lexer.h | 3 ++-
+ qobject/json-lexer.c          | 7 ++++++-
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/include/qapi/qmp/json-lexer.h b/include/qapi/qmp/json-lexer.h
+index cdff046..61a143f 100644
+--- a/include/qapi/qmp/json-lexer.h
++++ b/include/qapi/qmp/json-lexer.h
+@@ -18,7 +18,8 @@
+ #include "qapi/qmp/qlist.h"
+ 
+ typedef enum json_token_type {
+-    JSON_OPERATOR = 100,
++    JSON_MIN = 100,
++    JSON_OPERATOR = JSON_MIN,
+     JSON_INTEGER,
+     JSON_FLOAT,
+     JSON_KEYWORD,
+diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
+index 440df60..f106ffb 100644
+--- a/qobject/json-lexer.c
++++ b/qobject/json-lexer.c
+@@ -30,7 +30,7 @@
+  */
+ 
+ enum json_lexer_state {
+-    IN_ERROR = 0,
++    IN_ERROR = 0,               /* must really be 0, see json_lexer[] */
+     IN_DQ_UCODE3,
+     IN_DQ_UCODE2,
+     IN_DQ_UCODE1,
+@@ -62,6 +62,8 @@ enum json_lexer_state {
+     IN_START,
+ };
+ 
++QEMU_BUILD_BUG_ON((int)JSON_MIN <= (int)IN_START);
++
+ #define TERMINAL(state) [0 ... 0x7F] = (state)
+ 
+ /* Return whether TERMINAL is a terminal state and the transition to it
+@@ -71,6 +73,8 @@ enum json_lexer_state {
+             (json_lexer[(old_state)][0] == (terminal))
+ 
+ static const uint8_t json_lexer[][256] =  {
++    /* Relies on default initialization to IN_ERROR! */
++
+     /* double quote string */
+     [IN_DQ_UCODE3] = {
+         ['0' ... '9'] = IN_DQ_STRING,
+@@ -287,6 +291,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
+     }
+ 
+     do {
++        assert(lexer->state <= ARRAY_SIZE(json_lexer));
+         new_state = json_lexer[lexer->state][(uint8_t)ch];
+         char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state);
+         if (char_consumed) {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-replace-QString-in-JSONLexer-with-GString.patch b/SOURCES/kvm-qjson-replace-QString-in-JSONLexer-with-GString.patch
new file mode 100644
index 0000000..02baa00
--- /dev/null
+++ b/SOURCES/kvm-qjson-replace-QString-in-JSONLexer-with-GString.patch
@@ -0,0 +1,195 @@
+From 39da81cf143ccc400263362a5319803063ad14cf Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:07 +0200
+Subject: [PATCH 09/16] qjson: replace QString in JSONLexer with GString
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-11-git-send-email-armbru@redhat.com>
+Patchwork-id: 71480
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 09/15] qjson: replace QString in JSONLexer with GString
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+JSONLexer only needs a simple resizable buffer.  json-streamer.c
+can allocate memory for each token instead of relying on reference
+counting of QStrings.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Message-Id: <1448300659-23559-2-git-send-email-pbonzini@redhat.com>
+[Straightforwardly rebased on my patches, checkpatch made happy]
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit d2ca7c0b0d876cf0e219ae7a92252626b0913a28)
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ include/qapi/qmp/json-lexer.h    |  8 ++++----
+ include/qapi/qmp/json-streamer.h |  1 +
+ qobject/json-lexer.c             | 22 ++++++++--------------
+ qobject/json-streamer.c          |  9 +++++----
+ 4 files changed, 18 insertions(+), 22 deletions(-)
+
+diff --git a/include/qapi/qmp/json-lexer.h b/include/qapi/qmp/json-lexer.h
+index f3e8dc7..cb456d5 100644
+--- a/include/qapi/qmp/json-lexer.h
++++ b/include/qapi/qmp/json-lexer.h
+@@ -14,8 +14,7 @@
+ #ifndef QEMU_JSON_LEXER_H
+ #define QEMU_JSON_LEXER_H
+ 
+-#include "qapi/qmp/qstring.h"
+-#include "qapi/qmp/qlist.h"
++#include "glib-compat.h"
+ 
+ typedef enum json_token_type {
+     JSON_MIN = 100,
+@@ -36,13 +35,14 @@ typedef enum json_token_type {
+ 
+ typedef struct JSONLexer JSONLexer;
+ 
+-typedef void (JSONLexerEmitter)(JSONLexer *, QString *, JSONTokenType, int x, int y);
++typedef void (JSONLexerEmitter)(JSONLexer *, GString *,
++                                JSONTokenType, int x, int y);
+ 
+ struct JSONLexer
+ {
+     JSONLexerEmitter *emit;
+     int state;
+-    QString *token;
++    GString *token;
+     int x, y;
+ };
+ 
+diff --git a/include/qapi/qmp/json-streamer.h b/include/qapi/qmp/json-streamer.h
+index 823f7d7..e901144 100644
+--- a/include/qapi/qmp/json-streamer.h
++++ b/include/qapi/qmp/json-streamer.h
+@@ -14,6 +14,7 @@
+ #ifndef QEMU_JSON_STREAMER_H
+ #define QEMU_JSON_STREAMER_H
+ 
++#include <stdint.h>
+ #include "qapi/qmp/qlist.h"
+ #include "qapi/qmp/json-lexer.h"
+ 
+diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
+index 1bfff02..b89e24f 100644
+--- a/qobject/json-lexer.c
++++ b/qobject/json-lexer.c
+@@ -11,12 +11,9 @@
+  *
+  */
+ 
+-#include "qapi/qmp/qstring.h"
+-#include "qapi/qmp/qlist.h"
+-#include "qapi/qmp/qdict.h"
+-#include "qapi/qmp/qint.h"
+ #include "qemu-common.h"
+ #include "qapi/qmp/json-lexer.h"
++#include <stdint.h>
+ 
+ #define MAX_TOKEN_SIZE (64ULL << 20)
+ 
+@@ -276,7 +273,7 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func)
+ {
+     lexer->emit = func;
+     lexer->state = IN_START;
+-    lexer->token = qstring_new();
++    lexer->token = g_string_sized_new(3);
+     lexer->x = lexer->y = 0;
+ }
+ 
+@@ -295,7 +292,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
+         new_state = json_lexer[lexer->state][(uint8_t)ch];
+         char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state);
+         if (char_consumed) {
+-            qstring_append_chr(lexer->token, ch);
++            g_string_append_c(lexer->token, ch);
+         }
+ 
+         switch (new_state) {
+@@ -313,8 +310,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
+             lexer->emit(lexer, lexer->token, new_state, lexer->x, lexer->y);
+             /* fall through */
+         case JSON_SKIP:
+-            QDECREF(lexer->token);
+-            lexer->token = qstring_new();
++            g_string_truncate(lexer->token, 0);
+             new_state = IN_START;
+             break;
+         case IN_ERROR:
+@@ -332,8 +328,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
+              * induce an error/flush state.
+              */
+             lexer->emit(lexer, lexer->token, JSON_ERROR, lexer->x, lexer->y);
+-            QDECREF(lexer->token);
+-            lexer->token = qstring_new();
++            g_string_truncate(lexer->token, 0);
+             new_state = IN_START;
+             lexer->state = new_state;
+             return 0;
+@@ -346,10 +341,9 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
+     /* Do not let a single token grow to an arbitrarily large size,
+      * this is a security consideration.
+      */
+-    if (lexer->token->length > MAX_TOKEN_SIZE) {
++    if (lexer->token->len > MAX_TOKEN_SIZE) {
+         lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y);
+-        QDECREF(lexer->token);
+-        lexer->token = qstring_new();
++        g_string_truncate(lexer->token, 0);
+         lexer->state = IN_START;
+     }
+ 
+@@ -379,5 +373,5 @@ int json_lexer_flush(JSONLexer *lexer)
+ 
+ void json_lexer_destroy(JSONLexer *lexer)
+ {
+-    QDECREF(lexer->token);
++    g_string_free(lexer->token, true);
+ }
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index 4a161a1..7292f3a 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -12,6 +12,7 @@
+  */
+ 
+ #include "qapi/qmp/qlist.h"
++#include "qapi/qmp/qstring.h"
+ #include "qapi/qmp/qint.h"
+ #include "qapi/qmp/qdict.h"
+ #include "qemu-common.h"
+@@ -21,7 +22,8 @@
+ #define MAX_TOKEN_SIZE (64ULL << 20)
+ #define MAX_NESTING (1ULL << 10)
+ 
+-static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTokenType type, int x, int y)
++static void json_message_process_token(JSONLexer *lexer, GString *input,
++                                       JSONTokenType type, int x, int y)
+ {
+     JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
+     QDict *dict;
+@@ -45,12 +47,11 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
+ 
+     dict = qdict_new();
+     qdict_put(dict, "type", qint_from_int(type));
+-    QINCREF(token);
+-    qdict_put(dict, "token", token);
++    qdict_put(dict, "token", qstring_from_str(input->str));
+     qdict_put(dict, "x", qint_from_int(x));
+     qdict_put(dict, "y", qint_from_int(y));
+ 
+-    parser->token_size += token->length;
++    parser->token_size += input->len;
+ 
+     qlist_append(parser->tokens, dict);
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-store-tokens-in-a-GQueue.patch b/SOURCES/kvm-qjson-store-tokens-in-a-GQueue.patch
new file mode 100644
index 0000000..46ffff4
--- /dev/null
+++ b/SOURCES/kvm-qjson-store-tokens-in-a-GQueue.patch
@@ -0,0 +1,332 @@
+From 88ee76fed6344de6cede3bfbb3873423e9a90333 Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:09 +0200
+Subject: [PATCH 11/16] qjson: store tokens in a GQueue
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-13-git-send-email-armbru@redhat.com>
+Patchwork-id: 71478
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 11/15] qjson: store tokens in a GQueue
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+Even though we still have the "streamer" concept, the tokens can now
+be deleted as they are read.  While doing so convert from QList to
+GQueue, since the next step will make tokens not a QObject and we
+will have to do the conversion anyway.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Message-Id: <1448300659-23559-4-git-send-email-pbonzini@redhat.com>
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 95385fe9ace7db156b924da6b6f5c9082b68ba68)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	monitor.c
+
+Trivial context difference because we lack a small cleanup part of the
+(fairly invasive) series b821cbe..489653b.
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+---
+ include/qapi/qmp/json-parser.h   |  4 +--
+ include/qapi/qmp/json-streamer.h |  8 ++---
+ monitor.c                        |  2 +-
+ qga/main.c                       |  2 +-
+ qobject/json-parser.c            | 65 +++++++++++++---------------------------
+ qobject/json-streamer.c          | 25 +++++++++-------
+ qobject/qjson.c                  |  2 +-
+ tests/libqtest.c                 |  2 +-
+ 8 files changed, 45 insertions(+), 65 deletions(-)
+
+diff --git a/include/qapi/qmp/json-parser.h b/include/qapi/qmp/json-parser.h
+index 44d88f3..fea89f8 100644
+--- a/include/qapi/qmp/json-parser.h
++++ b/include/qapi/qmp/json-parser.h
+@@ -18,7 +18,7 @@
+ #include "qapi/qmp/qlist.h"
+ #include "qapi/error.h"
+ 
+-QObject *json_parser_parse(QList *tokens, va_list *ap);
+-QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp);
++QObject *json_parser_parse(GQueue *tokens, va_list *ap);
++QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp);
+ 
+ #endif
+diff --git a/include/qapi/qmp/json-streamer.h b/include/qapi/qmp/json-streamer.h
+index e901144..e9f2937 100644
+--- a/include/qapi/qmp/json-streamer.h
++++ b/include/qapi/qmp/json-streamer.h
+@@ -15,21 +15,21 @@
+ #define QEMU_JSON_STREAMER_H
+ 
+ #include <stdint.h>
+-#include "qapi/qmp/qlist.h"
++#include "glib-compat.h"
+ #include "qapi/qmp/json-lexer.h"
+ 
+ typedef struct JSONMessageParser
+ {
+-    void (*emit)(struct JSONMessageParser *parser, QList *tokens);
++    void (*emit)(struct JSONMessageParser *parser, GQueue *tokens);
+     JSONLexer lexer;
+     int brace_count;
+     int bracket_count;
+-    QList *tokens;
++    GQueue *tokens;
+     uint64_t token_size;
+ } JSONMessageParser;
+ 
+ void json_message_parser_init(JSONMessageParser *parser,
+-                              void (*func)(JSONMessageParser *, QList *));
++                              void (*func)(JSONMessageParser *, GQueue *));
+ 
+ int json_message_parser_feed(JSONMessageParser *parser,
+                              const char *buffer, size_t size);
+diff --git a/monitor.c b/monitor.c
+index 33c5bc8..1b28ff3 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -4514,7 +4514,7 @@ static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd,
+     qobject_decref(data);
+ }
+ 
+-static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
++static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
+ {
+     int err;
+     QObject *obj;
+diff --git a/qga/main.c b/qga/main.c
+index 0e04e73..7e8f9a0 100644
+--- a/qga/main.c
++++ b/qga/main.c
+@@ -569,7 +569,7 @@ static void process_command(GAState *s, QDict *req)
+ }
+ 
+ /* handle requests/control events coming in over the channel */
+-static void process_event(JSONMessageParser *parser, QList *tokens)
++static void process_event(JSONMessageParser *parser, GQueue *tokens)
+ {
+     GAState *s = container_of(parser, GAState, parser);
+     QObject *obj;
+diff --git a/qobject/json-parser.c b/qobject/json-parser.c
+index b242fba..6e5e257 100644
+--- a/qobject/json-parser.c
++++ b/qobject/json-parser.c
+@@ -27,11 +27,8 @@
+ typedef struct JSONParserContext
+ {
+     Error *err;
+-    struct {
+-        QObject **buf;
+-        size_t pos;
+-        size_t count;
+-    } tokens;
++    QObject *current;
++    GQueue *buf;
+ } JSONParserContext;
+ 
+ #define BUG_ON(cond) assert(!(cond))
+@@ -244,56 +241,34 @@ out:
+     return NULL;
+ }
+ 
++/* Note: unless the token object returned by parser_context_peek_token
++ * or parser_context_pop_token is explicitly incref'd, it will be
++ * deleted as soon as parser_context_pop_token is called again.
++ */
+ static QObject *parser_context_pop_token(JSONParserContext *ctxt)
+ {
+-    QObject *token;
+-    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+-    token = ctxt->tokens.buf[ctxt->tokens.pos];
+-    ctxt->tokens.pos++;
+-    return token;
++    qobject_decref(ctxt->current);
++    assert(!g_queue_is_empty(ctxt->buf));
++    ctxt->current = g_queue_pop_head(ctxt->buf);
++    return ctxt->current;
+ }
+ 
+-/* Note: parser_context_{peek|pop}_token do not increment the
+- * token object's refcount. In both cases the references will continue
+- * to be tracked and cleaned up in parser_context_free(), so do not
+- * attempt to free the token object.
+- */
+ static QObject *parser_context_peek_token(JSONParserContext *ctxt)
+ {
+-    QObject *token;
+-    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+-    token = ctxt->tokens.buf[ctxt->tokens.pos];
+-    return token;
+-}
+-
+-static void tokens_append_from_iter(QObject *obj, void *opaque)
+-{
+-    JSONParserContext *ctxt = opaque;
+-    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+-    ctxt->tokens.buf[ctxt->tokens.pos++] = obj;
+-    qobject_incref(obj);
++    assert(!g_queue_is_empty(ctxt->buf));
++    return g_queue_peek_head(ctxt->buf);
+ }
+ 
+-static JSONParserContext *parser_context_new(QList *tokens)
++static JSONParserContext *parser_context_new(GQueue *tokens)
+ {
+     JSONParserContext *ctxt;
+-    size_t count;
+ 
+     if (!tokens) {
+         return NULL;
+     }
+ 
+-    count = qlist_size(tokens);
+-    if (count == 0) {
+-        return NULL;
+-    }
+-
+     ctxt = g_malloc0(sizeof(JSONParserContext));
+-    ctxt->tokens.pos = 0;
+-    ctxt->tokens.count = count;
+-    ctxt->tokens.buf = g_malloc(count * sizeof(QObject *));
+-    qlist_iter(tokens, tokens_append_from_iter, ctxt);
+-    ctxt->tokens.pos = 0;
++    ctxt->buf = tokens;
+ 
+     return ctxt;
+ }
+@@ -301,12 +276,12 @@ static JSONParserContext *parser_context_new(QList *tokens)
+ /* to support error propagation, ctxt->err must be freed separately */
+ static void parser_context_free(JSONParserContext *ctxt)
+ {
+-    int i;
+     if (ctxt) {
+-        for (i = 0; i < ctxt->tokens.count; i++) {
+-            qobject_decref(ctxt->tokens.buf[i]);
++        while (!g_queue_is_empty(ctxt->buf)) {
++            parser_context_pop_token(ctxt);
+         }
+-        g_free(ctxt->tokens.buf);
++        qobject_decref(ctxt->current);
++        g_queue_free(ctxt->buf);
+         g_free(ctxt);
+     }
+ }
+@@ -597,12 +572,12 @@ static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
+     }
+ }
+ 
+-QObject *json_parser_parse(QList *tokens, va_list *ap)
++QObject *json_parser_parse(GQueue *tokens, va_list *ap)
+ {
+     return json_parser_parse_err(tokens, ap, NULL);
+ }
+ 
+-QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp)
++QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp)
+ {
+     JSONParserContext *ctxt = parser_context_new(tokens);
+     QObject *result;
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index 7292f3a..f7a3e78 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -22,6 +22,14 @@
+ #define MAX_TOKEN_SIZE (64ULL << 20)
+ #define MAX_NESTING (1ULL << 10)
+ 
++static void json_message_free_tokens(JSONMessageParser *parser)
++{
++    if (parser->tokens) {
++        g_queue_free(parser->tokens);
++        parser->tokens = NULL;
++    }
++}
++
+ static void json_message_process_token(JSONLexer *lexer, GString *input,
+                                        JSONTokenType type, int x, int y)
+ {
+@@ -53,7 +61,7 @@ static void json_message_process_token(JSONLexer *lexer, GString *input,
+ 
+     parser->token_size += input->len;
+ 
+-    qlist_append(parser->tokens, dict);
++    g_queue_push_tail(parser->tokens, dict);
+ 
+     if (type == JSON_ERROR) {
+         goto out_emit_bad;
+@@ -77,27 +85,24 @@ out_emit_bad:
+      * Clear out token list and tell the parser to emit an error
+      * indication by passing it a NULL list
+      */
+-    QDECREF(parser->tokens);
+-    parser->tokens = NULL;
++    json_message_free_tokens(parser);
+ out_emit:
+     /* send current list of tokens to parser and reset tokenizer */
+     parser->brace_count = 0;
+     parser->bracket_count = 0;
++    /* parser->emit takes ownership of parser->tokens.  */
+     parser->emit(parser, parser->tokens);
+-    if (parser->tokens) {
+-        QDECREF(parser->tokens);
+-    }
+-    parser->tokens = qlist_new();
++    parser->tokens = g_queue_new();
+     parser->token_size = 0;
+ }
+ 
+ void json_message_parser_init(JSONMessageParser *parser,
+-                              void (*func)(JSONMessageParser *, QList *))
++                              void (*func)(JSONMessageParser *, GQueue *))
+ {
+     parser->emit = func;
+     parser->brace_count = 0;
+     parser->bracket_count = 0;
+-    parser->tokens = qlist_new();
++    parser->tokens = g_queue_new();
+     parser->token_size = 0;
+ 
+     json_lexer_init(&parser->lexer, json_message_process_token);
+@@ -117,5 +122,5 @@ int json_message_parser_flush(JSONMessageParser *parser)
+ void json_message_parser_destroy(JSONMessageParser *parser)
+ {
+     json_lexer_destroy(&parser->lexer);
+-    QDECREF(parser->tokens);
++    json_message_free_tokens(parser);
+ }
+diff --git a/qobject/qjson.c b/qobject/qjson.c
+index 6cf2511..fdc274a 100644
+--- a/qobject/qjson.c
++++ b/qobject/qjson.c
+@@ -28,7 +28,7 @@ typedef struct JSONParsingState
+     QObject *result;
+ } JSONParsingState;
+ 
+-static void parse_json(JSONMessageParser *parser, QList *tokens)
++static void parse_json(JSONMessageParser *parser, GQueue *tokens)
+ {
+     JSONParsingState *s = container_of(parser, JSONParsingState, parser);
+     s->result = json_parser_parse(tokens, s->ap);
+diff --git a/tests/libqtest.c b/tests/libqtest.c
+index 359d571..69b7cd6 100644
+--- a/tests/libqtest.c
++++ b/tests/libqtest.c
+@@ -299,7 +299,7 @@ typedef struct {
+     QDict *response;
+ } QMPResponseParser;
+ 
+-static void qmp_response(JSONMessageParser *parser, QList *tokens)
++static void qmp_response(JSONMessageParser *parser, GQueue *tokens)
+ {
+     QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser);
+     QObject *obj;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qjson-surprise-allocating-6-QObjects-per-token-is-ex.patch b/SOURCES/kvm-qjson-surprise-allocating-6-QObjects-per-token-is-ex.patch
new file mode 100644
index 0000000..fb4fd05
--- /dev/null
+++ b/SOURCES/kvm-qjson-surprise-allocating-6-QObjects-per-token-is-ex.patch
@@ -0,0 +1,412 @@
+From 7bef5fab7d59aa9a6a1eb6ea747ba04811bc01e2 Mon Sep 17 00:00:00 2001
+From: Markus Armbruster <armbru@redhat.com>
+Date: Wed, 27 Jul 2016 07:35:10 +0200
+Subject: [PATCH 12/16] qjson: surprise, allocating 6 QObjects per token is
+ expensive
+
+RH-Author: Markus Armbruster <armbru@redhat.com>
+Message-id: <1469604913-12442-14-git-send-email-armbru@redhat.com>
+Patchwork-id: 71475
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 12/15] qjson: surprise, allocating 6 QObjects per token is expensive
+Bugzilla: 1276036
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+Replace the contents of the tokens GQueue with a simple struct.  This cuts
+the amount of memory allocated by tests/check-qjson from ~500MB to ~20MB,
+and the execution time from 600ms to 80ms on my laptop.  Still a lot (some
+could be saved by using an intrusive list, such as QSIMPLEQ, instead of
+the GQueue), but the savings are already massive and the right thing to
+do would probably be to get rid of json-streamer completely.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Message-Id: <1448300659-23559-5-git-send-email-pbonzini@redhat.com>
+[Straightforwardly rebased on my patches]
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 9bada8971173345ceb37ed1a47b00a01a4dd48cf)
+
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	qobject/json-parser.c
+
+Straighforward conflicts because lacking commit fc48ffc "qobject: Use
+'bool' for qbool", we still use qbool_from_int(), and we lack commit
+e549e71 "json-parser: Accept 'null' in QMP".
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+---
+ include/qapi/qmp/json-streamer.h |   7 +++
+ qobject/json-parser.c            | 113 ++++++++++++++++-----------------------
+ qobject/json-streamer.c          |  19 +++----
+ 3 files changed, 62 insertions(+), 77 deletions(-)
+
+diff --git a/include/qapi/qmp/json-streamer.h b/include/qapi/qmp/json-streamer.h
+index e9f2937..09b3d3e 100644
+--- a/include/qapi/qmp/json-streamer.h
++++ b/include/qapi/qmp/json-streamer.h
+@@ -18,6 +18,13 @@
+ #include "glib-compat.h"
+ #include "qapi/qmp/json-lexer.h"
+ 
++typedef struct JSONToken {
++    int type;
++    int x;
++    int y;
++    char str[];
++} JSONToken;
++
+ typedef struct JSONMessageParser
+ {
+     void (*emit)(struct JSONMessageParser *parser, GQueue *tokens);
+diff --git a/qobject/json-parser.c b/qobject/json-parser.c
+index 6e5e257..944e1a1 100644
+--- a/qobject/json-parser.c
++++ b/qobject/json-parser.c
+@@ -23,11 +23,12 @@
+ #include "qapi/qmp/json-parser.h"
+ #include "qapi/qmp/json-lexer.h"
+ #include "qapi/qmp/qerror.h"
++#include "qapi/qmp/json-streamer.h"
+ 
+ typedef struct JSONParserContext
+ {
+     Error *err;
+-    QObject *current;
++    JSONToken *current;
+     GQueue *buf;
+ } JSONParserContext;
+ 
+@@ -45,27 +46,10 @@ typedef struct JSONParserContext
+ static QObject *parse_value(JSONParserContext *ctxt, va_list *ap);
+ 
+ /**
+- * Token manipulators
+- *
+- * tokens are dictionaries that contain a type, a string value, and geometry information
+- * about a token identified by the lexer.  These are routines that make working with
+- * these objects a bit easier.
+- */
+-static const char *token_get_value(QObject *obj)
+-{
+-    return qdict_get_str(qobject_to_qdict(obj), "token");
+-}
+-
+-static JSONTokenType token_get_type(QObject *obj)
+-{
+-    return qdict_get_int(qobject_to_qdict(obj), "type");
+-}
+-
+-/**
+  * Error handler
+  */
+ static void GCC_FMT_ATTR(3, 4) parse_error(JSONParserContext *ctxt,
+-                                           QObject *token, const char *msg, ...)
++                                           JSONToken *token, const char *msg, ...)
+ {
+     va_list ap;
+     char message[1024];
+@@ -143,9 +127,10 @@ static int hex2decimal(char ch)
+  *      \t
+  *      \u four-hex-digits 
+  */
+-static QString *qstring_from_escaped_str(JSONParserContext *ctxt, QObject *token)
++static QString *qstring_from_escaped_str(JSONParserContext *ctxt,
++                                         JSONToken *token)
+ {
+-    const char *ptr = token_get_value(token);
++    const char *ptr = token->str;
+     QString *str;
+     int double_quote = 1;
+ 
+@@ -241,19 +226,19 @@ out:
+     return NULL;
+ }
+ 
+-/* Note: unless the token object returned by parser_context_peek_token
+- * or parser_context_pop_token is explicitly incref'd, it will be
+- * deleted as soon as parser_context_pop_token is called again.
++/* Note: the token object returned by parser_context_peek_token or
++ * parser_context_pop_token is deleted as soon as parser_context_pop_token
++ * is called again.
+  */
+-static QObject *parser_context_pop_token(JSONParserContext *ctxt)
++static JSONToken *parser_context_pop_token(JSONParserContext *ctxt)
+ {
+-    qobject_decref(ctxt->current);
++    g_free(ctxt->current);
+     assert(!g_queue_is_empty(ctxt->buf));
+     ctxt->current = g_queue_pop_head(ctxt->buf);
+     return ctxt->current;
+ }
+ 
+-static QObject *parser_context_peek_token(JSONParserContext *ctxt)
++static JSONToken *parser_context_peek_token(JSONParserContext *ctxt)
+ {
+     assert(!g_queue_is_empty(ctxt->buf));
+     return g_queue_peek_head(ctxt->buf);
+@@ -280,7 +265,7 @@ static void parser_context_free(JSONParserContext *ctxt)
+         while (!g_queue_is_empty(ctxt->buf)) {
+             parser_context_pop_token(ctxt);
+         }
+-        qobject_decref(ctxt->current);
++        g_free(ctxt->current);
+         g_queue_free(ctxt->buf);
+         g_free(ctxt);
+     }
+@@ -291,7 +276,8 @@ static void parser_context_free(JSONParserContext *ctxt)
+  */
+ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
+ {
+-    QObject *key = NULL, *token = NULL, *value, *peek;
++    QObject *key = NULL, *value;
++    JSONToken *peek, *token;
+ 
+     peek = parser_context_peek_token(ctxt);
+     if (peek == NULL) {
+@@ -311,7 +297,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
+         goto out;
+     }
+ 
+-    if (token_get_type(token) != JSON_COLON) {
++    if (token->type != JSON_COLON) {
+         parse_error(ctxt, token, "missing : in object pair");
+         goto out;
+     }
+@@ -337,10 +323,10 @@ out:
+ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+ {
+     QDict *dict = NULL;
+-    QObject *token, *peek;
++    JSONToken *token, *peek;
+ 
+     token = parser_context_pop_token(ctxt);
+-    assert(token && token_get_type(token) == JSON_LCURLY);
++    assert(token && token->type == JSON_LCURLY);
+ 
+     dict = qdict_new();
+ 
+@@ -350,7 +336,7 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+         goto out;
+     }
+ 
+-    if (token_get_type(peek) != JSON_RCURLY) {
++    if (peek->type != JSON_RCURLY) {
+         if (parse_pair(ctxt, dict, ap) == -1) {
+             goto out;
+         }
+@@ -361,8 +347,8 @@ static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
+             goto out;
+         }
+ 
+-        while (token_get_type(token) != JSON_RCURLY) {
+-            if (token_get_type(token) != JSON_COMMA) {
++        while (token->type != JSON_RCURLY) {
++            if (token->type != JSON_COMMA) {
+                 parse_error(ctxt, token, "expected separator in dict");
+                 goto out;
+             }
+@@ -391,10 +377,10 @@ out:
+ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+ {
+     QList *list = NULL;
+-    QObject *token, *peek;
++    JSONToken *token, *peek;
+ 
+     token = parser_context_pop_token(ctxt);
+-    assert(token && token_get_type(token) == JSON_LSQUARE);
++    assert(token && token->type == JSON_LSQUARE);
+ 
+     list = qlist_new();
+ 
+@@ -404,7 +390,7 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+         goto out;
+     }
+ 
+-    if (token_get_type(peek) != JSON_RSQUARE) {
++    if (peek->type != JSON_RSQUARE) {
+         QObject *obj;
+ 
+         obj = parse_value(ctxt, ap);
+@@ -421,8 +407,8 @@ static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
+             goto out;
+         }
+ 
+-        while (token_get_type(token) != JSON_RSQUARE) {
+-            if (token_get_type(token) != JSON_COMMA) {
++        while (token->type != JSON_RSQUARE) {
++            if (token->type != JSON_COMMA) {
+                 parse_error(ctxt, token, "expected separator in list");
+                 goto out;
+             }
+@@ -454,49 +440,45 @@ out:
+ 
+ static QObject *parse_keyword(JSONParserContext *ctxt)
+ {
+-    QObject *token;
+-    const char *val;
++    JSONToken *token;
+ 
+     token = parser_context_pop_token(ctxt);
+-    assert(token && token_get_type(token) == JSON_KEYWORD);
+-    val = token_get_value(token);
++    assert(token && token->type == JSON_KEYWORD);
+ 
+-    if (!strcmp(val, "true")) {
++    if (!strcmp(token->str, "true")) {
+         return QOBJECT(qbool_from_int(true));
+-    } else if (!strcmp(val, "false")) {
++    } else if (!strcmp(token->str, "false")) {
+         return QOBJECT(qbool_from_int(false));
+     }
+-    parse_error(ctxt, token, "invalid keyword '%s'", val);
++    parse_error(ctxt, token, "invalid keyword '%s'", token->str);
+     return NULL;
+ }
+ 
+ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
+ {
+-    QObject *token;
+-    const char *val;
++    JSONToken *token;
+ 
+     if (ap == NULL) {
+         return NULL;
+     }
+ 
+     token = parser_context_pop_token(ctxt);
+-    assert(token && token_get_type(token) == JSON_ESCAPE);
+-    val = token_get_value(token);
++    assert(token && token->type == JSON_ESCAPE);
+ 
+-    if (!strcmp(val, "%p")) {
++    if (!strcmp(token->str, "%p")) {
+         return va_arg(*ap, QObject *);
+-    } else if (!strcmp(val, "%i")) {
++    } else if (!strcmp(token->str, "%i")) {
+         return QOBJECT(qbool_from_int(va_arg(*ap, int)));
+-    } else if (!strcmp(val, "%d")) {
++    } else if (!strcmp(token->str, "%d")) {
+         return QOBJECT(qint_from_int(va_arg(*ap, int)));
+-    } else if (!strcmp(val, "%ld")) {
++    } else if (!strcmp(token->str, "%ld")) {
+         return QOBJECT(qint_from_int(va_arg(*ap, long)));
+-    } else if (!strcmp(val, "%lld") ||
+-               !strcmp(val, "%I64d")) {
++    } else if (!strcmp(token->str, "%lld") ||
++               !strcmp(token->str, "%I64d")) {
+         return QOBJECT(qint_from_int(va_arg(*ap, long long)));
+-    } else if (!strcmp(val, "%s")) {
++    } else if (!strcmp(token->str, "%s")) {
+         return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
+-    } else if (!strcmp(val, "%f")) {
++    } else if (!strcmp(token->str, "%f")) {
+         return QOBJECT(qfloat_from_double(va_arg(*ap, double)));
+     }
+     return NULL;
+@@ -504,12 +486,12 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
+ 
+ static QObject *parse_literal(JSONParserContext *ctxt)
+ {
+-    QObject *token;
++    JSONToken *token;
+ 
+     token = parser_context_pop_token(ctxt);
+     assert(token);
+ 
+-    switch (token_get_type(token)) {
++    switch (token->type) {
+     case JSON_STRING:
+         return QOBJECT(qstring_from_escaped_str(ctxt, token));
+     case JSON_INTEGER: {
+@@ -528,7 +510,7 @@ static QObject *parse_literal(JSONParserContext *ctxt)
+         int64_t value;
+ 
+         errno = 0; /* strtoll doesn't set errno on success */
+-        value = strtoll(token_get_value(token), NULL, 10);
++        value = strtoll(token->str, NULL, 10);
+         if (errno != ERANGE) {
+             return QOBJECT(qint_from_int(value));
+         }
+@@ -536,8 +518,7 @@ static QObject *parse_literal(JSONParserContext *ctxt)
+     }
+     case JSON_FLOAT:
+         /* FIXME dependent on locale */
+-        return QOBJECT(qfloat_from_double(strtod(token_get_value(token),
+-                                                 NULL)));
++        return QOBJECT(qfloat_from_double(strtod(token->str, NULL)));
+     default:
+         abort();
+     }
+@@ -545,7 +526,7 @@ static QObject *parse_literal(JSONParserContext *ctxt)
+ 
+ static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
+ {
+-    QObject *token;
++    JSONToken *token;
+ 
+     token = parser_context_peek_token(ctxt);
+     if (token == NULL) {
+@@ -553,7 +534,7 @@ static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
+         return NULL;
+     }
+ 
+-    switch (token_get_type(token)) {
++    switch (token->type) {
+     case JSON_LCURLY:
+         return parse_object(ctxt, ap);
+     case JSON_LSQUARE:
+diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
+index f7a3e78..e87230d 100644
+--- a/qobject/json-streamer.c
++++ b/qobject/json-streamer.c
+@@ -11,10 +11,6 @@
+  *
+  */
+ 
+-#include "qapi/qmp/qlist.h"
+-#include "qapi/qmp/qstring.h"
+-#include "qapi/qmp/qint.h"
+-#include "qapi/qmp/qdict.h"
+ #include "qemu-common.h"
+ #include "qapi/qmp/json-lexer.h"
+ #include "qapi/qmp/json-streamer.h"
+@@ -34,7 +30,7 @@ static void json_message_process_token(JSONLexer *lexer, GString *input,
+                                        JSONTokenType type, int x, int y)
+ {
+     JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
+-    QDict *dict;
++    JSONToken *token;
+ 
+     switch (type) {
+     case JSON_LCURLY:
+@@ -53,15 +49,16 @@ static void json_message_process_token(JSONLexer *lexer, GString *input,
+         break;
+     }
+ 
+-    dict = qdict_new();
+-    qdict_put(dict, "type", qint_from_int(type));
+-    qdict_put(dict, "token", qstring_from_str(input->str));
+-    qdict_put(dict, "x", qint_from_int(x));
+-    qdict_put(dict, "y", qint_from_int(y));
++    token = g_malloc(sizeof(JSONToken) + input->len + 1);
++    token->type = type;
++    memcpy(token->str, input->str, input->len);
++    token->str[input->len] = 0;
++    token->x = x;
++    token->y = y;
+ 
+     parser->token_size += input->len;
+ 
+-    g_queue_push_tail(parser->tokens, dict);
++    g_queue_push_tail(parser->tokens, token);
+ 
+     if (type == JSON_ERROR) {
+         goto out_emit_bad;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qxl-Fix-new-function-name-for-spice-server-library.patch b/SOURCES/kvm-qxl-Fix-new-function-name-for-spice-server-library.patch
new file mode 100644
index 0000000..418fa4e
--- /dev/null
+++ b/SOURCES/kvm-qxl-Fix-new-function-name-for-spice-server-library.patch
@@ -0,0 +1,57 @@
+From ac053d6013f7fab73f66db60462c388bea21b714 Mon Sep 17 00:00:00 2001
+Message-Id: <ac053d6013f7fab73f66db60462c388bea21b714.1464449390.git.jen@redhat.com>
+In-Reply-To: <c7936395ecf322b3de37662c7c6b772e36866cc7.1464449390.git.jen@redhat.com>
+References: <c7936395ecf322b3de37662c7c6b772e36866cc7.1464449390.git.jen@redhat.com>
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 13 May 2016 16:09:29 -0400
+Subject: [CHANGE 2/3] qxl: Fix new function name for spice-server library
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+To: rhvirt-patches@redhat.com,
+    jen@redhat.com
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1463155769-32352-3-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70403
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 2/2] qxl: Fix new function name for spice-server library
+Bugzilla: 1283198
+RH-Acked-by: Marc-André Lureau <mlureau@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+From: Frediano Ziglio <fziglio@redhat.com>
+
+The new spice-server function to limit the number of monitors (0.12.6)
+changed while development from spice_qxl_set_monitors_config_limit to
+spice_qxl_max_monitors (accepted upstream).
+By mistake I post patch with former name.
+This patch fix the function name.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+Acked-by: Martin Kletzander <mkletzan@redhat.com>
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+(cherry picked from commit a52b2cbf218d52f9e357961acb271a98a2bdff71)
+Signed-off-by: Jeff E. Nelson <jen@redhat.com>
+---
+ hw/display/qxl.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/hw/display/qxl.c b/hw/display/qxl.c
+index 1f6a303..748dfce 100644
+--- a/hw/display/qxl.c
++++ b/hw/display/qxl.c
+@@ -268,8 +268,7 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
+     } else {
+ #if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+         if (qxl->max_outputs) {
+-            spice_qxl_set_monitors_config_limit(&qxl->ssd.qxl,
+-                                                qxl->max_outputs);
++            spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs);
+         }
+ #endif
+         qxl->guest_monitors_config = qxl->ram->monitors_config;
+-- 
+2.5.5
+
diff --git a/SOURCES/kvm-qxl-allow-to-specify-head-limit-to-qxl-driver.patch b/SOURCES/kvm-qxl-allow-to-specify-head-limit-to-qxl-driver.patch
new file mode 100644
index 0000000..bc50ebd
--- /dev/null
+++ b/SOURCES/kvm-qxl-allow-to-specify-head-limit-to-qxl-driver.patch
@@ -0,0 +1,120 @@
+From c7936395ecf322b3de37662c7c6b772e36866cc7 Mon Sep 17 00:00:00 2001
+Message-Id: <c7936395ecf322b3de37662c7c6b772e36866cc7.1464449390.git.jen@redhat.com>
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 13 May 2016 16:09:28 -0400
+Subject: [CHANGE 1/3] qxl: allow to specify head limit to qxl driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+To: rhvirt-patches@redhat.com,
+    jen@redhat.com
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1463155769-32352-2-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70404
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/2] qxl: allow to specify head limit to qxl driver
+Bugzilla: 1283198
+RH-Acked-by: Marc-André Lureau <mlureau@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+
+From: Frediano Ziglio <fziglio@redhat.com>
+
+This patch allow to limit number of heads using qxl driver. By default
+qxl driver is not limited on any kind on head use so can decide to use
+as much heads.
+
+libvirt has this as a video card parameter (actually set to 1 but not
+used). This parameter will allow to limit setting a use can do (which
+could be confusing).
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+(cherry picked from commit 567161fdd47aeb6987e700702f6bbfef04ae0236)
+Signed-off-by: Jeff E. Nelson <jen@redhat.com>
+---
+ hw/display/qxl.c | 26 +++++++++++++++++++++-----
+ hw/display/qxl.h |  3 +++
+ 2 files changed, 24 insertions(+), 5 deletions(-)
+
+diff --git a/hw/display/qxl.c b/hw/display/qxl.c
+index f11210c..1f6a303 100644
+--- a/hw/display/qxl.c
++++ b/hw/display/qxl.c
+@@ -266,6 +266,12 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
+                     QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
+                     0));
+     } else {
++#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
++        if (qxl->max_outputs) {
++            spice_qxl_set_monitors_config_limit(&qxl->ssd.qxl,
++                                                qxl->max_outputs);
++        }
++#endif
+         qxl->guest_monitors_config = qxl->ram->monitors_config;
+         spice_qxl_monitors_config_async(&qxl->ssd.qxl,
+                 qxl->ram->monitors_config,
+@@ -991,6 +997,7 @@ static int interface_client_monitors_config(QXLInstance *sin,
+     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+     QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
+     int i;
++    unsigned max_outputs = ARRAY_SIZE(rom->client_monitors_config.heads);
+ 
+     if (qxl->revision < 4) {
+         trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,
+@@ -1013,17 +1020,23 @@ static int interface_client_monitors_config(QXLInstance *sin,
+     if (!monitors_config) {
+         return 1;
+     }
++
++#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
++    /* limit number of outputs based on setting limit */
++    if (qxl->max_outputs && qxl->max_outputs <= max_outputs) {
++        max_outputs = qxl->max_outputs;
++    }
++#endif
++
+     memset(&rom->client_monitors_config, 0,
+            sizeof(rom->client_monitors_config));
+     rom->client_monitors_config.count = monitors_config->num_of_monitors;
+     /* monitors_config->flags ignored */
+-    if (rom->client_monitors_config.count >=
+-            ARRAY_SIZE(rom->client_monitors_config.heads)) {
++    if (rom->client_monitors_config.count >= max_outputs) {
+         trace_qxl_client_monitors_config_capped(qxl->id,
+                                 monitors_config->num_of_monitors,
+-                                ARRAY_SIZE(rom->client_monitors_config.heads));
+-        rom->client_monitors_config.count =
+-            ARRAY_SIZE(rom->client_monitors_config.heads);
++                                max_outputs);
++        rom->client_monitors_config.count = max_outputs;
+     }
+     for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
+         VDAgentMonConfig *monitor = &monitors_config->monitors[i];
+@@ -2294,6 +2307,9 @@ static Property qxl_properties[] = {
+         DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
+         DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16),
+         DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024),
++#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
++        DEFINE_PROP_UINT16("max_outputs", PCIQXLDevice, max_outputs, 0),
++#endif
+         DEFINE_PROP_END_OF_LIST(),
+ };
+ 
+diff --git a/hw/display/qxl.h b/hw/display/qxl.h
+index 5da33e2..5247ce9 100644
+--- a/hw/display/qxl.h
++++ b/hw/display/qxl.h
+@@ -95,6 +95,9 @@ typedef struct PCIQXLDevice {
+     QXLModes           *modes;
+     uint32_t           rom_size;
+     MemoryRegion       rom_bar;
++#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
++    uint16_t           max_outputs;
++#endif
+ 
+     /* vram pci bar */
+     uint32_t           vram_size;
+-- 
+2.5.5
+
diff --git a/SOURCES/kvm-qxl-factor-out-qxl_get_check_slot_offset.patch b/SOURCES/kvm-qxl-factor-out-qxl_get_check_slot_offset.patch
new file mode 100644
index 0000000..7ba85fe
--- /dev/null
+++ b/SOURCES/kvm-qxl-factor-out-qxl_get_check_slot_offset.patch
@@ -0,0 +1,108 @@
+From 24a604e857d2797c3da9852bcbea75f2f9e6961c Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 22 Jul 2016 09:34:38 +0200
+Subject: [PATCH 1/4] qxl: factor out qxl_get_check_slot_offset
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1469180081-28522-2-git-send-email-kraxel@redhat.com>
+Patchwork-id: 71317
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 1/4] qxl: factor out qxl_get_check_slot_offset
+Bugzilla: 1355730
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+New helper function which translates a qxl physical address into
+memory slot and offset.  Also applies sanity checks.  Factored out
+from qxl_phys2virt.  No functional change.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 1466597244-5938-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit 726bdf653aca9b87e28c9a56dd94c4667ddfacbc)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/display/qxl.c | 59 ++++++++++++++++++++++++++++++++++++--------------------
+ 1 file changed, 38 insertions(+), 21 deletions(-)
+
+diff --git a/hw/display/qxl.c b/hw/display/qxl.c
+index 748dfce..5e1ecd8 100644
+--- a/hw/display/qxl.c
++++ b/hw/display/qxl.c
+@@ -1326,36 +1326,53 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
+ }
+ 
+ /* can be also called from spice server thread context */
+-void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
++static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
++                                      uint32_t *s, uint64_t *o)
+ {
+     uint64_t phys   = le64_to_cpu(pqxl);
+     uint32_t slot   = (phys >> (64 -  8)) & 0xff;
+     uint64_t offset = phys & 0xffffffffffff;
+ 
+-    switch (group_id) {
+-    case MEMSLOT_GROUP_HOST:
+-        return (void *)(intptr_t)offset;
+-    case MEMSLOT_GROUP_GUEST:
+-        if (slot >= NUM_MEMSLOTS) {
+-            qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
+-                              NUM_MEMSLOTS);
+-            return NULL;
+-        }
+-        if (!qxl->guest_slots[slot].active) {
+-            qxl_set_guest_bug(qxl, "inactive slot %d\n", slot);
+-            return NULL;
+-        }
+-        if (offset < qxl->guest_slots[slot].delta) {
+-            qxl_set_guest_bug(qxl,
++    if (slot >= NUM_MEMSLOTS) {
++        qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
++                          NUM_MEMSLOTS);
++        return false;
++    }
++    if (!qxl->guest_slots[slot].active) {
++        qxl_set_guest_bug(qxl, "inactive slot %d\n", slot);
++        return false;
++    }
++    if (offset < qxl->guest_slots[slot].delta) {
++        qxl_set_guest_bug(qxl,
+                           "slot %d offset %"PRIu64" < delta %"PRIu64"\n",
+                           slot, offset, qxl->guest_slots[slot].delta);
+-            return NULL;
+-        }
+-        offset -= qxl->guest_slots[slot].delta;
+-        if (offset > qxl->guest_slots[slot].size) {
+-            qxl_set_guest_bug(qxl,
++        return false;
++    }
++    offset -= qxl->guest_slots[slot].delta;
++    if (offset > qxl->guest_slots[slot].size) {
++        qxl_set_guest_bug(qxl,
+                           "slot %d offset %"PRIu64" > size %"PRIu64"\n",
+                           slot, offset, qxl->guest_slots[slot].size);
++        return false;
++    }
++
++    *s = slot;
++    *o = offset;
++    return true;
++}
++
++/* can be also called from spice server thread context */
++void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
++{
++    uint64_t offset;
++    uint32_t slot;
++
++    switch (group_id) {
++    case MEMSLOT_GROUP_HOST:
++        offset = le64_to_cpu(pqxl) & 0xffffffffffff;
++        return (void *)(intptr_t)offset;
++    case MEMSLOT_GROUP_GUEST:
++        if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset)) {
+             return NULL;
+         }
+         return qxl->guest_slots[slot].ptr + offset;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qxl-fix-qxl_set_dirty-call-in-qxl_dirty_one_surface.patch b/SOURCES/kvm-qxl-fix-qxl_set_dirty-call-in-qxl_dirty_one_surface.patch
new file mode 100644
index 0000000..99b1593
--- /dev/null
+++ b/SOURCES/kvm-qxl-fix-qxl_set_dirty-call-in-qxl_dirty_one_surface.patch
@@ -0,0 +1,79 @@
+From e7fe5cf70d63552006e8c9eb660db95279f2a3a9 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 22 Jul 2016 09:34:41 +0200
+Subject: [PATCH 4/4] qxl: fix qxl_set_dirty call in qxl_dirty_one_surface
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1469180081-28522-5-git-send-email-kraxel@redhat.com>
+Patchwork-id: 71316
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 4/4] qxl: fix qxl_set_dirty call in qxl_dirty_one_surface
+Bugzilla: 1355730
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+qxl_set_dirty() expects start and end as range specification.
+qxl_dirty_one_surface passes 'size' instead of 'offset + size' as end
+parameter.  Fix that.  Also use uint64_t everywhere while being at it.
+
+Bug was added by "e25139b qxl: set only off-screen surfaces dirty instead
+of the whole vram" and carried forward unnoticed by "5cdc402 qxl: fix
+surface migration".
+
+Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Message-id: 1468413187-22071-1-git-send-email-kraxel@redhat.com
+(cherry picked from commit e0127d2eec9cd5676ea9f3c47c2a7579a02c0466)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	hw/display/trace-events
+---
+ hw/display/qxl.c | 11 ++++++-----
+ trace-events     |  2 +-
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/hw/display/qxl.c b/hw/display/qxl.c
+index d65c830..f762439 100644
+--- a/hw/display/qxl.c
++++ b/hw/display/qxl.c
+@@ -1825,16 +1825,17 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
+ static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
+                                   uint32_t height, int32_t stride)
+ {
+-    uint64_t offset;
+-    uint32_t slot, size;
++    uint64_t offset, size;
++    uint32_t slot;
+     bool rc;
+ 
+     rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset);
+     assert(rc == true);
+-    size = height * abs(stride);
+-    trace_qxl_surfaces_dirty(qxl->id, (int)offset, size);
++    size = (uint64_t)height * abs(stride);
++    trace_qxl_surfaces_dirty(qxl->id, offset, size);
+     qxl_set_dirty(qxl->guest_slots[slot].mr,
+-                  qxl->guest_slots[slot].offset + offset, size);
++                  qxl->guest_slots[slot].offset + offset,
++                  qxl->guest_slots[slot].offset + offset + size);
+ }
+ 
+ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
+diff --git a/trace-events b/trace-events
+index 4da84b2..af5147a 100644
+--- a/trace-events
++++ b/trace-events
+@@ -1078,7 +1078,7 @@ qxl_spice_reset_image_cache(int qid) "%d"
+ qxl_spice_reset_memslots(int qid) "%d"
+ qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
+ qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
+-qxl_surfaces_dirty(int qid, int offset, int size) "%d offset=%d size=%d"
++qxl_surfaces_dirty(int qid, uint64_t offset, uint64_t size) "%d offset=0x%"PRIx64" size=0x%"PRIx64
+ qxl_send_events(int qid, uint32_t events) "%d %d"
+ qxl_send_events_vm_stopped(int qid, uint32_t events) "%d %d"
+ qxl_set_guest_bug(int qid) "%d"
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qxl-fix-surface-migration.patch b/SOURCES/kvm-qxl-fix-surface-migration.patch
new file mode 100644
index 0000000..f164825
--- /dev/null
+++ b/SOURCES/kvm-qxl-fix-surface-migration.patch
@@ -0,0 +1,124 @@
+From 13bf417cd4063f5db2f0a79265745481d4c69d0d Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 22 Jul 2016 09:34:40 +0200
+Subject: [PATCH 3/4] qxl: fix surface migration
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1469180081-28522-4-git-send-email-kraxel@redhat.com>
+Patchwork-id: 71315
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 3/4] qxl: fix surface migration
+Bugzilla: 1355730
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+Create a helper function qxl_dirty_one_surface() to mark a single qxl
+surface as dirty.  Use the new qxl_get_check_slot_offset function and
+lookup the memory region from the slot instead of assuming the surface
+is stored in vram.
+
+Use the new helper function in qxl_dirty_surfaces, for both primary and
+off-screen surfaces.  For off-screen surfaces this is no functional
+change.  For primary surfaces this will dirty only the memory actually
+used instead of the whole surface0 region.  It will also work correctly
+in case the guest places the primary surface in vram instead of the
+surface0 region (linux kms driver does that).
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1235732
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 1466597244-5938-3-git-send-email-kraxel@redhat.com
+(cherry picked from commit 1331eab216c9dc4e50a48a34d14926b31a7fd611)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	hw/display/trace-events
+---
+ hw/display/qxl.c | 37 +++++++++++++++++++++----------------
+ trace-events     |  2 +-
+ 2 files changed, 22 insertions(+), 17 deletions(-)
+
+diff --git a/hw/display/qxl.c b/hw/display/qxl.c
+index de5770e..d65c830 100644
+--- a/hw/display/qxl.c
++++ b/hw/display/qxl.c
+@@ -1822,9 +1822,23 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
+     }
+ }
+ 
++static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
++                                  uint32_t height, int32_t stride)
++{
++    uint64_t offset;
++    uint32_t slot, size;
++    bool rc;
++
++    rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset);
++    assert(rc == true);
++    size = height * abs(stride);
++    trace_qxl_surfaces_dirty(qxl->id, (int)offset, size);
++    qxl_set_dirty(qxl->guest_slots[slot].mr,
++                  qxl->guest_slots[slot].offset + offset, size);
++}
++
+ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
+ {
+-    uintptr_t vram_start;
+     int i;
+ 
+     if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
+@@ -1832,16 +1846,13 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
+     }
+ 
+     /* dirty the primary surface */
+-    qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
+-                  qxl->shadow_rom.surface0_area_size);
+-
+-    vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
++    qxl_dirty_one_surface(qxl, qxl->guest_primary.surface.mem,
++                          qxl->guest_primary.surface.height,
++                          qxl->guest_primary.surface.stride);
+ 
+     /* dirty the off-screen surfaces */
+     for (i = 0; i < qxl->ssd.num_surfaces; i++) {
+         QXLSurfaceCmd *cmd;
+-        intptr_t surface_offset;
+-        int surface_size;
+ 
+         if (qxl->guest_surfaces.cmds[i] == 0) {
+             continue;
+@@ -1851,15 +1862,9 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
+                             MEMSLOT_GROUP_GUEST);
+         assert(cmd);
+         assert(cmd->type == QXL_SURFACE_CMD_CREATE);
+-        surface_offset = (intptr_t)qxl_phys2virt(qxl,
+-                                                 cmd->u.surface_create.data,
+-                                                 MEMSLOT_GROUP_GUEST);
+-        assert(surface_offset);
+-        surface_offset -= vram_start;
+-        surface_size = cmd->u.surface_create.height *
+-                       abs(cmd->u.surface_create.stride);
+-        trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
+-        qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
++        qxl_dirty_one_surface(qxl, cmd->u.surface_create.data,
++                              cmd->u.surface_create.height,
++                              cmd->u.surface_create.stride);
+     }
+ }
+ 
+diff --git a/trace-events b/trace-events
+index b43132c..4da84b2 100644
+--- a/trace-events
++++ b/trace-events
+@@ -1078,7 +1078,7 @@ qxl_spice_reset_image_cache(int qid) "%d"
+ qxl_spice_reset_memslots(int qid) "%d"
+ qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
+ qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
+-qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
++qxl_surfaces_dirty(int qid, int offset, int size) "%d offset=%d size=%d"
+ qxl_send_events(int qid, uint32_t events) "%d %d"
+ qxl_send_events_vm_stopped(int qid, uint32_t events) "%d %d"
+ qxl_set_guest_bug(int qid) "%d"
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-qxl-store-memory-region-and-offset-instead-of-pointe.patch b/SOURCES/kvm-qxl-store-memory-region-and-offset-instead-of-pointe.patch
new file mode 100644
index 0000000..4d64bef
--- /dev/null
+++ b/SOURCES/kvm-qxl-store-memory-region-and-offset-instead-of-pointe.patch
@@ -0,0 +1,109 @@
+From 8f25ff7e1496ce8a26edacfa01c64f3a98c564a0 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 22 Jul 2016 09:34:39 +0200
+Subject: [PATCH 2/4] qxl: store memory region and offset instead of pointer
+ for guest slots
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1469180081-28522-3-git-send-email-kraxel@redhat.com>
+Patchwork-id: 71314
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 2/4] qxl: store memory region and offset instead of pointer for guest slots
+Bugzilla: 1355730
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+Store MemoryRegion and offset instead of a pointer for each qxl memory
+slot, so we can easily figure in which memory region an qxl object
+stored.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 1466597244-5938-2-git-send-email-kraxel@redhat.com
+(cherry picked from commit 3cb5158f15604a9f50287f2f06777d5835ff4c15)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/display/qxl.c | 15 +++++++++++----
+ hw/display/qxl.h |  3 ++-
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/hw/display/qxl.c b/hw/display/qxl.c
+index 5e1ecd8..de5770e 100644
+--- a/hw/display/qxl.c
++++ b/hw/display/qxl.c
+@@ -1232,6 +1232,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
+     int pci_region;
+     pcibus_t pci_start;
+     pcibus_t pci_end;
++    MemoryRegion *mr;
+     intptr_t virt_start;
+     QXLDevMemSlot memslot;
+     int i;
+@@ -1278,11 +1279,11 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
+ 
+     switch (pci_region) {
+     case QXL_RAM_RANGE_INDEX:
+-        virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
++        mr = &d->vga.vram;
+         break;
+     case QXL_VRAM_RANGE_INDEX:
+     case 4 /* vram 64bit */:
+-        virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
++        mr = &d->vram_bar;
+         break;
+     default:
+         /* should not happen */
+@@ -1290,6 +1291,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
+         return 1;
+     }
+ 
++    virt_start = (intptr_t)memory_region_get_ram_ptr(mr);
+     memslot.slot_id = slot_id;
+     memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */
+     memslot.virt_start = virt_start + (guest_start - pci_start);
+@@ -1299,7 +1301,8 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
+     qxl_rom_set_dirty(d);
+ 
+     qemu_spice_add_memslot(&d->ssd, &memslot, async);
+-    d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
++    d->guest_slots[slot_id].mr = mr;
++    d->guest_slots[slot_id].offset = memslot.virt_start - virt_start;
+     d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
+     d->guest_slots[slot_id].delta = delta;
+     d->guest_slots[slot_id].active = 1;
+@@ -1366,6 +1369,7 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
+ {
+     uint64_t offset;
+     uint32_t slot;
++    void *ptr;
+ 
+     switch (group_id) {
+     case MEMSLOT_GROUP_HOST:
+@@ -1375,7 +1379,10 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
+         if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset)) {
+             return NULL;
+         }
+-        return qxl->guest_slots[slot].ptr + offset;
++        ptr = memory_region_get_ram_ptr(qxl->guest_slots[slot].mr);
++        ptr += qxl->guest_slots[slot].offset;
++        ptr += offset;
++        return ptr;
+     }
+     return NULL;
+ }
+diff --git a/hw/display/qxl.h b/hw/display/qxl.h
+index 5247ce9..f3f51e2 100644
+--- a/hw/display/qxl.h
++++ b/hw/display/qxl.h
+@@ -49,7 +49,8 @@ typedef struct PCIQXLDevice {
+ 
+     struct guest_slots {
+         QXLMemSlot     slot;
+-        void           *ptr;
++        MemoryRegion   *mr;
++        uint64_t       offset;
+         uint64_t       size;
+         uint64_t       delta;
+         uint32_t       active;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-raw-posix-Fetch-max-sectors-for-host-block-device.patch b/SOURCES/kvm-raw-posix-Fetch-max-sectors-for-host-block-device.patch
new file mode 100644
index 0000000..e24544e
--- /dev/null
+++ b/SOURCES/kvm-raw-posix-Fetch-max-sectors-for-host-block-device.patch
@@ -0,0 +1,67 @@
+From 52288902dd647cbcfa470a11867163a6e5983297 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 11 Jul 2016 05:33:38 +0200
+Subject: [PATCH 5/7] raw-posix: Fetch max sectors for host block device
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1468215219-30793-6-git-send-email-famz@redhat.com>
+Patchwork-id: 71109
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 5/6] raw-posix: Fetch max sectors for host block device
+Bugzilla: 1318199
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+This is sometimes a useful value we should count in.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 6f6071745bd0366221f5a0160ed7d18d0e38b9f7)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/raw-posix.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/block/raw-posix.c b/block/raw-posix.c
+index 92fcb6c..ed97bd4 100644
+--- a/block/raw-posix.c
++++ b/block/raw-posix.c
+@@ -587,9 +587,33 @@ static void raw_reopen_abort(BDRVReopenState *state)
+     state->opaque = NULL;
+ }
+ 
++static int hdev_get_max_transfer_length(int fd)
++{
++#ifdef BLKSECTGET
++    int max_sectors = 0;
++    if (ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
++        return max_sectors;
++    } else {
++        return -errno;
++    }
++#else
++    return -ENOSYS;
++#endif
++}
++
+ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
+ {
+     BDRVRawState *s = bs->opaque;
++    struct stat st;
++
++    if (!fstat(s->fd, &st)) {
++        if (S_ISBLK(st.st_mode)) {
++            int ret = hdev_get_max_transfer_length(s->fd);
++            if (ret >= 0) {
++                bs->bl.max_transfer_length = ret;
++            }
++        }
++    }
+ 
+     raw_probe_alignment(bs, s->fd, errp);
+     bs->bl.opt_mem_alignment = s->buf_align;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-raw-posix-Fix-.bdrv_co_get_block_status-for-unaligne.patch b/SOURCES/kvm-raw-posix-Fix-.bdrv_co_get_block_status-for-unaligne.patch
index 841b730..adae243 100644
--- a/SOURCES/kvm-raw-posix-Fix-.bdrv_co_get_block_status-for-unaligne.patch
+++ b/SOURCES/kvm-raw-posix-Fix-.bdrv_co_get_block_status-for-unaligne.patch
@@ -1,13 +1,13 @@
-From 1a4a13c7c0f05f5a423c09607c7ef5151d315242 Mon Sep 17 00:00:00 2001
+From 4237964a9f433faaf643166a8ce9c070dc4cf165 Mon Sep 17 00:00:00 2001
 From: Max Reitz <mreitz@redhat.com>
-Date: Sat, 16 Jan 2016 14:02:12 +0100
+Date: Thu, 14 Jan 2016 15:10:31 +0100
 Subject: [PATCH] raw-posix: Fix .bdrv_co_get_block_status() for unaligned
  image size
 
-Message-id: <1452952932-2466-2-git-send-email-mreitz@redhat.com>
-Patchwork-id: 68783
-O-Subject: [RHEL-7.2.z qemu-kvm PATCH 1/1] raw-posix: Fix .bdrv_co_get_block_status() for unaligned image size
-Bugzilla: 1298828
+Message-id: <1452784231-14211-2-git-send-email-mreitz@redhat.com>
+Patchwork-id: 68756
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/1] raw-posix: Fix .bdrv_co_get_block_status() for unaligned image size
+Bugzilla: 1283116
 RH-Acked-by: Fam Zheng <famz@redhat.com>
 RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
 RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
diff --git a/SOURCES/kvm-rbd-fix-ceph-settings-precedence.patch b/SOURCES/kvm-rbd-fix-ceph-settings-precedence.patch
index 10d1536..a5b699e 100644
--- a/SOURCES/kvm-rbd-fix-ceph-settings-precedence.patch
+++ b/SOURCES/kvm-rbd-fix-ceph-settings-precedence.patch
@@ -1,12 +1,12 @@
-From a66fe0ea2e09b8d82a2d8940632ac06ee8bcc579 Mon Sep 17 00:00:00 2001
+From 109d7dedc79629f58fd9b685ccd9990b90f374e9 Mon Sep 17 00:00:00 2001
 From: Stefan Hajnoczi <stefanha@redhat.com>
 Date: Thu, 5 Nov 2015 15:20:58 +0100
-Subject: [PATCH 2/2] rbd: fix ceph settings precedence
+Subject: [PATCH 3/6] rbd: fix ceph settings precedence
 
 Message-id: <1446736858-29005-3-git-send-email-stefanha@redhat.com>
 Patchwork-id: 68294
 O-Subject: [RHEL-7.2.z qemu-kvm PATCH 2/2] rbd: fix ceph settings precedence
-Bugzilla: 1279389
+Bugzilla: 1277248 1279389
 RH-Acked-by: Max Reitz <mreitz@redhat.com>
 RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
 RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
diff --git a/SOURCES/kvm-rbd-make-qemu-s-cache-setting-override-any-ceph-sett.patch b/SOURCES/kvm-rbd-make-qemu-s-cache-setting-override-any-ceph-sett.patch
index 8a8bbe7..22705e6 100644
--- a/SOURCES/kvm-rbd-make-qemu-s-cache-setting-override-any-ceph-sett.patch
+++ b/SOURCES/kvm-rbd-make-qemu-s-cache-setting-override-any-ceph-sett.patch
@@ -1,12 +1,12 @@
-From 6f293e47850a873d0ccc39882be7b3ef6e1043b6 Mon Sep 17 00:00:00 2001
+From 23bc583f18eb8ffc28604a4ae42e2f7a55b31c3e Mon Sep 17 00:00:00 2001
 From: Stefan Hajnoczi <stefanha@redhat.com>
 Date: Thu, 5 Nov 2015 15:20:57 +0100
-Subject: [PATCH 1/2] rbd: make qemu's cache setting override any ceph setting
+Subject: [PATCH 2/6] rbd: make qemu's cache setting override any ceph setting
 
 Message-id: <1446736858-29005-2-git-send-email-stefanha@redhat.com>
 Patchwork-id: 68293
 O-Subject: [RHEL-7.2.z qemu-kvm PATCH 1/2] rbd: make qemu's cache setting override any ceph setting
-Bugzilla: 1279389
+Bugzilla: 1277248
 RH-Acked-by: Max Reitz <mreitz@redhat.com>
 RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
 RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
diff --git a/SOURCES/kvm-rtl8139-Do-not-consume-the-packet-during-overflow-in.patch b/SOURCES/kvm-rtl8139-Do-not-consume-the-packet-during-overflow-in.patch
new file mode 100644
index 0000000..db4b86a
--- /dev/null
+++ b/SOURCES/kvm-rtl8139-Do-not-consume-the-packet-during-overflow-in.patch
@@ -0,0 +1,48 @@
+From 9318bd2b84409c6f3810d410c6918fefec072408 Mon Sep 17 00:00:00 2001
+From: Vlad Yasevich <vyasevic@redhat.com>
+Date: Wed, 16 Dec 2015 02:58:23 +0100
+Subject: [PATCH 6/6] rtl8139: Do not consume the packet during overflow in
+ standard mode.
+
+Message-id: <1450234703-7606-3-git-send-email-vyasevic@redhat.com>
+Patchwork-id: 68618
+O-Subject: [RHEL7.3 qemu-kvm PATCH 2/2] rtl8139: Do not consume the packet during overflow in standard mode.
+Bugzilla: 1252757
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Xiao Wang <jasowang@redhat.com>
+
+When operation in standard mode, we currently return the size
+of packet during buffer overflow.  This consumes the overflow
+packet.  Return 0 instead so we can re-process the overflow packet
+when we have room.
+
+This fixes issues with lost/dropped fragments of large messages.
+
+Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
+Reviewed-by: Jason Wang <jasowang@redhat.com>
+Message-id: 1441121206-6997-3-git-send-email-vyasevic@redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 26c4e7ca72d970d120f0f51244bc8d37458512a0)
+Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/net/rtl8139.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index 6a167df..aa2503d 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -1148,7 +1148,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
+             s->IntrStatus |= RxOverflow;
+             ++s->RxMissed;
+             rtl8139_update_irq(s);
+-            return size_;
++            return 0;
+         }
+ 
+         packet_header |= RxStatusOK;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-rtl8139-Fix-receive-buffer-overflow-check.patch b/SOURCES/kvm-rtl8139-Fix-receive-buffer-overflow-check.patch
new file mode 100644
index 0000000..7399163
--- /dev/null
+++ b/SOURCES/kvm-rtl8139-Fix-receive-buffer-overflow-check.patch
@@ -0,0 +1,64 @@
+From dc546cbfdefb8ddbaf121d3b075ca723df264d1c Mon Sep 17 00:00:00 2001
+From: Vlad Yasevich <vyasevic@redhat.com>
+Date: Wed, 16 Dec 2015 02:58:22 +0100
+Subject: [PATCH 5/6] rtl8139: Fix receive buffer overflow check
+
+Message-id: <1450234703-7606-2-git-send-email-vyasevic@redhat.com>
+Patchwork-id: 68617
+O-Subject: [RHEL7.3 qemu-kvm PATCH 1/2] rtl8139: Fix receive buffer overflow check
+Bugzilla: 1252757
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
+RH-Acked-by: Xiao Wang <jasowang@redhat.com>
+
+rtl8139_do_receive() tries to check for the overflow condition
+by making sure that packet_size + 8 does not exceed the
+available buffer space.  The issue here is that RxBuffAddr,
+used to calculate available buffer space, is aligned to a
+a 4 byte boundry after every update.  So it is possible that
+every packet ends up being slightly padded when written
+to the receive buffer.  This padding is not taken into
+account when checking for overflow and we may end up missing
+the overflow condition can causing buffer overwrite.
+
+This patch takes alignment into consideration when
+checking for overflow condition.
+
+Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
+Reviewed-by: Jason Wang <jasowang@redhat.com>
+Message-id: 1441121206-6997-2-git-send-email-vyasevic@redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit fabdcd3392f16fc666b1d04fc1bbe5f1dbbf10a4)
+Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/net/rtl8139.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index 4f89328..6a167df 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -1137,7 +1137,9 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
+ 
+         /* if receiver buffer is empty then avail == 0 */
+ 
+-        if (avail != 0 && size + 8 >= avail)
++#define RX_ALIGN(x) (((x) + 3) & ~0x3)
++
++        if (avail != 0 && RX_ALIGN(size + 8) >= avail)
+         {
+             DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
+                 "read 0x%04x === available 0x%04x need 0x%04x\n",
+@@ -1165,7 +1167,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
+         rtl8139_write_buffer(s, (uint8_t *)&val, 4);
+ 
+         /* correct buffer write pointer */
+-        s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize);
++        s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize);
+ 
+         /* now we can signal we have received something */
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-scsi-Advertise-limits-by-blocksize-not-512.patch b/SOURCES/kvm-scsi-Advertise-limits-by-blocksize-not-512.patch
new file mode 100644
index 0000000..4d7aed1
--- /dev/null
+++ b/SOURCES/kvm-scsi-Advertise-limits-by-blocksize-not-512.patch
@@ -0,0 +1,54 @@
+From c8644154fb4b460f00c9d24ed9090edc40fef067 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 11 Jul 2016 05:33:39 +0200
+Subject: [PATCH 6/7] scsi: Advertise limits by blocksize, not 512
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1468215219-30793-7-git-send-email-famz@redhat.com>
+Patchwork-id: 71110
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 6/6] scsi: Advertise limits by blocksize, not 512
+Bugzilla: 1318199
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Eric Blake <eblake@redhat.com>
+
+s->blocksize may be larger than 512, in which case our
+tweaks to max_xfer_len and opt_xfer_len must be scaled
+appropriately.
+
+CC: qemu-stable@nongnu.org
+Reported-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit efaf4781a995aacd22b1dd521b14e4644bafae14)
+
+ Conflicts:
+	hw/scsi/scsi-generic.c
+Downstream uses bdrv_get_max_transfer_length().
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/scsi/scsi-generic.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
+index 6b0c1fe..ced92f7 100644
+--- a/hw/scsi/scsi-generic.c
++++ b/hw/scsi/scsi-generic.c
+@@ -210,7 +210,8 @@ static void scsi_read_complete(void * opaque, int ret)
+         } else if (s->type == TYPE_DISK &&
+             r->req.cmd.buf[0] == INQUIRY &&
+             r->req.cmd.buf[2] == 0xb0) {
+-            uint32_t max_xfer_len = bdrv_get_max_transfer_length(s->conf.bs);
++            uint32_t max_xfer_len = bdrv_get_max_transfer_length(s->conf.bs) /
++                (s->blocksize / BDRV_SECTOR_SIZE);
+             if (max_xfer_len) {
+                 stl_be_p(&r->buf[8], max_xfer_len);
+                 /* Also take care of the opt xfer len. */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-scsi-generic-Merge-block-max-xfer-len-in-INQUIRY-res.patch b/SOURCES/kvm-scsi-generic-Merge-block-max-xfer-len-in-INQUIRY-res.patch
new file mode 100644
index 0000000..9f465df
--- /dev/null
+++ b/SOURCES/kvm-scsi-generic-Merge-block-max-xfer-len-in-INQUIRY-res.patch
@@ -0,0 +1,67 @@
+From b3f427e4eb27091ca712f6c18e2e63a414dc4ce2 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 11 Jul 2016 05:33:37 +0200
+Subject: [PATCH 4/7] scsi-generic: Merge block max xfer len in INQUIRY
+ response
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1468215219-30793-5-git-send-email-famz@redhat.com>
+Patchwork-id: 71108
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 4/6] scsi-generic: Merge block max xfer len in INQUIRY response
+Bugzilla: 1318199
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+The rationale is similar to the above mode sense response interception:
+this is practically the only channel to communicate restraints from
+elsewhere such as host and block driver.
+
+The scsi bus we attach onto can have a larger max xfer len than what is
+accepted by the host file system (guarding between the host scsi LUN and
+QEMU), in which case the SG_IO we generate would get -EINVAL.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Message-Id: <1464243305-10661-3-git-send-email-famz@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 063143d5b1fde0fdcbae30bc7d6d14e76fa607d2)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+	hw/scsi/scsi-generic.c
+We don't have BlockBackend in downstream, use bdrv_get_max_transfer_length()
+instead.
+
+The context is different because we don't have fa0d653b0 (scsi-generic:
+identify AIO callbacks more clearly).
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+---
+ hw/scsi/scsi-generic.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
+index 3733d2c..6b0c1fe 100644
+--- a/hw/scsi/scsi-generic.c
++++ b/hw/scsi/scsi-generic.c
+@@ -207,6 +207,17 @@ static void scsi_read_complete(void * opaque, int ret)
+                    (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
+             s->blocksize = ldl_be_p(&r->buf[8]);
+             s->max_lba = ldq_be_p(&r->buf[0]);
++        } else if (s->type == TYPE_DISK &&
++            r->req.cmd.buf[0] == INQUIRY &&
++            r->req.cmd.buf[2] == 0xb0) {
++            uint32_t max_xfer_len = bdrv_get_max_transfer_length(s->conf.bs);
++            if (max_xfer_len) {
++                stl_be_p(&r->buf[8], max_xfer_len);
++                /* Also take care of the opt xfer len. */
++                if (ldl_be_p(&r->buf[12]) > max_xfer_len) {
++                    stl_be_p(&r->buf[12], max_xfer_len);
++                }
++            }
+         }
+         bdrv_set_guest_block_size(s->conf.bs, s->blocksize);
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-seccomp-adding-sysinfo-system-call-to-whitelist.patch b/SOURCES/kvm-seccomp-adding-sysinfo-system-call-to-whitelist.patch
new file mode 100644
index 0000000..1e6fac4
--- /dev/null
+++ b/SOURCES/kvm-seccomp-adding-sysinfo-system-call-to-whitelist.patch
@@ -0,0 +1,48 @@
+From 2dc9b654f678a1cfa95a680f31085cdff1e648b2 Mon Sep 17 00:00:00 2001
+From: Miroslav Rezanina <mrezanin@redhat.com>
+Date: Fri, 22 Apr 2016 05:14:07 +0200
+Subject: [PATCH 02/10] seccomp: adding sysinfo system call to whitelist
+
+RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
+Message-id: <1461302047-6677-1-git-send-email-mrezanin@redhat.com>
+Patchwork-id: 70221
+O-Subject: [RHEL 7.3 qemu-kvm PATCH] seccomp: adding sysinfo system call to whitelist
+Bugzilla: 1177318
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+From: Miroslav Rezanina <mrezanin@redhat.com>
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1177318
+Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=10914613
+RHEV: BZ 1177309, fixed with 2.6 rebase
+
+Newer version of nss-softokn libraries (> 3.16.2.3) use sysinfo call
+so qemu using rbd image hang after start when run in sandbox mode.
+
+To allow using rbd images in sandbox mode we have to whitelist it.
+
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+Acked-by: Eduardo Otubo <eduardo.otubo@profitbricks.com>
+(cherry picked from commit 8e08f8a4a7f613af65b29fcc3ac3bfc2a08a3343)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ qemu-seccomp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/qemu-seccomp.c b/qemu-seccomp.c
+index 5e60fce..e947909 100644
+--- a/qemu-seccomp.c
++++ b/qemu-seccomp.c
+@@ -249,6 +249,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
+     { SCMP_SYS(munlock), 240 },
+     { SCMP_SYS(semctl), 240 },
+     { SCMP_SYS(timerfd_create), 240 },
++    { SCMP_SYS(sysinfo), 240 },
+ };
+ 
+ int seccomp_start(void)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-spice-do-not-require-TCP-ports.patch b/SOURCES/kvm-spice-do-not-require-TCP-ports.patch
new file mode 100644
index 0000000..7e0f350
--- /dev/null
+++ b/SOURCES/kvm-spice-do-not-require-TCP-ports.patch
@@ -0,0 +1,48 @@
+From f40c437eed664b31984a21ec6bbed12c6b03dd0b Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Wed, 1 Jun 2016 13:16:08 +0200
+Subject: [PATCH 1/2] spice: do not require TCP ports
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1464786968-25518-2-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70523
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/1] spice: do not require TCP ports
+Bugzilla: 1336491
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@gmail.com>
+
+It is possible to use Spice server without TCP port.  On local VM,
+qemu (and libvirt) can add new clients thanks to QMP add_client command.
+
+Signed-off-by: Marc-André Lureau <marcandre.lureau@gmail.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+(cherry picked from commit cf7856adefebe86e0cd50302d93b3045e3111690)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ ui/spice-core.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/ui/spice-core.c b/ui/spice-core.c
+index 141afd1..8d6e726 100644
+--- a/ui/spice-core.c
++++ b/ui/spice-core.c
+@@ -648,10 +648,6 @@ void qemu_spice_init(void)
+     }
+     port = qemu_opt_get_number(opts, "port", 0);
+     tls_port = qemu_opt_get_number(opts, "tls-port", 0);
+-    if (!port && !tls_port) {
+-        error_report("neither port nor tls-port specified for spice");
+-        exit(1);
+-    }
+     if (port < 0 || port > 65535) {
+         error_report("spice port is out of range");
+         exit(1);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-target-i386-Add-more-Intel-AVX-512-instructions-supp.patch b/SOURCES/kvm-target-i386-Add-more-Intel-AVX-512-instructions-supp.patch
new file mode 100644
index 0000000..85efb16
--- /dev/null
+++ b/SOURCES/kvm-target-i386-Add-more-Intel-AVX-512-instructions-supp.patch
@@ -0,0 +1,93 @@
+From 73b0c0b62c08330e65e9ec3d54ae5738d4b5211d Mon Sep 17 00:00:00 2001
+From: Eduardo Habkost <ehabkost@redhat.com>
+Date: Fri, 9 Sep 2016 19:08:34 +0200
+Subject: [PATCH 2/2] target-i386: Add more Intel AVX-512 instructions support
+
+RH-Author: Eduardo Habkost <ehabkost@redhat.com>
+Message-id: <1473448114-1430-3-git-send-email-ehabkost@redhat.com>
+Patchwork-id: 72277
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 2/2] target-i386: Add more Intel AVX-512 instructions support
+Bugzilla: 1372459
+RH-Acked-by: Bandan Das <bsd@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Luwei Kang <luwei.kang@intel.com>
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1372459
+
+Add more AVX512 feature bits, include AVX512DQ, AVX512IFMA,
+AVX512BW, AVX512VL, AVX512VBMI. Its spec can be found at:
+https://software.intel.com/sites/default/files/managed/b4/3a/319433-024.pdf
+
+Signed-off-by: Luwei Kang <luwei.kang@intel.com>
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+(cherry picked from commit cc728d1493eee3e20c1547191862e43d3f55e714)
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ target-i386/cpu.c | 14 +++++++++-----
+ target-i386/cpu.h | 13 +++++++++++++
+ 2 files changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/target-i386/cpu.c b/target-i386/cpu.c
+index d9c214c..476306d 100644
+--- a/target-i386/cpu.c
++++ b/target-i386/cpu.c
+@@ -144,14 +144,18 @@ static const char *svm_feature_name[] = {
+ };
+ 
+ static const char *cpuid_7_0_ebx_feature_name[] = {
+-    "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep",
+-    "bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL,
+-    "avx512f", NULL, "rdseed", "adx", "smap", NULL, NULL, NULL,
+-    NULL, NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL,
++    "fsgsbase", NULL, NULL, "bmi1",
++    "hle", "avx2", NULL, "smep",
++    "bmi2", "erms", "invpcid", "rtm",
++    NULL, NULL, "mpx", NULL,
++    "avx512f", "avx512dq", "rdseed", "adx",
++    "smap", "avx512ifma", NULL, NULL,
++    NULL, NULL, "avx512pf", "avx512er",
++    "avx512cd", NULL, "avx512bw", "avx512vl",
+ };
+ 
+ static const char *cpuid_7_0_ecx_feature_name[] = {
+-    NULL, NULL, NULL, NULL,
++    NULL, "avx512vbmi", NULL, NULL,
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL,
+diff --git a/target-i386/cpu.h b/target-i386/cpu.h
+index 5c62ee3..d541809 100644
+--- a/target-i386/cpu.h
++++ b/target-i386/cpu.h
+@@ -560,12 +560,25 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
+ #define CPUID_7_0_EBX_RTM      (1U << 11)
+ #define CPUID_7_0_EBX_MPX      (1U << 14)
+ #define CPUID_7_0_EBX_AVX512F  (1U << 16) /* AVX-512 Foundation */
++#define CPUID_7_0_EBX_AVX512DQ (1U << 17) /* AVX-512 Doubleword & Quadword Instrs */
+ #define CPUID_7_0_EBX_RDSEED   (1U << 18)
+ #define CPUID_7_0_EBX_ADX      (1U << 19)
+ #define CPUID_7_0_EBX_SMAP     (1U << 20)
++#define CPUID_7_0_EBX_AVX512IFMA (1U << 21) /* AVX-512 Integer Fused Multiply Add */
++#define CPUID_7_0_EBX_PCOMMIT  (1U << 22) /* Persistent Commit */
++#define CPUID_7_0_EBX_CLFLUSHOPT (1U << 23) /* Flush a Cache Line Optimized */
++#define CPUID_7_0_EBX_CLWB     (1U << 24) /* Cache Line Write Back */
+ #define CPUID_7_0_EBX_AVX512PF (1U << 26) /* AVX-512 Prefetch */
+ #define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and Reciprocal */
+ #define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */
++#define CPUID_7_0_EBX_AVX512BW (1U << 30) /* AVX-512 Byte and Word Instructions */
++#define CPUID_7_0_EBX_AVX512VL (1U << 31) /* AVX-512 Vector Length Extensions */
++
++#define CPUID_7_0_ECX_VBMI     (1U << 1)  /* AVX-512 Vector Byte Manipulation Instrs */
++#define CPUID_7_0_ECX_UMIP     (1U << 2)
++#define CPUID_7_0_ECX_PKU      (1U << 3)
++#define CPUID_7_0_ECX_OSPKE    (1U << 4)
++#define CPUID_7_0_ECX_RDPID    (1U << 22)
+ 
+ #define CPUID_XSAVE_XSAVEOPT   (1U << 0)
+ #define CPUID_XSAVE_XSAVEC     (1U << 1)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-target-i386-Add-support-for-FEAT_7_0_ECX.patch b/SOURCES/kvm-target-i386-Add-support-for-FEAT_7_0_ECX.patch
new file mode 100644
index 0000000..43d29aa
--- /dev/null
+++ b/SOURCES/kvm-target-i386-Add-support-for-FEAT_7_0_ECX.patch
@@ -0,0 +1,147 @@
+From eb87f1106d038247356ecd3071e6fa5654386ff5 Mon Sep 17 00:00:00 2001
+From: Eduardo Habkost <ehabkost@redhat.com>
+Date: Fri, 9 Sep 2016 19:08:33 +0200
+Subject: [PATCH 1/2] target-i386: Add support for FEAT_7_0_ECX
+
+RH-Author: Eduardo Habkost <ehabkost@redhat.com>
+Message-id: <1473448114-1430-2-git-send-email-ehabkost@redhat.com>
+Patchwork-id: 72276
+O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 1/2] target-i386: Add support for FEAT_7_0_ECX
+Bugzilla: 1372459
+RH-Acked-by: Bandan Das <bsd@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1372459
+
+Done from scratch by copying what is done for FEAT_7_0_EBX.  Compare
+to upstream commit f74eefe ("target-i386: Add PKU and and OSPKE support",
+2016-01-21), but without actually adding PKU and OSPKE.  Because all
+these features are "-cpu host"-only, they can be added without modifying
+machine types.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+[ehabkost: v2: removed the non-upstream cpuid_level < 7 check]
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ target-i386/cpu.c | 29 ++++++++++++++++++++++++++++-
+ target-i386/cpu.h |  1 +
+ 2 files changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/target-i386/cpu.c b/target-i386/cpu.c
+index 1001c47..d9c214c 100644
+--- a/target-i386/cpu.c
++++ b/target-i386/cpu.c
+@@ -150,6 +150,17 @@ static const char *cpuid_7_0_ebx_feature_name[] = {
+     NULL, NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL,
+ };
+ 
++static const char *cpuid_7_0_ecx_feature_name[] = {
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++};
++
+ static const char *cpuid_xsave_feature_name[] = {
+     "xsaveopt", "xsavec", "xgetbv1", NULL,
+     NULL, NULL, NULL, NULL,
+@@ -204,6 +215,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
+         .cpuid_needs_ecx = true, .cpuid_ecx = 0,
+         .cpuid_reg = R_EBX,
+     },
++    [FEAT_7_0_ECX] = {
++        .feat_names = cpuid_7_0_ecx_feature_name,
++        .cpuid_eax = 7,
++        .cpuid_needs_ecx = true, .cpuid_ecx = 0,
++        .cpuid_reg = R_ECX,
++    },
+     [FEAT_XSAVE] = {
+         .feat_names = cpuid_xsave_feature_name,
+         .cpuid_eax = 0xd,
+@@ -462,6 +479,7 @@ typedef struct x86_def_t {
+           CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
+           CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
+           CPUID_7_0_EBX_RDSEED */
++#define TCG_7_0_ECX_FEATURES 0
+ 
+ /* built-in CPU model definitions
+  */
+@@ -1198,8 +1216,11 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
+     if (x86_cpu_def->level >= 7) {
+         x86_cpu_def->features[FEAT_7_0_EBX] =
+                     kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX);
++        x86_cpu_def->features[FEAT_7_0_ECX] =
++                    kvm_arch_get_supported_cpuid(s, 0x7, 0, R_ECX);
+     } else {
+         x86_cpu_def->features[FEAT_7_0_EBX] = 0;
++        x86_cpu_def->features[FEAT_7_0_ECX] = 0;
+     }
+     x86_cpu_def->features[FEAT_XSAVE] =
+                 kvm_arch_get_supported_cpuid(s, 0xd, 1, R_EAX);
+@@ -1283,6 +1304,9 @@ static int kvm_check_features_against_host(X86CPU *cpu)
+         {&env->features[FEAT_7_0_EBX],
+             &host_def.features[FEAT_7_0_EBX],
+             FEAT_7_0_EBX },
++        {&env->features[FEAT_7_0_ECX],
++            &host_def.features[FEAT_7_0_ECX],
++            FEAT_7_0_ECX },
+         {&env->features[FEAT_XSAVE],
+             &host_def.features[FEAT_XSAVE],
+             FEAT_XSAVE },
+@@ -1824,6 +1848,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
+     env->features[FEAT_KVM] |= plus_features[FEAT_KVM];
+     env->features[FEAT_SVM] |= plus_features[FEAT_SVM];
+     env->features[FEAT_7_0_EBX] |= plus_features[FEAT_7_0_EBX];
++    env->features[FEAT_7_0_ECX] |= plus_features[FEAT_7_0_ECX];
+     env->features[FEAT_XSAVE] |= plus_features[FEAT_XSAVE];
+     env->features[FEAT_1_EDX] &= ~minus_features[FEAT_1_EDX];
+     env->features[FEAT_1_ECX] &= ~minus_features[FEAT_1_ECX];
+@@ -1833,6 +1858,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
+     env->features[FEAT_KVM] &= ~minus_features[FEAT_KVM];
+     env->features[FEAT_SVM] &= ~minus_features[FEAT_SVM];
+     env->features[FEAT_7_0_EBX] &= ~minus_features[FEAT_7_0_EBX];
++    env->features[FEAT_7_0_ECX] &= ~minus_features[FEAT_7_0_ECX];
+     env->features[FEAT_XSAVE] &= ~minus_features[FEAT_XSAVE];
+ 
+ out:
+@@ -1969,6 +1995,7 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
+     env->features[FEAT_SVM] = def->features[FEAT_SVM];
+     env->features[FEAT_C000_0001_EDX] = def->features[FEAT_C000_0001_EDX];
+     env->features[FEAT_7_0_EBX] = def->features[FEAT_7_0_EBX];
++    env->features[FEAT_7_0_ECX] = def->features[FEAT_7_0_ECX];
+     env->features[FEAT_XSAVE] = def->features[FEAT_XSAVE];
+     env->cpuid_xlevel2 = def->xlevel2;
+ 
+@@ -2206,7 +2233,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+         if (count == 0) {
+             *eax = 0; /* Maximum ECX value for sub-leaves */
+             *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */
+-            *ecx = 0; /* Reserved */
++            *ecx = env->features[FEAT_7_0_ECX]; /* Feature flags */
+             *edx = 0; /* Reserved */
+         } else {
+             *eax = 0;
+diff --git a/target-i386/cpu.h b/target-i386/cpu.h
+index da7e060..5c62ee3 100644
+--- a/target-i386/cpu.h
++++ b/target-i386/cpu.h
+@@ -400,6 +400,7 @@ typedef enum FeatureWord {
+     FEAT_1_EDX,         /* CPUID[1].EDX */
+     FEAT_1_ECX,         /* CPUID[1].ECX */
+     FEAT_7_0_EBX,       /* CPUID[EAX=7,ECX=0].EBX */
++    FEAT_7_0_ECX,       /* CPUID[EAX=7,ECX=0].ECX */
+     FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
+     FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
+     FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-target-i386-add-Skylake-Client-cpu-model.patch b/SOURCES/kvm-target-i386-add-Skylake-Client-cpu-model.patch
new file mode 100644
index 0000000..e135496
--- /dev/null
+++ b/SOURCES/kvm-target-i386-add-Skylake-Client-cpu-model.patch
@@ -0,0 +1,92 @@
+From ce561d78c7199821beae26112f41da5733fab5bb Mon Sep 17 00:00:00 2001
+From: Eduardo Habkost <ehabkost@redhat.com>
+Date: Wed, 6 Jul 2016 20:47:53 +0200
+Subject: [PATCH 2/2] target-i386: add Skylake-Client cpu model
+
+RH-Author: Eduardo Habkost <ehabkost@redhat.com>
+Message-id: <1467838073-23873-3-git-send-email-ehabkost@redhat.com>
+Patchwork-id: 71052
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 2/2] target-i386: add Skylake-Client cpu model
+Bugzilla: 1327599
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Bandan Das <bsd@redhat.com>
+
+Introduce Skylake-Client cpu mode which inherits the features from
+Broadwell and supports some additional features that are: MPX,
+XSAVEC, and XGETBV1.
+
+Backport notes:
+* ARAT feature not included, as it is not available in the
+  qemu-kvm-1.5.3 tree (and disabled by compat code in
+  pc-i440fx-rhel7.2.0 and older on qemu-kvm-rhev)
+
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
+Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
+Reviewed-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+(cherry picked from commit f6f949e9295889fb272698aea763dcea77d616ce)
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ target-i386/cpu.c | 43 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+diff --git a/target-i386/cpu.c b/target-i386/cpu.c
+index 6650c72..80106ba 100644
+--- a/target-i386/cpu.c
++++ b/target-i386/cpu.c
+@@ -927,6 +927,49 @@ static x86_def_t builtin_x86_defs[] = {
+         .model_id = "Intel Core Processor (Broadwell)",
+     },
+     {
++        .name = "Skylake-Client",
++        .level = 0xd,
++        .vendor = CPUID_VENDOR_INTEL,
++        .family = 6,
++        .model = 94,
++        .stepping = 3,
++        .features[FEAT_1_EDX] =
++            CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
++            CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
++            CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
++            CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
++            CPUID_DE | CPUID_FP87,
++        .features[FEAT_1_ECX] =
++            CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
++            CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
++            CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
++            CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
++            CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
++            CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
++        .features[FEAT_8000_0001_EDX] =
++            CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
++            CPUID_EXT2_SYSCALL,
++        .features[FEAT_8000_0001_ECX] =
++            CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
++        .features[FEAT_7_0_EBX] =
++            CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
++            CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
++            CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
++            CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
++            CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX,
++        /* Missing: XSAVES (not supported by some Linux versions,
++         * including v4.1 to v4.6).
++         * KVM doesn't yet expose any XSAVES state save component,
++         * and the only one defined in Skylake (processor tracing)
++         * probably will block migration anyway.
++         */
++        .features[FEAT_XSAVE] =
++            CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
++            CPUID_XSAVE_XGETBV1,
++        .xlevel = 0x80000008,
++        .model_id = "Intel Core Processor (Skylake)",
++    },
++    {
+         .name = "Opteron_G1",
+         .level = 5,
+         .vendor = CPUID_VENDOR_AMD,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-target-i386-add-feature-flags-for-CPUID-EAX-0xd-ECX-.patch b/SOURCES/kvm-target-i386-add-feature-flags-for-CPUID-EAX-0xd-ECX-.patch
new file mode 100644
index 0000000..14bc767
--- /dev/null
+++ b/SOURCES/kvm-target-i386-add-feature-flags-for-CPUID-EAX-0xd-ECX-.patch
@@ -0,0 +1,168 @@
+From 5fcaf5176d7545518c76f3aa8ea7ce6fb063c62d Mon Sep 17 00:00:00 2001
+From: Eduardo Habkost <ehabkost@redhat.com>
+Date: Wed, 6 Jul 2016 20:47:52 +0200
+Subject: [PATCH 1/2] target-i386: add feature flags for CPUID[EAX=0xd, ECX=1]
+
+RH-Author: Eduardo Habkost <ehabkost@redhat.com>
+Message-id: <1467838073-23873-2-git-send-email-ehabkost@redhat.com>
+Patchwork-id: 71051
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/2] target-i386: add feature flags for CPUID[EAX=0xd, ECX=1]
+Bugzilla: 1327599
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
+RH-Acked-by: Bandan Das <bsd@redhat.com>
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+These represent xsave-related capabilities of the processor, and KVM may
+or may not support them.
+
+Add feature bits so that they are considered by "-cpu ...,enforce", and use
+the new feature work instead of calling kvm_arch_get_supported_cpuid.
+
+Bit 3 (XSAVES) is not migratables because it requires saving MSR_IA32_XSS.
+Neither KVM nor any commonly available hardware supports it anyway.
+
+RHEL backport notes:
+* In addition to allowing xsave flags to be configured, this
+  patch is a bug fix because we shouldn't use
+  kvm_arch_supported_cpuid() directly when configuring CPUID for
+  the guest
+* tcg_features didn't exist, handle it inside x86_cpu_realizefn()
+  directly in the !kvm_enabled() check
+* As the unmigratable_flags mechanism is not present yet,
+  remove the "xsaves" flag name so it can't be enabled manually
+  (otherwise we would need to backport upstream commit
+  18cd2c17b5370369a886155c001da0a7f54bbcca too)
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 0bb0b2d2fe7f645ddaf1f0ff40ac669c9feb4aa1)
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ target-i386/cpu.c | 28 +++++++++++++++++++++++++++-
+ target-i386/cpu.h |  6 ++++++
+ 2 files changed, 33 insertions(+), 1 deletion(-)
+
+diff --git a/target-i386/cpu.c b/target-i386/cpu.c
+index 06efe17..6650c72 100644
+--- a/target-i386/cpu.c
++++ b/target-i386/cpu.c
+@@ -150,6 +150,17 @@ static const char *cpuid_7_0_ebx_feature_name[] = {
+     NULL, NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL,
+ };
+ 
++static const char *cpuid_xsave_feature_name[] = {
++    "xsaveopt", "xsavec", "xgetbv1", NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++    NULL, NULL, NULL, NULL,
++};
++
+ typedef struct FeatureWordInfo {
+     const char **feat_names;
+     uint32_t cpuid_eax;   /* Input EAX for CPUID */
+@@ -193,6 +204,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
+         .cpuid_needs_ecx = true, .cpuid_ecx = 0,
+         .cpuid_reg = R_EBX,
+     },
++    [FEAT_XSAVE] = {
++        .feat_names = cpuid_xsave_feature_name,
++        .cpuid_eax = 0xd,
++        .cpuid_needs_ecx = true, .cpuid_ecx = 1,
++        .cpuid_reg = R_EAX,
++    },
+ };
+ 
+ typedef struct X86RegisterInfo32 {
+@@ -833,6 +850,8 @@ static x86_def_t builtin_x86_defs[] = {
+              CPUID_EXT2_SYSCALL,
+         .features[FEAT_8000_0001_ECX] =
+             CPUID_EXT3_LAHF_LM,
++        .features[FEAT_XSAVE] =
++            CPUID_XSAVE_XSAVEOPT,
+         .xlevel = 0x8000000A,
+         .model_id = "Intel Xeon E312xx (Sandy Bridge)",
+     },
+@@ -866,6 +885,8 @@ static x86_def_t builtin_x86_defs[] = {
+             CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
+             CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
+             CPUID_7_0_EBX_RTM,
++        .features[FEAT_XSAVE] =
++            CPUID_XSAVE_XSAVEOPT,
+         .xlevel = 0x8000000A,
+         .model_id = "Intel Core Processor (Haswell)",
+     },
+@@ -900,6 +921,8 @@ static x86_def_t builtin_x86_defs[] = {
+             CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
+             CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
+             CPUID_7_0_EBX_SMAP,
++        .features[FEAT_XSAVE] =
++            CPUID_XSAVE_XSAVEOPT,
+         .xlevel = 0x8000000A,
+         .model_id = "Intel Core Processor (Broadwell)",
+     },
+@@ -1017,6 +1040,7 @@ static x86_def_t builtin_x86_defs[] = {
+              CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
+              CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
+              CPUID_EXT3_LAHF_LM,
++        /* no xsaveopt! */
+         .xlevel = 0x8000001A,
+         .model_id = "AMD Opteron 62xx class CPU",
+     },
+@@ -1051,6 +1075,7 @@ static x86_def_t builtin_x86_defs[] = {
+              CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
+              CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
+              CPUID_EXT3_LAHF_LM,
++        /* no xsaveopt! */
+         .xlevel = 0x8000001A,
+         .model_id = "AMD Opteron 63xx class CPU",
+     },
+@@ -2196,7 +2221,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+             *eax |= kvm_mask & (XSTATE_FP | XSTATE_SSE);
+             *ebx = *ecx;
+         } else if (count == 1) {
+-            *eax = kvm_arch_get_supported_cpuid(s, 0xd, 1, R_EAX);
++            *eax = env->features[FEAT_XSAVE];
+         } else if (count < ARRAY_SIZE(ext_save_areas)) {
+             const ExtSaveArea *esa = &ext_save_areas[count];
+             if ((env->features[esa->feature] & esa->bits) == esa->bits &&
+@@ -2540,6 +2565,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
+             );
+         env->features[FEAT_8000_0001_ECX] &= TCG_EXT3_FEATURES;
+         env->features[FEAT_SVM] &= TCG_SVM_FEATURES;
++        env->features[FEAT_XSAVE] = 0;
+     } else {
+         if ((cpu->check_cpuid || cpu->enforce_cpuid)
+             && kvm_check_features_against_host(cpu) && cpu->enforce_cpuid) {
+diff --git a/target-i386/cpu.h b/target-i386/cpu.h
+index 61e9b86..da7e060 100644
+--- a/target-i386/cpu.h
++++ b/target-i386/cpu.h
+@@ -405,6 +405,7 @@ typedef enum FeatureWord {
+     FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
+     FEAT_KVM,           /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
+     FEAT_SVM,           /* CPUID[8000_000A].EDX */
++    FEAT_XSAVE,         /* CPUID[EAX=0xd,ECX=1].EAX */
+     FEATURE_WORDS,
+ } FeatureWord;
+ 
+@@ -565,6 +566,11 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
+ #define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and Reciprocal */
+ #define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */
+ 
++#define CPUID_XSAVE_XSAVEOPT   (1U << 0)
++#define CPUID_XSAVE_XSAVEC     (1U << 1)
++#define CPUID_XSAVE_XGETBV1    (1U << 2)
++#define CPUID_XSAVE_XSAVES     (1U << 3)
++
+ #define CPUID_VENDOR_SZ      12
+ 
+ #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-target-i386-fix-pcmpxstrx-equal-ordered-strstr-mode.patch b/SOURCES/kvm-target-i386-fix-pcmpxstrx-equal-ordered-strstr-mode.patch
new file mode 100644
index 0000000..f38645f
--- /dev/null
+++ b/SOURCES/kvm-target-i386-fix-pcmpxstrx-equal-ordered-strstr-mode.patch
@@ -0,0 +1,57 @@
+From b05eb2cc7decc07ed044484861587b3490144d02 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Wed, 8 Jun 2016 13:04:21 +0200
+Subject: [PATCH 2/3] target-i386: fix pcmpxstrx equal-ordered (strstr) mode
+
+RH-Author: Paolo Bonzini <pbonzini@redhat.com>
+Message-id: <1465391061-17748-1-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 70570
+O-Subject: [RHEL7.3/7.2.z qemu-kvm PATCH] target-i386: fix pcmpxstrx equal-ordered (strstr) mode
+Bugzilla: 1340971
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+
+Kindly requested by the Openstack folks, who sometimes uses TCG
+instead of nested virt.
+
+In this mode, referring an invalid element of the source forces the
+result to false (table 4-7, last column) but referring an invalid
+element of the destination forces the result to true, so the outer
+loop should still be run even if some elements of the destination
+will be invalid.  They will be avoided in the inner loop, which
+correctly bounds "i" to validd, but they will still contribute to a
+positive outcome of the search.
+
+This fixes tst_strstr in glibc 2.17.
+
+Reported-by: Florian Weimer <fweimer@redhat.com>
+Cc: Richard Henderson <rth@twiddle.net>
+Cc: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 54c54f8b56047d3c2420e1ae06a6a8890c220ac4)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ target-i386/ops_sse.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
+index eb24b5f..5145d9e 100644
+--- a/target-i386/ops_sse.h
++++ b/target-i386/ops_sse.h
+@@ -2034,10 +2034,10 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
+         }
+         break;
+     case 3:
+-        for (j = valids - validd; j >= 0; j--) {
++        for (j = valids; j >= 0; j--) {
+             res <<= 1;
+             v = 1;
+-            for (i = MIN(upper - j, validd); i >= 0; i--) {
++            for (i = MIN(valids - j, validd); i >= 0; i--) {
+                 v &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i));
+             }
+             res |= v;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-target-i386-get-put-MSR_TSC_AUX-across-reset-and-mig.patch b/SOURCES/kvm-target-i386-get-put-MSR_TSC_AUX-across-reset-and-mig.patch
new file mode 100644
index 0000000..17dd46a
--- /dev/null
+++ b/SOURCES/kvm-target-i386-get-put-MSR_TSC_AUX-across-reset-and-mig.patch
@@ -0,0 +1,93 @@
+From f9a24822687113e34194f05aeb641365b8202e9e Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Wed, 25 Nov 2015 05:51:34 +0100
+Subject: [PATCH 4/6] target-i386: get/put MSR_TSC_AUX across reset and
+ migration
+
+Message-id: <daab7f1c955ec81df8aff4ab10fd6ae17e16e99e.1448430513.git.amit.shah@redhat.com>
+Patchwork-id: 68467
+O-Subject: [RHEL 7.3 qemu-kvm PATCH 1/1] target-i386: get/put MSR_TSC_AUX across reset and migration
+Bugzilla: 1265427
+RH-Acked-by: Juan Quintela <quintela@redhat.com>
+RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+There's one report of migration breaking due to missing MSR_TSC_AUX
+save/restore.  Fix this by adding a new subsection that saves the state
+of this MSR.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1261797
+
+Reported-by: Xiaoqing Wei <xwei@redhat.com>
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+CC: Paolo Bonzini <pbonzini@redhat.com>
+CC: Juan Quintela <quintela@redhat.com>
+CC: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
+CC: Marcelo Tosatti <mtosatti@redhat.com>
+CC: Richard Henderson <rth@twiddle.net>
+CC: Eduardo Habkost <ehabkost@redhat.com>
+Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+(cherry picked from commit c9b8f6b6210847b4381c5b2ee172b1c7eb9985d6)
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ target-i386/kvm.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/target-i386/kvm.c b/target-i386/kvm.c
+index c91bfb8..e1b0ca2 100644
+--- a/target-i386/kvm.c
++++ b/target-i386/kvm.c
+@@ -63,6 +63,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+ 
+ static bool has_msr_star;
+ static bool has_msr_hsave_pa;
++static bool has_msr_tsc_aux;
+ static bool has_msr_tsc_adjust;
+ static bool has_msr_tsc_deadline;
+ static bool has_msr_async_pf_en;
+@@ -774,6 +775,10 @@ static int kvm_get_supported_msrs(KVMState *s)
+                     has_msr_hsave_pa = true;
+                     continue;
+                 }
++                if (kvm_msr_list->indices[i] == MSR_TSC_AUX) {
++                    has_msr_tsc_aux = true;
++                    continue;
++                }
+                 if (kvm_msr_list->indices[i] == MSR_TSC_ADJUST) {
+                     has_msr_tsc_adjust = true;
+                     continue;
+@@ -1159,6 +1164,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
+     if (has_msr_hsave_pa) {
+         kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
+     }
++    if (has_msr_tsc_aux) {
++        kvm_msr_entry_set(&msrs[n++], MSR_TSC_AUX, env->tsc_aux);
++    }
+     if (has_msr_tsc_adjust) {
+         kvm_msr_entry_set(&msrs[n++], MSR_TSC_ADJUST, env->tsc_adjust);
+     }
+@@ -1507,6 +1515,9 @@ static int kvm_get_msrs(X86CPU *cpu)
+     if (has_msr_hsave_pa) {
+         msrs[n++].index = MSR_VM_HSAVE_PA;
+     }
++    if (has_msr_tsc_aux) {
++        msrs[n++].index = MSR_TSC_AUX;
++    }
+     if (has_msr_tsc_adjust) {
+         msrs[n++].index = MSR_TSC_ADJUST;
+     }
+@@ -1636,6 +1647,9 @@ static int kvm_get_msrs(X86CPU *cpu)
+         case MSR_IA32_TSC:
+             env->tsc = msrs[i].data;
+             break;
++        case MSR_TSC_AUX:
++            env->tsc_aux = msrs[i].data;
++            break;
+         case MSR_TSC_ADJUST:
+             env->tsc_adjust = msrs[i].data;
+             break;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-trace-remove-malloc-tracing.patch b/SOURCES/kvm-trace-remove-malloc-tracing.patch
new file mode 100644
index 0000000..ef72ff0
--- /dev/null
+++ b/SOURCES/kvm-trace-remove-malloc-tracing.patch
@@ -0,0 +1,104 @@
+From d15566b6a91973dbf83c92a9678bd3ac4939af75 Mon Sep 17 00:00:00 2001
+From: Miroslav Rezanina <mrezanin@redhat.com>
+Date: Fri, 29 Jul 2016 07:41:27 +0200
+Subject: [PATCH 16/16] trace: remove malloc tracing
+
+RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
+Message-id: <1469778087-316-1-git-send-email-mrezanin@redhat.com>
+Patchwork-id: 71514
+O-Subject: [RHEL-7.3 qemu-kvm PATCH] trace: remove malloc tracing
+Bugzilla: 1360137
+RH-Acked-by: Fam Zheng <famz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+The malloc vtable is not supported anymore in glib, because it broke
+when constructors called g_malloc.  Remove tracing of g_malloc,
+g_realloc and g_free calls.
+
+Note that, for systemtap users, glib also provides tracepoints
+glib.mem_alloc, glib.mem_free, glib.mem_realloc, glib.slice_alloc
+and glib.slice_free.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Reviewed-by: Alberto Garcia <berto@igalia.com>
+Message-id: 1442417924-25831-1-git-send-email-pbonzini@redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 98cf48f60aa4999f5b2808569a193a401a390e6a)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ trace-events |  3 ---
+ vl.c         | 26 --------------------------
+ 2 files changed, 29 deletions(-)
+
+diff --git a/trace-events b/trace-events
+index af5147a..6cd46e9 100644
+--- a/trace-events
++++ b/trace-events
+@@ -474,9 +474,6 @@ scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d"
+ vm_state_notify(int running, int reason) "running %d reason %d"
+ load_file(const char *name, const char *path) "name %s location %s"
+ runstate_set(int new_state) "new state %d"
+-g_malloc(size_t size, void *ptr) "size %zu ptr %p"
+-g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p"
+-g_free(void *ptr) "ptr %p"
+ qemu_system_shutdown_request(void) ""
+ qemu_system_powerdown_request(void) ""
+ 
+diff --git a/vl.c b/vl.c
+index 35b927e..9756361 100644
+--- a/vl.c
++++ b/vl.c
+@@ -2738,26 +2738,6 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
+     return popt;
+ }
+ 
+-static gpointer malloc_and_trace(gsize n_bytes)
+-{
+-    void *ptr = malloc(n_bytes);
+-    trace_g_malloc(n_bytes, ptr);
+-    return ptr;
+-}
+-
+-static gpointer realloc_and_trace(gpointer mem, gsize n_bytes)
+-{
+-    void *ptr = realloc(mem, n_bytes);
+-    trace_g_realloc(mem, n_bytes, ptr);
+-    return ptr;
+-}
+-
+-static void free_and_trace(gpointer mem)
+-{
+-    trace_g_free(mem);
+-    free(mem);
+-}
+-
+ static int object_set_property(const char *name, const char *value, void *opaque)
+ {
+     Object *obj = OBJECT(opaque);
+@@ -2832,11 +2812,6 @@ int main(int argc, char **argv, char **envp)
+     bool userconfig = true;
+     const char *log_mask = NULL;
+     const char *log_file = NULL;
+-    GMemVTable mem_trace = {
+-        .malloc = malloc_and_trace,
+-        .realloc = realloc_and_trace,
+-        .free = free_and_trace,
+-    };
+     const char *trace_events = NULL;
+     const char *trace_file = NULL;
+     FILE *vmstate_dump_file = NULL;
+@@ -2845,7 +2820,6 @@ int main(int argc, char **argv, char **envp)
+     error_set_progname(argv[0]);
+     qemu_init_exec_dir(argv[0]);
+ 
+-    g_mem_set_vtable(&mem_trace);
+     if (!g_thread_supported()) {
+ #if !GLIB_CHECK_VERSION(2, 31, 0)
+         g_thread_init(NULL);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-util-Fix-MIN_NON_ZERO.patch b/SOURCES/kvm-util-Fix-MIN_NON_ZERO.patch
new file mode 100644
index 0000000..6b2577a
--- /dev/null
+++ b/SOURCES/kvm-util-Fix-MIN_NON_ZERO.patch
@@ -0,0 +1,46 @@
+From 756b23c15387acefe4139831c2f3c8a5f3d41bb2 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 18 Jul 2016 01:32:10 +0200
+Subject: [PATCH 7/7] util: Fix MIN_NON_ZERO
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1468805530-19033-1-git-send-email-famz@redhat.com>
+Patchwork-id: 71200
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 7/6] util: Fix MIN_NON_ZERO
+Bugzilla: 1318199
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+MIN_NON_ZERO(1, 0) is evaluated to 0. Rewrite the macro to fix it.
+
+Reported-by: Miroslav Rezanina <mrezanin@redhat.com>
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Message-Id: <1468306113-847-1-git-send-email-famz@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit d27ba624aa1dfe5c07cc01200d95967ffce905d9)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ include/qemu/osdep.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
+index c47a600..5ca05bc 100644
+--- a/include/qemu/osdep.h
++++ b/include/qemu/osdep.h
+@@ -71,7 +71,8 @@ typedef signed int              int_fast16_t;
+ /* Minimum function that returns zero only iff both values are zero.
+  * Intended for use with unsigned values only. */
+ #ifndef MIN_NON_ZERO
+-#define MIN_NON_ZERO(a, b) (((a) != 0 && (a) < (b)) ? (a) : (b))
++#define MIN_NON_ZERO(a, b) ((a) == 0 ? (b) : \
++                                ((b) == 0 ? (a) : (MIN(a, b))))
+ #endif
+ 
+ #ifndef ROUND_UP
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-util-introduce-MIN_NON_ZERO.patch b/SOURCES/kvm-util-introduce-MIN_NON_ZERO.patch
new file mode 100644
index 0000000..38e74e5
--- /dev/null
+++ b/SOURCES/kvm-util-introduce-MIN_NON_ZERO.patch
@@ -0,0 +1,52 @@
+From 6e14ac55a7b40804cf69de560f38561214129b07 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 11 Jul 2016 05:33:34 +0200
+Subject: [PATCH 1/7] util: introduce MIN_NON_ZERO
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1468215219-30793-2-git-send-email-famz@redhat.com>
+Patchwork-id: 71105
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/6] util: introduce MIN_NON_ZERO
+Bugzilla: 1318199
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: John Snow <jsnow@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Peter Lieven <pl@kamp.de>
+
+at least in block layer we have the case of limits being defined for a
+BlockDriverState. However, in this context often zero (0) has the special
+meanining of undefined which means no limit. If two of those limits are
+combined and the minimum is needed the minimum function should only return
+zero if both parameters are zero.
+
+Signed-off-by: Peter Lieven <pl@kamp.de>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit ac3a8726644d4783eacf54212d23db01d1d30044)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ include/qemu/osdep.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
+index 8984da0..c47a600 100644
+--- a/include/qemu/osdep.h
++++ b/include/qemu/osdep.h
+@@ -68,6 +68,12 @@ typedef signed int              int_fast16_t;
+ #define MAX(a, b) (((a) > (b)) ? (a) : (b))
+ #endif
+ 
++/* Minimum function that returns zero only iff both values are zero.
++ * Intended for use with unsigned values only. */
++#ifndef MIN_NON_ZERO
++#define MIN_NON_ZERO(a, b) (((a) != 0 && (a) < (b)) ? (a) : (b))
++#endif
++
+ #ifndef ROUND_UP
+ #define ROUND_UP(n,d) (((n) + (d) - 1) & -(d))
+ #endif
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vga-Remove-some-should-be-done-in-BIOS-comments.patch b/SOURCES/kvm-vga-Remove-some-should-be-done-in-BIOS-comments.patch
index 993d0ae..5cfc3f5 100644
--- a/SOURCES/kvm-vga-Remove-some-should-be-done-in-BIOS-comments.patch
+++ b/SOURCES/kvm-vga-Remove-some-should-be-done-in-BIOS-comments.patch
@@ -1,13 +1,13 @@
-From 9397be4c801c71c84bc4ba6036efea32f5426c2e Mon Sep 17 00:00:00 2001
+From c5ee3f3aab59ff26b0fed770077a16714da9696e Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 29 Apr 2016 07:02:46 +0200
-Subject: [PATCH 1/6] vga: Remove some "should be done in BIOS" comments
+Date: Thu, 28 Apr 2016 16:07:27 +0200
+Subject: [PATCH 22/27] vga: Remove some "should be done in BIOS" comments
 
 RH-Author: Gerd Hoffmann <kraxel@redhat.com>
-Message-id: <1461913371-3145-2-git-send-email-kraxel@redhat.com>
-Patchwork-id: 70301
-O-Subject: [virt-devel] [RHEL-7.2.z qemu-kvm PATCH 1/6] vga: Remove some "should be done in BIOS" comments
-Bugzilla: 1331412
+Message-id: <1461859652-20918-2-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70292
+O-Subject: [virt-devel] [RHEL-7.3 qemu-kvm PATCH 1/6] vga: Remove some "should be done in BIOS" comments
+Bugzilla: 1331413
 RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
 RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
 RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
@@ -20,6 +20,7 @@ using the DISPI interface to initialize the card.
 Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
 Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
+(cherry picked from commit ace89b8ff21cc3fb20986a334e54e6e6a1ccf729)
 Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
 ---
  hw/display/vga.c | 6 ++----
diff --git a/SOURCES/kvm-vga-add-sr_vbe-register-set.patch b/SOURCES/kvm-vga-add-sr_vbe-register-set.patch
index 989709b..49bd9a5 100644
--- a/SOURCES/kvm-vga-add-sr_vbe-register-set.patch
+++ b/SOURCES/kvm-vga-add-sr_vbe-register-set.patch
@@ -1,13 +1,13 @@
-From eaf59089f691d89a0811fa355e9579fd44011dbe Mon Sep 17 00:00:00 2001
+From 40d4a0ec487abcde65d4175dde0c9dda45b570f9 Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel@redhat.com>
 Date: Thu, 16 Jun 2016 15:30:11 +0200
-Subject: [PATCH] vga: add sr_vbe register set
+Subject: [PATCH 2/2] vga: add sr_vbe register set
 
 RH-Author: Gerd Hoffmann <kraxel@redhat.com>
 Message-id: <1466091011-8095-2-git-send-email-kraxel@redhat.com>
 Patchwork-id: 70639
 O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/1] vga: add sr_vbe register set
-Bugzilla: 1347527
+Bugzilla: 1346982
 RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
 RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
 RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
diff --git a/SOURCES/kvm-vga-add-vbe_enabled-helper.patch b/SOURCES/kvm-vga-add-vbe_enabled-helper.patch
index fb13245..fa400af 100644
--- a/SOURCES/kvm-vga-add-vbe_enabled-helper.patch
+++ b/SOURCES/kvm-vga-add-vbe_enabled-helper.patch
@@ -1,13 +1,13 @@
-From 0f24daf4c35cace529ae8441aa8b101ba53660ea Mon Sep 17 00:00:00 2001
+From 6e615e8fbbd979134868bcd63150365d48d12137 Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 29 Apr 2016 07:02:48 +0200
-Subject: [PATCH 3/6] vga: add vbe_enabled() helper
+Date: Thu, 28 Apr 2016 16:07:29 +0200
+Subject: [PATCH 24/27] vga: add vbe_enabled() helper
 
 RH-Author: Gerd Hoffmann <kraxel@redhat.com>
-Message-id: <1461913371-3145-4-git-send-email-kraxel@redhat.com>
-Patchwork-id: 70303
-O-Subject: [virt-devel] [RHEL-7.2.z qemu-kvm PATCH 3/6] vga: add vbe_enabled() helper
-Bugzilla: 1331412
+Message-id: <1461859652-20918-4-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70294
+O-Subject: [virt-devel] [RHEL-7.3 qemu-kvm PATCH 3/6] vga: add vbe_enabled() helper
+Bugzilla: 1331413
 RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
 RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
 RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
diff --git a/SOURCES/kvm-vga-factor-out-vga-register-setup.patch b/SOURCES/kvm-vga-factor-out-vga-register-setup.patch
index 4314346..01f3261 100644
--- a/SOURCES/kvm-vga-factor-out-vga-register-setup.patch
+++ b/SOURCES/kvm-vga-factor-out-vga-register-setup.patch
@@ -1,13 +1,13 @@
-From c3eb11a92f0fa90fe2976c9c5ea59fe8ab862e77 Mon Sep 17 00:00:00 2001
+From 445ec835479fd06142078a59f1a88f2b30708930 Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 29 Apr 2016 07:02:49 +0200
-Subject: [PATCH 4/6] vga: factor out vga register setup
+Date: Thu, 28 Apr 2016 16:07:30 +0200
+Subject: [PATCH 25/27] vga: factor out vga register setup
 
 RH-Author: Gerd Hoffmann <kraxel@redhat.com>
-Message-id: <1461913371-3145-5-git-send-email-kraxel@redhat.com>
-Patchwork-id: 70304
-O-Subject: [virt-devel] [RHEL-7.2.z qemu-kvm PATCH 4/6] vga: factor out vga register setup
-Bugzilla: 1331412
+Message-id: <1461859652-20918-5-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70295
+O-Subject: [virt-devel] [RHEL-7.3 qemu-kvm PATCH 4/6] vga: factor out vga register setup
+Bugzilla: 1331413
 RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
 RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
 RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
diff --git a/SOURCES/kvm-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch b/SOURCES/kvm-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch
deleted file mode 100644
index 13fd623..0000000
--- a/SOURCES/kvm-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-From 73714beab12fec056f3b38a7c2bc35a520405953 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 29 Apr 2016 07:02:47 +0200
-Subject: [PATCH 2/6] vga: fix banked access bounds checking (CVE-2016-3710)
-
-RH-Author: Gerd Hoffmann <kraxel@redhat.com>
-Message-id: <1461913371-3145-3-git-send-email-kraxel@redhat.com>
-Patchwork-id: 70302
-O-Subject: [virt-devel] [RHEL-7.2.z qemu-kvm PATCH 2/6] vga: fix banked access bounds checking (CVE-2016-3710)
-Bugzilla: 1331412
-RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
-RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
-RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
-
-vga allows banked access to video memory using the window at 0xa00000
-and it supports a different access modes with different address
-calculations.
-
-The VBE bochs extentions support banked access too, using the
-VBE_DISPI_INDEX_BANK register.  The code tries to take the different
-address calculations into account and applies different limits to
-VBE_DISPI_INDEX_BANK depending on the current access mode.
-
-Which is probably effective in stopping misprogramming by accident.
-But from a security point of view completely useless as an attacker
-can easily change access modes after setting the bank register.
-
-Drop the bogus check, add range checks to vga_mem_{readb,writeb}
-instead.
-
-Fixes: CVE-2016-3710
-Reported-by: Qinghao Tang <luodalongde@gmail.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
----
- hw/display/vga.c | 23 +++++++++++++++++------
- 1 file changed, 17 insertions(+), 6 deletions(-)
-
-diff --git a/hw/display/vga.c b/hw/display/vga.c
-index 48dad03..ba171ba 100644
---- a/hw/display/vga.c
-+++ b/hw/display/vga.c
-@@ -744,11 +744,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
-             vbe_fixup_regs(s);
-             break;
-         case VBE_DISPI_INDEX_BANK:
--            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
--              val &= (s->vbe_bank_mask >> 2);
--            } else {
--              val &= s->vbe_bank_mask;
--            }
-+            val &= s->vbe_bank_mask;
-             s->vbe_regs[s->vbe_index] = val;
-             s->bank_offset = (val << 16);
-             vga_update_memory_access(s);
-@@ -847,13 +843,21 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
- 
-     if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
-         /* chain 4 mode : simplest access */
-+        assert(addr < s->vram_size);
-         ret = s->vram_ptr[addr];
-     } else if (s->gr[VGA_GFX_MODE] & 0x10) {
-         /* odd/even mode (aka text mode mapping) */
-         plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
--        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
-+        addr = ((addr & ~1) << 1) | plane;
-+        if (addr >= s->vram_size) {
-+            return 0xff;
-+        }
-+        ret = s->vram_ptr[addr];
-     } else {
-         /* standard VGA latched access */
-+        if (addr * sizeof(uint32_t) >= s->vram_size) {
-+            return 0xff;
-+        }
-         s->latch = ((uint32_t *)s->vram_ptr)[addr];
- 
-         if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
-@@ -910,6 +914,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
-         plane = addr & 3;
-         mask = (1 << plane);
-         if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
-+            assert(addr < s->vram_size);
-             s->vram_ptr[addr] = val;
- #ifdef DEBUG_VGA_MEM
-             printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
-@@ -923,6 +928,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
-         mask = (1 << plane);
-         if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
-             addr = ((addr & ~1) << 1) | plane;
-+            if (addr >= s->vram_size) {
-+                return;
-+            }
-             s->vram_ptr[addr] = val;
- #ifdef DEBUG_VGA_MEM
-             printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
-@@ -996,6 +1004,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
-         mask = s->sr[VGA_SEQ_PLANE_WRITE];
-         s->plane_updated |= mask; /* only used to detect font change */
-         write_mask = mask16[mask];
-+        if (addr * sizeof(uint32_t) >= s->vram_size) {
-+            return;
-+        }
-         ((uint32_t *)s->vram_ptr)[addr] =
-             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
-             (val & write_mask);
--- 
-1.8.3.1
-
diff --git a/SOURCES/kvm-vga-fix-banked-access-bounds-checking-CVE-2016-xxxx.patch b/SOURCES/kvm-vga-fix-banked-access-bounds-checking-CVE-2016-xxxx.patch
new file mode 100644
index 0000000..681e31b
--- /dev/null
+++ b/SOURCES/kvm-vga-fix-banked-access-bounds-checking-CVE-2016-xxxx.patch
@@ -0,0 +1,108 @@
+From 27bca97bf22a55b1be7611e07c7592fcef5dd7cc Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Thu, 28 Apr 2016 16:07:28 +0200
+Subject: [PATCH 23/27] vga: fix banked access bounds checking (CVE-2016-xxxx).
+
+RH-Author: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: <1461859652-20918-3-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70293
+O-Subject: [virt-devel] [RHEL-7.3 qemu-kvm PATCH 2/6] vga: fix banked access bounds checking (CVE-2016-xxxx).
+Bugzilla: 1331413
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+
+vga allows banked access to video memory using the window at 0xa00000
+and it supports a different access modes with different address
+calculations.
+
+The VBE bochs extentions support banked access too, using the
+VBE_DISPI_INDEX_BANK register.  The code tries to take the different
+address calculations into account and applies different limits to
+VBE_DISPI_INDEX_BANK depending on the current access mode.
+
+Which is probably effective in stopping misprogramming by accident.
+But from a security point of view completely useless as an attacker
+can easily change access modes after setting the bank register.
+
+Drop the bogus check, add range checks to vga_mem_{readb,writeb}
+instead.
+
+Reported-by: Qinghao Tang <luodalongde@gmail.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/display/vga.c | 23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+diff --git a/hw/display/vga.c b/hw/display/vga.c
+index 48dad03..ba171ba 100644
+--- a/hw/display/vga.c
++++ b/hw/display/vga.c
+@@ -744,11 +744,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
+             vbe_fixup_regs(s);
+             break;
+         case VBE_DISPI_INDEX_BANK:
+-            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
+-              val &= (s->vbe_bank_mask >> 2);
+-            } else {
+-              val &= s->vbe_bank_mask;
+-            }
++            val &= s->vbe_bank_mask;
+             s->vbe_regs[s->vbe_index] = val;
+             s->bank_offset = (val << 16);
+             vga_update_memory_access(s);
+@@ -847,13 +843,21 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
+ 
+     if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
+         /* chain 4 mode : simplest access */
++        assert(addr < s->vram_size);
+         ret = s->vram_ptr[addr];
+     } else if (s->gr[VGA_GFX_MODE] & 0x10) {
+         /* odd/even mode (aka text mode mapping) */
+         plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
+-        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
++        addr = ((addr & ~1) << 1) | plane;
++        if (addr >= s->vram_size) {
++            return 0xff;
++        }
++        ret = s->vram_ptr[addr];
+     } else {
+         /* standard VGA latched access */
++        if (addr * sizeof(uint32_t) >= s->vram_size) {
++            return 0xff;
++        }
+         s->latch = ((uint32_t *)s->vram_ptr)[addr];
+ 
+         if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
+@@ -910,6 +914,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
+         plane = addr & 3;
+         mask = (1 << plane);
+         if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
++            assert(addr < s->vram_size);
+             s->vram_ptr[addr] = val;
+ #ifdef DEBUG_VGA_MEM
+             printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
+@@ -923,6 +928,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
+         mask = (1 << plane);
+         if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
+             addr = ((addr & ~1) << 1) | plane;
++            if (addr >= s->vram_size) {
++                return;
++            }
+             s->vram_ptr[addr] = val;
+ #ifdef DEBUG_VGA_MEM
+             printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
+@@ -996,6 +1004,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
+         mask = s->sr[VGA_SEQ_PLANE_WRITE];
+         s->plane_updated |= mask; /* only used to detect font change */
+         write_mask = mask16[mask];
++        if (addr * sizeof(uint32_t) >= s->vram_size) {
++            return;
++        }
+         ((uint32_t *)s->vram_ptr)[addr] =
+             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
+             (val & write_mask);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch b/SOURCES/kvm-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch
index 131c165..2cbc550 100644
--- a/SOURCES/kvm-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch
+++ b/SOURCES/kvm-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch
@@ -1,13 +1,13 @@
-From d4916c5677937634c50737ac3caa9b6823789f4f Mon Sep 17 00:00:00 2001
+From 3c18025a495a2c105c2c33051ece0f3525d1e0c4 Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 29 Apr 2016 07:02:51 +0200
-Subject: [PATCH 6/6] vga: make sure vga register setup for vbe stays intact.
+Date: Thu, 28 Apr 2016 16:07:32 +0200
+Subject: [PATCH 27/27] vga: make sure vga register setup for vbe stays intact.
 
 RH-Author: Gerd Hoffmann <kraxel@redhat.com>
-Message-id: <1461913371-3145-7-git-send-email-kraxel@redhat.com>
-Patchwork-id: 70306
-O-Subject: [virt-devel] [RHEL-7.2.z qemu-kvm PATCH 6/6] vga: make sure vga register setup for vbe stays intact.
-Bugzilla: 1331412
+Message-id: <1461859652-20918-7-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70297
+O-Subject: [virt-devel] [RHEL-7.3 qemu-kvm PATCH 6/6] vga: make sure vga register setup for vbe stays intact.
+Bugzilla: 1331413
 RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
 RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
 RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
diff --git a/SOURCES/kvm-vga-update-vga-register-setup-on-vbe-changes.patch b/SOURCES/kvm-vga-update-vga-register-setup-on-vbe-changes.patch
index 5c5a293..648f3dd 100644
--- a/SOURCES/kvm-vga-update-vga-register-setup-on-vbe-changes.patch
+++ b/SOURCES/kvm-vga-update-vga-register-setup-on-vbe-changes.patch
@@ -1,13 +1,13 @@
-From 1dfb069237e2ddf979407841a2907cd332017924 Mon Sep 17 00:00:00 2001
+From 6bf28a8a9e2e6d6505f2a906b7fc532427037c5f Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 29 Apr 2016 07:02:50 +0200
-Subject: [PATCH 5/6] vga: update vga register setup on vbe changes
+Date: Thu, 28 Apr 2016 16:07:31 +0200
+Subject: [PATCH 26/27] vga: update vga register setup on vbe changes
 
 RH-Author: Gerd Hoffmann <kraxel@redhat.com>
-Message-id: <1461913371-3145-6-git-send-email-kraxel@redhat.com>
-Patchwork-id: 70305
-O-Subject: [virt-devel] [RHEL-7.2.z qemu-kvm PATCH 5/6] vga: update vga register setup on vbe changes
-Bugzilla: 1331412
+Message-id: <1461859652-20918-6-git-send-email-kraxel@redhat.com>
+Patchwork-id: 70296
+O-Subject: [virt-devel] [RHEL-7.3 qemu-kvm PATCH 5/6] vga: update vga register setup on vbe changes
+Bugzilla: 1331413
 RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
 RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
 RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
diff --git a/SOURCES/kvm-virtio-error-out-if-guest-exceeds-virtqueue-size.patch b/SOURCES/kvm-virtio-error-out-if-guest-exceeds-virtqueue-size.patch
index 7444829..85dee6d 100644
--- a/SOURCES/kvm-virtio-error-out-if-guest-exceeds-virtqueue-size.patch
+++ b/SOURCES/kvm-virtio-error-out-if-guest-exceeds-virtqueue-size.patch
@@ -1,7 +1,7 @@
-From 328d99710a005b9042c4d4c423f3f5a21f0e8ead Mon Sep 17 00:00:00 2001
+From acb67d9c43f3921861eebbabb447a85644e99320 Mon Sep 17 00:00:00 2001
 From: Stefan Hajnoczi <stefanha@redhat.com>
 Date: Mon, 25 Jul 2016 12:55:36 +0200
-Subject: [PATCH] virtio: error out if guest exceeds virtqueue size
+Subject: [PATCH 2/2] virtio: error out if guest exceeds virtqueue size
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
@@ -10,7 +10,7 @@ RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
 Message-id: <1469451336-20117-2-git-send-email-stefanha@redhat.com>
 Patchwork-id: 71428
 O-Subject: [virt-devel] [RHEL-7.3 EMBARGOED qemu-kvm PATCH 1/1] virtio: error out if guest exceeds virtqueue size
-Bugzilla: 1359728
+Bugzilla: 1359729
 RH-Acked-by: Thomas Huth <thuth@redhat.com>
 RH-Acked-by: Marc-André Lureau <mlureau@redhat.com>
 RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
diff --git a/SOURCES/kvm-virtio-recalculate-vq-inuse-after-migration.patch b/SOURCES/kvm-virtio-recalculate-vq-inuse-after-migration.patch
new file mode 100644
index 0000000..4bb6852
--- /dev/null
+++ b/SOURCES/kvm-virtio-recalculate-vq-inuse-after-migration.patch
@@ -0,0 +1,73 @@
+From 4d0430b1f847d672a39c76e6567bb5e88bc33c78 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Fri, 16 Sep 2016 08:38:18 +0200
+Subject: [PATCH] virtio: recalculate vq->inuse after migration
+
+RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
+Message-id: <1474015098-11019-2-git-send-email-stefanha@redhat.com>
+Patchwork-id: 72372
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/1] virtio: recalculate vq->inuse after migration
+Bugzilla: 1376542
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+The vq->inuse field is not migrated.  Many devices don't hold
+VirtQueueElements across migration so it doesn't matter that vq->inuse
+starts at 0 on the destination QEMU.
+
+At least virtio-serial, virtio-blk, and virtio-balloon migrate while
+holding VirtQueueElements.  For these devices we need to recalculate
+vq->inuse upon load so the value is correct.
+
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+(cherry picked from commit bccdef6b1a204db0f41ffb6e24ce373e4d7890d4)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+
+Conflicts:
+
+  hw/virtio/virtio.c
+
+  Downstream does not have the vq->used_idx field which was added
+  upstream as a performance optimization reducing guest memory accesses.
+  Replace vq->used_idx with vring_used_idx(&vdev->vq[i]).
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/virtio/virtio.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index e67337b..0df4ed3 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -932,6 +932,21 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
+                              vdev->vq[i].last_avail_idx, nheads);
+                 return -1;
+             }
++
++            /*
++             * Some devices migrate VirtQueueElements that have been popped
++             * from the avail ring but not yet returned to the used ring.
++             */
++            vdev->vq[i].inuse = vdev->vq[i].last_avail_idx -
++                                vring_used_idx(&vdev->vq[i]);
++            if (vdev->vq[i].inuse > vdev->vq[i].vring.num) {
++                error_report("VQ %d size 0x%x < last_avail_idx 0x%x - "
++                             "used_idx 0x%x",
++                             i, vdev->vq[i].vring.num,
++                             vdev->vq[i].last_avail_idx,
++                             vring_used_idx(&vdev->vq[i]));
++                return -1;
++            }
+         } else if (vdev->vq[i].last_avail_idx) {
+             error_report("VQ %d address 0x0 "
+                          "inconsistent with Host index 0x%x",
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-virtio-scsi-Prevent-assertion-on-missed-events.patch b/SOURCES/kvm-virtio-scsi-Prevent-assertion-on-missed-events.patch
new file mode 100644
index 0000000..0f0cc02
--- /dev/null
+++ b/SOURCES/kvm-virtio-scsi-Prevent-assertion-on-missed-events.patch
@@ -0,0 +1,46 @@
+From 3fdd5ce3ece26d5fd0d7702e08167bf5e513f620 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 18 Apr 2016 02:50:12 +0200
+Subject: [PATCH 01/10] virtio-scsi: Prevent assertion on missed events
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1460947812-5704-1-git-send-email-famz@redhat.com>
+Patchwork-id: 70202
+O-Subject: [RHEL-7.3 qemu-kvm PATCH] virtio-scsi: Prevent assertion on missed events
+Bugzilla: 1312289
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
+
+From: Eric Farman <farman@linux.vnet.ibm.com>
+
+In some cases, an unplug can cause events to be dropped, which
+leads to an assertion failure when preparing to notify the guest
+kernel.
+
+Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 49fb65c7f985baa56d2964e0a85c1f098e3e2a9d)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/scsi/virtio-scsi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
+index 8232fc9..808eb54 100644
+--- a/hw/scsi/virtio-scsi.c
++++ b/hw/scsi/virtio-scsi.c
+@@ -530,7 +530,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
+     evt->event = event;
+     evt->reason = reason;
+     if (!dev) {
+-        assert(event == VIRTIO_SCSI_T_NO_EVENT);
++        assert(event == VIRTIO_SCSI_T_EVENTS_MISSED);
+     } else {
+         evt->lun[0] = 1;
+         evt->lun[1] = dev->id;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-virtio-validate-the-existence-of-handle_output-befor.patch b/SOURCES/kvm-virtio-validate-the-existence-of-handle_output-befor.patch
new file mode 100644
index 0000000..7927554
--- /dev/null
+++ b/SOURCES/kvm-virtio-validate-the-existence-of-handle_output-befor.patch
@@ -0,0 +1,59 @@
+From 612017cc4834cd5eabc12afc7dd6cebf890b42e5 Mon Sep 17 00:00:00 2001
+From: Xiao Wang <jasowang@redhat.com>
+Date: Fri, 19 Aug 2016 09:24:25 +0200
+Subject: [PATCH] virtio: validate the existence of handle_output before
+ calling it
+
+RH-Author: Xiao Wang <jasowang@redhat.com>
+Message-id: <1471598665-23846-1-git-send-email-jasowang@redhat.com>
+Patchwork-id: 72021
+O-Subject: [RHEL7.3 qemu-kvm PATCH] virtio: validate the existence of handle_output before calling it
+Bugzilla: 1367040
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Fam Zheng <famz@redhat.com>
+RH-Acked-by: Pankaj Gupta <pagupta@redhat.com>
+
+Bugzilla: 1367040
+Brew Build: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=11620539
+Test status: Tested by myself.
+
+We don't validate the existence of handle_output which may let a buggy
+guest to trigger a SIGSEV easily. E.g:
+
+1) write 10 to queue_sel to a virtio net device with only 1 queue
+2) setup an arbitrary pfn
+3) then notify queue 10
+
+Fixing this by validating the existence of handle_output before.
+
+Cc: qemu-stable@nongnu.org
+Cc: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Don Koch <dkoch@verizon.com>
+Reviewed-by: Fam Zheng <famz@redhat.com>
+(cherry picked from commit 9e0f5b8108e248b78444c9a2ec41a8309825736c)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ hw/virtio/virtio.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index a861870..e67337b 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -692,8 +692,9 @@ int virtio_queue_get_id(VirtQueue *vq)
+ 
+ void virtio_queue_notify_vq(VirtQueue *vq)
+ {
+-    if (vq->vring.desc) {
++    if (vq->vring.desc && vq->handle_output) {
+         VirtIODevice *vdev = vq->vdev;
++
+         trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
+         vq->handle_output(vdev, vq);
+     }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Check-descriptor-file-length-when-reading-it.patch b/SOURCES/kvm-vmdk-Check-descriptor-file-length-when-reading-it.patch
new file mode 100644
index 0000000..0d97d1a
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Check-descriptor-file-length-when-reading-it.patch
@@ -0,0 +1,56 @@
+From 86c71987b64382e1177f86e6bc00bfc19e20082d Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:18 +0100
+Subject: [PATCH 05/18] vmdk: Check descriptor file length when reading it
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-6-git-send-email-famz@redhat.com>
+Patchwork-id: 69171
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 05/18] vmdk: Check descriptor file length when reading it
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+Since a too small file cannot be a valid VMDK image, and also since the
+buffer's first 4 bytes will be unconditionally examined by
+vmdk_open_sparse, let's error out the small file case to be clear.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Don Koch <dkoch@verizon.com>
+Message-id: 1417649314-13704-5-git-send-email-famz@redhat.com
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 03c3359dfc490eaf922f88955d6a8cc51a37ce92)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 3dfbd41..db3cdc0 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -559,6 +559,14 @@ static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset,
+         return NULL;
+     }
+ 
++    if (size < 4) {
++        /* Both descriptor file and sparse image must be much larger than 4
++         * bytes, also callers of vmdk_read_desc want to compare the first 4
++         * bytes with VMDK4_MAGIC, let's error out if less is read. */
++        error_setg(errp, "File is too small, not a valid image");
++        return NULL;
++    }
++
+     size = MIN(size, (1 << 20) - 1);  /* avoid unbounded allocation */
+     buf = g_malloc(size + 1);
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Clean-up-descriptor-file-reading.patch b/SOURCES/kvm-vmdk-Clean-up-descriptor-file-reading.patch
new file mode 100644
index 0000000..cb60e19
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Clean-up-descriptor-file-reading.patch
@@ -0,0 +1,60 @@
+From 2aa26696846adf25a41fa082f4d42c98b2b05fe3 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:17 +0100
+Subject: [PATCH 04/18] vmdk: Clean up descriptor file reading
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-5-git-send-email-famz@redhat.com>
+Patchwork-id: 69170
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 04/18] vmdk: Clean up descriptor file reading
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+Zeroing a buffer that will be filled right after is not necessary, and
+allocating a power of two + 1 is naughty.
+
+Suggested-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Don Koch <dkoch@verizon.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Message-id: 1417649314-13704-4-git-send-email-famz@redhat.com
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 73b7bcad439e0edaced05049897090cc10d84b5b)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 3f34abf..3dfbd41 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -559,8 +559,8 @@ static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset,
+         return NULL;
+     }
+ 
+-    size = MIN(size, 1 << 20);  /* avoid unbounded allocation */
+-    buf = g_malloc0(size + 1);
++    size = MIN(size, (1 << 20) - 1);  /* avoid unbounded allocation */
++    buf = g_malloc(size + 1);
+ 
+     ret = bdrv_pread(file, desc_offset, buf, size);
+     if (ret < 0) {
+@@ -568,6 +568,7 @@ static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset,
+         g_free(buf);
+         return NULL;
+     }
++    buf[ret] = 0;
+ 
+     return buf;
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Create-streamOptimized-as-version-3.patch b/SOURCES/kvm-vmdk-Create-streamOptimized-as-version-3.patch
new file mode 100644
index 0000000..4df8e5a
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Create-streamOptimized-as-version-3.patch
@@ -0,0 +1,51 @@
+From 7777177c3c7291ff5c4b24040b075a1bd1c1db77 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:29 +0100
+Subject: [PATCH 16/18] vmdk: Create streamOptimized as version 3
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-17-git-send-email-famz@redhat.com>
+Patchwork-id: 69182
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 16/18] vmdk: Create streamOptimized as version 3
+Bugzilla: 1299116
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299116
+
+VMware products accept only version 3 for streamOptimized, let's bump
+the version.
+
+Reported-by: Radoslav Gerganov <rgerganov@vmware.com>
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit d62d9dc4b814950dcc8bd261a3e2e9300d9065e6)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 7009660..7b3e397 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -1658,7 +1658,13 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
+     }
+     magic = cpu_to_be32(VMDK4_MAGIC);
+     memset(&header, 0, sizeof(header));
+-    header.version = zeroed_grain ? 2 : 1;
++    if (compress) {
++        header.version = 3;
++    } else if (zeroed_grain) {
++        header.version = 2;
++    } else {
++        header.version = 1;
++    }
+     header.flags = VMDK4_FLAG_RGD | VMDK4_FLAG_NL_DETECT
+                    | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0)
+                    | (zeroed_grain ? VMDK4_FLAG_ZERO_GRAIN : 0);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Fix-calculation-of-block-status-s-offset.patch b/SOURCES/kvm-vmdk-Fix-calculation-of-block-status-s-offset.patch
new file mode 100644
index 0000000..ed9910c
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Fix-calculation-of-block-status-s-offset.patch
@@ -0,0 +1,60 @@
+From 0cdb7038a7027cbb63c820e60bb34abd191ac85f Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:31 +0100
+Subject: [PATCH 18/18] vmdk: Fix calculation of block status's offset
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-19-git-send-email-famz@redhat.com>
+Patchwork-id: 69184
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 18/18] vmdk: Fix calculation of block status's offset
+Bugzilla: 1299116
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+"offset" is the offset of cluster and sector_num doesn't necessarily
+refer to the start of it, it should add index_in_cluster.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Message-id: 1453780743-16806-12-git-send-email-famz@redhat.com
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+(cherry picked from commit d0a18f10251f515c86dcaec5bdf979a4e07fafc5)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index b0c312b..b4f0d44 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -1275,6 +1275,7 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
+                              0, 0);
+     qemu_co_mutex_unlock(&s->lock);
+ 
++    index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
+     switch (ret) {
+     case VMDK_ERROR:
+         ret = -EIO;
+@@ -1288,13 +1289,14 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
+     case VMDK_OK:
+         ret = BDRV_BLOCK_DATA;
+         if (extent->file == bs->file && !extent->compressed) {
+-            ret |= BDRV_BLOCK_OFFSET_VALID | offset;
++            ret |= BDRV_BLOCK_OFFSET_VALID;
++            ret |= (offset + (index_in_cluster << BDRV_SECTOR_BITS))
++                    & BDRV_BLOCK_OFFSET_MASK;
+         }
+ 
+         break;
+     }
+ 
+-    index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
+     n = extent->cluster_sectors - index_in_cluster;
+     if (n > nb_sectors) {
+         n = nb_sectors;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Fix-comment-to-match-code-of-extent-lines.patch b/SOURCES/kvm-vmdk-Fix-comment-to-match-code-of-extent-lines.patch
new file mode 100644
index 0000000..85330ef
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Fix-comment-to-match-code-of-extent-lines.patch
@@ -0,0 +1,56 @@
+From ad76b22d2d96499bbbd1172f347b4ec8a2327c7d Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:16 +0100
+Subject: [PATCH 03/18] vmdk: Fix comment to match code of extent lines
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-4-git-send-email-famz@redhat.com>
+Patchwork-id: 69169
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 03/18] vmdk: Fix comment to match code of extent lines
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+commit 04d542c8b (vmdk: support vmfs files) added support of VMFS extent
+type but the comment above the changed code is left out. Update the
+comment so they are consistent.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Don Koch <dkoch@verizon.com>
+Message-id: 1417649314-13704-3-git-send-email-famz@redhat.com
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 8a3e0bc370de9274170b82f48b0393204c3fb43b)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index a9f5bab..3f34abf 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -788,10 +788,12 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
+     VmdkExtent *extent;
+ 
+     while (*p) {
+-        /* parse extent line:
++        /* parse extent line in one of below formats:
++         *
+          * RW [size in sectors] FLAT "file-name.vmdk" OFFSET
+-         * or
+          * RW [size in sectors] SPARSE "file-name.vmdk"
++         * RW [size in sectors] VMFS "file-name.vmdk"
++         * RW [size in sectors] VMFSSPARSE "file-name.vmdk"
+          */
+         flat_offset = -1;
+         ret = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Fix-converting-to-streamOptimized.patch b/SOURCES/kvm-vmdk-Fix-converting-to-streamOptimized.patch
new file mode 100644
index 0000000..ab886e7
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Fix-converting-to-streamOptimized.patch
@@ -0,0 +1,65 @@
+From b72998772910dbd04c86a2332b1c69ac1afc7a9e Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:30 +0100
+Subject: [PATCH 17/18] vmdk: Fix converting to streamOptimized
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-18-git-send-email-famz@redhat.com>
+Patchwork-id: 69183
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 17/18] vmdk: Fix converting to streamOptimized
+Bugzilla: 1299116
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299116
+
+Commit d62d9dc4b8 lifted streamOptimized images's version to 3, but we
+now refuse to open version 3 images read-write.  We need to make
+streamOptimized an exception to allow converting to it. This fixes the
+accidentally broken iotests case 059 for the same reason.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+(cherry picked from commit 3db1d98a20262228373bb973ca62b1ab64b29af4)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 7b3e397..b0c312b 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -592,6 +592,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
+     VmdkExtent *extent;
+     BDRVVmdkState *s = bs->opaque;
+     int64_t l1_backup_offset = 0;
++    bool compressed;
+ 
+     ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
+     if (ret < 0) {
+@@ -666,6 +667,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
+         header = footer.header;
+     }
+ 
++    compressed =
++        le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
+     if (le32_to_cpu(header.version) > 3) {
+         char buf[64];
+         snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
+@@ -673,7 +676,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
+         error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
+                   bs->device_name, "vmdk", buf);
+         return -ENOTSUP;
+-    } else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) {
++    } else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR) &&
++               !compressed) {
+         /* VMware KB 2064959 explains that version 3 added support for
+          * persistent changed block tracking (CBT), and backup software can
+          * read it as version=1 if it doesn't care about the changed area
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Fix-index_in_cluster-calculation-in-vmdk_co_get.patch b/SOURCES/kvm-vmdk-Fix-index_in_cluster-calculation-in-vmdk_co_get.patch
new file mode 100644
index 0000000..311534c
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Fix-index_in_cluster-calculation-in-vmdk_co_get.patch
@@ -0,0 +1,65 @@
+From 32791762f04b3342e9b10d1f553326cd01ea451f Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:26 +0100
+Subject: [PATCH 13/18] vmdk: Fix index_in_cluster calculation in
+ vmdk_co_get_block_status
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-14-git-send-email-famz@redhat.com>
+Patchwork-id: 69179
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 13/18] vmdk: Fix index_in_cluster calculation in vmdk_co_get_block_status
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+It has the similar issue with b1649fae49a8. Since the calculation
+is repeated for a few times already, introduce a function so it can be
+reused.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 61f0ed1d54601b91b8195c1a30d7046f83283b40)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index dd8b638..10c08f3 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -1242,6 +1242,17 @@ static VmdkExtent *find_extent(BDRVVmdkState *s,
+     return NULL;
+ }
+ 
++static inline uint64_t vmdk_find_index_in_cluster(VmdkExtent *extent,
++                                                  int64_t sector_num)
++{
++    uint64_t index_in_cluster, extent_begin_sector, extent_relative_sector_num;
++
++    extent_begin_sector = extent->end_sector - extent->sectors;
++    extent_relative_sector_num = sector_num - extent_begin_sector;
++    index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
++    return index_in_cluster;
++}
++
+ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
+         int64_t sector_num, int nb_sectors, int *pnum)
+ {
+@@ -1279,7 +1290,7 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
+         break;
+     }
+ 
+-    index_in_cluster = sector_num % extent->cluster_sectors;
++    index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
+     n = extent->cluster_sectors - index_in_cluster;
+     if (n > nb_sectors) {
+         n = nb_sectors;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Fix-next_cluster_sector-for-compressed-write.patch b/SOURCES/kvm-vmdk-Fix-next_cluster_sector-for-compressed-write.patch
new file mode 100644
index 0000000..044ab7a
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Fix-next_cluster_sector-for-compressed-write.patch
@@ -0,0 +1,70 @@
+From 47886bf3b19f06d0a5255d9656d1c02800baddd0 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:25 +0100
+Subject: [PATCH 12/18] vmdk: Fix next_cluster_sector for compressed write
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-13-git-send-email-famz@redhat.com>
+Patchwork-id: 69178
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 12/18] vmdk: Fix next_cluster_sector for compressed write
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+This fixes the bug introduced by commit c6ac36e (vmdk: Optimize cluster
+allocation).
+
+Sometimes, write_len could be larger than cluster size, because it
+contains both data and marker.  We must advance next_cluster_sector in
+this case, otherwise the image gets corrupted.
+
+Cc: qemu-stable@nongnu.org
+Reported-by: Antoni Villalonga <qemu-list@friki.cat>
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 5e82a31eb967db135fc4e688b134fb0972d62de3)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 3810d75..dd8b638 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -1297,6 +1297,8 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
+     uLongf buf_len;
+     const uint8_t *write_buf = buf;
+     int write_len = nb_sectors * 512;
++    int64_t write_offset;
++    int64_t write_end_sector;
+ 
+     if (extent->compressed) {
+         if (!extent->has_marker) {
+@@ -1315,10 +1317,14 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
+         write_buf = (uint8_t *)data;
+         write_len = buf_len + sizeof(VmdkGrainMarker);
+     }
+-    ret = bdrv_pwrite(extent->file,
+-                        cluster_offset + offset_in_cluster,
+-                        write_buf,
+-                        write_len);
++    write_offset = cluster_offset + offset_in_cluster,
++    ret = bdrv_pwrite(extent->file, write_offset, write_buf, write_len);
++
++    write_end_sector = DIV_ROUND_UP(write_offset + write_len, BDRV_SECTOR_SIZE);
++
++    extent->next_cluster_sector = MAX(extent->next_cluster_sector,
++                                      write_end_sector);
++
+     if (ret != write_len) {
+         ret = ret < 0 ? ret : -EIO;
+         goto out;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Fix-next_cluster_sector-for-compressed-write2.patch b/SOURCES/kvm-vmdk-Fix-next_cluster_sector-for-compressed-write2.patch
new file mode 100644
index 0000000..f926460
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Fix-next_cluster_sector-for-compressed-write2.patch
@@ -0,0 +1,55 @@
+From bc048d2d5f362757fa0bf51add81d92ec19ad161 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:28 +0100
+Subject: [PATCH 15/18] vmdk: Fix next_cluster_sector for compressed write
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-16-git-send-email-famz@redhat.com>
+Patchwork-id: 69181
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 15/18] vmdk: Fix next_cluster_sector for compressed write
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+From: Radoslav Gerganov <rgerganov@vmware.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+When the VMDK is streamOptimized (or compressed), the
+next_cluster_sector must not be incremented by a fixed number of
+sectors. Instead of this, it must be rounded up to the next consecutive
+sector. Fixing this results in much smaller compressed images.
+
+Signed-off-by: Radoslav Gerganov <rgerganov@vmware.com>
+Reviewed-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 3efffc3292d94271a15b1606b4a56adf6c6f04ed)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index cb5255c..7009660 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -1333,8 +1333,12 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
+ 
+     write_end_sector = DIV_ROUND_UP(write_offset + write_len, BDRV_SECTOR_SIZE);
+ 
+-    extent->next_cluster_sector = MAX(extent->next_cluster_sector,
+-                                      write_end_sector);
++    if (extent->compressed) {
++        extent->next_cluster_sector = write_end_sector;
++    } else {
++        extent->next_cluster_sector = MAX(extent->next_cluster_sector,
++                                          write_end_sector);
++    }
+ 
+     if (ret != write_len) {
+         ret = ret < 0 ? ret : -EIO;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Leave-bdi-intact-if-ENOTSUP-in-vmdk_get_info.patch b/SOURCES/kvm-vmdk-Leave-bdi-intact-if-ENOTSUP-in-vmdk_get_info.patch
new file mode 100644
index 0000000..9566d00
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Leave-bdi-intact-if-ENOTSUP-in-vmdk_get_info.patch
@@ -0,0 +1,74 @@
+From 824614c344ceeb60dd27b38cfdb190471b6a2ef9 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:14 +0100
+Subject: [PATCH 01/18] vmdk: Leave bdi intact if -ENOTSUP in vmdk_get_info
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-2-git-send-email-famz@redhat.com>
+Patchwork-id: 69167
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 01/18] vmdk: Leave bdi intact if -ENOTSUP in vmdk_get_info
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+When extent types don't match, we return -ENOTSUP. In this case, be
+polite to the caller and don't modify bdi.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Message-id: 1415938161-16217-1-git-send-email-famz@redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 5f58330790b72c4705b373ee0646fb3adf800b4e)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 6b015ab..fa53d2f 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -2137,23 +2137,29 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
+     return spec_info;
+ }
+ 
++static bool vmdk_extents_type_eq(const VmdkExtent *a, const VmdkExtent *b)
++{
++    return a->flat == b->flat &&
++           a->compressed == b->compressed &&
++           (a->flat || a->cluster_sectors == b->cluster_sectors);
++}
++
+ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+ {
+     int i;
+     BDRVVmdkState *s = bs->opaque;
+     assert(s->num_extents);
+-    bdi->needs_compressed_writes = s->extents[0].compressed;
+-    if (!s->extents[0].flat) {
+-        bdi->cluster_size = s->extents[0].cluster_sectors << BDRV_SECTOR_BITS;
+-    }
++
+     /* See if we have multiple extents but they have different cases */
+     for (i = 1; i < s->num_extents; i++) {
+-        if (bdi->needs_compressed_writes != s->extents[i].compressed ||
+-            (bdi->cluster_size && bdi->cluster_size !=
+-                s->extents[i].cluster_sectors << BDRV_SECTOR_BITS)) {
++        if (!vmdk_extents_type_eq(&s->extents[0], &s->extents[i])) {
+             return -ENOTSUP;
+         }
+     }
++    bdi->needs_compressed_writes = s->extents[0].compressed;
++    if (!s->extents[0].flat) {
++        bdi->cluster_size = s->extents[0].cluster_sectors << BDRV_SECTOR_BITS;
++    }
+     return 0;
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Remove-unnecessary-initialization.patch b/SOURCES/kvm-vmdk-Remove-unnecessary-initialization.patch
new file mode 100644
index 0000000..2d5267e
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Remove-unnecessary-initialization.patch
@@ -0,0 +1,49 @@
+From aea042fc3e0a8454edb4e9884635af63128b15d3 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:19 +0100
+Subject: [PATCH 06/18] vmdk: Remove unnecessary initialization
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-7-git-send-email-famz@redhat.com>
+Patchwork-id: 69172
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 06/18] vmdk: Remove unnecessary initialization
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+It will be assigned to the return value of vmdk_read_desc.
+
+Suggested-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Don Koch <dkoch@verizon.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Message-id: 1417649314-13704-6-git-send-email-famz@redhat.com
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 9aeecbbc62ce52a94b2621a0d53567b5d4ed915d)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index db3cdc0..69d8a6e 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -916,7 +916,7 @@ exit:
+ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
+                      Error **errp)
+ {
+-    char *buf = NULL;
++    char *buf;
+     int ret;
+     BDRVVmdkState *s = bs->opaque;
+     uint32_t magic;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Set-errp-on-failures-in-vmdk_open_vmdk4.patch b/SOURCES/kvm-vmdk-Set-errp-on-failures-in-vmdk_open_vmdk4.patch
new file mode 100644
index 0000000..af942ef
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Set-errp-on-failures-in-vmdk_open_vmdk4.patch
@@ -0,0 +1,62 @@
+From 005308f5b469f749980310be141315e8bd46556f Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:20 +0100
+Subject: [PATCH 07/18] vmdk: Set errp on failures in vmdk_open_vmdk4
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-8-git-send-email-famz@redhat.com>
+Patchwork-id: 69173
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 07/18] vmdk: Set errp on failures in vmdk_open_vmdk4
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+Reported-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Don Koch <dkoch@verizon.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Message-id: 1417649314-13704-7-git-send-email-famz@redhat.com
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit d899d2e248b900c53dd9081bde9f110e05747433)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 69d8a6e..1247ea4 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -647,6 +647,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
+             bs->file->total_sectors * 512 - 1536,
+             &footer, sizeof(footer));
+         if (ret < 0) {
++            error_setg_errno(errp, -ret, "Failed to read footer");
+             return ret;
+         }
+ 
+@@ -658,6 +659,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
+             le32_to_cpu(footer.eos_marker.size) != 0  ||
+             le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM)
+         {
++            error_setg(errp, "Invalid footer");
+             return -EINVAL;
+         }
+ 
+@@ -688,6 +690,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
+     l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gt)
+                         * le64_to_cpu(header.granularity);
+     if (l1_entry_sectors == 0) {
++        error_setg(errp, "L1 entry size is invalid");
+         return -EINVAL;
+     }
+     l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Use-g_random_int-to-generate-CID.patch b/SOURCES/kvm-vmdk-Use-g_random_int-to-generate-CID.patch
new file mode 100644
index 0000000..0294a48
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Use-g_random_int-to-generate-CID.patch
@@ -0,0 +1,73 @@
+From bf9dd867ef8d4164685cac6451e88b6c32b190b1 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:15 +0100
+Subject: [PATCH 02/18] vmdk: Use g_random_int to generate CID
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-3-git-send-email-famz@redhat.com>
+Patchwork-id: 69168
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 02/18] vmdk: Use g_random_int to generate CID
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+This replaces two "time(NULL)" invocations with "g_random_int()".
+According to VMDK spec, CID "is a random 32‐bit value updated the first
+time the content of the virtual disk is modified after the virtual disk
+is opened". Using "seconds since epoch" is just a "lame way" to generate
+it, and not completely safe because of the low precision.
+
+Suggested-by: Markus Armbruster <armbru@redhat.com>
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Don Koch <dkoch@verizon.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Message-id: 1417649314-13704-2-git-send-email-famz@redhat.com
+Signed-off-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit e5dc64b8ff09cc4c186273e4461c7479739db2ae)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index fa53d2f..a9f5bab 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -28,6 +28,7 @@
+ #include "qemu/module.h"
+ #include "migration/migration.h"
+ #include <zlib.h>
++#include <glib.h>
+ 
+ #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
+ #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
+@@ -1540,7 +1541,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
+         /* update CID on the first write every time the virtual disk is
+          * opened */
+         if (!s->cid_updated) {
+-            ret = vmdk_write_cid(bs, time(NULL));
++            ret = vmdk_write_cid(bs, g_random_int());
+             if (ret < 0) {
+                 return ret;
+             }
+@@ -1927,7 +1928,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
+     }
+     /* generate descriptor file */
+     desc = g_strdup_printf(desc_template,
+-                           (uint32_t)time(NULL),
++                           g_random_int(),
+                            parent_cid,
+                            fmt,
+                            parent_desc_line,
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Use-vmdk_find_index_in_cluster-everywhere.patch b/SOURCES/kvm-vmdk-Use-vmdk_find_index_in_cluster-everywhere.patch
new file mode 100644
index 0000000..69ee291
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Use-vmdk_find_index_in_cluster-everywhere.patch
@@ -0,0 +1,71 @@
+From f7f34dfdb448a0344210f6bfa77b67c637ffea56 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:27 +0100
+Subject: [PATCH 14/18] vmdk: Use vmdk_find_index_in_cluster everywhere
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-15-git-send-email-famz@redhat.com>
+Patchwork-id: 69180
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 14/18] vmdk: Use vmdk_find_index_in_cluster everywhere
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: Max Reitz <mreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 90df601f06de14f062d2e8dc1bc57f0decf86fd1)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 10c08f3..cb5255c 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -1418,7 +1418,6 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
+     BDRVVmdkState *s = bs->opaque;
+     int ret;
+     uint64_t n, index_in_cluster;
+-    uint64_t extent_begin_sector, extent_relative_sector_num;
+     VmdkExtent *extent = NULL;
+     uint64_t cluster_offset;
+ 
+@@ -1430,9 +1429,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
+         ret = get_cluster_offset(bs, extent, NULL,
+                                  sector_num << 9, false, &cluster_offset,
+                                  0, 0);
+-        extent_begin_sector = extent->end_sector - extent->sectors;
+-        extent_relative_sector_num = sector_num - extent_begin_sector;
+-        index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
++        index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
+         n = extent->cluster_sectors - index_in_cluster;
+         if (n > nb_sectors) {
+             n = nb_sectors;
+@@ -1494,7 +1491,6 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
+     VmdkExtent *extent = NULL;
+     int ret;
+     int64_t index_in_cluster, n;
+-    uint64_t extent_begin_sector, extent_relative_sector_num;
+     uint64_t cluster_offset;
+     VmdkMetaData m_data;
+ 
+@@ -1510,9 +1506,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
+         if (!extent) {
+             return -EIO;
+         }
+-        extent_begin_sector = extent->end_sector - extent->sectors;
+-        extent_relative_sector_num = sector_num - extent_begin_sector;
+-        index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
++        index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
+         n = extent->cluster_sectors - index_in_cluster;
+         if (n > nb_sectors) {
+             n = nb_sectors;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/kvm-vmdk-Widen-before-shifting-32-bit-header-field.patch b/SOURCES/kvm-vmdk-Widen-before-shifting-32-bit-header-field.patch
new file mode 100644
index 0000000..3042981
--- /dev/null
+++ b/SOURCES/kvm-vmdk-Widen-before-shifting-32-bit-header-field.patch
@@ -0,0 +1,47 @@
+From 649835536d4bb1366e01ff5600d3005042dd50d5 Mon Sep 17 00:00:00 2001
+From: Fam Zheng <famz@redhat.com>
+Date: Mon, 15 Feb 2016 09:28:24 +0100
+Subject: [PATCH 11/18] vmdk: Widen before shifting 32 bit header field
+
+RH-Author: Fam Zheng <famz@redhat.com>
+Message-id: <1455528511-9357-12-git-send-email-famz@redhat.com>
+Patchwork-id: 69177
+O-Subject: [RHEL-7.3 qemu-kvm PATCH 11/18] vmdk: Widen before shifting 32 bit header field
+Bugzilla: 1299250
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Max Reitz <mreitz@redhat.com>
+RH-Acked-by: Markus Armbruster <armbru@redhat.com>
+
+BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1299250
+
+Coverity spotted this.
+
+The field is 32 bits, but if it's possible to overflow in 32 bit
+left shift.
+
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Reviewed-by: John Snow <jsnow@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 7237aecd7e8fcc3ccf7fded77b6c127b4df5d3ac)
+Signed-off-by: Fam Zheng <famz@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ block/vmdk.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 32b3d4c..3810d75 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -525,7 +525,7 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
+     }
+     ret = vmdk_add_extent(bs, file, false,
+                           le32_to_cpu(header.disk_sectors),
+-                          le32_to_cpu(header.l1dir_offset) << 9,
++                          (int64_t)le32_to_cpu(header.l1dir_offset) << 9,
+                           0,
+                           le32_to_cpu(header.l1dir_size),
+                           4096,
+-- 
+1.8.3.1
+
diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec
index 1345496..10713e5 100644
--- a/SPECS/qemu-kvm.spec
+++ b/SPECS/qemu-kvm.spec
@@ -76,7 +76,7 @@ Obsoletes: %1 < %{obsoletes_version}                                      \
 Summary: QEMU is a FAST! processor emulator
 Name: %{pkgname}%{?pkgsuffix}
 Version: 1.5.3
-Release: 105%{?dist}.7
+Release: 126%{?dist}
 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
 Epoch: 10
 License: GPLv2+ and LGPLv2+ and BSD
@@ -97,6 +97,7 @@ Requires: libseccomp >= 1.0.0
 %if 0%{!?build_only_sub:1}
 Requires: glusterfs-api >= 3.6.0
 %endif
+Requires: libusbx >= 1.0.19
 # OOM killer breaks builds with parallel make on s390(x)
 %ifarch s390 s390x
     %define _smp_mflags %{nil}
@@ -3161,32 +3162,232 @@ Patch1551: kvm-util-uri-Add-overflow-check-to-rfc3986_parse_port.patch
 Patch1552: kvm-qemu-iotests-Filter-qemu-io-output-in-025.patch
 # For bz#1270341 - qemu-kvm build failure race condition in tests/ide-test
 Patch1553: kvm-qtest-ide-test-disable-flush-test.patch
-# For bz#1279389 - ceph.conf properties override qemu's command-line properties
-Patch1554: kvm-rbd-make-qemu-s-cache-setting-override-any-ceph-sett.patch
-# For bz#1279389 - ceph.conf properties override qemu's command-line properties
-Patch1555: kvm-rbd-fix-ceph-settings-precedence.patch
-# For bz#1298828 - [abrt] qemu-img: get_block_status(): qemu-img killed by SIGABRT
-Patch1556: kvm-raw-posix-Fix-.bdrv_co_get_block_status-for-unaligne.patch
-# For bz#1298047 - CVE-2016-1714 qemu-kvm: Qemu: nvram: OOB r/w access in processing firmware configurations [rhel-7.2.z]
-Patch1557: kvm-fw_cfg-add-check-to-validate-current-entry-value-CVE.patch
-# For bz#1331412 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.2.z]
-Patch1558: kvm-vga-Remove-some-should-be-done-in-BIOS-comments.patch
-# For bz#1331412 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.2.z]
-Patch1559: kvm-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch
-# For bz#1331412 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.2.z]
-Patch1560: kvm-vga-add-vbe_enabled-helper.patch
-# For bz#1331412 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.2.z]
-Patch1561: kvm-vga-factor-out-vga-register-setup.patch
-# For bz#1331412 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.2.z]
-Patch1562: kvm-vga-update-vga-register-setup-on-vbe-changes.patch
-# For bz#1331412 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.2.z]
-Patch1563: kvm-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch
-# For bz#1347527 - Regression from CVE-2016-3712: windows installer fails to start
-Patch1564: kvm-vga-add-sr_vbe-register-set.patch
-# For bz#1359728 - EMBARGOED CVE-2016-5403 qemu-kvm: Qemu: virtio: unbounded memory allocation on host via guest leading to DoS [rhel-7.2.z]
-Patch1565: kvm-virtio-error-out-if-guest-exceeds-virtqueue-size.patch
-# For bz#1358996 - CVE-2016-5126 qemu-kvm: Qemu: block: iscsi: buffer overflow in iscsi_aio_ioctl [rhel-7.2.z]
-Patch1566: kvm-block-iscsi-avoid-potential-overflow-of-acb-task-cdb.patch
+# For bz#1268879 - Camera stops work after remote-viewer re-connection [qemu-kvm]
+Patch1554: kvm-ehci-clear-suspend-bit-on-detach.patch
+# For bz#1277248 - ceph.conf properties override qemu's command-line properties
+Patch1555: kvm-rbd-make-qemu-s-cache-setting-override-any-ceph-sett.patch
+# For bz#1277248 - ceph.conf properties override qemu's command-line properties
+Patch1556: kvm-rbd-fix-ceph-settings-precedence.patch
+# For bz#1265427 - contents of MSR_TSC_AUX are not migrated
+Patch1557: kvm-target-i386-get-put-MSR_TSC_AUX-across-reset-and-mig.patch
+# For bz#1252757 - [RHEL-7.2-qmu-kvm] Package is 100% lost when ping from host to Win2012r2 guest with 64000 size
+Patch1558: kvm-rtl8139-Fix-receive-buffer-overflow-check.patch
+# For bz#1252757 - [RHEL-7.2-qmu-kvm] Package is 100% lost when ping from host to Win2012r2 guest with 64000 size
+Patch1559: kvm-rtl8139-Do-not-consume-the-packet-during-overflow-in.patch
+# For bz#1283116 - [abrt] qemu-img: get_block_status(): qemu-img killed by SIGABRT
+Patch1560: kvm-raw-posix-Fix-.bdrv_co_get_block_status-for-unaligne.patch
+# For bz#1269738 - Vlan table display repeat four times in qmp when queues=4
+Patch1561: kvm-net-Make-qmp_query_rx_filter-with-name-argument-more.patch
+# For bz#1298048 - CVE-2016-1714 qemu-kvm: Qemu: nvram: OOB r/w access in processing firmware configurations [rhel-7.3]
+Patch1562: kvm-fw_cfg-add-check-to-validate-current-entry-value-CVE.patch
+# For bz#1296044 - qemu-kvm: insufficient loop termination conditions in start_xmit() and e1000_receive() [rhel-7.3]
+Patch1563: kvm-e1000-eliminate-infinite-loops-on-out-of-bounds-tran.patch
+# For bz#1285453 - An NBD client can cause QEMU main loop to block when connecting to built-in NBD server
+Patch1564: kvm-nbd-Always-call-close_fn-in-nbd_client_new.patch
+# For bz#1285453 - An NBD client can cause QEMU main loop to block when connecting to built-in NBD server
+Patch1565: kvm-nbd-server-Coroutine-based-negotiation.patch
+# For bz#1285453 - An NBD client can cause QEMU main loop to block when connecting to built-in NBD server
+Patch1566: kvm-nbd-client_close-on-error-in-nbd_co_client_start.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1567: kvm-qemu-io-Remove-unused-args_command.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1568: kvm-cutils-Support-P-and-E-suffixes-in-strtosz.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1569: kvm-qemu-io-Make-cvtnum-a-wrapper-around-strtosz_suffix.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1570: kvm-qemu-io-Handle-cvtnum-errors-in-alloc.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1571: kvm-qemu-io-Don-t-use-global-bs-in-command-implementatio.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1572: kvm-qemu-io-Split-off-commands-to-qemu-io-cmds.c.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1573: kvm-qemu-io-Factor-out-qemuio_command.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1574: kvm-qemu-io-Move-help-function.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1575: kvm-qemu-io-Move-quit-function.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1576: kvm-qemu-io-Move-qemu_strsep-to-cutils.c.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1577: kvm-qemu-io-Move-functions-for-registering-and-running-c.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1578: kvm-qemu-io-Move-command_loop-and-friends.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1579: kvm-qemu-io-Move-remaining-helpers-from-cmd.c.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1580: kvm-qemu-io-Interface-cleanup.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1581: kvm-qemu-io-Use-the-qemu-version-for-V.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1582: kvm-Make-qemu-io-commands-available-in-HMP.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1583: kvm-blkdebug-Add-BLKDBG_FLUSH_TO_OS-DISK-events.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1584: kvm-qemu-io-fix-cvtnum-lval-types.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1585: kvm-qemu-io-Check-for-trailing-chars.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1586: kvm-qemu-io-Correct-error-messages.patch
+# For bz#1272523 - qemu-kvm build failure race condition in tests/ide-test
+Patch1587: kvm-ide-test-fix-failure-for-test_flush.patch
+# For bz#1331413 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.3]
+Patch1588: kvm-vga-Remove-some-should-be-done-in-BIOS-comments.patch
+# For bz#1331413 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.3]
+Patch1589: kvm-vga-fix-banked-access-bounds-checking-CVE-2016-xxxx.patch
+# For bz#1331413 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.3]
+Patch1590: kvm-vga-add-vbe_enabled-helper.patch
+# For bz#1331413 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.3]
+Patch1591: kvm-vga-factor-out-vga-register-setup.patch
+# For bz#1331413 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.3]
+Patch1592: kvm-vga-update-vga-register-setup-on-vbe-changes.patch
+# For bz#1331413 - EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.3]
+Patch1593: kvm-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1594: kvm-vmdk-Leave-bdi-intact-if-ENOTSUP-in-vmdk_get_info.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1595: kvm-vmdk-Use-g_random_int-to-generate-CID.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1596: kvm-vmdk-Fix-comment-to-match-code-of-extent-lines.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1597: kvm-vmdk-Clean-up-descriptor-file-reading.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1598: kvm-vmdk-Check-descriptor-file-length-when-reading-it.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1599: kvm-vmdk-Remove-unnecessary-initialization.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1600: kvm-vmdk-Set-errp-on-failures-in-vmdk_open_vmdk4.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1601: kvm-block-vmdk-make-ret-variable-usage-clear.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1602: kvm-block-vmdk-move-string-allocations-from-stack-to-the.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1603: kvm-block-vmdk-fixed-sizeof-error.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1604: kvm-vmdk-Widen-before-shifting-32-bit-header-field.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1605: kvm-vmdk-Fix-next_cluster_sector-for-compressed-write.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1606: kvm-vmdk-Fix-index_in_cluster-calculation-in-vmdk_co_get.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1607: kvm-vmdk-Use-vmdk_find_index_in_cluster-everywhere.patch
+# For bz#1299250 - qemu-img created VMDK images are unbootable
+Patch1608: kvm-vmdk-Fix-next_cluster_sector-for-compressed-write2.patch
+# For bz#1299116 - qemu-img created VMDK images lead to "Not a supported disk format (sparse VMDK version too old)"
+Patch1609: kvm-vmdk-Create-streamOptimized-as-version-3.patch
+# For bz#1299116 - qemu-img created VMDK images lead to "Not a supported disk format (sparse VMDK version too old)"
+Patch1610: kvm-vmdk-Fix-converting-to-streamOptimized.patch
+# For bz#1299116 - qemu-img created VMDK images lead to "Not a supported disk format (sparse VMDK version too old)"
+Patch1611: kvm-vmdk-Fix-calculation-of-block-status-s-offset.patch
+# For bz#1312289 - "qemu-kvm: /builddir/build/BUILD/qemu-1.5.3/hw/scsi/virtio-scsi.c:533: virtio_scsi_push_event: Assertion `event == 0' failed" after hotplug 20 virtio-scsi disks then hotunplug them
+Patch1612: kvm-virtio-scsi-Prevent-assertion-on-missed-events.patch
+# For bz#1177318 - Guest using rbd based image as disk failed to start when sandbox was enabled
+Patch1613: kvm-seccomp-adding-sysinfo-system-call-to-whitelist.patch
+# For bz#1330969 - match the OEM ID and OEM Table ID fields of the FADT and the RSDT to those of the SLIC
+Patch1614: kvm-acpi-strip-compiler-info-in-built-in-DSDT.patch
+# For bz#1330969 - match the OEM ID and OEM Table ID fields of the FADT and the RSDT to those of the SLIC
+Patch1615: kvm-acpi-fix-endian-ness-for-table-ids.patch
+# For bz#1330969 - match the OEM ID and OEM Table ID fields of the FADT and the RSDT to those of the SLIC
+Patch1616: kvm-acpi-support-specified-oem-table-id-for-build_header.patch
+# For bz#1330969 - match the OEM ID and OEM Table ID fields of the FADT and the RSDT to those of the SLIC
+Patch1617: kvm-acpi-take-oem_id-in-build_header-optionally.patch
+# For bz#1330969 - match the OEM ID and OEM Table ID fields of the FADT and the RSDT to those of the SLIC
+Patch1618: kvm-acpi-expose-oem_id-and-oem_table_id-in-build_rsdt.patch
+# For bz#1330969 - match the OEM ID and OEM Table ID fields of the FADT and the RSDT to those of the SLIC
+Patch1619: kvm-acpi-add-function-to-extract-oem_id-and-oem_table_id.patch
+# For bz#1330969 - match the OEM ID and OEM Table ID fields of the FADT and the RSDT to those of the SLIC
+Patch1620: kvm-pc-set-the-OEM-fields-in-the-RSDT-and-the-FADT-from-.patch
+# For bz#1156635 - Libvirt is confused that qemu-kvm exposes 'block-job-cancel' but not 'block-stream'
+Patch1621: kvm-block-jobs-qemu-kvm-rhel-differentiation.patch
+# For bz#1283198 - RFE: backport max monitor limitation from Qemu upstream
+Patch1622: kvm-qxl-allow-to-specify-head-limit-to-qxl-driver.patch
+# For bz#1283198 - RFE: backport max monitor limitation from Qemu upstream
+Patch1623: kvm-qxl-Fix-new-function-name-for-spice-server-library.patch
+# For bz#1268345 - posix_fallocate emulation on NFS fails with Bad file descriptor if fd is opened O_WRONLY
+Patch1624: kvm-block-raw-posix-Open-file-descriptor-O_RDWR-to-work-.patch
+# For bz#1256741 - "CapsLock" will work as "\" when boot a guest with usb-kbd
+Patch1625: kvm-hw-input-hid.c-Fix-capslock-hid-code.patch
+# For bz#1340971 - qemu: accel=tcg does not implement SSE 4 properly
+Patch1626: kvm-target-i386-fix-pcmpxstrx-equal-ordered-strstr-mode.patch
+# For bz#1336491 - Ship FD connection patches qemu-kvm part
+Patch1627: kvm-spice-do-not-require-TCP-ports.patch
+# For bz#1346982 - Regression from CVE-2016-3712: windows installer fails to start
+Patch1628: kvm-vga-add-sr_vbe-register-set.patch
+# For bz#1340929 - CVE-2016-5126 qemu-kvm: Qemu: block: iscsi: buffer overflow in iscsi_aio_ioctl [rhel-7.3]
+Patch1629: kvm-block-iscsi-avoid-potential-overflow-of-acb-task-cdb.patch
+# For bz#1327599 - Add Skylake CPU model
+Patch1630: kvm-target-i386-add-feature-flags-for-CPUID-EAX-0xd-ECX-.patch
+# For bz#1327599 - Add Skylake CPU model
+Patch1631: kvm-target-i386-add-Skylake-Client-cpu-model.patch
+# For bz#1318199 - expose host BLKSECTGET limit in scsi-block (qemu-kvm)
+Patch1632: kvm-util-introduce-MIN_NON_ZERO.patch
+# For bz#1318199 - expose host BLKSECTGET limit in scsi-block (qemu-kvm)
+Patch1633: kvm-BlockLimits-introduce-max_transfer_length.patch
+# For bz#1318199 - expose host BLKSECTGET limit in scsi-block (qemu-kvm)
+Patch1634: kvm-block-backend-expose-bs-bl.max_transfer_length.patch
+# For bz#1318199 - expose host BLKSECTGET limit in scsi-block (qemu-kvm)
+Patch1635: kvm-scsi-generic-Merge-block-max-xfer-len-in-INQUIRY-res.patch
+# For bz#1318199 - expose host BLKSECTGET limit in scsi-block (qemu-kvm)
+Patch1636: kvm-raw-posix-Fetch-max-sectors-for-host-block-device.patch
+# For bz#1318199 - expose host BLKSECTGET limit in scsi-block (qemu-kvm)
+Patch1637: kvm-scsi-Advertise-limits-by-blocksize-not-512.patch
+# For bz#1318199 - expose host BLKSECTGET limit in scsi-block (qemu-kvm)
+Patch1638: kvm-util-Fix-MIN_NON_ZERO.patch
+# For bz#1355730 - spice-gtk shows outdated screen state after migration [qemu-kvm]
+Patch1639: kvm-qxl-factor-out-qxl_get_check_slot_offset.patch
+# For bz#1355730 - spice-gtk shows outdated screen state after migration [qemu-kvm]
+Patch1640: kvm-qxl-store-memory-region-and-offset-instead-of-pointe.patch
+# For bz#1355730 - spice-gtk shows outdated screen state after migration [qemu-kvm]
+Patch1641: kvm-qxl-fix-surface-migration.patch
+# For bz#1355730 - spice-gtk shows outdated screen state after migration [qemu-kvm]
+Patch1642: kvm-qxl-fix-qxl_set_dirty-call-in-qxl_dirty_one_surface.patch
+# For bz#1359729 - CVE-2016-5403 qemu-kvm: Qemu: virtio: unbounded memory allocation on host via guest leading to DoS [rhel-7.3]
+Patch1643: kvm-virtio-error-out-if-guest-exceeds-virtqueue-size.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1644: kvm-json-parser-drop-superfluous-assignment-for-token-va.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1645: kvm-qjson-Apply-nesting-limit-more-sanely.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1646: kvm-qjson-Don-t-crash-when-input-exceeds-nesting-limit.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1647: kvm-check-qjson-Add-test-for-JSON-nesting-depth-limit.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1648: kvm-qjson-Spell-out-some-silent-assumptions.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1649: kvm-qjson-Give-each-of-the-six-structural-chars-its-own-.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1650: kvm-qjson-Inline-token_is_keyword-and-simplify.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1651: kvm-qjson-Inline-token_is_escape-and-simplify.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1652: kvm-qjson-replace-QString-in-JSONLexer-with-GString.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1653: kvm-qjson-Convert-to-parser-to-recursive-descent.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1654: kvm-qjson-store-tokens-in-a-GQueue.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1655: kvm-qjson-surprise-allocating-6-QObjects-per-token-is-ex.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1656: kvm-qjson-Limit-number-of-tokens-in-addition-to-total-si.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1657: kvm-json-streamer-Don-t-leak-tokens-on-incomplete-parse.patch
+# For bz#1276036 - Crash on QMP input exceeding limits
+Patch1658: kvm-json-streamer-fix-double-free-on-exiting-during-a-pa.patch
+# For bz#1360137 - GLib-WARNING **: gmem.c:482: custom memory allocation vtable not supported
+Patch1659: kvm-trace-remove-malloc-tracing.patch
+# For bz#1367040 - QEMU crash when guest notifies non-existent virtqueue
+Patch1660: kvm-virtio-validate-the-existence-of-handle_output-befor.patch
+# For bz#1371619 - Flags xsaveopt xsavec xgetbv1 are missing on qemu-kvm
+Patch1661: kvm-Fix-backport-of-target-i386-add-feature-flags-for-CP.patch
+# For bz#1373088 - [FJ7.3 Bug]: virsh dump with both --memory-only and --format option fails
+Patch1662: kvm-Add-skip_dump-flag-to-ignore-memory-region-during-du.patch
+# For bz#1372459 - [Intel 7.3 Bug] SKL-SP Guest cpu doesn't support avx512 instruction sets(avx512bw, avx512dq and avx512vl) (qemu-kvm)
+Patch1663: kvm-target-i386-Add-support-for-FEAT_7_0_ECX.patch
+# For bz#1372459 - [Intel 7.3 Bug] SKL-SP Guest cpu doesn't support avx512 instruction sets(avx512bw, avx512dq and avx512vl) (qemu-kvm)
+Patch1664: kvm-target-i386-Add-more-Intel-AVX-512-instructions-supp.patch
+# For bz#1285453 - An NBD client can cause QEMU main loop to block when connecting to built-in NBD server
+Patch1665: kvm-nbd-server-Set-O_NONBLOCK-on-client-fd.patch
+# For bz#1376542 - RHSA-2016-1756 breaks migration of instances
+Patch1666: kvm-virtio-recalculate-vq-inuse-after-migration.patch
 
 
 BuildRequires: zlib-devel
@@ -3366,37 +3567,6 @@ This package contains some diagnostics and debugging tools for KVM,
 such as kvm_stat.
 %endif
 
-%package -n libcacard%{?pkgsuffix}
-Summary:        Common Access Card (CAC) Emulation
-Group:          Development/Libraries
-
-%rhel_rhev_conflicts libcacard
-
-%description -n libcacard%{?pkgsuffix}
-Common Access Card (CAC) emulation library.
-
-%package -n libcacard-tools%{?pkgsuffix}
-Summary:        CAC Emulation tools
-Group:          Development/Libraries
-Requires:       libcacard = %{epoch}:%{version}-%{release}
-# older qemu-img has vscclient which is now in libcacard-tools
-Requires:       qemu-img >= 3:1.3.0-5
-
-%rhel_rhev_conflicts libcacard-tools
-
-%description -n libcacard-tools%{?pkgsuffix}
-CAC emulation tools.
-
-%package -n libcacard-devel%{?pkgsuffix}
-Summary:        CAC Emulation devel
-Group:          Development/Libraries
-Requires:       libcacard = %{epoch}:%{version}-%{release}
-
-%rhel_rhev_conflicts libcacard-devel
-
-%description -n libcacard-devel%{?pkgsuffix}
-CAC emulation development files.
-
 %prep
 %setup -q -n qemu-%{version}
 cp %{SOURCE18} pc-bios # keep "make check" happy
@@ -4966,6 +5136,106 @@ cp %{SOURCE18} pc-bios # keep "make check" happy
 %patch1564 -p1
 %patch1565 -p1
 %patch1566 -p1
+%patch1567 -p1
+%patch1568 -p1
+%patch1569 -p1
+%patch1570 -p1
+%patch1571 -p1
+%patch1572 -p1
+%patch1573 -p1
+%patch1574 -p1
+%patch1575 -p1
+%patch1576 -p1
+%patch1577 -p1
+%patch1578 -p1
+%patch1579 -p1
+%patch1580 -p1
+%patch1581 -p1
+%patch1582 -p1
+%patch1583 -p1
+%patch1584 -p1
+%patch1585 -p1
+%patch1586 -p1
+%patch1587 -p1
+%patch1588 -p1
+%patch1589 -p1
+%patch1590 -p1
+%patch1591 -p1
+%patch1592 -p1
+%patch1593 -p1
+%patch1594 -p1
+%patch1595 -p1
+%patch1596 -p1
+%patch1597 -p1
+%patch1598 -p1
+%patch1599 -p1
+%patch1600 -p1
+%patch1601 -p1
+%patch1602 -p1
+%patch1603 -p1
+%patch1604 -p1
+%patch1605 -p1
+%patch1606 -p1
+%patch1607 -p1
+%patch1608 -p1
+%patch1609 -p1
+%patch1610 -p1
+%patch1611 -p1
+%patch1612 -p1
+%patch1613 -p1
+%patch1614 -p1
+%patch1615 -p1
+%patch1616 -p1
+%patch1617 -p1
+%patch1618 -p1
+%patch1619 -p1
+%patch1620 -p1
+%patch1621 -p1
+%patch1622 -p1
+%patch1623 -p1
+%patch1624 -p1
+%patch1625 -p1
+%patch1626 -p1
+%patch1627 -p1
+%patch1628 -p1
+%patch1629 -p1
+%patch1630 -p1
+%patch1631 -p1
+%patch1632 -p1
+%patch1633 -p1
+%patch1634 -p1
+%patch1635 -p1
+%patch1636 -p1
+%patch1637 -p1
+%patch1638 -p1
+%patch1639 -p1
+%patch1640 -p1
+%patch1641 -p1
+%patch1642 -p1
+%patch1643 -p1
+%patch1644 -p1
+%patch1645 -p1
+%patch1646 -p1
+%patch1647 -p1
+%patch1648 -p1
+%patch1649 -p1
+%patch1650 -p1
+%patch1651 -p1
+%patch1652 -p1
+%patch1653 -p1
+%patch1654 -p1
+%patch1655 -p1
+%patch1656 -p1
+%patch1657 -p1
+%patch1658 -p1
+%patch1659 -p1
+%patch1660 -p1
+%patch1661 -p1
+%patch1662 -p1
+%patch1663 -p1
+%patch1664 -p1
+%patch1665 -p1
+%patch1666 -p1
 
 %build
 buildarch="%{kvm_target}-softmmu"
@@ -5065,8 +5335,6 @@ dobuild() {
                --disable-guest-agent \
                "$@"
 
-   make libcacard.la %{?_smp_mflags} $buildldflags
-   make vscclient %{?_smp_mflags} $buildldflags
    make qemu-img %{?_smp_mflags} $buildldflags
    make qemu-io %{?_smp_mflags} $buildldflags
    make qemu-nbd %{?_smp_mflags} $buildldflags
@@ -5215,6 +5483,12 @@ dobuild --target-list="$buildarch"
     rom_link ../sgabios/sgabios.bin sgabios.bin
 %endif
 
+# Remove libcacard
+rm -rf $RPM_BUILD_ROOT%{_bindir}/vscclient
+rm -rf $RPM_BUILD_ROOT%{_includedir}/cacard
+rm -rf $RPM_BUILD_ROOT%{_libdir}/libcacard.so*
+rm -rf $RPM_BUILD_ROOT%{_libdir}/pkgconfig/libcacard.pc
+
 %if %{with guest_agent}
     # For the qemu-guest-agent subpackage, install:
     # - the systemd service file and the udev rules:
@@ -5250,8 +5524,6 @@ dobuild --target-list="$buildarch"
     install -m 0644 %{SOURCE12} $RPM_BUILD_ROOT%{_sysconfdir}/%{pkgname}
 %endif
 
-make %{?_smp_mflags} $buildldflags DESTDIR=$RPM_BUILD_ROOT install-libcacard
-find $RPM_BUILD_ROOT -name "libcacard.so*" -exec chmod +x \{\} \;
 
 find $RPM_BUILD_ROOT -name '*.la' -or -name '*.a' | xargs rm -f
 
@@ -5259,7 +5531,6 @@ find $RPM_BUILD_ROOT -name '*.la' -or -name '*.a' | xargs rm -f
     mkdir -p $RPM_BUILD_ROOT%{_bindir}
     mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1/*
     mkdir -p $RPM_BUILD_ROOT%{_mandir}/man8/*
-    libtool --mode=install install -m 0755 vscclient $RPM_BUILD_ROOT%{_bindir}/vscclient
     install -m 0755 qemu-img $RPM_BUILD_ROOT%{_bindir}/qemu-img
     install -m 0755 qemu-io $RPM_BUILD_ROOT%{_bindir}/qemu-io
     install -m 0755 qemu-nbd $RPM_BUILD_ROOT%{_bindir}/qemu-nbd
@@ -5280,6 +5551,7 @@ find $RPM_BUILD_ROOT -name '*.la' -or -name '*.a' | xargs rm -f
 %post
 # load kvm modules now, so we can make sure no reboot is needed.
 # If there's already a kvm module installed, we don't mess with it
+%udev_rules_update
 sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || :
     udevadm trigger --subsystem-match=misc --sysname-match=kvm --action=add || :
 
@@ -5407,60 +5679,241 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || :
 %{_mandir}/man1/qemu-img.1*
 %{_mandir}/man8/qemu-nbd.8*
 
-%files -n libcacard%{?pkgsuffix}
-%defattr(-,root,root,-)
-%{_libdir}/libcacard.so.*
-
-%files -n libcacard-tools%{?pkgsuffix}
-%defattr(-,root,root,-)
-%{_bindir}/vscclient
-
-%files -n libcacard-devel%{?pkgsuffix}
-%defattr(-,root,root,-)
-%{_includedir}/cacard
-%{_libdir}/libcacard.so
-%{_libdir}/pkgconfig/libcacard.pc
-
 %changelog
-* Tue Aug 02 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-105.el7_2.7
-- kvm-block-iscsi-avoid-potential-overflow-of-acb-task-cdb.patch [bz#1358996]
-- Resolves: bz#1358996
-  (CVE-2016-5126 qemu-kvm: Qemu: block: iscsi: buffer overflow in iscsi_aio_ioctl [rhel-7.2.z])
-
-* Wed Jul 27 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-105.el7_2.6
-- kvm-virtio-error-out-if-guest-exceeds-virtqueue-size.patch [bz#1359728]
-- Resolves: bz#1359728
-  (EMBARGOED CVE-2016-5403 qemu-kvm: Qemu: virtio: unbounded memory allocation on host via guest leading to DoS [rhel-7.2.z])
-
-* Fri Jul 01 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-105.el7_2.5
-- kvm-vga-add-sr_vbe-register-set.patch [bz#1347527]
-- Resolves: bz#1347527
+* Tue Sep 20 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7
+- kvm-virtio-recalculate-vq-inuse-after-migration.patch [bz#1376542]
+- Resolves: bz#1376542
+  (RHSA-2016-1756 breaks migration of instances)
+
+* Thu Sep 15 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-125.el7
+- kvm-nbd-server-Set-O_NONBLOCK-on-client-fd.patch [bz#1285453]
+- Resolves: bz#1285453
+  (An NBD client can cause QEMU main loop to block when connecting to built-in NBD server)
+
+* Tue Sep 13 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-124.el7
+- kvm-target-i386-Add-support-for-FEAT_7_0_ECX.patch [bz#1372459]
+- kvm-target-i386-Add-more-Intel-AVX-512-instructions-supp.patch [bz#1372459]
+- Resolves: bz#1372459
+  ([Intel 7.3 Bug] SKL-SP Guest cpu doesn't support avx512 instruction sets(avx512bw, avx512dq and avx512vl) (qemu-kvm))
+
+* Fri Sep 09 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-123.el7
+- kvm-Fix-backport-of-target-i386-add-feature-flags-for-CP.patch [bz#1371619]
+- kvm-Add-skip_dump-flag-to-ignore-memory-region-during-du.patch [bz#1373088]
+- Resolves: bz#1371619
+  (Flags xsaveopt xsavec xgetbv1 are missing on qemu-kvm)
+- Resolves: bz#1373088
+  ([FJ7.3 Bug]: virsh dump with both --memory-only and --format option fails)
+
+* Fri Aug 26 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-122.el7
+- kvm-virtio-validate-the-existence-of-handle_output-befor.patch [bz#1367040]
+- Resolves: bz#1367040
+  (QEMU crash when guest notifies non-existent virtqueue)
+
+* Tue Aug 02 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-121.el7
+- kvm-json-parser-drop-superfluous-assignment-for-token-va.patch [bz#1276036]
+- kvm-qjson-Apply-nesting-limit-more-sanely.patch [bz#1276036]
+- kvm-qjson-Don-t-crash-when-input-exceeds-nesting-limit.patch [bz#1276036]
+- kvm-check-qjson-Add-test-for-JSON-nesting-depth-limit.patch [bz#1276036]
+- kvm-qjson-Spell-out-some-silent-assumptions.patch [bz#1276036]
+- kvm-qjson-Give-each-of-the-six-structural-chars-its-own-.patch [bz#1276036]
+- kvm-qjson-Inline-token_is_keyword-and-simplify.patch [bz#1276036]
+- kvm-qjson-Inline-token_is_escape-and-simplify.patch [bz#1276036]
+- kvm-qjson-replace-QString-in-JSONLexer-with-GString.patch [bz#1276036]
+- kvm-qjson-Convert-to-parser-to-recursive-descent.patch [bz#1276036]
+- kvm-qjson-store-tokens-in-a-GQueue.patch [bz#1276036]
+- kvm-qjson-surprise-allocating-6-QObjects-per-token-is-ex.patch [bz#1276036]
+- kvm-qjson-Limit-number-of-tokens-in-addition-to-total-si.patch [bz#1276036]
+- kvm-json-streamer-Don-t-leak-tokens-on-incomplete-parse.patch [bz#1276036]
+- kvm-json-streamer-fix-double-free-on-exiting-during-a-pa.patch [bz#1276036]
+- kvm-trace-remove-malloc-tracing.patch [bz#1360137]
+- Resolves: bz#1276036
+  (Crash on QMP input exceeding limits)
+- Resolves: bz#1360137
+  (GLib-WARNING **: gmem.c:482: custom memory allocation vtable not supported)
+
+* Fri Jul 29 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-120.el7
+- kvm-Add-install-dependency-to-newer-libusbx-version.patch [bz#1351106]
+- kvm-virtio-error-out-if-guest-exceeds-virtqueue-size.patch [bz#1359729]
+- Resolves: bz#1351106
+  (symbol lookup error: /usr/libexec/qemu-kvm: undefined symbol: libusb_get_port_numbers)
+- Resolves: bz#1359729
+  (CVE-2016-5403 qemu-kvm: Qemu: virtio: unbounded memory allocation on host via guest leading to DoS [rhel-7.3])
+
+* Tue Jul 26 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-119.el7
+- kvm-qxl-factor-out-qxl_get_check_slot_offset.patch [bz#1355730]
+- kvm-qxl-store-memory-region-and-offset-instead-of-pointe.patch [bz#1355730]
+- kvm-qxl-fix-surface-migration.patch [bz#1355730]
+- kvm-qxl-fix-qxl_set_dirty-call-in-qxl_dirty_one_surface.patch [bz#1355730]
+- Resolves: bz#1355730
+  (spice-gtk shows outdated screen state after migration [qemu-kvm])
+
+* Tue Jul 19 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-118.el7
+- kvm-util-introduce-MIN_NON_ZERO.patch [bz#1318199]
+- kvm-BlockLimits-introduce-max_transfer_length.patch [bz#1318199]
+- kvm-block-backend-expose-bs-bl.max_transfer_length.patch [bz#1318199]
+- kvm-scsi-generic-Merge-block-max-xfer-len-in-INQUIRY-res.patch [bz#1318199]
+- kvm-raw-posix-Fetch-max-sectors-for-host-block-device.patch [bz#1318199]
+- kvm-scsi-Advertise-limits-by-blocksize-not-512.patch [bz#1318199]
+- kvm-util-Fix-MIN_NON_ZERO.patch [bz#1318199]
+- Resolves: bz#1318199
+  (expose host BLKSECTGET limit in scsi-block (qemu-kvm))
+
+* Tue Jul 12 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-117.el7
+- kvm-target-i386-add-feature-flags-for-CPUID-EAX-0xd-ECX-.patch [bz#1327599]
+- kvm-target-i386-add-Skylake-Client-cpu-model.patch [bz#1327599]
+- Resolves: bz#1327599
+  (Add Skylake CPU model)
+
+* Tue Jun 28 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-116.el7
+- kvm-block-iscsi-avoid-potential-overflow-of-acb-task-cdb.patch [bz#1340929]
+- Resolves: bz#1340929
+  (CVE-2016-5126 qemu-kvm: Qemu: block: iscsi: buffer overflow in iscsi_aio_ioctl [rhel-7.3])
+
+* Mon Jun 20 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-115.el7
+- kvm-spice-do-not-require-TCP-ports.patch [bz#1336491]
+- kvm-vga-add-sr_vbe-register-set.patch [bz#1346982]
+- Resolves: bz#1336491
+  (Ship FD connection patches qemu-kvm part)
+- Resolves: bz#1346982
   (Regression from CVE-2016-3712: windows installer fails to start)
 
-* Tue May 03 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-105.el7_2.4
-- kvm-vga-Remove-some-should-be-done-in-BIOS-comments.patch [bz#1331412]
-- kvm-vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch [bz#1331412]
-- kvm-vga-add-vbe_enabled-helper.patch [bz#1331412]
-- kvm-vga-factor-out-vga-register-setup.patch [bz#1331412]
-- kvm-vga-update-vga-register-setup-on-vbe-changes.patch [bz#1331412]
-- kvm-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch [bz#1331412]
-- Resolves: bz#1331412
-  (EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.2.z])
-
-* Thu Jan 21 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-105.el7_2.3
-- kvm-fw_cfg-add-check-to-validate-current-entry-value-CVE.patch [bz#1298047]
-- Resolves: bz#1298047
-  (CVE-2016-1714 qemu-kvm: Qemu: nvram: OOB r/w access in processing firmware configurations [rhel-7.2.z])
-
-* Wed Jan 20 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-105.el7_2.2
-- kvm-raw-posix-Fix-.bdrv_co_get_block_status-for-unaligne.patch [bz#1298828]
-- Resolves: bz#1298828
+* Wed Jun 15 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-114.el7
+- kvm-hw-input-hid.c-Fix-capslock-hid-code.patch [bz#1256741]
+- kvm-target-i386-fix-pcmpxstrx-equal-ordered-strstr-mode.patch [bz#1340971]
+- kvm-spec-Update-rules-before-triggering-for-kvm-device.patch [bz#1333159]
+- Resolves: bz#1256741
+  ("CapsLock" will work as "\" when boot a guest with usb-kbd)
+- Resolves: bz#1333159
+  (qemu-kvm doesn't reload udev rules before triggering for kvm device)
+- Resolves: bz#1340971
+  (qemu: accel=tcg does not implement SSE 4 properly)
+
+* Sat May 28 2016 Jeff E. Nelson <jen@redhat.com> - 1.5.3-113.el7
+- kvm-qxl-allow-to-specify-head-limit-to-qxl-driver.patch [bz#1283198]
+- kvm-qxl-Fix-new-function-name-for-spice-server-library.patch [bz#1283198]
+- kvm-block-raw-posix-Open-file-descriptor-O_RDWR-to-work-.patch [bz#1268345]
+- Resolves: bz#1268345
+  (posix_fallocate emulation on NFS fails with Bad file descriptor if fd is opened O_WRONLY)
+- Resolves: bz#1283198
+  (RFE: backport max monitor limitation from Qemu upstream)
+
+* Mon May 16 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-112.el7
+- kvm-virtio-scsi-Prevent-assertion-on-missed-events.patch [bz#1312289]
+- kvm-seccomp-adding-sysinfo-system-call-to-whitelist.patch [bz#1177318]
+- kvm-acpi-strip-compiler-info-in-built-in-DSDT.patch [bz#1330969]
+- kvm-acpi-fix-endian-ness-for-table-ids.patch [bz#1330969]
+- kvm-acpi-support-specified-oem-table-id-for-build_header.patch [bz#1330969]
+- kvm-acpi-take-oem_id-in-build_header-optionally.patch [bz#1330969]
+- kvm-acpi-expose-oem_id-and-oem_table_id-in-build_rsdt.patch [bz#1330969]
+- kvm-acpi-add-function-to-extract-oem_id-and-oem_table_id.patch [bz#1330969]
+- kvm-pc-set-the-OEM-fields-in-the-RSDT-and-the-FADT-from-.patch [bz#1330969]
+- kvm-block-jobs-qemu-kvm-rhel-differentiation.patch [bz#1156635]
+- Resolves: bz#1156635
+  (Libvirt is confused that qemu-kvm exposes 'block-job-cancel' but not 'block-stream')
+- Resolves: bz#1177318
+  (Guest using rbd based image as disk failed to start when sandbox was enabled)
+- Resolves: bz#1312289
+  ("qemu-kvm: /builddir/build/BUILD/qemu-1.5.3/hw/scsi/virtio-scsi.c:533: virtio_scsi_push_event: Assertion `event == 0' failed" after hotplug 20 virtio-scsi disks then hotunplug them)
+- Resolves: bz#1330969
+  (match the OEM ID and OEM Table ID fields of the FADT and the RSDT to those of the SLIC)
+
+* Thu May 05 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-111.el7
+- kvm-vmdk-Leave-bdi-intact-if-ENOTSUP-in-vmdk_get_info.patch [bz#1299250]
+- kvm-vmdk-Use-g_random_int-to-generate-CID.patch [bz#1299250]
+- kvm-vmdk-Fix-comment-to-match-code-of-extent-lines.patch [bz#1299250]
+- kvm-vmdk-Clean-up-descriptor-file-reading.patch [bz#1299250]
+- kvm-vmdk-Check-descriptor-file-length-when-reading-it.patch [bz#1299250]
+- kvm-vmdk-Remove-unnecessary-initialization.patch [bz#1299250]
+- kvm-vmdk-Set-errp-on-failures-in-vmdk_open_vmdk4.patch [bz#1299250]
+- kvm-block-vmdk-make-ret-variable-usage-clear.patch [bz#1299250]
+- kvm-block-vmdk-move-string-allocations-from-stack-to-the.patch [bz#1299250]
+- kvm-block-vmdk-fixed-sizeof-error.patch [bz#1299250]
+- kvm-vmdk-Widen-before-shifting-32-bit-header-field.patch [bz#1299250]
+- kvm-vmdk-Fix-next_cluster_sector-for-compressed-write.patch [bz#1299250]
+- kvm-vmdk-Fix-index_in_cluster-calculation-in-vmdk_co_get.patch [bz#1299250]
+- kvm-vmdk-Use-vmdk_find_index_in_cluster-everywhere.patch [bz#1299250]
+- kvm-vmdk-Fix-next_cluster_sector-for-compressed-write2.patch [bz#1299250]
+- kvm-vmdk-Create-streamOptimized-as-version-3.patch [bz#1299116]
+- kvm-vmdk-Fix-converting-to-streamOptimized.patch [bz#1299116]
+- kvm-vmdk-Fix-calculation-of-block-status-s-offset.patch [bz#1299116]
+- Resolves: bz#1299116
+  (qemu-img created VMDK images lead to "Not a supported disk format (sparse VMDK version too old)")
+- Resolves: bz#1299250
+  (qemu-img created VMDK images are unbootable)
+
+* Wed May 04 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-110.el7
+- kvm-qemu-io-Remove-unused-args_command.patch [bz#1272523]
+- kvm-cutils-Support-P-and-E-suffixes-in-strtosz.patch [bz#1272523]
+- kvm-qemu-io-Make-cvtnum-a-wrapper-around-strtosz_suffix.patch [bz#1272523]
+- kvm-qemu-io-Handle-cvtnum-errors-in-alloc.patch [bz#1272523]
+- kvm-qemu-io-Don-t-use-global-bs-in-command-implementatio.patch [bz#1272523]
+- kvm-qemu-io-Split-off-commands-to-qemu-io-cmds.c.patch [bz#1272523]
+- kvm-qemu-io-Factor-out-qemuio_command.patch [bz#1272523]
+- kvm-qemu-io-Move-help-function.patch [bz#1272523]
+- kvm-qemu-io-Move-quit-function.patch [bz#1272523]
+- kvm-qemu-io-Move-qemu_strsep-to-cutils.c.patch [bz#1272523]
+- kvm-qemu-io-Move-functions-for-registering-and-running-c.patch [bz#1272523]
+- kvm-qemu-io-Move-command_loop-and-friends.patch [bz#1272523]
+- kvm-qemu-io-Move-remaining-helpers-from-cmd.c.patch [bz#1272523]
+- kvm-qemu-io-Interface-cleanup.patch [bz#1272523]
+- kvm-qemu-io-Use-the-qemu-version-for-V.patch [bz#1272523]
+- kvm-Make-qemu-io-commands-available-in-HMP.patch [bz#1272523]
+- kvm-blkdebug-Add-BLKDBG_FLUSH_TO_OS-DISK-events.patch [bz#1272523]
+- kvm-qemu-io-fix-cvtnum-lval-types.patch [bz#1272523]
+- kvm-qemu-io-Check-for-trailing-chars.patch [bz#1272523]
+- kvm-qemu-io-Correct-error-messages.patch [bz#1272523]
+- kvm-ide-test-fix-failure-for-test_flush.patch [bz#1272523]
+- kvm-vga-Remove-some-should-be-done-in-BIOS-comments.patch [bz#1331413]
+- kvm-vga-fix-banked-access-bounds-checking-CVE-2016-xxxx.patch [bz#1331413]
+- kvm-vga-add-vbe_enabled-helper.patch [bz#1331413]
+- kvm-vga-factor-out-vga-register-setup.patch [bz#1331413]
+- kvm-vga-update-vga-register-setup-on-vbe-changes.patch [bz#1331413]
+- kvm-vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch [bz#1331413]
+- Resolves: bz#1272523
+  (qemu-kvm build failure race condition in tests/ide-test)
+- Resolves: bz#1331413
+  (EMBARGOED CVE-2016-3710 qemu-kvm: qemu: incorrect banked access bounds checking in vga module [rhel-7.3])
+
+* Mon Mar 14 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-109.el7
+- kvm-e1000-eliminate-infinite-loops-on-out-of-bounds-tran.patch [bz#1296044]
+- kvm-nbd-Always-call-close_fn-in-nbd_client_new.patch [bz#1285453]
+- kvm-nbd-server-Coroutine-based-negotiation.patch [bz#1285453]
+- kvm-nbd-client_close-on-error-in-nbd_co_client_start.patch [bz#1285453]
+- kvm-Remove-libcacard-build.patch [bz#1314153]
+- Resolves: bz#1285453
+  (An NBD client can cause QEMU main loop to block when connecting to built-in NBD server)
+- Resolves: bz#1296044
+  (qemu-kvm: insufficient loop termination conditions in start_xmit() and e1000_receive() [rhel-7.3])
+- Resolves: bz#1314153
+  (Disable building of libcacard)
+
+* Mon Feb 08 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-108.el7
+- kvm-net-Make-qmp_query_rx_filter-with-name-argument-more.patch [bz#1269738]
+- kvm-fw_cfg-add-check-to-validate-current-entry-value-CVE.patch [bz#1298048]
+- Resolves: bz#1269738
+  (Vlan table display repeat four times in qmp when queues=4)
+- Resolves: bz#1298048
+  (CVE-2016-1714 qemu-kvm: Qemu: nvram: OOB r/w access in processing firmware configurations [rhel-7.3])
+
+* Wed Jan 20 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-107.el7
+- kvm-raw-posix-Fix-.bdrv_co_get_block_status-for-unaligne.patch [bz#1283116]
+- Resolves: bz#1283116
   ([abrt] qemu-img: get_block_status(): qemu-img killed by SIGABRT)
 
-* Tue Nov 17 2015 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-105.el7_2.1
-- kvm-rbd-make-qemu-s-cache-setting-override-any-ceph-sett.patch [bz#1279389]
-- kvm-rbd-fix-ceph-settings-precedence.patch [bz#1279389]
-- Resolves: bz#1279389
+* Wed Jan 13 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-106.el7
+- kvm-ehci-clear-suspend-bit-on-detach.patch [bz#1268879]
+- kvm-rbd-make-qemu-s-cache-setting-override-any-ceph-sett.patch [bz#1277248]
+- kvm-rbd-fix-ceph-settings-precedence.patch [bz#1277248]
+- kvm-target-i386-get-put-MSR_TSC_AUX-across-reset-and-mig.patch [bz#1265427]
+- kvm-rtl8139-Fix-receive-buffer-overflow-check.patch [bz#1252757]
+- kvm-rtl8139-Do-not-consume-the-packet-during-overflow-in.patch [bz#1252757]
+- Resolves: bz#1252757
+  ([RHEL-7.2-qmu-kvm] Package is 100% lost when ping from host to Win2012r2 guest with 64000 size)
+- Resolves: bz#1265427
+  (contents of MSR_TSC_AUX are not migrated)
+- Resolves: bz#1268879
+  (Camera stops work after remote-viewer re-connection [qemu-kvm])
+- Resolves: bz#1277248
   (ceph.conf properties override qemu's command-line properties)
 
 * Fri Oct 16 2015 Jeff E. Nelson <jen@redhat.com> - 1.5.3-105.el7