Merge branch 'realize-isa.v2' of git://github.com/afaerber/qemu-cpu

* 'realize-isa.v2' of git://github.com/afaerber/qemu-cpu:
  qdev: Drop FROM_QBUS() macro
  isa: QOM'ify ISADevice
  isa: QOM'ify ISABus
  i8259: Convert PICCommonState to use QOM realizefn
  kvm/i8259: QOM'ify some more
  i8259: QOM'ify some more
  i8254: Convert PITCommonState to QOM realizefn
  kvm/i8254: QOM'ify some more
  i8254: QOM'ify some more
  isa: Use realizefn for ISADevice
  cs4231a: QOM'ify some more
  gus: QOM'ify some more
diff --git a/.gitignore b/.gitignore
index 64e9466..0fe114d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,7 +82,6 @@
 *.swp
 *.orig
 .pc
-*.patch
 *.gcda
 *.gcno
 patches
diff --git a/MAINTAINERS b/MAINTAINERS
index be02724..3412b07 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -685,11 +685,12 @@
 S: Supported
 F: vl.c
 
-Monitor (QMP/HMP)
+Human Monitor (HMP)
 M: Luiz Capitulino <lcapitulino@redhat.com>
-M: Markus Armbruster <armbru@redhat.com>
 S: Supported
 F: monitor.c
+F: hmp.c
+F: hmp-commands.hx
 
 Network device layer
 M: Anthony Liguori <aliguori@us.ibm.com>
@@ -706,6 +707,27 @@
 F: qemu-nbd.c
 T: git git://github.com/bonzini/qemu.git nbd-next
 
+QAPI
+M: Luiz Capitulino <lcapitulino@redhat.com>
+M: Michael Roth <mdroth@linux.vnet.ibm.com>
+S: Supported
+F: qapi/
+
+QAPI Schema
+M: Eric Blake <eblake@redhat.com>
+M: Luiz Capitulino <lcapitulino@redhat.com>
+M: Markus Armbruster <armbru@redhat.com>
+S: Supported
+F: qapi-schema.json
+
+QMP
+M: Luiz Capitulino <lcapitulino@redhat.com>
+S: Supported
+F: qmp.c
+F: monitor.c
+F: qmp-commands.hx
+F: QMP/
+
 SLIRP
 M: Jan Kiszka <jan.kiszka@siemens.com>
 S: Maintained
@@ -745,6 +767,12 @@
 S: Maintained
 F: tcg/
 
+AArch64 target
+M: Claudio Fontana <claudio.fontana@huawei.com>
+M: Claudio Fontana <claudio.fontana@gmail.com>
+S: Maintained
+F: tcg/aarch64/
+
 ARM target
 M: Andrzej Zaborowski <balrogg@gmail.com>
 S: Maintained
diff --git a/Makefile b/Makefile
index a96736b..3cfa7d0 100644
--- a/Makefile
+++ b/Makefile
@@ -186,7 +186,7 @@
 
 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 $(block-obj-y) libqemuutil.a libqemustub.a
 
 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
 
@@ -289,7 +289,7 @@
 pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
 efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
 efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \
-qemu-icon.bmp \
+qemu-icon.bmp qemu_logo_no_text.svg \
 bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
 multiboot.bin linuxboot.bin kvmvapic.bin \
 s390-zipl.rom \
@@ -306,10 +306,13 @@
 	$(INSTALL_DATA) QMP/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
 ifdef CONFIG_POSIX
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
-	$(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
+	$(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1"
+ifneq ($(TOOLS),)
+	$(INSTALL_DATA) qemu-img.1 "$(DESTDIR)$(mandir)/man1"
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
 	$(INSTALL_DATA) qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
 endif
+endif
 ifdef CONFIG_VIRTFS
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
 	$(INSTALL_DATA) fsdev/virtfs-proxy-helper.1 "$(DESTDIR)$(mandir)/man1"
diff --git a/Makefile.objs b/Makefile.objs
index 286ce06..5b288ba 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -13,6 +13,7 @@
 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/Makefile.target b/Makefile.target
index ce4391f..b0be124 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -63,8 +63,6 @@
 CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
 CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
 CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
-CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
-CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
 
 #########################################################
 # cpu emulator library
@@ -111,10 +109,8 @@
 obj-$(CONFIG_FDT) += device_tree.o
 obj-$(CONFIG_KVM) += kvm-all.o
 obj-y += memory.o savevm.o cputlb.o
-obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
-obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
-obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o
-obj-$(CONFIG_NO_CORE_DUMP) += dump-stub.o
+obj-y += memory_mapping.o
+obj-y += dump.o
 LIBS+=$(libs_softmmu)
 
 # xen support
diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index 92fe5fb..24e804e9 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -203,7 +203,8 @@
 
 Data:
 
-- "offset": delta against the host UTC in seconds (json-number)
+- "offset": Offset between base RTC clock (as specified by -rtc base), and
+new RTC clock value (json-number)
 
 Example:
 
diff --git a/arch_init.c b/arch_init.c
index 5d32ecf..872020e 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1029,7 +1029,7 @@
         return -1;
     }
 #ifdef TARGET_I386
-    smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, uuid);
+    smbios_add_field(1, offsetof(struct smbios_type_1, uuid), uuid, 16);
 #endif
     return 0;
 }
@@ -1053,7 +1053,6 @@
 {
 #ifdef TARGET_I386
     if (smbios_entry_add(optarg) < 0) {
-        fprintf(stderr, "Wrong smbios provided\n");
         exit(1);
     }
 #endif
diff --git a/backends/baum.c b/backends/baum.c
index 4cba79f..62aa784 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -611,8 +611,6 @@
 
     qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
 
-    qemu_chr_be_generic_open(chr);
-
     return chr;
 
 fail:
diff --git a/backends/msmouse.c b/backends/msmouse.c
index 0ac05a0..c0dbfcd 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -70,6 +70,7 @@
     chr = g_malloc0(sizeof(CharDriverState));
     chr->chr_write = msmouse_chr_write;
     chr->chr_close = msmouse_chr_close;
+    chr->explicit_be_open = true;
 
     qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
 
diff --git a/block.c b/block.c
index 3f616de..79ad33d 100644
--- a/block.c
+++ b/block.c
@@ -3186,13 +3186,11 @@
 
 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,
@@ -4024,6 +4022,7 @@
     }
 
     /* 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) {
@@ -4036,6 +4035,7 @@
         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 71f99e4..ccb627a 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -182,6 +182,9 @@
     [BLKDBG_CLUSTER_ALLOC]                  = "cluster_alloc",
     [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",
 };
 
 static int get_event_by_name(const char *name, BlkDebugEvent *event)
diff --git a/block/curl.c b/block/curl.c
index b8935fd..4dc3b4b 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -462,8 +462,8 @@
     // initialize the multi interface!
 
     s->multi = curl_multi_init();
-    curl_multi_setopt( s->multi, CURLMOPT_SOCKETDATA, s); 
-    curl_multi_setopt( s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb ); 
+    curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s);
+    curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
     curl_multi_do(s);
 
     qemu_opts_del(opts);
diff --git a/block/qapi.c b/block/qapi.c
index 794dbf8..a4bc411 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -26,29 +26,56 @@
 #include "block/block_int.h"
 #include "qmp-commands.h"
 
-void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info)
+/*
+ * Returns 0 on success, with *p_list either set to describe snapshot
+ * information, or NULL because there are no snapshots.  Returns -errno on
+ * error, with *p_list untouched.
+ */
+int bdrv_query_snapshot_info_list(BlockDriverState *bs,
+                                  SnapshotInfoList **p_list,
+                                  Error **errp)
 {
     int i, sn_count;
     QEMUSnapshotInfo *sn_tab = NULL;
-    SnapshotInfoList *info_list, *cur_item = NULL;
+    SnapshotInfoList *info_list, *cur_item = NULL, *head = NULL;
+    SnapshotInfo *info;
+
     sn_count = bdrv_snapshot_list(bs, &sn_tab);
+    if (sn_count < 0) {
+        const char *dev = bdrv_get_device_name(bs);
+        switch (sn_count) {
+        case -ENOMEDIUM:
+            error_setg(errp, "Device '%s' is not inserted", dev);
+            break;
+        case -ENOTSUP:
+            error_setg(errp,
+                       "Device '%s' does not support internal snapshots",
+                       dev);
+            break;
+        default:
+            error_setg_errno(errp, -sn_count,
+                             "Can't list snapshots of device '%s'", dev);
+            break;
+        }
+        return sn_count;
+    }
 
     for (i = 0; i < sn_count; i++) {
-        info->has_snapshots = true;
-        info_list = g_new0(SnapshotInfoList, 1);
+        info = g_new0(SnapshotInfo, 1);
+        info->id            = g_strdup(sn_tab[i].id_str);
+        info->name          = g_strdup(sn_tab[i].name);
+        info->vm_state_size = sn_tab[i].vm_state_size;
+        info->date_sec      = sn_tab[i].date_sec;
+        info->date_nsec     = sn_tab[i].date_nsec;
+        info->vm_clock_sec  = sn_tab[i].vm_clock_nsec / 1000000000;
+        info->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
 
-        info_list->value                = g_new0(SnapshotInfo, 1);
-        info_list->value->id            = g_strdup(sn_tab[i].id_str);
-        info_list->value->name          = g_strdup(sn_tab[i].name);
-        info_list->value->vm_state_size = sn_tab[i].vm_state_size;
-        info_list->value->date_sec      = sn_tab[i].date_sec;
-        info_list->value->date_nsec     = sn_tab[i].date_nsec;
-        info_list->value->vm_clock_sec  = sn_tab[i].vm_clock_nsec / 1000000000;
-        info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
+        info_list = g_new0(SnapshotInfoList, 1);
+        info_list->value = info;
 
         /* XXX: waiting for the qapi to support qemu-queue.h types */
         if (!cur_item) {
-            info->snapshots = cur_item = info_list;
+            head = cur_item = info_list;
         } else {
             cur_item->next = info_list;
             cur_item = info_list;
@@ -57,20 +84,40 @@
     }
 
     g_free(sn_tab);
+    *p_list = head;
+    return 0;
 }
 
-void bdrv_collect_image_info(BlockDriverState *bs,
-                             ImageInfo *info,
-                             const char *filename)
+/**
+ * bdrv_query_image_info:
+ * @bs: block device to examine
+ * @p_info: location to store image information
+ * @errp: location to store error information
+ *
+ * Store "flat" image information in @p_info.
+ *
+ * "Flat" means it does *not* query backing image information,
+ * i.e. (*pinfo)->has_backing_image will be set to false and
+ * (*pinfo)->backing_image to NULL even when the image does in fact have
+ * a backing image.
+ *
+ * @p_info will be set only on success. On error, store error in @errp.
+ */
+void bdrv_query_image_info(BlockDriverState *bs,
+                           ImageInfo **p_info,
+                           Error **errp)
 {
     uint64_t total_sectors;
-    char backing_filename[1024];
+    const char *backing_filename;
     char backing_filename2[1024];
     BlockDriverInfo bdi;
+    int ret;
+    Error *err = NULL;
+    ImageInfo *info = g_new0(ImageInfo, 1);
 
     bdrv_get_geometry(bs, &total_sectors);
 
-    info->filename        = g_strdup(filename);
+    info->filename        = g_strdup(bs->filename);
     info->format          = g_strdup(bdrv_get_format_name(bs));
     info->virtual_size    = total_sectors * 512;
     info->actual_size     = bdrv_get_allocated_file_size(bs);
@@ -87,7 +134,7 @@
         info->dirty_flag = bdi.is_dirty;
         info->has_dirty_flag = true;
     }
-    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
+    backing_filename = bs->backing_file;
     if (backing_filename[0] != '\0') {
         info->backing_filename = g_strdup(backing_filename);
         info->has_backing_filename = true;
@@ -105,11 +152,37 @@
             info->has_backing_filename_format = true;
         }
     }
+
+    ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err);
+    switch (ret) {
+    case 0:
+        if (info->snapshots) {
+            info->has_snapshots = true;
+        }
+        break;
+    /* recoverable error */
+    case -ENOMEDIUM:
+    case -ENOTSUP:
+        error_free(err);
+        break;
+    default:
+        error_propagate(errp, err);
+        qapi_free_ImageInfo(info);
+        return;
+    }
+
+    *p_info = info;
 }
 
-BlockInfo *bdrv_query_info(BlockDriverState *bs)
+/* @p_info will be set only on success. */
+void bdrv_query_info(BlockDriverState *bs,
+                     BlockInfo **p_info,
+                     Error **errp)
 {
     BlockInfo *info = g_malloc0(sizeof(*info));
+    BlockDriverState *bs0;
+    ImageInfo **p_image_info;
+    Error *local_err = NULL;
     info->device = g_strdup(bs->device_name);
     info->type = g_strdup("unknown");
     info->locked = bdrv_dev_is_medium_locked(bs);
@@ -163,8 +236,30 @@
             info->inserted->iops_wr =
                            bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
         }
+
+        bs0 = bs;
+        p_image_info = &info->inserted->image;
+        while (1) {
+            bdrv_query_image_info(bs0, p_image_info, &local_err);
+            if (error_is_set(&local_err)) {
+                error_propagate(errp, local_err);
+                goto err;
+            }
+            if (bs0->drv && bs0->backing_hd) {
+                bs0 = bs0->backing_hd;
+                (*p_image_info)->has_backing_image = true;
+                p_image_info = &((*p_image_info)->backing_image);
+            } else {
+                break;
+            }
+        }
     }
-    return info;
+
+    *p_info = info;
+    return;
+
+ err:
+    qapi_free_BlockInfo(info);
 }
 
 BlockStats *bdrv_query_stats(const BlockDriverState *bs)
@@ -201,16 +296,25 @@
 {
     BlockInfoList *head = NULL, **p_next = &head;
     BlockDriverState *bs = NULL;
+    Error *local_err = NULL;
 
      while ((bs = bdrv_next(bs))) {
         BlockInfoList *info = g_malloc0(sizeof(*info));
-        info->value = bdrv_query_info(bs);
+        bdrv_query_info(bs, &info->value, &local_err);
+        if (error_is_set(&local_err)) {
+            error_propagate(errp, local_err);
+            goto err;
+        }
 
         *p_next = info;
         p_next = &info->next;
     }
 
     return head;
+
+ err:
+    qapi_free_BlockInfoList(head);
+    return NULL;
 }
 
 BlockStatsList *qmp_query_blockstats(Error **errp)
diff --git a/blockdev.c b/blockdev.c
index b9b2d10..9937311 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1180,6 +1180,10 @@
      */
     if (bdrv_get_attached_dev(bs)) {
         bdrv_make_anon(bs);
+
+        /* Further I/O must not pause the guest */
+        bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
+                          BLOCKDEV_ON_ERROR_REPORT);
     } else {
         drive_uninit(drive_get_by_blockdev(bs));
     }
diff --git a/cmd.c b/cmd.c
deleted file mode 100644
index 10a8688..0000000
--- a/cmd.c
+++ /dev/null
@@ -1,612 +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 */
-
-cmdinfo_t	*cmdtab;
-int		ncmds;
-
-static argsfunc_t	args_func;
-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(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(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)
-{
-    cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
-    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;
-
-    qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
-    *fetchable= 1;
-}
-
-static char *get_prompt(void);
-
-void command_loop(void)
-{
-    int c, i, j = 0, 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) {
-                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);
-                    }
-                }
-            } else {
-                fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
-            }
-	}
-        doneline(input, v);
-    }
-    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;
-        }
-        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);
-
-        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
-
-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;
-    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;
-}
-
-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)
-#define GIGABYTES(x)	((long long)(x) << 30)
-#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))
-#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));
-	}
-}
-
-
-/* from libxcmd/quit.c */
-
-static cmdinfo_t quit_cmd;
-
-/* ARGSUSED */
-static int
-quit_f(
-	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);
-}
-
-/* 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(
-	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
deleted file mode 100644
index b763b19..0000000
--- a/cmd.h
+++ /dev/null
@@ -1,79 +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__
-
-#define CMD_FLAG_GLOBAL	((int)0x80000000)	/* don't iterate "args" */
-
-typedef int (*cfunc_t)(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;
-
-extern cmdinfo_t	*cmdtab;
-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);
-
-void command_loop(void);
-int command_usage(const cmdinfo_t *ci);
-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);
-
-long long cvtnum(char *s);
-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);
-
-extern char *progname;
-
-#endif	/* __COMMAND_H__ */
diff --git a/configure b/configure
index 1654413..60b0811 100755
--- a/configure
+++ b/configure
@@ -386,6 +386,8 @@
   fi
 elif check_define __arm__ ; then
   cpu="arm"
+elif check_define __aarch64__ ; then
+  cpu="aarch64"
 elif check_define __hppa__ ; then
   cpu="hppa"
 else
@@ -408,6 +410,9 @@
   armv*b|armv*l|arm)
     cpu="arm"
   ;;
+  aarch64)
+    cpu="aarch64"
+  ;;
   hppa|parisc|parisc64)
     cpu="hppa"
   ;;
@@ -553,7 +558,9 @@
 
 if [ "$bsd" = "yes" ] ; then
   if [ "$darwin" != "yes" ] ; then
-    usb="bsd"
+    if [ "$targetos" != "FreeBSD" ]; then
+      usb="bsd"
+    fi
     bsd_user="yes"
   fi
 fi
@@ -2557,29 +2564,6 @@
   fi
 fi
 
-#
-# Check for xxxat() functions when we are building linux-user
-# emulator.  This is done because older glibc versions don't
-# have syscall stubs for these implemented.
-#
-atfile=no
-cat > $TMPC << EOF
-#define _ATFILE_SOURCE
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-int
-main(void)
-{
-	/* try to unlink nonexisting file */
-	return (unlinkat(AT_FDCWD, "nonexistent_file", 0));
-}
-EOF
-if compile_prog "" "" ; then
-  atfile=yes
-fi
-
 # Check for inotify functions when we are building linux-user
 # emulator.  This is done because older glibc versions don't
 # have syscall stubs for these implemented.  In that case we
@@ -3556,7 +3540,6 @@
 fi
 
 config_host_mak="config-host.mak"
-config_host_ld="config-host.ld"
 
 echo "# Automatically generated by configure - do not modify" >config-all-disas.mak
 
@@ -3722,9 +3705,6 @@
 if test "$curses" = "yes" ; then
   echo "CONFIG_CURSES=y" >> $config_host_mak
 fi
-if test "$atfile" = "yes" ; then
-  echo "CONFIG_ATFILE=y" >> $config_host_mak
-fi
 if test "$utimens" = "yes" ; then
   echo "CONFIG_UTIMENSAT=y" >> $config_host_mak
 fi
@@ -4071,7 +4051,7 @@
 fi
 
 # generate list of library paths for linker script
-$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > ${config_host_ld}
+$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > config-host.ld
 
 # use included Linux headers
 if test "$linux" = "yes" ; then
@@ -4086,6 +4066,9 @@
   s390x)
     linux_arch=s390
     ;;
+  aarch64)
+    linux_arch=arm64
+    ;;
   *)
     # For most CPUs the kernel architecture name and QEMU CPU name match.
     linux_arch="$cpu"
@@ -4298,19 +4281,11 @@
       fi
     fi
 esac
-case "$target_arch2" in
-  i386|x86_64)
-    echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
-esac
 if test "$target_bigendian" = "yes" ; then
   echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
 fi
 if test "$target_softmmu" = "yes" ; then
   echo "CONFIG_SOFTMMU=y" >> $config_target_mak
-  case "$target_arch2" in
-    i386|x86_64)
-      echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
-  esac
 fi
 if test "$target_user_only" = "yes" ; then
   echo "CONFIG_USER_ONLY=y" >> $config_target_mak
@@ -4450,7 +4425,7 @@
 
 if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
   case "$ARCH" in
-  alpha | s390x)
+  alpha | s390x | aarch64)
     # The default placement of the application is fine.
     ;;
   *)
diff --git a/cputlb.c b/cputlb.c
index 86666c8..1230e9e 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -262,8 +262,8 @@
 
 #if defined(DEBUG_TLB)
     printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
-           " prot=%x idx=%d pd=0x%08lx\n",
-           vaddr, paddr, prot, mmu_idx, pd);
+           " prot=%x idx=%d\n",
+           vaddr, paddr, prot, mmu_idx);
 #endif
 
     address = vaddr;
diff --git a/device_tree.c b/device_tree.c
index 56af24b..69be9da 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -213,7 +213,7 @@
     uint32_t r;
 
     r = fdt_get_phandle(fdt, findnode_nofail(fdt, path));
-    if (r <= 0) {
+    if (r == 0) {
         fprintf(stderr, "%s: Couldn't get phandle for %s: %s\n", __func__,
                 path, fdt_strerror(r));
         exit(1);
diff --git a/dump.c b/dump.c
index c0d3da5..44a1339 100644
--- a/dump.c
+++ b/dump.c
@@ -21,6 +21,7 @@
 #include "sysemu/dump.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/memory_mapping.h"
+#include "sysemu/cpus.h"
 #include "qapi/error.h"
 #include "qmp-commands.h"
 
@@ -706,6 +707,7 @@
 {
     CPUArchState *env;
     int nr_cpus;
+    Error *err = NULL;
     int ret;
 
     if (runstate_is_running()) {
@@ -731,12 +733,12 @@
      * If the target architecture is not supported, cpu_get_dump_info() will
      * return -1.
      *
-     * if we use kvm, we should synchronize the register before we get dump
+     * If we use KVM, we should synchronize the registers before we get dump
      * info.
      */
+    cpu_synchronize_all_states();
     nr_cpus = 0;
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu_synchronize_state(env);
         nr_cpus++;
     }
 
@@ -756,7 +758,11 @@
     /* get memory mapping */
     memory_mapping_list_init(&s->list);
     if (paging) {
-        qemu_get_guest_memory_mapping(&s->list);
+        qemu_get_guest_memory_mapping(&s->list, &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            goto cleanup;
+        }
     } else {
         qemu_get_guest_simple_memory_mapping(&s->list);
     }
diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h
index b5164af..9b09545 100644
--- a/fpu/softfloat-macros.h
+++ b/fpu/softfloat-macros.h
@@ -168,7 +168,7 @@
         z0 = a0>>count;
     }
     else {
-        z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
+        z1 = (count < 128) ? (a0 >> (count & 63)) : 0;
         z0 = 0;
     }
     *z1Ptr = z1;
diff --git a/gdbstub.c b/gdbstub.c
index 90e54cb..94c78ce 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -371,7 +371,10 @@
 #ifdef CONFIG_USER_ONLY
     s->running_state = 1;
 #else
-    if (runstate_check(RUN_STATE_DEBUG)) {
+    if (runstate_check(RUN_STATE_GUEST_PANICKED)) {
+        runstate_set(RUN_STATE_DEBUG);
+    }
+    if (!runstate_needs_reset()) {
         vm_start();
     }
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9cea415..915b0d1 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -185,6 +185,8 @@
 submitted against the host device underlying the disk.  Once a drive has
 been deleted, the QEMU Block layer returns -EIO which results in IO
 errors in the guest for applications that are reading/writing to the device.
+These errors are always reported to the guest, regardless of the drive's error
+actions (drive options rerror, werror).
 ETEXI
 
     {
@@ -989,7 +991,6 @@
 new parameters (if specified) once the vm migration finished successfully.
 ETEXI
 
-#if defined(CONFIG_HAVE_CORE_DUMP)
     {
         .name       = "dump-guest-memory",
         .args_type  = "paging:-p,filename:F,begin:i?,length:i?",
@@ -1013,7 +1014,6 @@
     length: the memory size, in bytes. It's optional, and should be specified
             with begin together.
 ETEXI
-#endif
 
     {
         .name       = "snapshot_blkdev",
@@ -1551,6 +1551,22 @@
 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 4fb76ec..494a9aa 100644
--- a/hmp.c
+++ b/hmp.c
@@ -22,6 +22,8 @@
 #include "qemu/sockets.h"
 #include "monitor/monitor.h"
 #include "ui/console.h"
+#include "block/qapi.h"
+#include "qemu-io.h"
 
 static void hmp_handle_error(Monitor *mon, Error **errp)
 {
@@ -277,10 +279,16 @@
 void hmp_info_block(Monitor *mon, const QDict *qdict)
 {
     BlockInfoList *block_list, *info;
+    ImageInfo *image_info;
+    const char *device = qdict_get_try_str(qdict, "device");
+    bool verbose = qdict_get_try_bool(qdict, "verbose", 0);
 
     block_list = qmp_query_block(NULL);
 
     for (info = block_list; info; info = info->next) {
+        if (device && strcmp(device, info->value->device)) {
+            continue;
+        }
         monitor_printf(mon, "%s: removable=%d",
                        info->value->device, info->value->removable);
 
@@ -318,6 +326,20 @@
                             info->value->inserted->iops,
                             info->value->inserted->iops_rd,
                             info->value->inserted->iops_wr);
+
+            if (verbose) {
+                monitor_printf(mon, " images:\n");
+                image_info = info->value->inserted->image;
+                while (1) {
+                        bdrv_image_info_dump((fprintf_function)monitor_printf,
+                                             mon, image_info);
+                    if (image_info->has_backing_image) {
+                        image_info = image_info->backing_image;
+                    } else {
+                        break;
+                    }
+                }
+            }
         } else {
             monitor_printf(mon, " [not inserted]");
         }
@@ -1425,3 +1447,20 @@
     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 95fe76e..56d2e92 100644
--- a/hmp.h
+++ b/hmp.h
@@ -85,5 +85,6 @@
 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
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index e6525ac..756df3b 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -518,7 +518,7 @@
     PIIX4PMState *s = opaque;
     uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
 
-    PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
+    PIIX4_DPRINTF("gpe read %" HWADDR_PRIx " == %" PRIu32 "\n", addr, val);
     return val;
 }
 
@@ -530,7 +530,7 @@
     acpi_gpe_ioport_writeb(&s->ar, addr, val);
     pm_update_sci(s);
 
-    PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
+    PIIX4_DPRINTF("gpe write %" HWADDR_PRIx " <== %" PRIu64 "\n", addr, val);
 }
 
 static const MemoryRegionOps piix4_gpe_ops = {
@@ -553,15 +553,15 @@
         /* Manufacture an "up" value to cause a device check on any hotplug
          * slot with a device.  Extra device checks are harmless. */
         val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
-        PIIX4_DPRINTF("pci_up_read %x\n", val);
+        PIIX4_DPRINTF("pci_up_read %" PRIu32 "\n", val);
         break;
     case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR:
         val = s->pci0_status.down;
-        PIIX4_DPRINTF("pci_down_read %x\n", val);
+        PIIX4_DPRINTF("pci_down_read %" PRIu32 "\n", val);
         break;
     case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
         /* No feature defined yet */
-        PIIX4_DPRINTF("pci_features_read %x\n", val);
+        PIIX4_DPRINTF("pci_features_read %" PRIu32 "\n", val);
         break;
     case PCI_RMV_BASE - PCI_HOTPLUG_ADDR:
         val = s->pci0_hotplug_enable;
@@ -579,7 +579,7 @@
     switch (addr) {
     case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
         acpi_piix_eject_slot(opaque, (uint32_t)data);
-        PIIX4_DPRINTF("pciej write %" HWADDR_PRIx " <== % " PRIu64 "\n",
+        PIIX4_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n",
                       addr, data);
         break;
     default:
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 1016af0..3ac90d5 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -189,6 +189,11 @@
     uint32_t msi;
 };
 
+#define TYPE_INTEL_HDA_GENERIC "intel-hda-generic"
+
+#define INTEL_HDA(obj) \
+    OBJECT_CHECK(IntelHDAState, (obj), TYPE_INTEL_HDA_GENERIC)
+
 struct IntelHDAReg {
     const char *name;      /* register name */
     uint32_t   size;       /* size in bytes */
@@ -498,7 +503,7 @@
 static void intel_hda_set_g_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old)
 {
     if ((d->g_ctl & ICH6_GCTL_RESET) == 0) {
-        intel_hda_reset(&d->pci.qdev);
+        intel_hda_reset(DEVICE(d));
     }
 }
 
@@ -1102,7 +1107,7 @@
 static void intel_hda_reset(DeviceState *dev)
 {
     BusChild *kid;
-    IntelHDAState *d = DO_UPCAST(IntelHDAState, pci.qdev, dev);
+    IntelHDAState *d = INTEL_HDA(dev);
     HDACodecDevice *cdev;
 
     intel_hda_regs_reset(d);
@@ -1120,7 +1125,7 @@
 
 static int intel_hda_init(PCIDevice *pci)
 {
-    IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
+    IntelHDAState *d = INTEL_HDA(pci);
     uint8_t *conf = d->pci.config;
 
     d->name = object_get_typename(OBJECT(d));
@@ -1137,7 +1142,7 @@
         msi_init(&d->pci, 0x50, 1, true, false);
     }
 
-    hda_codec_bus_init(&d->pci.qdev, &d->codecs,
+    hda_codec_bus_init(DEVICE(pci), &d->codecs,
                        intel_hda_response, intel_hda_xfer);
 
     return 0;
@@ -1145,7 +1150,7 @@
 
 static void intel_hda_exit(PCIDevice *pci)
 {
-    IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
+    IntelHDAState *d = INTEL_HDA(pci);
 
     msi_uninit(&d->pci);
     memory_region_destroy(&d->mmio);
@@ -1232,7 +1237,7 @@
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void intel_hda_class_init_common(ObjectClass *klass)
+static void intel_hda_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
@@ -1251,7 +1256,6 @@
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    intel_hda_class_init_common(klass);
     k->device_id = 0x2668;
     k->revision = 1;
     dc->desc = "Intel HD Audio Controller (ich6)";
@@ -1262,23 +1266,28 @@
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    intel_hda_class_init_common(klass);
     k->device_id = 0x293e;
     k->revision = 3;
     dc->desc = "Intel HD Audio Controller (ich9)";
 }
 
-static const TypeInfo intel_hda_info_ich6 = {
-    .name          = "intel-hda",
+static const TypeInfo intel_hda_info = {
+    .name          = TYPE_INTEL_HDA_GENERIC,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(IntelHDAState),
+    .class_init    = intel_hda_class_init,
+    .abstract      = true,
+};
+
+static const TypeInfo intel_hda_info_ich6 = {
+    .name          = "intel-hda",
+    .parent        = TYPE_INTEL_HDA_GENERIC,
     .class_init    = intel_hda_class_init_ich6,
 };
 
 static const TypeInfo intel_hda_info_ich9 = {
     .name          = "ich9-intel-hda",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(IntelHDAState),
+    .parent        = TYPE_INTEL_HDA_GENERIC,
     .class_init    = intel_hda_class_init_ich9,
 };
 
@@ -1306,12 +1315,12 @@
  */
 static int intel_hda_and_codec_init(PCIBus *bus)
 {
-    PCIDevice *controller;
+    DeviceState *controller;
     BusState *hdabus;
     DeviceState *codec;
 
-    controller = pci_create_simple(bus, -1, "intel-hda");
-    hdabus = QLIST_FIRST(&controller->qdev.child_bus);
+    controller = DEVICE(pci_create_simple(bus, -1, "intel-hda"));
+    hdabus = QLIST_FIRST(&controller->child_bus);
     codec = qdev_create(hdabus, "hda-duplex");
     qdev_init_nofail(codec);
     return 0;
@@ -1320,6 +1329,7 @@
 static void intel_hda_register_types(void)
 {
     type_register_static(&hda_codec_bus_info);
+    type_register_static(&intel_hda_info);
     type_register_static(&intel_hda_info_ich6);
     type_register_static(&intel_hda_info_ich9);
     type_register_static(&hda_codec_device_type_info);
diff --git a/hw/char/serial.c b/hw/char/serial.c
index f2701e8..b537e42 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -92,8 +92,6 @@
 #define UART_FCR_RFR        0x02    /* RCVR Fifo Reset */
 #define UART_FCR_FE         0x01    /* FIFO Enable */
 
-#define XMIT_FIFO           0
-#define RECV_FIFO           1
 #define MAX_XMIT_RETRY      4
 
 #ifdef DEBUG_SERIAL
@@ -106,50 +104,14 @@
 
 static void serial_receive1(void *opaque, const uint8_t *buf, int size);
 
-static void fifo_clear(SerialState *s, int fifo)
+static inline void recv_fifo_put(SerialState *s, uint8_t chr)
 {
-    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
-    memset(f->data, 0, UART_FIFO_LENGTH);
-    f->count = 0;
-    f->head = 0;
-    f->tail = 0;
-}
-
-static int fifo_put(SerialState *s, int fifo, uint8_t chr)
-{
-    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
-
     /* Receive overruns do not overwrite FIFO contents. */
-    if (fifo == XMIT_FIFO || f->count < UART_FIFO_LENGTH) {
-
-        f->data[f->head++] = chr;
-
-        if (f->head == UART_FIFO_LENGTH)
-            f->head = 0;
-    }
-
-    if (f->count < UART_FIFO_LENGTH)
-        f->count++;
-    else if (fifo == RECV_FIFO)
+    if (!fifo8_is_full(&s->recv_fifo)) {
+        fifo8_push(&s->recv_fifo, chr);
+    } else {
         s->lsr |= UART_LSR_OE;
-
-    return 1;
-}
-
-static uint8_t fifo_get(SerialState *s, int fifo)
-{
-    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
-    uint8_t c;
-
-    if(f->count == 0)
-        return 0;
-
-    c = f->data[f->tail++];
-    if (f->tail == UART_FIFO_LENGTH)
-        f->tail = 0;
-    f->count--;
-
-    return c;
+    }
 }
 
 static void serial_update_irq(SerialState *s)
@@ -165,7 +127,7 @@
         tmp_iir = UART_IIR_CTI;
     } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR) &&
                (!(s->fcr & UART_FCR_FE) ||
-                s->recv_fifo.count >= s->recv_fifo.itl)) {
+                s->recv_fifo.num >= s->recv_fifo_itl)) {
         tmp_iir = UART_IIR_RDI;
     } else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {
         tmp_iir = UART_IIR_THRI;
@@ -262,9 +224,11 @@
 
     if (s->tsr_retry <= 0) {
         if (s->fcr & UART_FCR_FE) {
-            s->tsr = fifo_get(s,XMIT_FIFO);
-            if (!s->xmit_fifo.count)
+            s->tsr = fifo8_is_full(&s->xmit_fifo) ?
+                        0 : fifo8_pop(&s->xmit_fifo);
+            if (!s->xmit_fifo.num) {
                 s->lsr |= UART_LSR_THRE;
+            }
         } else if ((s->lsr & UART_LSR_THRE)) {
             return FALSE;
         } else {
@@ -316,16 +280,16 @@
         } else {
             s->thr = (uint8_t) val;
             if(s->fcr & UART_FCR_FE) {
-                fifo_put(s, XMIT_FIFO, s->thr);
-                s->thr_ipending = 0;
+                /* xmit overruns overwrite data, so make space if needed */
+                if (fifo8_is_full(&s->xmit_fifo)) {
+                    fifo8_pop(&s->xmit_fifo);
+                }
+                fifo8_push(&s->xmit_fifo, s->thr);
                 s->lsr &= ~UART_LSR_TEMT;
-                s->lsr &= ~UART_LSR_THRE;
-                serial_update_irq(s);
-            } else {
-                s->thr_ipending = 0;
-                s->lsr &= ~UART_LSR_THRE;
-                serial_update_irq(s);
             }
+            s->thr_ipending = 0;
+            s->lsr &= ~UART_LSR_THRE;
+            serial_update_irq(s);
             serial_xmit(NULL, G_IO_OUT, s);
         }
         break;
@@ -367,28 +331,28 @@
         if (val & UART_FCR_RFR) {
             qemu_del_timer(s->fifo_timeout_timer);
             s->timeout_ipending=0;
-            fifo_clear(s,RECV_FIFO);
+            fifo8_reset(&s->recv_fifo);
         }
 
         if (val & UART_FCR_XFR) {
-            fifo_clear(s,XMIT_FIFO);
+            fifo8_reset(&s->xmit_fifo);
         }
 
         if (val & UART_FCR_FE) {
             s->iir |= UART_IIR_FE;
-            /* Set RECV_FIFO trigger Level */
+            /* Set recv_fifo trigger Level */
             switch (val & 0xC0) {
             case UART_FCR_ITL_1:
-                s->recv_fifo.itl = 1;
+                s->recv_fifo_itl = 1;
                 break;
             case UART_FCR_ITL_2:
-                s->recv_fifo.itl = 4;
+                s->recv_fifo_itl = 4;
                 break;
             case UART_FCR_ITL_3:
-                s->recv_fifo.itl = 8;
+                s->recv_fifo_itl = 8;
                 break;
             case UART_FCR_ITL_4:
-                s->recv_fifo.itl = 14;
+                s->recv_fifo_itl = 14;
                 break;
             }
         } else
@@ -460,11 +424,13 @@
             ret = s->divider & 0xff;
         } else {
             if(s->fcr & UART_FCR_FE) {
-                ret = fifo_get(s,RECV_FIFO);
-                if (s->recv_fifo.count == 0)
+                ret = fifo8_is_full(&s->recv_fifo) ?
+                            0 : fifo8_pop(&s->recv_fifo);
+                if (s->recv_fifo.num == 0) {
                     s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
-                else
+                } else {
                     qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
+                }
                 s->timeout_ipending = 0;
             } else {
                 ret = s->rbr;
@@ -534,15 +500,21 @@
 static int serial_can_receive(SerialState *s)
 {
     if(s->fcr & UART_FCR_FE) {
-        if(s->recv_fifo.count < UART_FIFO_LENGTH)
-        /* Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1 if above. If UART_FIFO_LENGTH - fifo.count is
-        advertised the effect will be to almost always fill the fifo completely before the guest has a chance to respond,
-        effectively overriding the ITL that the guest has set. */
-             return (s->recv_fifo.count <= s->recv_fifo.itl) ? s->recv_fifo.itl - s->recv_fifo.count : 1;
-        else
-             return 0;
+        if (s->recv_fifo.num < UART_FIFO_LENGTH) {
+            /*
+             * Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1
+             * if above. If UART_FIFO_LENGTH - fifo.count is advertised the
+             * effect will be to almost always fill the fifo completely before
+             * the guest has a chance to respond, effectively overriding the ITL
+             * that the guest has set.
+             */
+            return (s->recv_fifo.num <= s->recv_fifo_itl) ?
+                        s->recv_fifo_itl - s->recv_fifo.num : 1;
+        } else {
+            return 0;
+        }
     } else {
-    return !(s->lsr & UART_LSR_DR);
+        return !(s->lsr & UART_LSR_DR);
     }
 }
 
@@ -550,7 +522,7 @@
 {
     s->rbr = 0;
     /* When the LSR_DR is set a null byte is pushed into the fifo */
-    fifo_put(s, RECV_FIFO, '\0');
+    recv_fifo_put(s, '\0');
     s->lsr |= UART_LSR_BI | UART_LSR_DR;
     serial_update_irq(s);
 }
@@ -558,7 +530,7 @@
 /* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */
 static void fifo_timeout_int (void *opaque) {
     SerialState *s = opaque;
-    if (s->recv_fifo.count) {
+    if (s->recv_fifo.num) {
         s->timeout_ipending = 1;
         serial_update_irq(s);
     }
@@ -580,7 +552,7 @@
     if(s->fcr & UART_FCR_FE) {
         int i;
         for (i = 0; i < size; i++) {
-            fifo_put(s, RECV_FIFO, buf[i]);
+            recv_fifo_put(s, buf[i]);
         }
         s->lsr |= UART_LSR_DR;
         /* call the timeout receive callback in 4 char transmit time */
@@ -660,8 +632,8 @@
     s->char_transmit_time = (get_ticks_per_sec() / 9600) * 10;
     s->poll_msl = 0;
 
-    fifo_clear(s,RECV_FIFO);
-    fifo_clear(s,XMIT_FIFO);
+    fifo8_reset(&s->recv_fifo);
+    fifo8_reset(&s->xmit_fifo);
 
     s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
 
@@ -684,6 +656,8 @@
 
     qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
                           serial_event, s);
+    fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
+    fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
 }
 
 void serial_exit_core(SerialState *s)
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index 3a3ef8a..50054cf 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -514,8 +514,9 @@
             break;
     }
     if (sid == 1 && d->notify) {
-        d->notify(d->notify_opaque);
+        StreamCanPushNotifyFn notifytmp = d->notify;
         d->notify = NULL;
+        notifytmp(d->notify_opaque);
     }
     stream_update_irq(s);
 }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 0ad062c..e0fbb86 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -934,6 +934,11 @@
     DeviceState *icc_bridge;
     int64_t apic_id = x86_cpu_apic_id_from_index(id);
 
+    if (id < 0) {
+        error_setg(errp, "Invalid CPU id: %" PRIi64, id);
+        return;
+    }
+
     if (cpu_exists(apic_id)) {
         error_setg(errp, "Unable to add CPU: %" PRIi64
                    ", it already exists", id);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index af1e9af..97362f2 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -327,8 +327,8 @@
 }
 #endif
 
-static QEMUMachine pc_i440fx_machine_v1_5 = {
-    .name = "pc-i440fx-1.5",
+static QEMUMachine pc_i440fx_machine_v1_6 = {
+    .name = "pc-i440fx-1.6",
     .alias = "pc",
     .desc = "Standard PC (i440FX + PIIX, 1996)",
     .init = pc_init_pci,
@@ -338,6 +338,19 @@
     DEFAULT_MACHINE_OPTIONS,
 };
 
+static QEMUMachine pc_i440fx_machine_v1_5 = {
+    .name = "pc-i440fx-1.5",
+    .desc = "Standard PC (i440FX + PIIX, 1996)",
+    .init = pc_init_pci,
+    .hot_add_cpu = pc_hot_add_cpu,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_5,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
 static QEMUMachine pc_i440fx_machine_v1_4 = {
     .name = "pc-i440fx-1.4",
     .desc = "Standard PC (i440FX + PIIX, 1996)",
@@ -735,6 +748,7 @@
 
 static void pc_machine_init(void)
 {
+    qemu_register_machine(&pc_i440fx_machine_v1_6);
     qemu_register_machine(&pc_i440fx_machine_v1_5);
     qemu_register_machine(&pc_i440fx_machine_v1_4);
     qemu_register_machine(&pc_machine_v1_3);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 7888dfe..bb0ce6a 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -215,8 +215,8 @@
     pc_q35_init(args);
 }
 
-static QEMUMachine pc_q35_machine_v1_5 = {
-    .name = "pc-q35-1.5",
+static QEMUMachine pc_q35_machine_v1_6 = {
+    .name = "pc-q35-1.6",
     .alias = "q35",
     .desc = "Standard PC (Q35 + ICH9, 2009)",
     .init = pc_q35_init,
@@ -225,6 +225,19 @@
     DEFAULT_MACHINE_OPTIONS,
 };
 
+static QEMUMachine pc_q35_machine_v1_5 = {
+    .name = "pc-q35-1.5",
+    .desc = "Standard PC (Q35 + ICH9, 2009)",
+    .init = pc_q35_init,
+    .hot_add_cpu = pc_hot_add_cpu,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_5,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
 static QEMUMachine pc_q35_machine_v1_4 = {
     .name = "pc-q35-1.4",
     .desc = "Standard PC (Q35 + ICH9, 2009)",
@@ -239,6 +252,7 @@
 
 static void pc_q35_machine_init(void)
 {
+    qemu_register_machine(&pc_q35_machine_v1_6);
     qemu_register_machine(&pc_q35_machine_v1_5);
     qemu_register_machine(&pc_q35_machine_v1_4);
 }
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index c00bb2f..e708cb8 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -13,6 +13,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
+#include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
 #include "hw/i386/smbios.h"
 #include "hw/loader.h"
@@ -48,8 +49,7 @@
 static void smbios_validate_table(void)
 {
     if (smbios_type4_count && smbios_type4_count != smp_cpus) {
-         fprintf(stderr,
-                 "Number of SMBIOS Type 4 tables must match cpu count.\n");
+        error_report("Number of SMBIOS Type 4 tables must match cpu count");
         exit(1);
     }
 }
@@ -82,16 +82,16 @@
         if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
             struct smbios_field *field = (void *)header;
             if (type == field->type) {
-                fprintf(stderr, "SMBIOS type %d field already defined, "
-                                "cannot add table\n", type);
+                error_report("SMBIOS type %d field already defined, "
+                             "cannot add table", type);
                 exit(1);
             }
         } else if (entry == SMBIOS_FIELD_ENTRY &&
                    header->type == SMBIOS_TABLE_ENTRY) {
             struct smbios_structure_header *table = (void *)(header + 1);
             if (type == table->type) {
-                fprintf(stderr, "SMBIOS type %d table already defined, "
-                                "cannot add field\n", type);
+                error_report("SMBIOS type %d table already defined, "
+                             "cannot add field", type);
                 exit(1);
             }
         }
@@ -99,7 +99,7 @@
     }
 }
 
-void smbios_add_field(int type, int offset, int len, void *data)
+void smbios_add_field(int type, int offset, const void *data, size_t len)
 {
     struct smbios_field *field;
 
@@ -127,24 +127,29 @@
 static void smbios_build_type_0_fields(const char *t)
 {
     char buf[1024];
+    unsigned char major, minor;
 
     if (get_param_value(buf, sizeof(buf), "vendor", t))
         smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
-                         strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
     if (get_param_value(buf, sizeof(buf), "version", t))
         smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
-                         strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
     if (get_param_value(buf, sizeof(buf), "date", t))
         smbios_add_field(0, offsetof(struct smbios_type_0,
                                      bios_release_date_str),
-                                     strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
     if (get_param_value(buf, sizeof(buf), "release", t)) {
-        int major, minor;
-        sscanf(buf, "%d.%d", &major, &minor);
+        if (sscanf(buf, "%hhu.%hhu", &major, &minor) != 2) {
+            error_report("Invalid release");
+            exit(1);
+        }
         smbios_add_field(0, offsetof(struct smbios_type_0,
-                                     system_bios_major_release), 1, &major);
+                                     system_bios_major_release),
+                         &major, 1);
         smbios_add_field(0, offsetof(struct smbios_type_0,
-                                     system_bios_minor_release), 1, &minor);
+                                     system_bios_minor_release),
+                         &minor, 1);
     }
 }
 
@@ -154,28 +159,28 @@
 
     if (get_param_value(buf, sizeof(buf), "manufacturer", t))
         smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
-                         strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
     if (get_param_value(buf, sizeof(buf), "product", t))
         smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
-                         strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
     if (get_param_value(buf, sizeof(buf), "version", t))
         smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
-                         strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
     if (get_param_value(buf, sizeof(buf), "serial", t))
         smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
-                         strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
     if (get_param_value(buf, sizeof(buf), "uuid", t)) {
         if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
-            fprintf(stderr, "Invalid SMBIOS UUID string\n");
+            error_report("Invalid UUID");
             exit(1);
         }
     }
     if (get_param_value(buf, sizeof(buf), "sku", t))
         smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
-                         strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
     if (get_param_value(buf, sizeof(buf), "family", t))
         smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
-                         strlen(buf) + 1, buf);
+                         buf, strlen(buf) + 1);
 }
 
 int smbios_entry_add(const char *t)
@@ -188,7 +193,7 @@
         int size = get_image_size(buf);
 
         if (size == -1 || size < sizeof(struct smbios_structure_header)) {
-            fprintf(stderr, "Cannot read smbios file %s\n", buf);
+            error_report("Cannot read SMBIOS file %s", buf);
             exit(1);
         }
 
@@ -204,7 +209,7 @@
         table->header.length = cpu_to_le16(sizeof(*table) + size);
 
         if (load_image(buf, table->data) != size) {
-            fprintf(stderr, "Failed to load smbios file %s", buf);
+            error_report("Failed to load SMBIOS file %s", buf);
             exit(1);
         }
 
@@ -230,12 +235,12 @@
             smbios_build_type_1_fields(t);
             return 0;
         default:
-            fprintf(stderr, "Don't know how to build fields for SMBIOS type "
-                    "%ld\n", type);
+            error_report("Don't know how to build fields for SMBIOS type %ld",
+                         type);
             exit(1);
         }
     }
 
-    fprintf(stderr, "smbios: must specify type= or file=\n");
+    error_report("Must specify type= or file=");
     return -1;
 }
diff --git a/hw/ide/core.c b/hw/ide/core.c
index c7a8041..9926d92 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -814,6 +814,7 @@
         return;
     }
 
+    s->status |= BUSY_STAT;
     bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
     bdrv_aio_flush(s->bs, ide_flush_cb, s);
 }
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
index b106e72..5df7008 100644
--- a/hw/intc/xilinx_intc.c
+++ b/hw/intc/xilinx_intc.c
@@ -66,11 +66,7 @@
         i = ~0;
 
     p->regs[R_IVR] = i;
-    if ((p->regs[R_MER] & 1) && p->regs[R_IPR]) {
-        qemu_irq_raise(p->parent_irq);
-    } else {
-        qemu_irq_lower(p->parent_irq);
-    }
+    qemu_set_irq(p->parent_irq, (p->regs[R_MER] & 1) && p->regs[R_IPR]);
 }
 
 static uint64_t
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index a19a6d6..5658f73 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -735,6 +735,7 @@
 
         if (s->shmobj == NULL) {
             fprintf(stderr, "Must specify 'chardev' or 'shm' to ivshmem\n");
+            exit(1);
         }
 
         IVSHMEM_DPRINTF("using shm_open (shm object = %s)\n", s->shmobj);
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 5f483e7..4c575e5 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1892,7 +1892,7 @@
     vmxnet_tx_pkt_reset(s->tx_pkt);
     vmxnet_tx_pkt_uninit(s->tx_pkt);
     vmxnet_rx_pkt_uninit(s->rx_pkt);
-    qemu_del_net_client(qemu_get_queue(s->nic));
+    qemu_del_nic(s->nic);
 }
 
 static void vmxnet3_net_init(VMXNET3State *s)
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index 8989e95..2ca1511 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -575,7 +575,7 @@
             break;
 
         case R_MC:
-             value &= ((1 < 7) - 1);
+             value &= ((1 << 7) - 1);
 
              /* Enable the MII.  */
              if (value & MC_EN) {
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 8ecaa5f..f4bd3c9 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -130,7 +130,6 @@
                                          uint32_t nret, target_ulong rets)
 {
     target_ulong id;
-    CPUPPCState *env;
     CPUState *cpu;
 
     if (nargs != 1 || nret != 2) {
@@ -139,12 +138,8 @@
     }
 
     id = rtas_ld(args, 0);
-    for (env = first_cpu; env; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        if (cpu->cpu_index != id) {
-            continue;
-        }
-
+    cpu = qemu_get_cpu(id);
+    if (cpu != NULL) {
         if (cpu->halted) {
             rtas_st(rets, 1, 0);
         } else {
@@ -165,8 +160,7 @@
                            uint32_t nret, target_ulong rets)
 {
     target_ulong id, start, r3;
-    CPUState *cpu;
-    CPUPPCState *env;
+    CPUState *cs;
 
     if (nargs != 3 || nret != 1) {
         rtas_st(rets, 0, -3);
@@ -177,14 +171,12 @@
     start = rtas_ld(args, 1);
     r3 = rtas_ld(args, 2);
 
-    for (env = first_cpu; env; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
+    cs = qemu_get_cpu(id);
+    if (cs != NULL) {
+        PowerPCCPU *cpu = POWERPC_CPU(cs);
+        CPUPPCState *env = &cpu->env;
 
-        if (cpu->cpu_index != id) {
-            continue;
-        }
-
-        if (!cpu->halted) {
+        if (!cs->halted) {
             rtas_st(rets, 0, -1);
             return;
         }
@@ -197,9 +189,9 @@
         env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
         env->nip = start;
         env->gpr[3] = r3;
-        cpu->halted = 0;
+        cs->halted = 0;
 
-        qemu_cpu_kick(cpu);
+        qemu_cpu_kick(cs);
 
         rtas_st(rets, 0, 0);
         return;
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index e526a1c..f82abfe 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -777,7 +777,7 @@
             (p->chars & PMCW_CHARS_MASK_CSENSE)) {
             irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
             memcpy(irb.ecw, sch->sense_data, sizeof(sch->sense_data));
-            irb.esw[1] = 0x02000000 | (sizeof(sch->sense_data) << 8);
+            irb.esw[1] = 0x01000000 | (sizeof(sch->sense_data) << 8);
         }
     }
     /* Store the irb to the guest. */
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 5f5e267..44f5772 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -328,10 +328,10 @@
             ret = -EINVAL;
             break;
         }
-        indicators = ldq_phys(ccw.cda);
-        if (!indicators) {
+        if (!ccw.cda) {
             ret = -EFAULT;
         } else {
+            indicators = ldq_phys(ccw.cda);
             dev->indicators = indicators;
             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
             ret = 0;
@@ -348,10 +348,10 @@
             ret = -EINVAL;
             break;
         }
-        indicators = ldq_phys(ccw.cda);
-        if (!indicators) {
+        if (!ccw.cda) {
             ret = -EFAULT;
         } else {
+            indicators = ldq_phys(ccw.cda);
             dev->indicators2 = indicators;
             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
             ret = 0;
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 48d12f4..446f723 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -389,7 +389,7 @@
         QTAILQ_REMOVE(&s->completion_queue, pvscsi_req, next);
         pvscsi_cmp_ring_put(s, &pvscsi_req->cmp);
         g_free(pvscsi_req);
-        has_completed++;
+        has_completed = true;
     }
 
     if (has_completed) {
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
index 01872db..8ccc2e4 100644
--- a/hw/xen/xen_pt_config_init.c
+++ b/hw/xen/xen_pt_config_init.c
@@ -1777,12 +1777,12 @@
         rc = reg->init(s, reg_entry->reg,
                        reg_grp->base_offset + reg->offset, &data);
         if (rc < 0) {
-            free(reg_entry);
+            g_free(reg_entry);
             return rc;
         }
         if (data == XEN_PT_INVALID_REG) {
             /* free unused BAR register entry */
-            free(reg_entry);
+            g_free(reg_entry);
             return 0;
         }
         /* set register value */
diff --git a/include/block/block.h b/include/block/block.h
index dc5b388..2307f67 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -424,6 +424,9 @@
     BLKDBG_CLUSTER_ALLOC_BYTES,
     BLKDBG_CLUSTER_FREE,
 
+    BLKDBG_FLUSH_TO_OS,
+    BLKDBG_FLUSH_TO_DISK,
+
     BLKDBG_EVENT_MAX,
 } BlkDebugEvent;
 
diff --git a/include/block/qapi.h b/include/block/qapi.h
index e6e568d..0496cc9 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -29,11 +29,15 @@
 #include "block/block.h"
 #include "block/snapshot.h"
 
-void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info);
-void bdrv_collect_image_info(BlockDriverState *bs,
-                             ImageInfo *info,
-                             const char *filename);
-BlockInfo *bdrv_query_info(BlockDriverState *s);
+int bdrv_query_snapshot_info_list(BlockDriverState *bs,
+                                  SnapshotInfoList **p_list,
+                                  Error **errp);
+void bdrv_query_image_info(BlockDriverState *bs,
+                           ImageInfo **p_info,
+                           Error **errp);
+void bdrv_query_info(BlockDriverState *bs,
+                     BlockInfo **p_info,
+                     Error **errp);
 BlockStats *bdrv_query_stats(const BlockDriverState *bs);
 
 void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
diff --git a/include/elf.h b/include/elf.h
index a21ea53..cf0d3e2 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -129,6 +129,8 @@
 
 #define EM_XTENSA   94      /* Tensilica Xtensa */
 
+#define EM_AARCH64  183
+
 /* This is the info that is needed to parse the dynamic section of the file */
 #define DT_NULL		0
 #define DT_NEEDED	1
@@ -616,6 +618,133 @@
 /* Keep this the last entry.  */
 #define R_ARM_NUM		256
 
+/* ARM Aarch64 relocation types */
+#define R_AARCH64_NONE                256 /* also accepts R_ARM_NONE (0) */
+/* static data relocations */
+#define R_AARCH64_ABS64               257
+#define R_AARCH64_ABS32               258
+#define R_AARCH64_ABS16               259
+#define R_AARCH64_PREL64              260
+#define R_AARCH64_PREL32              261
+#define R_AARCH64_PREL16              262
+/* static aarch64 group relocations */
+/* group relocs to create unsigned data value or address inline */
+#define R_AARCH64_MOVW_UABS_G0        263
+#define R_AARCH64_MOVW_UABS_G0_NC     264
+#define R_AARCH64_MOVW_UABS_G1        265
+#define R_AARCH64_MOVW_UABS_G1_NC     266
+#define R_AARCH64_MOVW_UABS_G2        267
+#define R_AARCH64_MOVW_UABS_G2_NC     268
+#define R_AARCH64_MOVW_UABS_G3        269
+/* group relocs to create signed data or offset value inline */
+#define R_AARCH64_MOVW_SABS_G0        270
+#define R_AARCH64_MOVW_SABS_G1        271
+#define R_AARCH64_MOVW_SABS_G2        272
+/* relocs to generate 19, 21, and 33 bit PC-relative addresses */
+#define R_AARCH64_LD_PREL_LO19        273
+#define R_AARCH64_ADR_PREL_LO21       274
+#define R_AARCH64_ADR_PREL_PG_HI21    275
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276
+#define R_AARCH64_ADD_ABS_LO12_NC     277
+#define R_AARCH64_LDST8_ABS_LO12_NC   278
+#define R_AARCH64_LDST16_ABS_LO12_NC  284
+#define R_AARCH64_LDST32_ABS_LO12_NC  285
+#define R_AARCH64_LDST64_ABS_LO12_NC  286
+#define R_AARCH64_LDST128_ABS_LO12_NC 299
+/* relocs for control-flow - all offsets as multiple of 4 */
+#define R_AARCH64_TSTBR14             279
+#define R_AARCH64_CONDBR19            280
+#define R_AARCH64_JUMP26              282
+#define R_AARCH64_CALL26              283
+/* group relocs to create pc-relative offset inline */
+#define R_AARCH64_MOVW_PREL_G0        287
+#define R_AARCH64_MOVW_PREL_G0_NC     288
+#define R_AARCH64_MOVW_PREL_G1        289
+#define R_AARCH64_MOVW_PREL_G1_NC     290
+#define R_AARCH64_MOVW_PREL_G2        291
+#define R_AARCH64_MOVW_PREL_G2_NC     292
+#define R_AARCH64_MOVW_PREL_G3        293
+/* group relocs to create a GOT-relative offset inline */
+#define R_AARCH64_MOVW_GOTOFF_G0      300
+#define R_AARCH64_MOVW_GOTOFF_G0_NC   301
+#define R_AARCH64_MOVW_GOTOFF_G1      302
+#define R_AARCH64_MOVW_GOTOFF_G1_NC   303
+#define R_AARCH64_MOVW_GOTOFF_G2      304
+#define R_AARCH64_MOVW_GOTOFF_G2_NC   305
+#define R_AARCH64_MOVW_GOTOFF_G3      306
+/* GOT-relative data relocs */
+#define R_AARCH64_GOTREL64            307
+#define R_AARCH64_GOTREL32            308
+/* GOT-relative instr relocs */
+#define R_AARCH64_GOT_LD_PREL19       309
+#define R_AARCH64_LD64_GOTOFF_LO15    310
+#define R_AARCH64_ADR_GOT_PAGE        311
+#define R_AARCH64_LD64_GOT_LO12_NC    312
+#define R_AARCH64_LD64_GOTPAGE_LO15   313
+/* General Dynamic TLS relocations */
+#define R_AARCH64_TLSGD_ADR_PREL21            512
+#define R_AARCH64_TLSGD_ADR_PAGE21            513
+#define R_AARCH64_TLSGD_ADD_LO12_NC           514
+#define R_AARCH64_TLSGD_MOVW_G1               515
+#define R_AARCH64_TLSGD_MOVW_G0_NC            516
+/* Local Dynamic TLS relocations */
+#define R_AARCH64_TLSLD_ADR_PREL21            517
+#define R_AARCH64_TLSLD_ADR_PAGE21            518
+#define R_AARCH64_TLSLD_ADD_LO12_NC           519
+#define R_AARCH64_TLSLD_MOVW_G1               520
+#define R_AARCH64_TLSLD_MOVW_G0_NC            521
+#define R_AARCH64_TLSLD_LD_PREL19             522
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2        523
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1        524
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC     525
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0        526
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC     527
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12       528
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12       529
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC    530
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12     531
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC  532
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12    533
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12    535
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12    537
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538
+/* initial exec TLS relocations */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1      539
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC   540
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21   541
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19    543
+/* local exec TLS relocations */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2         544
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1         545
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC      546
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0         547
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC      548
+#define R_AARCH64_TLSLE_ADD_TPREL_HI12        549
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12        550
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC     551
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12      552
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC   553
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12     554
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC  555
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12     556
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC  557
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12     558
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC  559
+/* Dynamic Relocations */
+#define R_AARCH64_COPY         1024
+#define R_AARCH64_GLOB_DAT     1025
+#define R_AARCH64_JUMP_SLOT    1026
+#define R_AARCH64_RELATIVE     1027
+#define R_AARCH64_TLS_DTPREL64 1028
+#define R_AARCH64_TLS_DTPMOD64 1029
+#define R_AARCH64_TLS_TPREL64  1030
+#define R_AARCH64_TLS_DTPREL32 1031
+#define R_AARCH64_TLS_DTPMOD32 1032
+#define R_AARCH64_TLS_TPREL32  1033
+
 /* s390 relocations defined by the ABIs */
 #define R_390_NONE		0	/* No reloc.  */
 #define R_390_8			1	/* Direct 8 bit.  */
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index d8c64e9..2e5a9ba 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -99,7 +99,7 @@
                    sizeof(uintptr_t))];
 } CPUTLBEntry;
 
-extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BITS) ? 1 : -1];
+QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
 
 #define CPU_COMMON_TLB \
     /* The meaning of the MMU modes is defined in the target code. */   \
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 17fde25..b2162a4 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -128,7 +128,7 @@
 
 #if defined(__arm__) || defined(_ARCH_PPC) \
     || defined(__x86_64__) || defined(__i386__) \
-    || defined(__sparc__) \
+    || defined(__sparc__) || defined(__aarch64__) \
     || defined(CONFIG_TCG_INTERPRETER)
 #define USE_DIRECT_JUMP
 #endif
@@ -230,6 +230,9 @@
     *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
     /* no need to flush icache explicitly */
 }
+#elif defined(__aarch64__)
+void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
+#define tb_set_jmp_target1 aarch64_tb_set_jmp_target
 #elif defined(__arm__)
 static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
 {
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index c15354a..85f58ac 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -28,17 +28,10 @@
 #include "hw/hw.h"
 #include "sysemu/sysemu.h"
 #include "exec/memory.h"
+#include "qemu/fifo8.h"
 
 #define UART_FIFO_LENGTH    16      /* 16550A Fifo Length */
 
-typedef struct SerialFIFO {
-    uint8_t data[UART_FIFO_LENGTH];
-    uint8_t count;
-    uint8_t itl;                        /* Interrupt Trigger Level */
-    uint8_t tail;
-    uint8_t head;
-} SerialFIFO;
-
 struct SerialState {
     uint16_t divider;
     uint8_t rbr; /* receive register */
@@ -67,8 +60,10 @@
 
     /* Time when the last byte was successfully sent out of the tsr */
     uint64_t last_xmit_ts;
-    SerialFIFO recv_fifo;
-    SerialFIFO xmit_fifo;
+    Fifo8 recv_fifo;
+    Fifo8 xmit_fifo;
+    /* Interrupt trigger level for recv_fifo */
+    uint8_t recv_fifo_itl;
 
     struct QEMUTimer *fifo_timeout_timer;
     int timeout_ipending;           /* timeout interrupt pending state */
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 5d883eb..7f04967 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -189,7 +189,35 @@
 
 int e820_add_entry(uint64_t, uint64_t, uint32_t);
 
+#define PC_COMPAT_1_5 \
+        {\
+            .driver   = "Conroe-" TYPE_X86_CPU,\
+            .property = "model",\
+            .value    = stringify(2),\
+        },{\
+            .driver   = "Conroe-" TYPE_X86_CPU,\
+            .property = "level",\
+            .value    = stringify(2),\
+        },{\
+            .driver   = "Penryn-" TYPE_X86_CPU,\
+            .property = "model",\
+            .value    = stringify(2),\
+        },{\
+            .driver   = "Penryn-" TYPE_X86_CPU,\
+            .property = "level",\
+            .value    = stringify(2),\
+        },{\
+            .driver   = "Nehalem-" TYPE_X86_CPU,\
+            .property = "model",\
+            .value    = stringify(2),\
+        },{\
+            .driver   = "Nehalem-" TYPE_X86_CPU,\
+            .property = "level",\
+            .value    = stringify(2),\
+        }
+
 #define PC_COMPAT_1_4 \
+        PC_COMPAT_1_5, \
         {\
             .driver   = "scsi-hd",\
             .property = "discard_granularity",\
diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
index 94e3641..9babeaf 100644
--- a/include/hw/i386/smbios.h
+++ b/include/hw/i386/smbios.h
@@ -14,7 +14,7 @@
  */
 
 int smbios_entry_add(const char *t);
-void smbios_add_field(int type, int offset, int len, void *data);
+void smbios_add_field(int type, int offset, const void *data, size_t len);
 uint8_t *smbios_get_table(size_t *length);
 
 /*
diff --git a/include/qemu-common.h b/include/qemu-common.h
index cb82ef3..3c91375 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -42,19 +42,6 @@
 #include <signal.h>
 #include "glib-compat.h"
 
-#if defined(__GLIBC__)
-# include <pty.h>
-#elif defined CONFIG_BSD
-# include <termios.h>
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-#  include <libutil.h>
-# else
-#  include <util.h>
-# endif
-#elif defined CONFIG_SOLARIS
-# include <stropts.h>
-#endif
-
 #ifdef _WIN32
 #include "sysemu/os-win32.h"
 #endif
@@ -174,6 +161,7 @@
 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);
@@ -191,6 +179,8 @@
  * 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'
@@ -232,6 +222,8 @@
 
 #ifndef _WIN32
 int qemu_pipe(int pipefd[2]);
+/* like openpty() but also makes it raw; return master fd */
+int qemu_openpty_raw(int *aslave, char *pty_name);
 #endif
 
 #ifdef _WIN32
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/include/qemu/error-report.h b/include/qemu/error-report.h
index c902cc1..14c1719 100644
--- a/include/qemu/error-report.h
+++ b/include/qemu/error-report.h
@@ -14,6 +14,7 @@
 #define QEMU_ERROR_H
 
 #include <stdarg.h>
+#include "qemu/compiler.h"
 
 typedef struct Location {
     /* all members are private to qemu-error.c */
diff --git a/include/qemu/log.h b/include/qemu/log.h
index 6b0db02..fd76f91 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -2,6 +2,9 @@
 #define QEMU_LOG_H
 
 #include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include "qemu/compiler.h"
 #ifdef NEED_CPU_H
 #include "disas/disas.h"
 #endif
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index afe4ec7..698fc03 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -22,6 +22,8 @@
 typedef struct MemoryRegion MemoryRegion;
 typedef struct MemoryRegionSection MemoryRegionSection;
 
+typedef struct MemoryMappingList MemoryMappingList;
+
 typedef struct NICInfo NICInfo;
 typedef struct HCIInfo HCIInfo;
 typedef struct AudioState AudioState;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7cd9442..a5bb515 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -23,6 +23,7 @@
 #include <signal.h>
 #include "hw/qdev-core.h"
 #include "qemu/thread.h"
+#include "qemu/typedefs.h"
 
 typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
 
@@ -48,6 +49,8 @@
  * @reset: Callback to reset the #CPUState to its initial state.
  * @do_interrupt: Callback for interrupt handling.
  * @get_arch_id: Callback for getting architecture-dependent CPU ID.
+ * @get_paging_enabled: Callback for inquiring whether paging is enabled.
+ * @get_memory_mapping: Callback for obtaining the memory mappings.
  * @vmsd: State description for migration.
  *
  * Represents a CPU family or model.
@@ -62,6 +65,9 @@
     void (*reset)(CPUState *cpu);
     void (*do_interrupt)(CPUState *cpu);
     int64_t (*get_arch_id)(CPUState *cpu);
+    bool (*get_paging_enabled)(const CPUState *cpu);
+    void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
+                               Error **errp);
 
     const struct VMStateDescription *vmsd;
     int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
@@ -138,6 +144,23 @@
 };
 
 /**
+ * cpu_paging_enabled:
+ * @cpu: The CPU whose state is to be inspected.
+ *
+ * Returns: %true if paging is enabled, %false otherwise.
+ */
+bool cpu_paging_enabled(const CPUState *cpu);
+
+/**
+ * cpu_get_memory_mapping:
+ * @cpu: The CPU whose memory mappings are to be obtained.
+ * @list: Where to write the memory mappings to.
+ * @errp: Pointer for reporting an #Error.
+ */
+void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+                            Error **errp);
+
+/**
  * cpu_write_elf64_note:
  * @f: pointer to a function that writes memory to a file
  * @cpu: The CPU whose memory is to be dumped
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 5e42c90..066c216 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -70,12 +70,12 @@
     void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
     void (*chr_set_fe_open)(struct CharDriverState *chr, int fe_open);
     void *opaque;
-    int idle_tag;
     char *label;
     char *filename;
     int be_open;
     int fe_open;
     int explicit_fe_open;
+    int explicit_be_open;
     int avail_connections;
     QemuOpts *opts;
     QTAILQ_ENTRY(CharDriverState) next;
diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h
index 1256125..6dfb68d 100644
--- a/include/sysemu/memory_mapping.h
+++ b/include/sysemu/memory_mapping.h
@@ -15,6 +15,7 @@
 #define MEMORY_MAPPING_H
 
 #include "qemu/queue.h"
+#include "qemu/typedefs.h"
 
 /* The physical and virtual address in the memory mapping are contiguous. */
 typedef struct MemoryMapping {
@@ -24,14 +25,11 @@
     QTAILQ_ENTRY(MemoryMapping) next;
 } MemoryMapping;
 
-typedef struct MemoryMappingList {
+struct MemoryMappingList {
     unsigned int num;
     MemoryMapping *last_mapping;
     QTAILQ_HEAD(, MemoryMapping) head;
-} MemoryMappingList;
-
-int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
-bool cpu_paging_enabled(CPUArchState *env);
+};
 
 /*
  * add or merge the memory region [phys_addr, phys_addr + length) into the
@@ -47,13 +45,7 @@
 
 void memory_mapping_list_init(MemoryMappingList *list);
 
-/*
- * Return value:
- *    0: success
- *   -1: failed
- *   -2: unsupported
- */
-int qemu_get_guest_memory_mapping(MemoryMappingList *list);
+void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp);
 
 /* get guest's memory mapping without do paging(virtual address is 0). */
 void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
diff --git a/include/ui/console.h b/include/ui/console.h
index 4307b5f..f1d79f9 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -339,6 +339,6 @@
 
 /* gtk.c */
 void early_gtk_display_init(void);
-void gtk_display_init(DisplayState *ds);
+void gtk_display_init(DisplayState *ds, bool full_screen);
 
 #endif
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index ac23647..5180d29 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -618,18 +618,22 @@
     if (ret != 0) {
         /* Error */
         fprintf(stderr, "getaddrinfo failed\n");
-        return -1;
+        goto cleanup_socket;
     }
 
     if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
         /* Error */
         fprintf(stderr, "Could not connect\n");
-        return -1;
+        goto cleanup_socket;
     }
     if (verbose) {
         printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
     }
     return sock;
+
+cleanup_socket:
+    closesocket(sock);
+    return -1;
 }
 
 int
@@ -759,5 +763,6 @@
     g_io_channel_unref(channel_socket);
     g_byte_array_unref(socket_to_send);
 
+    closesocket(sock);
     return 0;
 }
diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
index 023bfeb..c1ee007 100644
--- a/linux-headers/asm-arm/kvm.h
+++ b/linux-headers/asm-arm/kvm.h
@@ -53,12 +53,12 @@
 #define KVM_ARM_FIQ_spsr	fiq_regs[7]
 
 struct kvm_regs {
-	struct pt_regs usr_regs;/* R0_usr - R14_usr, PC, CPSR */
-	__u32 svc_regs[3];	/* SP_svc, LR_svc, SPSR_svc */
-	__u32 abt_regs[3];	/* SP_abt, LR_abt, SPSR_abt */
-	__u32 und_regs[3];	/* SP_und, LR_und, SPSR_und */
-	__u32 irq_regs[3];	/* SP_irq, LR_irq, SPSR_irq */
-	__u32 fiq_regs[8];	/* R8_fiq - R14_fiq, SPSR_fiq */
+	struct pt_regs usr_regs;	/* R0_usr - R14_usr, PC, CPSR */
+	unsigned long svc_regs[3];	/* SP_svc, LR_svc, SPSR_svc */
+	unsigned long abt_regs[3];	/* SP_abt, LR_abt, SPSR_abt */
+	unsigned long und_regs[3];	/* SP_und, LR_und, SPSR_und */
+	unsigned long irq_regs[3];	/* SP_irq, LR_irq, SPSR_irq */
+	unsigned long fiq_regs[8];	/* R8_fiq - R14_fiq, SPSR_fiq */
 };
 
 /* Supported Processor Types */
diff --git a/linux-headers/asm-mips/kvm.h b/linux-headers/asm-mips/kvm.h
new file mode 100644
index 0000000..3f424f5
--- /dev/null
+++ b/linux-headers/asm-mips/kvm.h
@@ -0,0 +1,138 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2013 Cavium, Inc.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#ifndef __LINUX_KVM_MIPS_H
+#define __LINUX_KVM_MIPS_H
+
+#include <linux/types.h>
+
+/*
+ * KVM MIPS specific structures and definitions.
+ *
+ * Some parts derived from the x86 version of this file.
+ */
+
+/*
+ * for KVM_GET_REGS and KVM_SET_REGS
+ *
+ * If Config[AT] is zero (32-bit CPU), the register contents are
+ * stored in the lower 32-bits of the struct kvm_regs fields and sign
+ * extended to 64-bits.
+ */
+struct kvm_regs {
+	/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+	__u64 gpr[32];
+	__u64 hi;
+	__u64 lo;
+	__u64 pc;
+};
+
+/*
+ * for KVM_GET_FPU and KVM_SET_FPU
+ *
+ * If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs
+ * are zero filled.
+ */
+struct kvm_fpu {
+	__u64 fpr[32];
+	__u32 fir;
+	__u32 fccr;
+	__u32 fexr;
+	__u32 fenr;
+	__u32 fcsr;
+	__u32 pad;
+};
+
+
+/*
+ * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0
+ * registers.  The id field is broken down as follows:
+ *
+ *  bits[2..0]   - Register 'sel' index.
+ *  bits[7..3]   - Register 'rd'  index.
+ *  bits[15..8]  - Must be zero.
+ *  bits[63..16] - 1 -> CP0 registers.
+ *
+ * Other sets registers may be added in the future.  Each set would
+ * have its own identifier in bits[63..16].
+ *
+ * The addr field of struct kvm_one_reg must point to an aligned
+ * 64-bit wide location.  For registers that are narrower than
+ * 64-bits, the value is stored in the low order bits of the location,
+ * and sign extended to 64-bits.
+ *
+ * The registers defined in struct kvm_regs are also accessible, the
+ * id values for these are below.
+ */
+
+#define KVM_REG_MIPS_R0 0
+#define KVM_REG_MIPS_R1 1
+#define KVM_REG_MIPS_R2 2
+#define KVM_REG_MIPS_R3 3
+#define KVM_REG_MIPS_R4 4
+#define KVM_REG_MIPS_R5 5
+#define KVM_REG_MIPS_R6 6
+#define KVM_REG_MIPS_R7 7
+#define KVM_REG_MIPS_R8 8
+#define KVM_REG_MIPS_R9 9
+#define KVM_REG_MIPS_R10 10
+#define KVM_REG_MIPS_R11 11
+#define KVM_REG_MIPS_R12 12
+#define KVM_REG_MIPS_R13 13
+#define KVM_REG_MIPS_R14 14
+#define KVM_REG_MIPS_R15 15
+#define KVM_REG_MIPS_R16 16
+#define KVM_REG_MIPS_R17 17
+#define KVM_REG_MIPS_R18 18
+#define KVM_REG_MIPS_R19 19
+#define KVM_REG_MIPS_R20 20
+#define KVM_REG_MIPS_R21 21
+#define KVM_REG_MIPS_R22 22
+#define KVM_REG_MIPS_R23 23
+#define KVM_REG_MIPS_R24 24
+#define KVM_REG_MIPS_R25 25
+#define KVM_REG_MIPS_R26 26
+#define KVM_REG_MIPS_R27 27
+#define KVM_REG_MIPS_R28 28
+#define KVM_REG_MIPS_R29 29
+#define KVM_REG_MIPS_R30 30
+#define KVM_REG_MIPS_R31 31
+
+#define KVM_REG_MIPS_HI 32
+#define KVM_REG_MIPS_LO 33
+#define KVM_REG_MIPS_PC 34
+
+/*
+ * KVM MIPS specific structures and definitions
+ *
+ */
+struct kvm_debug_exit_arch {
+	__u64 epc;
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+/* dummy definition */
+struct kvm_sregs {
+};
+
+struct kvm_mips_interrupt {
+	/* in */
+	__u32 cpu;
+	__u32 irq;
+};
+
+#endif /* __LINUX_KVM_MIPS_H */
diff --git a/linux-headers/asm-mips/kvm_para.h b/linux-headers/asm-mips/kvm_para.h
new file mode 100644
index 0000000..14fab8f
--- /dev/null
+++ b/linux-headers/asm-mips/kvm_para.h
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index ef072b1..0fb1a6e 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -25,6 +25,8 @@
 /* Select powerpc specific features in <linux/kvm.h> */
 #define __KVM_HAVE_SPAPR_TCE
 #define __KVM_HAVE_PPC_SMT
+#define __KVM_HAVE_IRQCHIP
+#define __KVM_HAVE_IRQ_LINE
 
 struct kvm_regs {
 	__u64 pc;
@@ -272,8 +274,31 @@
 
 /* for KVM_SET_GUEST_DEBUG */
 struct kvm_guest_debug_arch {
+	struct {
+		/* H/W breakpoint/watchpoint address */
+		__u64 addr;
+		/*
+		 * Type denotes h/w breakpoint, read watchpoint, write
+		 * watchpoint or watchpoint (both read and write).
+		 */
+#define KVMPPC_DEBUG_NONE		0x0
+#define KVMPPC_DEBUG_BREAKPOINT		(1UL << 1)
+#define KVMPPC_DEBUG_WATCH_WRITE	(1UL << 2)
+#define KVMPPC_DEBUG_WATCH_READ		(1UL << 3)
+		__u32 type;
+		__u32 reserved;
+	} bp[16];
 };
 
+/* Debug related defines */
+/*
+ * kvm_guest_debug->control is a 32 bit field. The lower 16 bits are generic
+ * and upper 16 bits are architecture specific. Architecture specific defines
+ * that ioctl is for setting hardware breakpoint or software breakpoint.
+ */
+#define KVM_GUESTDBG_USE_SW_BP		0x00010000
+#define KVM_GUESTDBG_USE_HW_BP		0x00020000
+
 /* definition of registers in kvm_run */
 struct kvm_sync_regs {
 };
@@ -299,6 +324,12 @@
 	__u64 rma_size;
 };
 
+/* for KVM_CAP_PPC_RTAS */
+struct kvm_rtas_token_args {
+	char name[120];
+	__u64 token;	/* Use a token of 0 to undefine a mapping */
+};
+
 struct kvm_book3e_206_tlb_entry {
 	__u32 mas8;
 	__u32 mas1;
@@ -359,6 +390,26 @@
 	__u16	n_invalid;
 };
 
+/* Per-vcpu XICS interrupt controller state */
+#define KVM_REG_PPC_ICP_STATE	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
+
+#define  KVM_REG_PPC_ICP_CPPR_SHIFT	56	/* current proc priority */
+#define  KVM_REG_PPC_ICP_CPPR_MASK	0xff
+#define  KVM_REG_PPC_ICP_XISR_SHIFT	32	/* interrupt status field */
+#define  KVM_REG_PPC_ICP_XISR_MASK	0xffffff
+#define  KVM_REG_PPC_ICP_MFRR_SHIFT	24	/* pending IPI priority */
+#define  KVM_REG_PPC_ICP_MFRR_MASK	0xff
+#define  KVM_REG_PPC_ICP_PPRI_SHIFT	16	/* pending irq priority */
+#define  KVM_REG_PPC_ICP_PPRI_MASK	0xff
+
+/* Device control API: PPC-specific devices */
+#define KVM_DEV_MPIC_GRP_MISC		1
+#define   KVM_DEV_MPIC_BASE_ADDR	0	/* 64-bit */
+
+#define KVM_DEV_MPIC_GRP_REGISTER	2	/* 32-bit */
+#define KVM_DEV_MPIC_GRP_IRQ_ACTIVE	3	/* 32-bit */
+
+/* One-Reg API: PPC-specific registers */
 #define KVM_REG_PPC_HIOR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
 #define KVM_REG_PPC_IAC1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
 #define KVM_REG_PPC_IAC2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
@@ -422,4 +473,42 @@
 #define KVM_REG_PPC_CLEAR_TSR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x88)
 #define KVM_REG_PPC_TCR		(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89)
 #define KVM_REG_PPC_TSR		(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a)
+
+/* Debugging: Special instruction for software breakpoint */
+#define KVM_REG_PPC_DEBUG_INST	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8b)
+
+/* MMU registers */
+#define KVM_REG_PPC_MAS0	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8c)
+#define KVM_REG_PPC_MAS1	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8d)
+#define KVM_REG_PPC_MAS2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8e)
+#define KVM_REG_PPC_MAS7_3	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8f)
+#define KVM_REG_PPC_MAS4	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x90)
+#define KVM_REG_PPC_MAS6	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x91)
+#define KVM_REG_PPC_MMUCFG	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x92)
+/*
+ * TLBnCFG fields TLBnCFG_N_ENTRY and TLBnCFG_ASSOC can be changed only using
+ * KVM_CAP_SW_TLB ioctl
+ */
+#define KVM_REG_PPC_TLB0CFG	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x93)
+#define KVM_REG_PPC_TLB1CFG	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x94)
+#define KVM_REG_PPC_TLB2CFG	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x95)
+#define KVM_REG_PPC_TLB3CFG	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x96)
+#define KVM_REG_PPC_TLB0PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x97)
+#define KVM_REG_PPC_TLB1PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x98)
+#define KVM_REG_PPC_TLB2PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x99)
+#define KVM_REG_PPC_TLB3PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
+#define KVM_REG_PPC_EPTCFG	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b)
+
+/* PPC64 eXternal Interrupt Controller Specification */
+#define KVM_DEV_XICS_GRP_SOURCES	1	/* 64-bit source attributes */
+
+/* Layout of 64-bit source attribute values */
+#define  KVM_XICS_DESTINATION_SHIFT	0
+#define  KVM_XICS_DESTINATION_MASK	0xffffffffULL
+#define  KVM_XICS_PRIORITY_SHIFT	32
+#define  KVM_XICS_PRIORITY_MASK		0xff
+#define  KVM_XICS_LEVEL_SENSITIVE	(1ULL << 40)
+#define  KVM_XICS_MASKED		(1ULL << 41)
+#define  KVM_XICS_PENDING		(1ULL << 42)
+
 #endif /* __LINUX_KVM_POWERPC_H */
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
index a65ec29..5d9a303 100644
--- a/linux-headers/asm-x86/kvm.h
+++ b/linux-headers/asm-x86/kvm.h
@@ -29,7 +29,6 @@
 #define __KVM_HAVE_PIT
 #define __KVM_HAVE_IOAPIC
 #define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_DEVICE_ASSIGNMENT
 #define __KVM_HAVE_MSI
 #define __KVM_HAVE_USER_NMI
 #define __KVM_HAVE_GUEST_DEBUG
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index eb02d8a..c614070 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -561,9 +561,7 @@
 #define KVM_CAP_MP_STATE 14
 #define KVM_CAP_COALESCED_MMIO 15
 #define KVM_CAP_SYNC_MMU 16  /* Changes to host mmap are reflected in guest */
-#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
 #define KVM_CAP_DEVICE_ASSIGNMENT 17
-#endif
 #define KVM_CAP_IOMMU 18
 #ifdef __KVM_HAVE_MSI
 #define KVM_CAP_DEVICE_MSI 20
@@ -579,13 +577,9 @@
 #ifdef __KVM_HAVE_PIT
 #define KVM_CAP_REINJECT_CONTROL 24
 #endif
-#ifdef __KVM_HAVE_IOAPIC
 #define KVM_CAP_IRQ_ROUTING 25
-#endif
 #define KVM_CAP_IRQ_INJECT_STATUS 26
-#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
 #define KVM_CAP_DEVICE_DEASSIGNMENT 27
-#endif
 #ifdef __KVM_HAVE_MSIX
 #define KVM_CAP_DEVICE_MSIX 28
 #endif
@@ -668,6 +662,10 @@
 #define KVM_CAP_PPC_EPR 86
 #define KVM_CAP_ARM_PSCI 87
 #define KVM_CAP_ARM_SET_DEVICE_ADDR 88
+#define KVM_CAP_DEVICE_CTRL 89
+#define KVM_CAP_IRQ_MPIC 90
+#define KVM_CAP_PPC_RTAS 91
+#define KVM_CAP_IRQ_XICS 92
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -821,6 +819,28 @@
 };
 
 /*
+ * Device control API, available with KVM_CAP_DEVICE_CTRL
+ */
+#define KVM_CREATE_DEVICE_TEST		1
+
+struct kvm_create_device {
+	__u32	type;	/* in: KVM_DEV_TYPE_xxx */
+	__u32	fd;	/* out: device handle */
+	__u32	flags;	/* in: KVM_CREATE_DEVICE_xxx */
+};
+
+struct kvm_device_attr {
+	__u32	flags;		/* no flags currently defined */
+	__u32	group;		/* device-defined */
+	__u64	attr;		/* group-defined */
+	__u64	addr;		/* userspace address of attr data */
+};
+
+#define KVM_DEV_TYPE_FSL_MPIC_20	1
+#define KVM_DEV_TYPE_FSL_MPIC_42	2
+#define KVM_DEV_TYPE_XICS		3
+
+/*
  * ioctls for VM fds
  */
 #define KVM_SET_MEMORY_REGION     _IOW(KVMIO,  0x40, struct kvm_memory_region)
@@ -907,6 +927,16 @@
 #define KVM_PPC_GET_HTAB_FD	  _IOW(KVMIO,  0xaa, struct kvm_get_htab_fd)
 /* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
 #define KVM_ARM_SET_DEVICE_ADDR	  _IOW(KVMIO,  0xab, struct kvm_arm_device_addr)
+/* Available with KVM_CAP_PPC_RTAS */
+#define KVM_PPC_RTAS_DEFINE_TOKEN _IOW(KVMIO,  0xac, struct kvm_rtas_token_args)
+
+/* ioctl for vm fd */
+#define KVM_CREATE_DEVICE	  _IOWR(KVMIO,  0xe0, struct kvm_create_device)
+
+/* ioctls for fds returned by KVM_CREATE_DEVICE */
+#define KVM_SET_DEVICE_ATTR	  _IOW(KVMIO,  0xe1, struct kvm_device_attr)
+#define KVM_GET_DEVICE_ATTR	  _IOW(KVMIO,  0xe2, struct kvm_device_attr)
+#define KVM_HAS_DEVICE_ATTR	  _IOW(KVMIO,  0xe3, struct kvm_device_attr)
 
 /*
  * ioctls for vcpu fds
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index e094121..7ec1864 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -319,6 +319,7 @@
 	VFIO_PCI_INTX_IRQ_INDEX,
 	VFIO_PCI_MSI_IRQ_INDEX,
 	VFIO_PCI_MSIX_IRQ_INDEX,
+	VFIO_PCI_ERR_IRQ_INDEX,
 	VFIO_PCI_NUM_IRQS
 };
 
diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h
index 165a484..c656f61 100644
--- a/linux-headers/linux/vhost.h
+++ b/linux-headers/linux/vhost.h
@@ -127,4 +127,32 @@
 /* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
 #define VHOST_NET_F_VIRTIO_NET_HDR 27
 
+/* VHOST_SCSI specific definitions */
+
+/*
+ * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
+ *
+ * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
+ *            RFC-v2 vhost-scsi userspace.  Add GET_ABI_VERSION ioctl usage
+ * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
+ *            All the targets under vhost_wwpn can be seen and used by guset.
+ */
+
+#define VHOST_SCSI_ABI_VERSION	1
+
+struct vhost_scsi_target {
+	int abi_version;
+	char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
+	unsigned short vhost_tpgt;
+	unsigned short reserved;
+};
+
+#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
+#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
+/* Changing this breaks userspace. */
+#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
+/* Set and get the events missed flag */
+#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
+#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
+
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0099d64..cdd0c28 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -181,29 +181,14 @@
 
 
 #define __NR_sys_uname __NR_uname
-#define __NR_sys_faccessat __NR_faccessat
-#define __NR_sys_fchmodat __NR_fchmodat
-#define __NR_sys_fchownat __NR_fchownat
-#define __NR_sys_fstatat64 __NR_fstatat64
-#define __NR_sys_futimesat __NR_futimesat
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
 #define __NR_sys_getpriority __NR_getpriority
-#define __NR_sys_linkat __NR_linkat
-#define __NR_sys_mkdirat __NR_mkdirat
-#define __NR_sys_mknodat __NR_mknodat
-#define __NR_sys_newfstatat __NR_newfstatat
-#define __NR_sys_openat __NR_openat
-#define __NR_sys_readlinkat __NR_readlinkat
-#define __NR_sys_renameat __NR_renameat
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
-#define __NR_sys_symlinkat __NR_symlinkat
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_tgkill __NR_tgkill
 #define __NR_sys_tkill __NR_tkill
-#define __NR_sys_unlinkat __NR_unlinkat
-#define __NR_sys_utimensat __NR_utimensat
 #define __NR_sys_futex __NR_futex
 #define __NR_sys_inotify_init __NR_inotify_init
 #define __NR_sys_inotify_add_watch __NR_inotify_add_watch
@@ -223,8 +208,11 @@
     return -ENOSYS;
 }
 #endif
+#ifdef __NR_getdents
 _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
-#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
+#endif
+#if !defined(__NR_getdents) || \
+    (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
 _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
 #endif
 #if defined(TARGET_NR__llseek) && defined(__NR_llseek)
@@ -336,72 +324,6 @@
   return strlen(buf)+1;
 }
 
-#ifdef CONFIG_ATFILE
-/*
- * Host system seems to have atfile syscall stubs available.  We
- * now enable them one by one as specified by target syscall_nr.h.
- */
-
-#ifdef TARGET_NR_faccessat
-static int sys_faccessat(int dirfd, const char *pathname, int mode)
-{
-  return (faccessat(dirfd, pathname, mode, 0));
-}
-#endif
-#ifdef TARGET_NR_fchmodat
-static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
-{
-  return (fchmodat(dirfd, pathname, mode, 0));
-}
-#endif
-#if defined(TARGET_NR_fchownat)
-static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
-    gid_t group, int flags)
-{
-  return (fchownat(dirfd, pathname, owner, group, flags));
-}
-#endif
-#ifdef __NR_fstatat64
-static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
-    int flags)
-{
-  return (fstatat(dirfd, pathname, buf, flags));
-}
-#endif
-#ifdef __NR_newfstatat
-static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
-    int flags)
-{
-  return (fstatat(dirfd, pathname, buf, flags));
-}
-#endif
-#ifdef TARGET_NR_futimesat
-static int sys_futimesat(int dirfd, const char *pathname,
-    const struct timeval times[2])
-{
-  return (futimesat(dirfd, pathname, times));
-}
-#endif
-#ifdef TARGET_NR_linkat
-static int sys_linkat(int olddirfd, const char *oldpath,
-    int newdirfd, const char *newpath, int flags)
-{
-  return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
-}
-#endif
-#ifdef TARGET_NR_mkdirat
-static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
-{
-  return (mkdirat(dirfd, pathname, mode));
-}
-#endif
-#ifdef TARGET_NR_mknodat
-static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
-    dev_t dev)
-{
-  return (mknodat(dirfd, pathname, mode, dev));
-}
-#endif
 #ifdef TARGET_NR_openat
 static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
 {
@@ -415,91 +337,6 @@
   return (openat(dirfd, pathname, flags));
 }
 #endif
-#ifdef TARGET_NR_readlinkat
-static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
-{
-  return (readlinkat(dirfd, pathname, buf, bufsiz));
-}
-#endif
-#ifdef TARGET_NR_renameat
-static int sys_renameat(int olddirfd, const char *oldpath,
-    int newdirfd, const char *newpath)
-{
-  return (renameat(olddirfd, oldpath, newdirfd, newpath));
-}
-#endif
-#ifdef TARGET_NR_symlinkat
-static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
-{
-  return (symlinkat(oldpath, newdirfd, newpath));
-}
-#endif
-#ifdef TARGET_NR_unlinkat
-static int sys_unlinkat(int dirfd, const char *pathname, int flags)
-{
-  return (unlinkat(dirfd, pathname, flags));
-}
-#endif
-#else /* !CONFIG_ATFILE */
-
-/*
- * Try direct syscalls instead
- */
-#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
-_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
-#endif
-#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
-_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
-#endif
-#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
-_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
-          uid_t,owner,gid_t,group,int,flags)
-#endif
-#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
-        defined(__NR_fstatat64)
-_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
-          struct stat *,buf,int,flags)
-#endif
-#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
-_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
-         const struct timeval *,times)
-#endif
-#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
-        defined(__NR_newfstatat)
-_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
-          struct stat *,buf,int,flags)
-#endif
-#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
-_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
-      int,newdirfd,const char *,newpath,int,flags)
-#endif
-#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
-_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
-#endif
-#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
-_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
-          mode_t,mode,dev_t,dev)
-#endif
-#if defined(TARGET_NR_openat) && defined(__NR_openat)
-_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
-#endif
-#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
-_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
-          char *,buf,size_t,bufsize)
-#endif
-#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
-_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
-          int,newdirfd,const char *,newpath)
-#endif
-#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
-_syscall3(int,sys_symlinkat,const char *,oldpath,
-          int,newdirfd,const char *,newpath)
-#endif
-#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
-_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
-#endif
-
-#endif /* CONFIG_ATFILE */
 
 #ifdef CONFIG_UTIMENSAT
 static int sys_utimensat(int dirfd, const char *pathname,
@@ -5342,7 +5179,7 @@
             unlock_user(p, arg1, 0);
         }
         break;
-#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
+#if defined(TARGET_NR_linkat)
     case TARGET_NR_linkat:
         {
             void * p2 = NULL;
@@ -5353,7 +5190,7 @@
             if (!p || !p2)
                 ret = -TARGET_EFAULT;
             else
-                ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
+                ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
             unlock_user(p, arg2, 0);
             unlock_user(p2, arg4, 0);
         }
@@ -5365,11 +5202,11 @@
         ret = get_errno(unlink(p));
         unlock_user(p, arg1, 0);
         break;
-#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
+#if defined(TARGET_NR_unlinkat)
     case TARGET_NR_unlinkat:
         if (!(p = lock_user_string(arg2)))
             goto efault;
-        ret = get_errno(sys_unlinkat(arg1, p, arg3));
+        ret = get_errno(unlinkat(arg1, p, arg3));
         unlock_user(p, arg2, 0);
         break;
 #endif
@@ -5487,11 +5324,11 @@
         ret = get_errno(mknod(p, arg2, arg3));
         unlock_user(p, arg1, 0);
         break;
-#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
+#if defined(TARGET_NR_mknodat)
     case TARGET_NR_mknodat:
         if (!(p = lock_user_string(arg2)))
             goto efault;
-        ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
+        ret = get_errno(mknodat(arg1, p, arg3, arg4));
         unlock_user(p, arg2, 0);
         break;
 #endif
@@ -5622,7 +5459,7 @@
             unlock_user(p, arg1, 0);
         }
         break;
-#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
+#if defined(TARGET_NR_futimesat)
     case TARGET_NR_futimesat:
         {
             struct timeval *tvp, tv[2];
@@ -5637,7 +5474,7 @@
             }
             if (!(p = lock_user_string(arg2)))
                 goto efault;
-            ret = get_errno(sys_futimesat(arg1, path(p), tvp));
+            ret = get_errno(futimesat(arg1, path(p), tvp));
             unlock_user(p, arg2, 0);
         }
         break;
@@ -5660,7 +5497,7 @@
     case TARGET_NR_faccessat:
         if (!(p = lock_user_string(arg2)))
             goto efault;
-        ret = get_errno(sys_faccessat(arg1, p, arg3));
+        ret = get_errno(faccessat(arg1, p, arg3, 0));
         unlock_user(p, arg2, 0);
         break;
 #endif
@@ -5693,7 +5530,7 @@
             unlock_user(p, arg1, 0);
         }
         break;
-#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
+#if defined(TARGET_NR_renameat)
     case TARGET_NR_renameat:
         {
             void *p2;
@@ -5702,7 +5539,7 @@
             if (!p || !p2)
                 ret = -TARGET_EFAULT;
             else
-                ret = get_errno(sys_renameat(arg1, p, arg3, p2));
+                ret = get_errno(renameat(arg1, p, arg3, p2));
             unlock_user(p2, arg4, 0);
             unlock_user(p, arg2, 0);
         }
@@ -5714,11 +5551,11 @@
         ret = get_errno(mkdir(p, arg2));
         unlock_user(p, arg1, 0);
         break;
-#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
+#if defined(TARGET_NR_mkdirat)
     case TARGET_NR_mkdirat:
         if (!(p = lock_user_string(arg2)))
             goto efault;
-        ret = get_errno(sys_mkdirat(arg1, p, arg3));
+        ret = get_errno(mkdirat(arg1, p, arg3));
         unlock_user(p, arg2, 0);
         break;
 #endif
@@ -6404,7 +6241,7 @@
             unlock_user(p, arg1, 0);
         }
         break;
-#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
+#if defined(TARGET_NR_symlinkat)
     case TARGET_NR_symlinkat:
         {
             void *p2;
@@ -6413,7 +6250,7 @@
             if (!p || !p2)
                 ret = -TARGET_EFAULT;
             else
-                ret = get_errno(sys_symlinkat(p, arg2, p2));
+                ret = get_errno(symlinkat(p, arg2, p2));
             unlock_user(p2, arg3, 0);
             unlock_user(p, arg1, 0);
         }
@@ -6444,7 +6281,7 @@
             unlock_user(p, arg1, 0);
         }
         break;
-#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
+#if defined(TARGET_NR_readlinkat)
     case TARGET_NR_readlinkat:
         {
             void *p2;
@@ -6453,7 +6290,7 @@
             if (!p || !p2)
         	ret = -TARGET_EFAULT;
             else
-                ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
+                ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
             unlock_user(p2, arg3, ret);
             unlock_user(p, arg2, 0);
         }
@@ -6588,11 +6425,11 @@
     case TARGET_NR_fchmod:
         ret = get_errno(fchmod(arg1, arg2));
         break;
-#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
+#if defined(TARGET_NR_fchmodat)
     case TARGET_NR_fchmodat:
         if (!(p = lock_user_string(arg2)))
             goto efault;
-        ret = get_errno(sys_fchmodat(arg1, p, arg3));
+        ret = get_errno(fchmodat(arg1, p, arg3, 0));
         unlock_user(p, arg2, 0);
         break;
 #endif
@@ -7123,6 +6960,7 @@
         break;
 #endif
     case TARGET_NR_getdents:
+#ifdef __NR_getdents
 #if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
         {
             struct target_dirent *target_dirp;
@@ -7195,6 +7033,61 @@
             unlock_user(dirp, arg2, ret);
         }
 #endif
+#else
+        /* Implement getdents in terms of getdents64 */
+        {
+            struct linux_dirent64 *dirp;
+            abi_long count = arg3;
+
+            dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
+            if (!dirp) {
+                goto efault;
+            }
+            ret = get_errno(sys_getdents64(arg1, dirp, count));
+            if (!is_error(ret)) {
+                /* Convert the dirent64 structs to target dirent.  We do this
+                 * in-place, since we can guarantee that a target_dirent is no
+                 * larger than a dirent64; however this means we have to be
+                 * careful to read everything before writing in the new format.
+                 */
+                struct linux_dirent64 *de;
+                struct target_dirent *tde;
+                int len = ret;
+                int tlen = 0;
+
+                de = dirp;
+                tde = (struct target_dirent *)dirp;
+                while (len > 0) {
+                    int namelen, treclen;
+                    int reclen = de->d_reclen;
+                    uint64_t ino = de->d_ino;
+                    int64_t off = de->d_off;
+                    uint8_t type = de->d_type;
+
+                    namelen = strlen(de->d_name);
+                    treclen = offsetof(struct target_dirent, d_name)
+                        + namelen + 2;
+                    treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
+
+                    memmove(tde->d_name, de->d_name, namelen + 1);
+                    tde->d_ino = tswapal(ino);
+                    tde->d_off = tswapal(off);
+                    tde->d_reclen = tswap16(treclen);
+                    /* The target_dirent type is in what was formerly a padding
+                     * byte at the end of the structure:
+                     */
+                    *(((char *)tde) + treclen - 1) = type;
+
+                    de = (struct linux_dirent64 *)((char *)de + reclen);
+                    tde = (struct target_dirent *)((char *)tde + treclen);
+                    len -= reclen;
+                    tlen += treclen;
+                }
+                ret = tlen;
+            }
+            unlock_user(dirp, arg2, ret);
+        }
+#endif
         break;
 #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
     case TARGET_NR_getdents64:
@@ -7680,8 +7573,7 @@
             ret = host_to_target_stat64(cpu_env, arg2, &st);
         break;
 #endif
-#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
-        (defined(__NR_fstatat64) || defined(__NR_newfstatat))
+#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
 #ifdef TARGET_NR_fstatat64
     case TARGET_NR_fstatat64:
 #endif
@@ -7690,11 +7582,7 @@
 #endif
         if (!(p = lock_user_string(arg2)))
             goto efault;
-#ifdef __NR_fstatat64
-        ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
-#else
-        ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
-#endif
+        ret = get_errno(fstatat(arg1, path(p), &st, arg4));
         if (!is_error(ret))
             ret = host_to_target_stat64(cpu_env, arg3, &st);
         break;
@@ -7776,11 +7664,12 @@
     case TARGET_NR_fchown:
         ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
         break;
-#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
+#if defined(TARGET_NR_fchownat)
     case TARGET_NR_fchownat:
         if (!(p = lock_user_string(arg2))) 
             goto efault;
-        ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
+        ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
+                                 low2highgid(arg4), arg5));
         unlock_user(p, arg2, 0);
         break;
 #endif
diff --git a/main-loop.c b/main-loop.c
index cf36645..a44fff6 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -24,7 +24,8 @@
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "slirp/slirp.h"
+#include "qemu/sockets.h"	// struct in_addr needed for libslirp.h
+#include "slirp/libslirp.h"
 #include "qemu/main-loop.h"
 #include "block/aio.h"
 
diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c
deleted file mode 100644
index 24d5d67..0000000
--- a/memory_mapping-stub.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * QEMU memory mapping
- *
- * Copyright Fujitsu, Corp. 2011, 2012
- *
- * Authors:
- *     Wen Congyang <wency@cn.fujitsu.com>
- *
- * 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 "cpu.h"
-#include "exec/cpu-all.h"
-#include "sysemu/memory_mapping.h"
-
-int qemu_get_guest_memory_mapping(MemoryMappingList *list)
-{
-    return -2;
-}
-
-int cpu_get_memory_mapping(MemoryMappingList *list,
-					                                          CPUArchState *env)
-{
-    return -1;
-}
-
-bool cpu_paging_enabled(CPUArchState *env)
-{
-    return true;
-}
-
diff --git a/memory_mapping.c b/memory_mapping.c
index ff45b3a..5634f81 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -170,7 +170,7 @@
     CPUArchState *env;
 
     for (env = start_cpu; env != NULL; env = env->next_cpu) {
-        if (cpu_paging_enabled(env)) {
+        if (cpu_paging_enabled(ENV_GET_CPU(env))) {
             return env;
         }
     }
@@ -178,22 +178,23 @@
     return NULL;
 }
 
-int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp)
 {
     CPUArchState *env, *first_paging_enabled_cpu;
     RAMBlock *block;
     ram_addr_t offset, length;
-    int ret;
 
     first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
     if (first_paging_enabled_cpu) {
         for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) {
-            ret = cpu_get_memory_mapping(list, env);
-            if (ret < 0) {
-                return -1;
+            Error *err = NULL;
+            cpu_get_memory_mapping(ENV_GET_CPU(env), list, &err);
+            if (err) {
+                error_propagate(errp, err);
+                return;
             }
         }
-        return 0;
+        return;
     }
 
     /*
@@ -205,8 +206,6 @@
         length = block->length;
         create_new_memory_mapping(list, offset, offset, length);
     }
-
-    return 0;
 }
 
 void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
diff --git a/monitor.c b/monitor.c
index eefc7f0..70ae8f5 100644
--- a/monitor.c
+++ b/monitor.c
@@ -93,10 +93,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
@@ -2013,7 +2013,6 @@
 static void do_inject_mce(Monitor *mon, const QDict *qdict)
 {
     X86CPU *cpu;
-    CPUX86State *cenv;
     CPUState *cs;
     int cpu_index = qdict_get_int(qdict, "cpu_index");
     int bank = qdict_get_int(qdict, "bank");
@@ -2026,14 +2025,11 @@
     if (qdict_get_try_bool(qdict, "broadcast", 0)) {
         flags |= MCE_INJECT_BROADCAST;
     }
-    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
-        cpu = x86_env_get_cpu(cenv);
-        cs = CPU(cpu);
-        if (cs->cpu_index == cpu_index) {
-            cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
-                               flags);
-            break;
-        }
+    cs = qemu_get_cpu(cpu_index);
+    if (cs != NULL) {
+        cpu = X86_CPU(cs);
+        cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
+                           flags);
     }
 }
 #endif
@@ -2472,9 +2468,10 @@
     },
     {
         .name       = "block",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show the block devices",
+        .args_type  = "verbose:-v,device:B?",
+        .params     = "[-v] [device]",
+        .help       = "show info of one block device or all block devices "
+                      "(and details of images with -v option)",
         .mhandler.cmd = hmp_info_block,
     },
     {
diff --git a/net/tap.c b/net/tap.c
index e0b7a2a..39c1cda 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -698,9 +698,10 @@
     if (tap->has_fd) {
         if (tap->has_ifname || tap->has_script || tap->has_downscript ||
             tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
-            tap->has_fds) {
+            tap->has_fds || tap->has_vhostfds) {
             error_report("ifname=, script=, downscript=, vnet_hdr=, "
-                         "helper=, queues=, and fds= are invalid with fd=");
+                         "helper=, queues=, fds=, and vhostfds= "
+                         "are invalid with fd=");
             return -1;
         }
 
@@ -725,9 +726,10 @@
 
         if (tap->has_ifname || tap->has_script || tap->has_downscript ||
             tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
-            tap->has_fd) {
+            tap->has_vhostfd) {
             error_report("ifname=, script=, downscript=, vnet_hdr=, "
-                         "helper=, queues=, and fd= are invalid with fds=");
+                         "helper=, queues=, and vhostfd= "
+                         "are invalid with fds=");
             return -1;
         }
 
@@ -765,9 +767,9 @@
         }
     } else if (tap->has_helper) {
         if (tap->has_ifname || tap->has_script || tap->has_downscript ||
-            tap->has_vnet_hdr || tap->has_queues || tap->has_fds) {
+            tap->has_vnet_hdr || tap->has_queues || tap->has_vhostfds) {
             error_report("ifname=, script=, downscript=, and vnet_hdr= "
-                         "queues=, and fds= are invalid with helper=");
+                         "queues=, and vhostfds= are invalid with helper=");
             return -1;
         }
 
@@ -785,6 +787,10 @@
             return -1;
         }
     } else {
+        if (tap->has_vhostfds) {
+            error_report("vhostfds= is invalid if fds= wasn't specified");
+            return -1;
+        }
         script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT;
         downscript = tap->has_downscript ? tap->downscript :
             DEFAULT_NETWORK_DOWN_SCRIPT;
diff --git a/pc-bios/qemu_logo_no_text.svg b/pc-bios/qemu_logo_no_text.svg
new file mode 100644
index 0000000..24ca23a
--- /dev/null
+++ b/pc-bios/qemu_logo_no_text.svg
@@ -0,0 +1,976 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="111.71874"
+   height="111.12498"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="qemu_logo_no_text.svg">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient4686">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4688" />
+      <stop
+         id="stop3956"
+         offset="0.75"
+         style="stop-color:#000000;stop-opacity:0.87843138;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.43921569;"
+         offset="0.75"
+         id="stop3958" />
+      <stop
+         id="stop3960"
+         offset="0.88"
+         style="stop-color:#181818;stop-opacity:1;" />
+      <stop
+         style="stop-color:#242424;stop-opacity:1;"
+         offset="0.88"
+         id="stop3962" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop4690" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4467">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4469" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0.8974359;"
+         offset="1"
+         id="stop4471" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4431">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4433" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4435" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4466">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4468" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4470" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4321">
+      <stop
+         style="stop-color:#ff6702;stop-opacity:1;"
+         offset="0"
+         id="stop4323" />
+      <stop
+         style="stop-color:#ff9a55;stop-opacity:1;"
+         offset="1"
+         id="stop4325" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4283">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4285" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4287" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4251">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4253" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4255" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4007">
+      <stop
+         style="stop-color:#ff6600;stop-opacity:1;"
+         offset="0"
+         id="stop4009" />
+      <stop
+         style="stop-color:#ff9148;stop-opacity:1;"
+         offset="1"
+         id="stop4011" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3999">
+      <stop
+         style="stop-color:#fff7f2;stop-opacity:1;"
+         offset="0"
+         id="stop4001" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4003" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3890">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3892" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3894" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3880">
+      <stop
+         style="stop-color:#eb7400;stop-opacity:1;"
+         offset="0"
+         id="stop3882" />
+      <stop
+         style="stop-color:#f7b06a;stop-opacity:1;"
+         offset="1"
+         id="stop3884" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4011">
+      <stop
+         style="stop-color:#042dc8;stop-opacity:1;"
+         offset="0"
+         id="stop4013" />
+      <stop
+         style="stop-color:#4260d5;stop-opacity:1;"
+         offset="1"
+         id="stop4015" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3879">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.90598291;"
+         offset="0"
+         id="stop3881" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3869">
+      <stop
+         style="stop-color:#c95000;stop-opacity:1;"
+         offset="0"
+         id="stop3871" />
+      <stop
+         style="stop-color:#ff9e5e;stop-opacity:1;"
+         offset="1"
+         id="stop3873" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3861">
+      <stop
+         style="stop-color:#f06000;stop-opacity:1;"
+         offset="0"
+         id="stop3863" />
+      <stop
+         style="stop-color:#ffccaa;stop-opacity:1;"
+         offset="1"
+         id="stop3865" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3826">
+      <stop
+         style="stop-color:#ff6600;stop-opacity:1;"
+         offset="0"
+         id="stop3828" />
+      <stop
+         style="stop-color:#ff893b;stop-opacity:1;"
+         offset="1"
+         id="stop3830" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3879-6">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.90598291;"
+         offset="0"
+         id="stop3881-4" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-7" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3869-5">
+      <stop
+         style="stop-color:#c95000;stop-opacity:1;"
+         offset="0"
+         id="stop3871-9" />
+      <stop
+         style="stop-color:#ff9e5e;stop-opacity:1;"
+         offset="1"
+         id="stop3873-4" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3879-4"
+       id="linearGradient3885-6"
+       x1="76.025352"
+       y1="124.8497"
+       x2="75.874107"
+       y2="143.03978"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient3879-4">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.93162394;"
+         offset="0"
+         id="stop3881-6" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-74" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3869-2">
+      <stop
+         style="stop-color:#c95000;stop-opacity:1;"
+         offset="0"
+         id="stop3871-99" />
+      <stop
+         style="stop-color:#ff9e5e;stop-opacity:1;"
+         offset="1"
+         id="stop3873-6" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4011"
+       id="radialGradient4017"
+       cx="66.639"
+       cy="93.096375"
+       fx="66.639"
+       fy="93.096375"
+       r="11.515625"
+       gradientTransform="matrix(0.23244854,1.600893,-1.0124495,0.14700695,145.40424,-26.300303)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3879-4-7"
+       id="linearGradient3885-6-2"
+       x1="76.025352"
+       y1="124.8497"
+       x2="75.874107"
+       y2="143.03978"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient3879-4-7">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.93162394;"
+         offset="0"
+         id="stop3881-6-7" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-74-6" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4011-5"
+       id="radialGradient4017-7"
+       cx="66.639"
+       cy="93.096375"
+       fx="66.639"
+       fy="93.096375"
+       r="11.515625"
+       gradientTransform="matrix(0.99779178,6.8718773,-4.3459674,0.6310314,452.75975,-225.98471)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4011-5">
+      <stop
+         style="stop-color:#042dc8;stop-opacity:1;"
+         offset="0"
+         id="stop4013-1" />
+      <stop
+         style="stop-color:#4260d5;stop-opacity:1;"
+         offset="1"
+         id="stop4015-3" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3879-4-75"
+       id="linearGradient3885-6-8"
+       x1="76.025352"
+       y1="124.8497"
+       x2="75.874107"
+       y2="143.03978"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient3879-4-75">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.93162394;"
+         offset="0"
+         id="stop3881-6-1" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-74-4" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4011-0"
+       id="radialGradient4017-5"
+       cx="66.639"
+       cy="93.096375"
+       fx="66.639"
+       fy="93.096375"
+       r="11.515625"
+       gradientTransform="matrix(0.23244854,1.600893,-1.0124495,0.14700695,146.34996,53.681728)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4011-0">
+      <stop
+         style="stop-color:#042dc8;stop-opacity:1;"
+         offset="0"
+         id="stop4013-4" />
+      <stop
+         style="stop-color:#4260d5;stop-opacity:1;"
+         offset="1"
+         id="stop4015-0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4011-0"
+       id="linearGradient4117"
+       x1="107.03001"
+       y1="189.72537"
+       x2="107.18476"
+       y2="173.47537"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3879-4-7-2"
+       id="linearGradient3885-6-2-8"
+       x1="76.025352"
+       y1="124.8497"
+       x2="75.874107"
+       y2="143.03978"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient3879-4-7-2">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.93162394;"
+         offset="0"
+         id="stop3881-6-7-9" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-74-6-9" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4011-5-1"
+       id="radialGradient4017-7-9"
+       cx="66.639"
+       cy="93.096375"
+       fx="66.639"
+       fy="93.096375"
+       r="11.515625"
+       gradientTransform="matrix(0.99779178,6.8718773,-4.3459674,0.6310314,448.94742,-406.99277)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4011-5-1">
+      <stop
+         style="stop-color:#042dc8;stop-opacity:1;"
+         offset="0"
+         id="stop4013-1-9" />
+      <stop
+         style="stop-color:#4260d5;stop-opacity:1;"
+         offset="1"
+         id="stop4015-3-8" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3879-4-7-2-7"
+       id="linearGradient3885-6-2-8-0"
+       x1="76.025352"
+       y1="124.8497"
+       x2="75.874107"
+       y2="143.03978"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient3879-4-7-2-7">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.93162394;"
+         offset="0"
+         id="stop3881-6-7-9-3" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-74-6-9-6" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4011-5-1-5"
+       id="radialGradient4017-7-9-5"
+       cx="66.639"
+       cy="93.096375"
+       fx="66.639"
+       fy="93.096375"
+       r="11.515625"
+       gradientTransform="matrix(0.55965334,3.8543806,-2.4376181,0.3539404,454.75182,-145.44353)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4011-5-1-5">
+      <stop
+         style="stop-color:#042dc8;stop-opacity:1;"
+         offset="0"
+         id="stop4013-1-9-6" />
+      <stop
+         style="stop-color:#4260d5;stop-opacity:1;"
+         offset="1"
+         id="stop4015-3-8-9" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3879-4-7-2-4"
+       id="linearGradient3885-6-2-8-4"
+       x1="76.025352"
+       y1="124.8497"
+       x2="75.874107"
+       y2="143.03978"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient3879-4-7-2-4">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.93162394;"
+         offset="0"
+         id="stop3881-6-7-9-9" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-74-6-9-3" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4011-5-1-7"
+       id="radialGradient4017-7-9-7"
+       cx="66.639"
+       cy="93.096375"
+       fx="66.639"
+       fy="93.096375"
+       r="11.515625"
+       gradientTransform="matrix(0.26837158,1.8482981,-1.1689154,0.16972569,466.57614,26.180822)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4011-5-1-7">
+      <stop
+         style="stop-color:#042dc8;stop-opacity:1;"
+         offset="0"
+         id="stop4013-1-9-1" />
+      <stop
+         style="stop-color:#4260d5;stop-opacity:1;"
+         offset="1"
+         id="stop4015-3-8-5" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3879-4-7-2-0">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.93162394;"
+         offset="0"
+         id="stop3881-6-7-9-7" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-74-6-9-8" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4011-5-1-55">
+      <stop
+         style="stop-color:#000a30;stop-opacity:1;"
+         offset="0"
+         id="stop4013-1-9-8" />
+      <stop
+         style="stop-color:#4260d5;stop-opacity:1;"
+         offset="1"
+         id="stop4015-3-8-3" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3890-9">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3892-0" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3894-9" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3880-4">
+      <stop
+         style="stop-color:#eb7400;stop-opacity:1;"
+         offset="0"
+         id="stop3882-5" />
+      <stop
+         style="stop-color:#f7b06a;stop-opacity:1;"
+         offset="1"
+         id="stop3884-1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3999-7">
+      <stop
+         style="stop-color:#fff7f2;stop-opacity:1;"
+         offset="0"
+         id="stop4001-9" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4003-4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4007-9">
+      <stop
+         style="stop-color:#ff6600;stop-opacity:1;"
+         offset="0"
+         id="stop4009-1" />
+      <stop
+         style="stop-color:#ff9148;stop-opacity:1;"
+         offset="1"
+         id="stop4011-9" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4007-9-5">
+      <stop
+         style="stop-color:#ff6600;stop-opacity:1;"
+         offset="0"
+         id="stop4009-1-9" />
+      <stop
+         style="stop-color:#ff9148;stop-opacity:1;"
+         offset="1"
+         id="stop4011-9-5" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3999-7-1">
+      <stop
+         style="stop-color:#fff7f2;stop-opacity:1;"
+         offset="0"
+         id="stop4001-9-1" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4003-4-4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4007-9-5-3">
+      <stop
+         style="stop-color:#ff6600;stop-opacity:1;"
+         offset="0"
+         id="stop4009-1-9-3" />
+      <stop
+         style="stop-color:#ff9148;stop-opacity:1;"
+         offset="1"
+         id="stop4011-9-5-9" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3999-7-1-4">
+      <stop
+         style="stop-color:#fff7f2;stop-opacity:1;"
+         offset="0"
+         id="stop4001-9-1-4" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4003-4-4-4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3879-4-7-2-3">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.93162394;"
+         offset="0"
+         id="stop3881-6-7-9-1" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3883-74-6-9-87" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4011-5-1-1">
+      <stop
+         style="stop-color:#fde8a1;stop-opacity:1;"
+         offset="0"
+         id="stop4013-1-9-63" />
+      <stop
+         style="stop-color:#2947b9;stop-opacity:1;"
+         offset="1"
+         id="stop4015-3-8-8" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4466"
+       id="linearGradient4472"
+       x1="161.7561"
+       y1="540.72662"
+       x2="161.7561"
+       y2="579.80206"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4321"
+       id="radialGradient4474"
+       cx="130.8242"
+       cy="575.27838"
+       fx="130.8242"
+       fy="575.27838"
+       r="49.498173"
+       gradientTransform="matrix(0.95670828,0.96684666,-0.72623533,0.71862001,423.45109,35.05138)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4466-5"
+       id="linearGradient4472-9"
+       x1="161.7561"
+       y1="540.72662"
+       x2="161.7561"
+       y2="579.80206"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4466-5">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4468-2" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4470-3" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4321-0"
+       id="radialGradient4474-6"
+       cx="130.8242"
+       cy="575.27838"
+       fx="130.8242"
+       fy="575.27838"
+       r="49.498173"
+       gradientTransform="matrix(0.95670828,0.96684666,-0.72623533,0.71862001,442.64399,170.9169)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4321-0">
+      <stop
+         style="stop-color:#ff6702;stop-opacity:1;"
+         offset="0"
+         id="stop4323-3" />
+      <stop
+         style="stop-color:#ff9a55;stop-opacity:1;"
+         offset="1"
+         id="stop4325-1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4466-5-5">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4468-2-9" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4470-3-4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4321-0-0">
+      <stop
+         style="stop-color:#ff6702;stop-opacity:1;"
+         offset="0"
+         id="stop4323-3-9" />
+      <stop
+         style="stop-color:#ff9a55;stop-opacity:1;"
+         offset="1"
+         id="stop4325-1-1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4466-5-9">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4468-2-7" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4470-3-7" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4321-0-7">
+      <stop
+         style="stop-color:#ff6702;stop-opacity:1;"
+         offset="0"
+         id="stop4323-3-3" />
+      <stop
+         style="stop-color:#ff9a55;stop-opacity:1;"
+         offset="1"
+         id="stop4325-1-6" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4431"
+       id="linearGradient4437"
+       x1="142.81854"
+       y1="831.52283"
+       x2="142.81854"
+       y2="878.90735"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4467"
+       id="radialGradient4475"
+       cx="116.51958"
+       cy="98.282051"
+       fx="116.51958"
+       fy="98.282051"
+       r="55.859375"
+       gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,79.641615,-130.28522)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4431-3"
+       id="linearGradient4437-6"
+       x1="142.81854"
+       y1="831.52283"
+       x2="142.81854"
+       y2="878.90735"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4431-3">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4433-0" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4435-2" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4467-7"
+       id="radialGradient4475-0"
+       cx="116.51958"
+       cy="98.282051"
+       fx="116.51958"
+       fy="98.282051"
+       r="55.859375"
+       gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,225.10358,63.664066)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4467-7">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4469-4" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0.8974359;"
+         offset="1"
+         id="stop4471-7" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4467"
+       id="radialGradient3262"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,59.641615,-150.28522)"
+       cx="116.51958"
+       cy="98.282051"
+       fx="116.51958"
+       fy="98.282051"
+       r="55.859375" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4431"
+       id="linearGradient3264"
+       gradientUnits="userSpaceOnUse"
+       x1="142.81854"
+       y1="831.52283"
+       x2="142.81854"
+       y2="878.90735" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.6"
+     inkscape:cx="31.144191"
+     inkscape:cy="38.335716"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     showguides="false"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="1920"
+     inkscape:window-height="1056"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     fit-margin-top="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     fit-margin-left="0">
+    <sodipodi:guide
+       orientation="0,1"
+       position="72.563745,37.346999"
+       id="guide2989" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="74.584055,7.2949693"
+       id="guide2991" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="71.048515,20.426949"
+       id="guide2993" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="97.817565,20.174409"
+       id="guide2995" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="71.048515,20.426949"
+       id="guide3017" />
+    <inkscape:grid
+       type="xygrid"
+       id="grid3019"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="105.6589,-12.377861"
+       id="guide3021" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="126.6589,-16.377861"
+       id="guide3023" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="110.6589,-3.3778607"
+       id="guide3025" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="110.6589,-27.377861"
+       id="guide3027" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="19.658895,-35.37786"
+       id="guide3810" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="21.658895,-70.377861"
+       id="guide3814" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="2.301752,-9.4850007"
+       id="guide3856" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="26.601806,-9.4850007"
+       id="guide3887" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="44.658283,37.346999"
+       id="guide4019" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="126.6589,-27.377861"
+       id="guide4481" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="159.08747,-213.94929"
+       id="guide4483" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-42.341105,-35.859333)">
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:url(#radialGradient3262);fill-opacity:1;stroke:none"
+       d="m 98.2161,35.859333 c -30.850815,0 -55.874995,24.87043 -55.874995,55.562497 0,30.69207 25.02418,55.56249 55.874995,55.56249 10.09496,0 19.54625,-2.6525 27.71875,-7.3125 l 2.90625,7.3125 2.40625,0 20,0 0.125,0 -8.8125,-21.78124 c 7.21537,-9.3622 11.5,-21.07236 11.5,-33.78125 0,-30.692067 -24.99293,-55.562497 -55.84375,-55.562497 z"
+       id="path3834-7-7-2-5-5-0-5-4" />
+    <path
+       sodipodi:type="arc"
+       style="fill:url(#linearGradient3264);fill-opacity:1;stroke:none"
+       id="path3661"
+       sodipodi:cx="142.5"
+       sodipodi:cy="856.29077"
+       sodipodi:rx="35.357143"
+       sodipodi:ry="24.642857"
+       d="m 177.85714,856.29077 c 0,13.60988 -15.82993,24.64286 -35.35714,24.64286 -19.52721,0 -35.35714,-11.03298 -35.35714,-24.64286 0,-13.60987 15.82993,-24.64286 35.35714,-24.64286 19.52721,0 35.35714,11.03299 35.35714,24.64286 z"
+       transform="matrix(1.0465082,0,0,1.2920463,-51.641235,-1036.8612)" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#000000;fill-opacity:1;stroke:none"
+       id="path4442"
+       sodipodi:cx="115.66247"
+       sodipodi:cy="856.39258"
+       sodipodi:rx="6.5659914"
+       sodipodi:ry="6.5659914"
+       d="m 122.22846,856.39258 c 0,3.6263 -2.9397,6.56599 -6.56599,6.56599 -3.6263,0 -6.56599,-2.93969 -6.56599,-6.56599 0,-3.6263 2.93969,-6.56599 6.56599,-6.56599 3.62629,0 6.56599,2.93969 6.56599,6.56599 z"
+       transform="translate(-12.329975,-797.60351)" />
+    <rect
+       style="fill:#000000;fill-opacity:1;stroke:none"
+       id="rect4444"
+       width="37.643608"
+       height="5.5005069"
+       x="101.55376"
+       y="48.297417"
+       transform="matrix(0.98974903,0.14281759,-0.18972639,0.981837,0,0)" />
+    <rect
+       style="fill:#000000;fill-opacity:1;stroke:none"
+       id="rect4446"
+       width="6.5659914"
+       height="2.9041886"
+       x="124.92451"
+       y="69.016899" />
+    <path
+       style="fill:#ff6600;fill-opacity:1"
+       d="m 83.38797,45.010543 c -0.057,2.18531 -3.865755,0.28296 -4.031245,2.78125 -4.22387,-1.88052 0.32884,2.87188 -0.0937,3.3125 l -0.0312,0 -0.3125,-0.0312 c -0.20386,-0.0728 -0.49977,-0.19904 -0.9375,-0.46875 -2.9499,2.35025 -3.02157,7.23369 -6.0625,9.9375 -1.99467,4.30504 -2.47977,8.98337 -3.9375,13.46875 -0.71796,4.30292 -1.34881,8.597857 -0.28125,12.906247 0.32053,3.50159 -0.68919,8.25865 2.5,10.71875 4.72728,3.88304 8.65575,8.79543 12.624995,13.46875 6.21914,7.65333 11.72948,15.86251 16.59375,24.4375 0.32431,-2.11756 1.10954,4.26459 2.53125,4.6875 -0.49161,-3.19231 -1.13213,-8.26328 -1.4375,-12.1875 -1.5814,-10.2909 -6.65305,-19.64903 -8.5625,-29.84375 -0.0587,-0.43037 -0.12809,-0.87203 -0.1875,-1.3125 l 0,-1.28125 -0.15625,0 c -0.62551,-5.04297 -0.8504,-10.46546 2.8125,-14.40625 3.73968,-3.772097 9.30633,-4.722447 13.8125,-7.343747 1.00194,-0.59119 2.04921,-1.07174 3.125,-1.40625 0.009,-0.003 0.0228,0.003 0.0312,0 3.11701,-0.96341 6.44862,-0.93323 9.6875,-0.40625 0.0479,0.008 0.10841,0.0233 0.15625,0.0312 0.29455,0.0493 0.61389,0.099 0.90625,0.15625 2.37136,0.21133 7.14463,1.13687 8,-0.5 -3.27225,-2.78631 -7.98526,-2.59211 -11.96875,-3.6875 -0.63059,-0.11469 -1.41182,-0.24041 -2.1875,-0.3125 l -3.90625,-0.875 -0.96875,-0.25 0,0.0312 -13.96875,-2.71875 c -0.22212,-0.20226 -0.46434,-0.40933 -0.6875,-0.5625 l 13.625,1.6875 0,-0.0625 c 0.48011,0.10699 0.95576,0.19361 1.4375,0.25 l 0,0.0312 9.625,1.78125 c 1.66103,0.61952 3.4322,1.08374 5.09375,1.1875 2.74263,0.39907 6.22526,4.49092 7.125,4.6875 -0.44096,-4.307 -4.7422,-6.23586 -8.3125,-7.5 -4.1712,-2.02803 -10.4023,-1.95417 -11.0625,-7.5625 -0.1756,-0.39076 -0.34902,-0.78118 -0.5625,-1.15625 l -1.625,-2.15625 0.0625,-0.0312 c -2.21724,-2.61691 -5.34011,-4.52196 -8.65625,-5.25 -3.2914,-1.13611 -6.98773,-2.2671 -10.46875,-2.71875 -1.18132,3.47826 -2.5031,-2.75561 -5.34375,-0.90625 -2.48996,0.29488 -2.14614,0.95256 -4,-0.625 z m 17.90625,10.15625 c 0.90187,-0.0238 1.93277,0.14208 2.96875,0.5 2.76259,0.95447 4.56151,2.96523 4.03125,4.5 -0.53026,1.53477 -3.20616,1.98572 -5.96875,1.03125 -2.76259,-0.95447 -4.5615,-2.93398 -4.03125,-4.46875 0.33141,-0.95923 1.49689,-1.52281 3,-1.5625 z"
+       id="path3499-9-7"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/qapi-schema.json b/qapi-schema.json
index ef1f657..5ad6894 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -236,6 +236,8 @@
 #
 # @snapshots: #optional list of VM snapshots
 #
+# @backing-image: #optional info of the backing image (since 1.6)
+#
 # Since: 1.3
 #
 ##
@@ -245,7 +247,8 @@
            '*actual-size': 'int', 'virtual-size': 'int',
            '*cluster-size': 'int', '*encrypted': 'bool',
            '*backing-filename': 'str', '*full-backing-filename': 'str',
-           '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } }
+           '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
+           '*backing-image': 'ImageInfo' } }
 
 ##
 # @ImageCheck:
@@ -756,6 +759,8 @@
 #
 # @iops_wr: write I/O operations per second is specified
 #
+# @image: the info of image used (since: 1.6)
+#
 # Since: 0.14.0
 #
 # Notes: This interface is only found in @BlockInfo.
@@ -765,7 +770,8 @@
             '*backing_file': 'str', 'backing_file_depth': 'int',
             'encrypted': 'bool', 'encryption_key_missing': 'bool',
             'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
-            'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }
+            'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
+            'image': 'ImageInfo' } }
 
 ##
 # @BlockDeviceIoStatus:
diff --git a/qemu-char.c b/qemu-char.c
index d04b429..2c3cfe6 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -76,8 +76,6 @@
 #include <netinet/ip_icmp.h> // must come after ip.h
 #include <netinet/udp.h>
 #include <netinet/tcp.h>
-#include <net/if.h>
-#include <syslog.h>
 #endif
 #endif
 #endif
@@ -110,19 +108,9 @@
     s->chr_event(s->handler_opaque, event);
 }
 
-static gboolean qemu_chr_be_generic_open_bh(gpointer opaque)
-{
-    CharDriverState *s = opaque;
-    qemu_chr_be_event(s, CHR_EVENT_OPENED);
-    s->idle_tag = 0;
-    return FALSE;
-}
-
 void qemu_chr_be_generic_open(CharDriverState *s)
 {
-    if (s->idle_tag == 0) {
-        s->idle_tag = g_idle_add(qemu_chr_be_generic_open_bh, s);
-    }
+    qemu_chr_be_event(s, CHR_EVENT_OPENED);
 }
 
 int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len)
@@ -247,6 +235,7 @@
 
     chr = g_malloc0(sizeof(CharDriverState));
     chr->chr_write = null_chr_write;
+    chr->explicit_be_open = true;
     return chr;
 }
 
@@ -504,9 +493,6 @@
     /* Frontend guest-open / -close notification is not support with muxes */
     chr->chr_set_fe_open = NULL;
 
-    /* Muxes are always open on creation */
-    qemu_chr_be_generic_open(chr);
-
     return chr;
 }
 
@@ -883,8 +869,6 @@
     chr->chr_update_read_handler = fd_chr_update_read_handler;
     chr->chr_close = fd_chr_close;
 
-    qemu_chr_be_generic_open(chr);
-
     return chr;
 }
 
@@ -980,63 +964,6 @@
     return chr;
 }
 
-#ifdef __sun__
-/* Once Solaris has openpty(), this is going to be removed. */
-static int openpty(int *amaster, int *aslave, char *name,
-                   struct termios *termp, struct winsize *winp)
-{
-        const char *slave;
-        int mfd = -1, sfd = -1;
-
-        *amaster = *aslave = -1;
-
-        mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
-        if (mfd < 0)
-                goto err;
-
-        if (grantpt(mfd) == -1 || unlockpt(mfd) == -1)
-                goto err;
-
-        if ((slave = ptsname(mfd)) == NULL)
-                goto err;
-
-        if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1)
-                goto err;
-
-        if (ioctl(sfd, I_PUSH, "ptem") == -1 ||
-            (termp != NULL && tcgetattr(sfd, termp) < 0))
-                goto err;
-
-        if (amaster)
-                *amaster = mfd;
-        if (aslave)
-                *aslave = sfd;
-        if (winp)
-                ioctl(sfd, TIOCSWINSZ, winp);
-
-        return 0;
-
-err:
-        if (sfd != -1)
-                close(sfd);
-        close(mfd);
-        return -1;
-}
-
-static void cfmakeraw (struct termios *termios_p)
-{
-        termios_p->c_iflag &=
-                ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
-        termios_p->c_oflag &= ~OPOST;
-        termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
-        termios_p->c_cflag &= ~(CSIZE|PARENB);
-        termios_p->c_cflag |= CS8;
-
-        termios_p->c_cc[VMIN] = 0;
-        termios_p->c_cc[VTIME] = 0;
-}
-#endif
-
 #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
     || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
     || defined(__GLIBC__)
@@ -1208,34 +1135,24 @@
 {
     CharDriverState *chr;
     PtyCharDriver *s;
-    struct termios tty;
     int master_fd, slave_fd;
-#if defined(__OpenBSD__) || defined(__DragonFly__)
     char pty_name[PATH_MAX];
-#define q_ptsname(x) pty_name
-#else
-    char *pty_name = NULL;
-#define q_ptsname(x) ptsname(x)
-#endif
 
-    if (openpty(&master_fd, &slave_fd, pty_name, NULL, NULL) < 0) {
+    master_fd = qemu_openpty_raw(&slave_fd, pty_name);
+    if (master_fd < 0) {
         return NULL;
     }
 
-    /* Set raw attributes on the pty. */
-    tcgetattr(slave_fd, &tty);
-    cfmakeraw(&tty);
-    tcsetattr(slave_fd, TCSAFLUSH, &tty);
     close(slave_fd);
 
     chr = g_malloc0(sizeof(CharDriverState));
 
-    chr->filename = g_strdup_printf("pty:%s", q_ptsname(master_fd));
-    ret->pty = g_strdup(q_ptsname(master_fd));
+    chr->filename = g_strdup_printf("pty:%s", pty_name);
+    ret->pty = g_strdup(pty_name);
     ret->has_pty = true;
 
     fprintf(stderr, "char device redirected to %s (label %s)\n",
-            q_ptsname(master_fd), id);
+            pty_name, id);
 
     s = g_malloc0(sizeof(PtyCharDriver));
     chr->opaque = s;
@@ -1243,6 +1160,7 @@
     chr->chr_update_read_handler = pty_chr_update_read_handler;
     chr->chr_close = pty_chr_close;
     chr->chr_add_watch = pty_chr_add_watch;
+    chr->explicit_be_open = true;
 
     s->fd = io_channel_from_fd(master_fd);
     s->timer_tag = 0;
@@ -1595,8 +1513,6 @@
     chr->chr_close = pp_close;
     chr->opaque = drv;
 
-    qemu_chr_be_generic_open(chr);
-
     return chr;
 }
 #endif /* __linux__ */
@@ -1650,6 +1566,7 @@
     chr->opaque = (void *)(intptr_t)fd;
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
+    chr->explicit_be_open = true;
     return chr;
 }
 #endif
@@ -1880,7 +1797,6 @@
         g_free(chr);
         return NULL;
     }
-    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -1980,7 +1896,6 @@
         g_free(chr);
         return NULL;
     }
-    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -1994,7 +1909,6 @@
     s->hcom = fd_out;
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -2329,6 +2243,8 @@
     chr->chr_write = udp_chr_write;
     chr->chr_update_read_handler = udp_chr_update_read_handler;
     chr->chr_close = udp_chr_close;
+    /* be isn't opened until we get a connection */
+    chr->explicit_be_open = true;
     return chr;
 }
 
@@ -2731,6 +2647,8 @@
     chr->get_msgfd = tcp_get_msgfd;
     chr->chr_add_client = tcp_chr_add_client;
     chr->chr_add_watch = tcp_chr_add_watch;
+    /* be isn't opened until we get a connection */
+    chr->explicit_be_open = true;
 
     if (is_listen) {
         s->listen_fd = fd;
@@ -3325,6 +3243,12 @@
     if (!chr->filename)
         chr->filename = g_strdup(qemu_opt_get(opts, "backend"));
     chr->init = init;
+    /* if we didn't create the chardev via qmp_chardev_add, we
+     * need to send the OPENED event here
+     */
+    if (!chr->explicit_be_open) {
+        qemu_chr_be_event(chr, CHR_EVENT_OPENED);
+    }
     QTAILQ_INSERT_TAIL(&chardevs, chr, next);
 
     if (qemu_opt_get_bool(opts, "mux", 0)) {
@@ -3804,6 +3728,9 @@
         if (!chr->filename) {
             chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]);
         }
+        if (!chr->explicit_be_open) {
+            qemu_chr_be_event(chr, CHR_EVENT_OPENED);
+        }
         QTAILQ_INSERT_TAIL(&chardevs, chr, next);
         return ret;
     } else {
diff --git a/qemu-img.c b/qemu-img.c
index 82c7977..809b4f1 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -85,8 +85,9 @@
            "    options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
            "    'directsync' and 'unsafe' (default for convert)\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"
@@ -387,8 +388,9 @@
                 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.");
             }
             return 1;
         }
@@ -1642,6 +1644,7 @@
     ImageInfoList *head = NULL;
     ImageInfoList **last = &head;
     GHashTable *filenames;
+    Error *err = NULL;
 
     filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
 
@@ -1663,9 +1666,12 @@
             goto err;
         }
 
-        info = g_new0(ImageInfo, 1);
-        bdrv_collect_image_info(bs, info, filename);
-        bdrv_collect_snapshots(bs, info);
+        bdrv_query_image_info(bs, &info, &err);
+        if (error_is_set(&err)) {
+            error_report("%s", error_get_pretty(err));
+            error_free(err);
+            goto err;
+        }
 
         elem = g_new0(ImageInfoList, 1);
         elem->value = info;
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
new file mode 100644
index 0000000..ffbcf31
--- /dev/null
+++ b/qemu-io-cmds.c
@@ -0,0 +1,2118 @@
+/*
+ * 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-io.h"
+#include "block/block_int.h"
+
+#define CMD_NOFILE_OK   0x01
+
+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(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
+                   char **argv)
+{
+    char *cmd = argv[0];
+
+    if (!init_check_command(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(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;
+    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.
+ *
+ * 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);
+    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 qemuio_command_usage(&read_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return qemuio_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 qemuio_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 qemuio_command_usage(&readv_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return qemuio_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 qemuio_command_usage(&write_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return qemuio_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 qemuio_command_usage(&writev_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return qemuio_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 qemuio_command_usage(&writev_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        return qemuio_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 qemuio_command_usage(&aio_read_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        g_free(ctx);
+        return qemuio_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 qemuio_command_usage(&aio_write_cmd);
+        }
+    }
+
+    if (optind > argc - 2) {
+        g_free(ctx);
+        return qemuio_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;
+    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);
+
+    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 qemuio_command_usage(&discard_cmd);
+        }
+    }
+
+    if (optind != argc - 2) {
+        return qemuio_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);
+        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_is_allocated(BlockDriverState *bs, int64_t sector_num,
+                            int64_t nb_sectors, int64_t *pnum)
+{
+    int num, num_checked;
+    int ret, firstret;
+
+    num_checked = MIN(nb_sectors, INT_MAX);
+    ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
+    if (ret < 0) {
+        return ret;
+    }
+
+    firstret = ret;
+    *pnum = num;
+
+    while (nb_sectors > 0 && ret == firstret) {
+        sector_num += num;
+        nb_sectors -= num;
+
+        num_checked = MIN(nb_sectors, INT_MAX);
+        ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
+        if (ret == firstret) {
+            *pnum += num;
+        } else {
+            break;
+        }
+    }
+
+    return firstret;
+}
+
+static int map_f(BlockDriverState *bs, int argc, char **argv)
+{
+    int64_t offset;
+    int64_t nb_sectors;
+    char s1[64];
+    int64_t num;
+    int ret;
+    const char *retstr;
+
+    offset = 0;
+    nb_sectors = bs->total_sectors;
+
+    do {
+        ret = map_is_allocated(bs, offset, nb_sectors, &num);
+        if (ret < 0) {
+            error_report("Failed to get allocation status: %s", strerror(-ret));
+            return 0;
+        }
+
+        retstr = ret ? "    allocated" : "not allocated";
+        cvtstr(offset << 9ULL, s1, sizeof(s1));
+        printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
+               "at offset %s (%d)\n",
+               offset << 9ULL, num, nb_sectors, 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 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",
+};
+
+bool qemuio_command(BlockDriverState *bs, 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(bs, 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 */
+    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);
+}
diff --git a/qemu-io.c b/qemu-io.c
index 5e6680b..cb9def5 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -14,1776 +14,26 @@
 #include <getopt.h>
 #include <libgen.h>
 
-#include "qemu-common.h"
+#include "qemu-io.h"
 #include "qemu/main-loop.h"
 #include "block/block_int.h"
-#include "cmd.h"
 #include "trace/control.h"
 
-#define VERSION	"0.0.1"
-
 #define CMD_NOFILE_OK   0x01
 
 char *progname;
-static BlockDriverState *bs;
 
-static int misalign;
+BlockDriverState *qemuio_bs;
+extern int qemuio_misalign;
 
-/*
- * 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;
+/* qemu-io commands passed using -c */
+static int ncmdline;
+static char **cmdline;
 
-    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(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(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(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(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(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(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(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 {
-    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(bs, data->offset / BDRV_SECTOR_SIZE,
-                                     data->count / BDRV_SECTOR_SIZE);
-    data->done = true;
-    if (data->ret < 0) {
-        *data->total = data->ret;
-        return;
-    }
-
-    *data->total = data->count;
-}
-
-static int do_co_write_zeroes(int64_t offset, int count, int *total)
-{
-    Coroutine *co;
-    CoWriteZeroes data = {
-        .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(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(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(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(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(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(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(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(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(count, 0xab);
-
-    gettimeofday(&t1, NULL);
-    if (pflag) {
-        cnt = do_pread(buf, offset, count, &total);
-    } else if (bflag) {
-        cnt = do_load_vmstate(buf, offset, count, &total);
-    } else {
-        cnt = do_read(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(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(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(&qiov, &argv[optind], nr_iov, 0xab);
-    if (buf == NULL) {
-        return 0;
-    }
-
-    gettimeofday(&t1, NULL);
-    cnt = do_aio_readv(&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(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(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(count, pattern);
-    }
-
-    gettimeofday(&t1, NULL);
-    if (pflag) {
-        cnt = do_pwrite(buf, offset, count, &total);
-    } else if (bflag) {
-        cnt = do_save_vmstate(buf, offset, count, &total);
-    } else if (zflag) {
-        cnt = do_co_write_zeroes(offset, count, &total);
-    } else if (cflag) {
-        cnt = do_write_compressed(buf, offset, count, &total);
-    } else {
-        cnt = do_write(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(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(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(&qiov, &argv[optind], nr_iov, pattern);
-    if (buf == NULL) {
-        return 0;
-    }
-
-    gettimeofday(&t1, NULL);
-    cnt = do_aio_writev(&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(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(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(&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(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(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(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(&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(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(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(&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(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(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(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(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(int argc, char **argv)
-{
-    BlockDriverInfo bdi;
-    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);
-
-    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(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(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(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 & 0x1ff) {
-        printf("offset %" PRId64 " is not sector aligned\n",
-               offset);
-        return 0;
-    }
-
-    if (argc == 3) {
-        nb_sectors = cvtnum(argv[2]);
-    } 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);
-        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_is_allocated(int64_t sector_num, int64_t nb_sectors, int64_t *pnum)
-{
-    int num, num_checked;
-    int ret, firstret;
-
-    num_checked = MIN(nb_sectors, INT_MAX);
-    ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
-    if (ret < 0) {
-        return ret;
-    }
-
-    firstret = ret;
-    *pnum = num;
-
-    while (nb_sectors > 0 && ret == firstret) {
-        sector_num += num;
-        nb_sectors -= num;
-
-        num_checked = MIN(nb_sectors, INT_MAX);
-        ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
-        if (ret == firstret) {
-            *pnum += num;
-        } else {
-            break;
-        }
-    }
-
-    return firstret;
-}
-
-static int map_f(int argc, char **argv)
-{
-    int64_t offset;
-    int64_t nb_sectors;
-    char s1[64];
-    int64_t num;
-    int ret;
-    const char *retstr;
-
-    offset = 0;
-    nb_sectors = bs->total_sectors;
-
-    do {
-        ret = map_is_allocated(offset, nb_sectors, &num);
-        if (ret < 0) {
-            error_report("Failed to get allocation status: %s", strerror(-ret));
-            return 0;
-        }
-
-        retstr = ret ? "    allocated" : "not allocated";
-        cvtstr(offset << 9ULL, s1, sizeof(s1));
-        printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
-               "at offset %s (%d)\n",
-               offset << 9ULL, num, nb_sectors, 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(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(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(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(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 int close_f(int argc, char **argv)
+static int close_f(BlockDriverState *bs, int argc, char **argv)
 {
     bdrv_delete(bs);
-    bs = NULL;
+    qemuio_bs = NULL;
     return 0;
 }
 
@@ -1796,23 +46,23 @@
 
 static int openfile(char *name, int flags, int growable)
 {
-    if (bs) {
+    if (qemuio_bs) {
         fprintf(stderr, "file open already, try 'help close'\n");
         return 1;
     }
 
     if (growable) {
-        if (bdrv_file_open(&bs, name, NULL, flags)) {
+        if (bdrv_file_open(&qemuio_bs, name, NULL, flags)) {
             fprintf(stderr, "%s: can't open device %s\n", progname, name);
             return 1;
         }
     } else {
-        bs = bdrv_new("hda");
+        qemuio_bs = bdrv_new("hda");
 
-        if (bdrv_open(bs, name, NULL, flags, NULL) < 0) {
+        if (bdrv_open(qemuio_bs, name, NULL, flags, NULL) < 0) {
             fprintf(stderr, "%s: can't open device %s\n", progname, name);
-            bdrv_delete(bs);
-            bs = NULL;
+            bdrv_delete(qemuio_bs);
+            qemuio_bs = NULL;
             return 1;
         }
     }
@@ -1837,7 +87,7 @@
 "\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",
@@ -1851,7 +101,7 @@
     .help       = open_help,
 };
 
-static int open_f(int argc, char **argv)
+static int open_f(BlockDriverState *bs, int argc, char **argv)
 {
     int flags = 0;
     int readonly = 0;
@@ -1873,7 +123,7 @@
             growable = 1;
             break;
         default:
-            return command_usage(&open_cmd);
+            return qemuio_command_usage(&open_cmd);
         }
     }
 
@@ -1882,33 +132,27 @@
     }
 
     if (optind != argc - 1) {
-        return command_usage(&open_cmd);
+        return qemuio_command_usage(&open_cmd);
     }
 
     return openfile(argv[optind], flags, growable);
 }
 
-static int init_args_command(int index)
+static int quit_f(BlockDriverState *bs, int argc, char **argv)
 {
-    /* 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) {
-        return 1;
-    }
-    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
-        fprintf(stderr, "no file open, try 'help open'\n");
-        return 0;
-    }
     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(
@@ -1931,6 +175,141 @@
 }
 
 
+#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(qemuio_bs, 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(qemuio_bs, 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;
@@ -1979,7 +358,7 @@
             readonly = 1;
             break;
         case 'm':
-            misalign = 1;
+            qemuio_misalign = 1;
             break;
         case 'g':
             growable = 1;
@@ -1999,7 +378,7 @@
             }
             break;
         case 'V':
-            printf("%s version %s\n", progname, VERSION);
+            printf("%s version %s\n", progname, QEMU_VERSION);
             exit(0);
         case 'h':
             usage(progname);
@@ -2019,32 +398,9 @@
     bdrv_init();
 
     /* 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_args_command(init_args_command);
-    add_check_command(init_check_command);
+    qemuio_add_command(&quit_cmd);
+    qemuio_add_command(&open_cmd);
+    qemuio_add_command(&close_cmd);
 
     /* open the device */
     if (!readonly) {
@@ -2061,8 +417,8 @@
      */
     bdrv_drain_all();
 
-    if (bs) {
-        bdrv_delete(bs);
+    if (qemuio_bs) {
+        bdrv_delete(qemuio_bs);
     }
     return 0;
 }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ffd130e..8cea5e5 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1704,6 +1704,47 @@
          - "iops": limit total I/O operations per second (json-int)
          - "iops_rd": limit read operations per second (json-int)
          - "iops_wr": limit write operations per second (json-int)
+         - "image": the detail of the image, it is a json-object containing
+            the following:
+             - "filename": image file name (json-string)
+             - "format": image format (json-string)
+             - "virtual-size": image capacity in bytes (json-int)
+             - "dirty-flag": true if image is not cleanly closed, not present
+                             means clean (json-bool, optional)
+             - "actual-size": actual size on disk in bytes of the image, not
+                              present when image does not support thin
+                              provision (json-int, optional)
+             - "cluster-size": size of a cluster in bytes, not present if image
+                               format does not support it (json-int, optional)
+             - "encrypted": true if the image is encrypted, not present means
+                            false or the image format does not support
+                            encryption (json-bool, optional)
+             - "backing_file": backing file name, not present means no backing
+                               file is used or the image format does not
+                               support backing file chain
+                               (json-string, optional)
+             - "full-backing-filename": full path of the backing file, not
+                                        present if it equals backing_file or no
+                                        backing file is used
+                                        (json-string, optional)
+             - "backing-filename-format": the format of the backing file, not
+                                          present means unknown or no backing
+                                          file (json-string, optional)
+             - "snapshots": the internal snapshot info, it is an optional list
+                of json-object containing the following:
+                 - "id": unique snapshot id (json-string)
+                 - "name": snapshot name (json-string)
+                 - "vm-state-size": size of the VM state in bytes (json-int)
+                 - "date-sec": UTC date of the snapshot in seconds (json-int)
+                 - "date-nsec": fractional part in nanoseconds to be used with
+                                date-sec(json-int)
+                 - "vm-clock-sec": VM clock relative to boot in seconds
+                                   (json-int)
+                 - "vm-clock-nsec": fractional part in nanoseconds to be used
+                                    with vm-clock-sec (json-int)
+             - "backing-image": the detail of the backing image, it is an
+                                optional json-object only present when a
+                                backing image present for this image
 
 - "io-status": I/O operation status, only present if the device supports it
                and the VM is configured to stop on errors. It's always reset
@@ -1724,14 +1765,38 @@
                "ro":false,
                "drv":"qcow2",
                "encrypted":false,
-               "file":"disks/test.img",
-               "backing_file_depth":0,
+               "file":"disks/test.qcow2",
+               "backing_file_depth":1,
                "bps":1000000,
                "bps_rd":0,
                "bps_wr":0,
                "iops":1000000,
                "iops_rd":0,
                "iops_wr":0,
+               "image":{
+                  "filename":"disks/test.qcow2",
+                  "format":"qcow2",
+                  "virtual-size":2048000,
+                  "backing_file":"base.qcow2",
+                  "full-backing-filename":"disks/base.qcow2",
+                  "backing-filename-format:"qcow2",
+                  "snapshots":[
+                     {
+                        "id": "1",
+                        "name": "snapshot1",
+                        "vm-state-size": 0,
+                        "date-sec": 10000200,
+                        "date-nsec": 12,
+                        "vm-clock-sec": 206,
+                        "vm-clock-nsec": 30
+                     }
+                  ],
+                  "backing-image":{
+                      "filename":"disks/base.qcow2",
+                      "format":"qcow2",
+                      "virtual-size":2048000
+                  }
+               }
             },
             "type":"unknown"
          },
diff --git a/qom/cpu.c b/qom/cpu.c
index 04aefbb..dba4a11 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -50,6 +50,33 @@
     return data.found;
 }
 
+bool cpu_paging_enabled(const CPUState *cpu)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    return cc->get_paging_enabled(cpu);
+}
+
+static bool cpu_common_get_paging_enabled(const CPUState *cpu)
+{
+    return false;
+}
+
+void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+                            Error **errp)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    return cc->get_memory_mapping(cpu, list, errp);
+}
+
+static void cpu_common_get_memory_mapping(CPUState *cpu,
+                                          MemoryMappingList *list,
+                                          Error **errp)
+{
+    error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
+}
+
 /* CPU hot-plug notifiers */
 static NotifierList cpu_added_notifiers =
     NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers);
@@ -176,6 +203,8 @@
     k->class_by_name = cpu_common_class_by_name;
     k->reset = cpu_common_reset;
     k->get_arch_id = cpu_common_get_arch_id;
+    k->get_paging_enabled = cpu_common_get_paging_enabled;
+    k->get_memory_mapping = cpu_common_get_memory_mapping;
     k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;
     k->write_elf32_note = cpu_common_write_elf32_note;
     k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index f10970c..6d147a7 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -255,6 +255,7 @@
     chr->chr_add_watch = spice_chr_add_watch;
     chr->chr_close = spice_chr_close;
     chr->chr_set_fe_open = spice_chr_set_fe_open;
+    chr->explicit_be_open = true;
 
     QLIST_INSERT_HEAD(&spice_chars, s, next);
 
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 03dff20..9b701b4 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -2,6 +2,7 @@
 stub-obj-y += clock-warp.o
 stub-obj-y += cpu-get-clock.o
 stub-obj-y += cpu-get-icount.o
+stub-obj-y += dump.o
 stub-obj-y += fdset-add-fd.o
 stub-obj-y += fdset-find-fd.o
 stub-obj-y += fdset-get-fd.o
diff --git a/dump-stub.c b/stubs/dump.c
similarity index 64%
rename from dump-stub.c
rename to stubs/dump.c
index b3f42cb..43c9a3f 100644
--- a/dump-stub.c
+++ b/stubs/dump.c
@@ -16,14 +16,6 @@
 #include "qapi/qmp/qerror.h"
 #include "qmp-commands.h"
 
-/* we need this function in hmp.c */
-void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
-                           int64_t begin, bool has_length, int64_t length,
-                           Error **errp)
-{
-    error_set(errp, QERR_UNSUPPORTED);
-}
-
 int cpu_get_dump_info(ArchDumpInfo *info)
 {
     return -1;
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index b7bdc03..27dcab9 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -491,3 +491,7 @@
 {
     qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
 }
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index b3f26d6..2a18ffe 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6752,7 +6752,7 @@
             tcg_gen_qemu_ld32u(tmp, addr, 0);
             tcg_gen_addi_i32(addr, addr, 4);
             tmp2 = tcg_temp_new_i32();
-            tcg_gen_qemu_ld32u(tmp, addr, 0);
+            tcg_gen_qemu_ld32u(tmp2, addr, 0);
             if (insn & (1 << 21)) {
                 /* Base writeback.  */
                 switch (i) {
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
index 5096fbd..2566a04 100644
--- a/target-i386/arch_memory_mapping.c
+++ b/target-i386/arch_memory_mapping.c
@@ -239,11 +239,15 @@
 }
 #endif
 
-int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
+void x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list,
+                                Error **errp)
 {
-    if (!cpu_paging_enabled(env)) {
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    if (!cpu_paging_enabled(cs)) {
         /* paging is disabled */
-        return 0;
+        return;
     }
 
     if (env->cr[4] & CR4_PAE_MASK) {
@@ -269,11 +273,5 @@
         pse = !!(env->cr[4] & CR4_PSE_MASK);
         walk_pde2(list, pde_addr, env->a20_mask, pse);
     }
-
-    return 0;
 }
 
-bool cpu_paging_enabled(CPUArchState *env)
-{
-    return env->cr[0] & CR0_PG_MASK;
-}
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 849cedf..e0ac072 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -98,4 +98,7 @@
 int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
                                  void *opaque);
 
+void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+                                Error **errp);
+
 #endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 1a501d9..a7154af 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -221,7 +221,7 @@
 
 const char *get_register_name_32(unsigned int reg)
 {
-    if (reg > CPU_NB_REGS32) {
+    if (reg >= CPU_NB_REGS32) {
         return NULL;
     }
     return x86_reg_info_32[reg].name;
@@ -669,10 +669,10 @@
     },
     {
         .name = "Conroe",
-        .level = 2,
+        .level = 4,
         .vendor = CPUID_VENDOR_INTEL,
         .family = 6,
-        .model = 2,
+        .model = 15,
         .stepping = 3,
         .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
@@ -691,10 +691,10 @@
     },
     {
         .name = "Penryn",
-        .level = 2,
+        .level = 4,
         .vendor = CPUID_VENDOR_INTEL,
         .family = 6,
-        .model = 2,
+        .model = 23,
         .stepping = 3,
         .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
@@ -714,10 +714,10 @@
     },
     {
         .name = "Nehalem",
-        .level = 2,
+        .level = 4,
         .vendor = CPUID_VENDOR_INTEL,
         .family = 6,
-        .model = 2,
+        .model = 26,
         .stepping = 3,
         .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
@@ -2505,6 +2505,13 @@
     return env->cpuid_apic_id;
 }
 
+static bool x86_cpu_get_paging_enabled(const CPUState *cs)
+{
+    X86CPU *cpu = X86_CPU(cs);
+
+    return cpu->env.cr[0] & CR0_PG_MASK;
+}
+
 static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 {
     X86CPUClass *xcc = X86_CPU_CLASS(oc);
@@ -2519,15 +2526,16 @@
     cc->reset = x86_cpu_reset;
 
     cc->do_interrupt = x86_cpu_do_interrupt;
+    cc->get_arch_id = x86_cpu_get_arch_id;
+    cc->get_paging_enabled = x86_cpu_get_paging_enabled;
 #ifndef CONFIG_USER_ONLY
+    cc->get_memory_mapping = x86_cpu_get_memory_mapping;
     cc->write_elf64_note = x86_cpu_write_elf64_note;
     cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
     cc->write_elf32_note = x86_cpu_write_elf32_note;
     cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
 #endif
     cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
-
-    cc->get_arch_id = x86_cpu_get_arch_id;
 }
 
 static const TypeInfo x86_cpu_type_info = {
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 3ab2946..2bbc3b8 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1797,3 +1797,7 @@
 {
     return 1;
 }
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 862fb12..4d9ac4a 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -928,3 +928,7 @@
     r = kvm_vcpu_ioctl(CPU(cpu), KVM_ENABLE_CAP, &cap);
     assert(r == 0);
 }
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 290b580..13bb7bb 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -614,7 +614,7 @@
     return 0;
 
  error:
-    free(s);
+    g_free(s);
     return -1;
 }
 
diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c
new file mode 100644
index 0000000..562a549
--- /dev/null
+++ b/tcg/aarch64/tcg-target.c
@@ -0,0 +1,1404 @@
+/*
+ * Initial TCG Implementation for aarch64
+ *
+ * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
+ * Written by Claudio Fontana
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.
+ *
+ * See the COPYING file in the top-level directory for details.
+ */
+
+#include "qemu/bitops.h"
+
+#ifndef NDEBUG
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+    "%x0", "%x1", "%x2", "%x3", "%x4", "%x5", "%x6", "%x7",
+    "%x8", "%x9", "%x10", "%x11", "%x12", "%x13", "%x14", "%x15",
+    "%x16", "%x17", "%x18", "%x19", "%x20", "%x21", "%x22", "%x23",
+    "%x24", "%x25", "%x26", "%x27", "%x28",
+    "%fp", /* frame pointer */
+    "%lr", /* link register */
+    "%sp",  /* stack pointer */
+};
+#endif /* NDEBUG */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ #define TCG_LDST_BSWAP 1
+#else
+ #define TCG_LDST_BSWAP 0
+#endif
+
+static const int tcg_target_reg_alloc_order[] = {
+    TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23,
+    TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27,
+    TCG_REG_X28, /* we will reserve this for GUEST_BASE if configured */
+
+    TCG_REG_X9, TCG_REG_X10, TCG_REG_X11, TCG_REG_X12,
+    TCG_REG_X13, TCG_REG_X14, TCG_REG_X15,
+    TCG_REG_X16, TCG_REG_X17,
+
+    TCG_REG_X18, TCG_REG_X19, /* will not use these, see tcg_target_init */
+
+    TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
+    TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7,
+
+    TCG_REG_X8, /* will not use, see tcg_target_init */
+};
+
+static const int tcg_target_call_iarg_regs[8] = {
+    TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
+    TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7
+};
+static const int tcg_target_call_oarg_regs[1] = {
+    TCG_REG_X0
+};
+
+#define TCG_REG_TMP TCG_REG_X8
+
+#ifndef CONFIG_SOFTMMU
+# if defined(CONFIG_USE_GUEST_BASE)
+# define TCG_REG_GUEST_BASE TCG_REG_X28
+# else
+# define TCG_REG_GUEST_BASE TCG_REG_XZR
+# endif
+#endif
+
+static inline void reloc_pc26(void *code_ptr, tcg_target_long target)
+{
+    tcg_target_long offset; uint32_t insn;
+    offset = (target - (tcg_target_long)code_ptr) / 4;
+    /* read instruction, mask away previous PC_REL26 parameter contents,
+       set the proper offset, then write back the instruction. */
+    insn = *(uint32_t *)code_ptr;
+    insn = deposit32(insn, 0, 26, offset);
+    *(uint32_t *)code_ptr = insn;
+}
+
+static inline void reloc_pc19(void *code_ptr, tcg_target_long target)
+{
+    tcg_target_long offset; uint32_t insn;
+    offset = (target - (tcg_target_long)code_ptr) / 4;
+    /* read instruction, mask away previous PC_REL19 parameter contents,
+       set the proper offset, then write back the instruction. */
+    insn = *(uint32_t *)code_ptr;
+    insn = deposit32(insn, 5, 19, offset);
+    *(uint32_t *)code_ptr = insn;
+}
+
+static inline void patch_reloc(uint8_t *code_ptr, int type,
+                               tcg_target_long value, tcg_target_long addend)
+{
+    value += addend;
+
+    switch (type) {
+    case R_AARCH64_JUMP26:
+    case R_AARCH64_CALL26:
+        reloc_pc26(code_ptr, value);
+        break;
+    case R_AARCH64_CONDBR19:
+        reloc_pc19(code_ptr, value);
+        break;
+
+    default:
+        tcg_abort();
+    }
+}
+
+/* parse target specific constraints */
+static int target_parse_constraint(TCGArgConstraint *ct,
+                                   const char **pct_str)
+{
+    const char *ct_str = *pct_str;
+
+    switch (ct_str[0]) {
+    case 'r':
+        ct->ct |= TCG_CT_REG;
+        tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
+        break;
+    case 'l': /* qemu_ld / qemu_st address, data_reg */
+        ct->ct |= TCG_CT_REG;
+        tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
+#ifdef CONFIG_SOFTMMU
+        /* x0 and x1 will be overwritten when reading the tlb entry,
+           and x2, and x3 for helper args, better to avoid using them. */
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
+#endif
+        break;
+    default:
+        return -1;
+    }
+
+    ct_str++;
+    *pct_str = ct_str;
+    return 0;
+}
+
+static inline int tcg_target_const_match(tcg_target_long val,
+                                         const TCGArgConstraint *arg_ct)
+{
+    int ct = arg_ct->ct;
+
+    if (ct & TCG_CT_CONST) {
+        return 1;
+    }
+
+    return 0;
+}
+
+enum aarch64_cond_code {
+    COND_EQ = 0x0,
+    COND_NE = 0x1,
+    COND_CS = 0x2,     /* Unsigned greater or equal */
+    COND_HS = COND_CS, /* ALIAS greater or equal */
+    COND_CC = 0x3,     /* Unsigned less than */
+    COND_LO = COND_CC, /* ALIAS Lower */
+    COND_MI = 0x4,     /* Negative */
+    COND_PL = 0x5,     /* Zero or greater */
+    COND_VS = 0x6,     /* Overflow */
+    COND_VC = 0x7,     /* No overflow */
+    COND_HI = 0x8,     /* Unsigned greater than */
+    COND_LS = 0x9,     /* Unsigned less or equal */
+    COND_GE = 0xa,
+    COND_LT = 0xb,
+    COND_GT = 0xc,
+    COND_LE = 0xd,
+    COND_AL = 0xe,
+    COND_NV = 0xf, /* behaves like COND_AL here */
+};
+
+static const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
+    [TCG_COND_EQ] = COND_EQ,
+    [TCG_COND_NE] = COND_NE,
+    [TCG_COND_LT] = COND_LT,
+    [TCG_COND_GE] = COND_GE,
+    [TCG_COND_LE] = COND_LE,
+    [TCG_COND_GT] = COND_GT,
+    /* unsigned */
+    [TCG_COND_LTU] = COND_LO,
+    [TCG_COND_GTU] = COND_HI,
+    [TCG_COND_GEU] = COND_HS,
+    [TCG_COND_LEU] = COND_LS,
+};
+
+/* opcodes for LDR / STR instructions with base + simm9 addressing */
+enum aarch64_ldst_op_data { /* size of the data moved */
+    LDST_8 = 0x38,
+    LDST_16 = 0x78,
+    LDST_32 = 0xb8,
+    LDST_64 = 0xf8,
+};
+enum aarch64_ldst_op_type { /* type of operation */
+    LDST_ST = 0x0,    /* store */
+    LDST_LD = 0x4,    /* load */
+    LDST_LD_S_X = 0x8,  /* load and sign-extend into Xt */
+    LDST_LD_S_W = 0xc,  /* load and sign-extend into Wt */
+};
+
+enum aarch64_arith_opc {
+    ARITH_AND = 0x0a,
+    ARITH_ADD = 0x0b,
+    ARITH_OR = 0x2a,
+    ARITH_ADDS = 0x2b,
+    ARITH_XOR = 0x4a,
+    ARITH_SUB = 0x4b,
+    ARITH_ANDS = 0x6a,
+    ARITH_SUBS = 0x6b,
+};
+
+enum aarch64_srr_opc {
+    SRR_SHL = 0x0,
+    SRR_SHR = 0x4,
+    SRR_SAR = 0x8,
+    SRR_ROR = 0xc
+};
+
+static inline enum aarch64_ldst_op_data
+aarch64_ldst_get_data(TCGOpcode tcg_op)
+{
+    switch (tcg_op) {
+    case INDEX_op_ld8u_i32:
+    case INDEX_op_ld8s_i32:
+    case INDEX_op_ld8u_i64:
+    case INDEX_op_ld8s_i64:
+    case INDEX_op_st8_i32:
+    case INDEX_op_st8_i64:
+        return LDST_8;
+
+    case INDEX_op_ld16u_i32:
+    case INDEX_op_ld16s_i32:
+    case INDEX_op_ld16u_i64:
+    case INDEX_op_ld16s_i64:
+    case INDEX_op_st16_i32:
+    case INDEX_op_st16_i64:
+        return LDST_16;
+
+    case INDEX_op_ld_i32:
+    case INDEX_op_st_i32:
+    case INDEX_op_ld32u_i64:
+    case INDEX_op_ld32s_i64:
+    case INDEX_op_st32_i64:
+        return LDST_32;
+
+    case INDEX_op_ld_i64:
+    case INDEX_op_st_i64:
+        return LDST_64;
+
+    default:
+        tcg_abort();
+    }
+}
+
+static inline enum aarch64_ldst_op_type
+aarch64_ldst_get_type(TCGOpcode tcg_op)
+{
+    switch (tcg_op) {
+    case INDEX_op_st8_i32:
+    case INDEX_op_st16_i32:
+    case INDEX_op_st8_i64:
+    case INDEX_op_st16_i64:
+    case INDEX_op_st_i32:
+    case INDEX_op_st32_i64:
+    case INDEX_op_st_i64:
+        return LDST_ST;
+
+    case INDEX_op_ld8u_i32:
+    case INDEX_op_ld16u_i32:
+    case INDEX_op_ld8u_i64:
+    case INDEX_op_ld16u_i64:
+    case INDEX_op_ld_i32:
+    case INDEX_op_ld32u_i64:
+    case INDEX_op_ld_i64:
+        return LDST_LD;
+
+    case INDEX_op_ld8s_i32:
+    case INDEX_op_ld16s_i32:
+        return LDST_LD_S_W;
+
+    case INDEX_op_ld8s_i64:
+    case INDEX_op_ld16s_i64:
+    case INDEX_op_ld32s_i64:
+        return LDST_LD_S_X;
+
+    default:
+        tcg_abort();
+    }
+}
+
+static inline uint32_t tcg_in32(TCGContext *s)
+{
+    uint32_t v = *(uint32_t *)s->code_ptr;
+    return v;
+}
+
+static inline void tcg_out_ldst_9(TCGContext *s,
+                                  enum aarch64_ldst_op_data op_data,
+                                  enum aarch64_ldst_op_type op_type,
+                                  TCGReg rd, TCGReg rn, tcg_target_long offset)
+{
+    /* use LDUR with BASE register with 9bit signed unscaled offset */
+    unsigned int mod, off;
+
+    if (offset < 0) {
+        off = (256 + offset);
+        mod = 0x1;
+    } else {
+        off = offset;
+        mod = 0x0;
+    }
+
+    mod |= op_type;
+    tcg_out32(s, op_data << 24 | mod << 20 | off << 12 | rn << 5 | rd);
+}
+
+static inline void tcg_out_movr(TCGContext *s, int ext, TCGReg rd, TCGReg src)
+{
+    /* register to register move using MOV (shifted register with no shift) */
+    /* using MOV 0x2a0003e0 | (shift).. */
+    unsigned int base = ext ? 0xaa0003e0 : 0x2a0003e0;
+    tcg_out32(s, base | src << 16 | rd);
+}
+
+static inline void tcg_out_movi_aux(TCGContext *s,
+                                    TCGReg rd, uint64_t value)
+{
+    uint32_t half, base, shift, movk = 0;
+    /* construct halfwords of the immediate with MOVZ/MOVK with LSL */
+    /* using MOVZ 0x52800000 | extended reg.. */
+    base = (value > 0xffffffff) ? 0xd2800000 : 0x52800000;
+    /* count trailing zeros in 16 bit steps, mapping 64 to 0. Emit the
+       first MOVZ with the half-word immediate skipping the zeros, with a shift
+       (LSL) equal to this number. Then morph all next instructions into MOVKs.
+       Zero the processed half-word in the value, continue until empty.
+       We build the final result 16bits at a time with up to 4 instructions,
+       but do not emit instructions for 16bit zero holes. */
+    do {
+        shift = ctz64(value) & (63 & -16);
+        half = (value >> shift) & 0xffff;
+        tcg_out32(s, base | movk | shift << 17 | half << 5 | rd);
+        movk = 0x20000000; /* morph next MOVZs into MOVKs */
+        value &= ~(0xffffUL << shift);
+    } while (value);
+}
+
+static inline void tcg_out_movi(TCGContext *s, TCGType type,
+                                TCGReg rd, tcg_target_long value)
+{
+    if (type == TCG_TYPE_I64) {
+        tcg_out_movi_aux(s, rd, value);
+    } else {
+        tcg_out_movi_aux(s, rd, value & 0xffffffff);
+    }
+}
+
+static inline void tcg_out_ldst_r(TCGContext *s,
+                                  enum aarch64_ldst_op_data op_data,
+                                  enum aarch64_ldst_op_type op_type,
+                                  TCGReg rd, TCGReg base, TCGReg regoff)
+{
+    /* load from memory to register using base + 64bit register offset */
+    /* using f.e. STR Wt, [Xn, Xm] 0xb8600800|(regoff << 16)|(base << 5)|rd */
+    /* the 0x6000 is for the "no extend field" */
+    tcg_out32(s, 0x00206800
+              | op_data << 24 | op_type << 20 | regoff << 16 | base << 5 | rd);
+}
+
+/* solve the whole ldst problem */
+static inline void tcg_out_ldst(TCGContext *s, enum aarch64_ldst_op_data data,
+                                enum aarch64_ldst_op_type type,
+                                TCGReg rd, TCGReg rn, tcg_target_long offset)
+{
+    if (offset >= -256 && offset < 256) {
+        tcg_out_ldst_9(s, data, type, rd, rn, offset);
+    } else {
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
+        tcg_out_ldst_r(s, data, type, rd, rn, TCG_REG_TMP);
+    }
+}
+
+/* mov alias implemented with add immediate, useful to move to/from SP */
+static inline void tcg_out_movr_sp(TCGContext *s, int ext, TCGReg rd, TCGReg rn)
+{
+    /* using ADD 0x11000000 | (ext) | rn << 5 | rd */
+    unsigned int base = ext ? 0x91000000 : 0x11000000;
+    tcg_out32(s, base | rn << 5 | rd);
+}
+
+static inline void tcg_out_mov(TCGContext *s,
+                               TCGType type, TCGReg ret, TCGReg arg)
+{
+    if (ret != arg) {
+        tcg_out_movr(s, type == TCG_TYPE_I64, ret, arg);
+    }
+}
+
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
+{
+    tcg_out_ldst(s, (type == TCG_TYPE_I64) ? LDST_64 : LDST_32, LDST_LD,
+                 arg, arg1, arg2);
+}
+
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, tcg_target_long arg2)
+{
+    tcg_out_ldst(s, (type == TCG_TYPE_I64) ? LDST_64 : LDST_32, LDST_ST,
+                 arg, arg1, arg2);
+}
+
+static inline void tcg_out_arith(TCGContext *s, enum aarch64_arith_opc opc,
+                                 int ext, TCGReg rd, TCGReg rn, TCGReg rm,
+                                 int shift_imm)
+{
+    /* Using shifted register arithmetic operations */
+    /* if extended register operation (64bit) just OR with 0x80 << 24 */
+    unsigned int shift, base = ext ? (0x80 | opc) << 24 : opc << 24;
+    if (shift_imm == 0) {
+        shift = 0;
+    } else if (shift_imm > 0) {
+        shift = shift_imm << 10 | 1 << 22;
+    } else /* (shift_imm < 0) */ {
+        shift = (-shift_imm) << 10;
+    }
+    tcg_out32(s, base | rm << 16 | shift | rn << 5 | rd);
+}
+
+static inline void tcg_out_mul(TCGContext *s, int ext,
+                               TCGReg rd, TCGReg rn, TCGReg rm)
+{
+    /* Using MADD 0x1b000000 with Ra = wzr alias MUL 0x1b007c00 */
+    unsigned int base = ext ? 0x9b007c00 : 0x1b007c00;
+    tcg_out32(s, base | rm << 16 | rn << 5 | rd);
+}
+
+static inline void tcg_out_shiftrot_reg(TCGContext *s,
+                                        enum aarch64_srr_opc opc, int ext,
+                                        TCGReg rd, TCGReg rn, TCGReg rm)
+{
+    /* using 2-source data processing instructions 0x1ac02000 */
+    unsigned int base = ext ? 0x9ac02000 : 0x1ac02000;
+    tcg_out32(s, base | rm << 16 | opc << 8 | rn << 5 | rd);
+}
+
+static inline void tcg_out_ubfm(TCGContext *s, int ext, TCGReg rd, TCGReg rn,
+                                unsigned int a, unsigned int b)
+{
+    /* Using UBFM 0x53000000 Wd, Wn, a, b */
+    unsigned int base = ext ? 0xd3400000 : 0x53000000;
+    tcg_out32(s, base | a << 16 | b << 10 | rn << 5 | rd);
+}
+
+static inline void tcg_out_sbfm(TCGContext *s, int ext, TCGReg rd, TCGReg rn,
+                                unsigned int a, unsigned int b)
+{
+    /* Using SBFM 0x13000000 Wd, Wn, a, b */
+    unsigned int base = ext ? 0x93400000 : 0x13000000;
+    tcg_out32(s, base | a << 16 | b << 10 | rn << 5 | rd);
+}
+
+static inline void tcg_out_extr(TCGContext *s, int ext, TCGReg rd,
+                                TCGReg rn, TCGReg rm, unsigned int a)
+{
+    /* Using EXTR 0x13800000 Wd, Wn, Wm, a */
+    unsigned int base = ext ? 0x93c00000 : 0x13800000;
+    tcg_out32(s, base | rm << 16 | a << 10 | rn << 5 | rd);
+}
+
+static inline void tcg_out_shl(TCGContext *s, int ext,
+                               TCGReg rd, TCGReg rn, unsigned int m)
+{
+    int bits, max;
+    bits = ext ? 64 : 32;
+    max = bits - 1;
+    tcg_out_ubfm(s, ext, rd, rn, bits - (m & max), max - (m & max));
+}
+
+static inline void tcg_out_shr(TCGContext *s, int ext,
+                               TCGReg rd, TCGReg rn, unsigned int m)
+{
+    int max = ext ? 63 : 31;
+    tcg_out_ubfm(s, ext, rd, rn, m & max, max);
+}
+
+static inline void tcg_out_sar(TCGContext *s, int ext,
+                               TCGReg rd, TCGReg rn, unsigned int m)
+{
+    int max = ext ? 63 : 31;
+    tcg_out_sbfm(s, ext, rd, rn, m & max, max);
+}
+
+static inline void tcg_out_rotr(TCGContext *s, int ext,
+                                TCGReg rd, TCGReg rn, unsigned int m)
+{
+    int max = ext ? 63 : 31;
+    tcg_out_extr(s, ext, rd, rn, rn, m & max);
+}
+
+static inline void tcg_out_rotl(TCGContext *s, int ext,
+                                TCGReg rd, TCGReg rn, unsigned int m)
+{
+    int bits, max;
+    bits = ext ? 64 : 32;
+    max = bits - 1;
+    tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max));
+}
+
+static inline void tcg_out_cmp(TCGContext *s, int ext, TCGReg rn, TCGReg rm,
+                               int shift_imm)
+{
+    /* Using CMP alias SUBS wzr, Wn, Wm */
+    tcg_out_arith(s, ARITH_SUBS, ext, TCG_REG_XZR, rn, rm, shift_imm);
+}
+
+static inline void tcg_out_cset(TCGContext *s, int ext, TCGReg rd, TCGCond c)
+{
+    /* Using CSET alias of CSINC 0x1a800400 Xd, XZR, XZR, invert(cond) */
+    unsigned int base = ext ? 0x9a9f07e0 : 0x1a9f07e0;
+    tcg_out32(s, base | tcg_cond_to_aarch64[tcg_invert_cond(c)] << 12 | rd);
+}
+
+static inline void tcg_out_goto(TCGContext *s, tcg_target_long target)
+{
+    tcg_target_long offset;
+    offset = (target - (tcg_target_long)s->code_ptr) / 4;
+
+    if (offset < -0x02000000 || offset >= 0x02000000) {
+        /* out of 26bit range */
+        tcg_abort();
+    }
+
+    tcg_out32(s, 0x14000000 | (offset & 0x03ffffff));
+}
+
+static inline void tcg_out_goto_noaddr(TCGContext *s)
+{
+    /* We pay attention here to not modify the branch target by
+       reading from the buffer. This ensure that caches and memory are
+       kept coherent during retranslation.
+       Mask away possible garbage in the high bits for the first translation,
+       while keeping the offset bits for retranslation. */
+    uint32_t insn;
+    insn = (tcg_in32(s) & 0x03ffffff) | 0x14000000;
+    tcg_out32(s, insn);
+}
+
+static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
+{
+    /* see comments in tcg_out_goto_noaddr */
+    uint32_t insn;
+    insn = tcg_in32(s) & (0x07ffff << 5);
+    insn |= 0x54000000 | tcg_cond_to_aarch64[c];
+    tcg_out32(s, insn);
+}
+
+static inline void tcg_out_goto_cond(TCGContext *s, TCGCond c,
+                                     tcg_target_long target)
+{
+    tcg_target_long offset;
+    offset = (target - (tcg_target_long)s->code_ptr) / 4;
+
+    if (offset < -0x40000 || offset >= 0x40000) {
+        /* out of 19bit range */
+        tcg_abort();
+    }
+
+    offset &= 0x7ffff;
+    tcg_out32(s, 0x54000000 | tcg_cond_to_aarch64[c] | offset << 5);
+}
+
+static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
+{
+    tcg_out32(s, 0xd63f0000 | reg << 5);
+}
+
+static inline void tcg_out_gotor(TCGContext *s, TCGReg reg)
+{
+    tcg_out32(s, 0xd61f0000 | reg << 5);
+}
+
+static inline void tcg_out_call(TCGContext *s, tcg_target_long target)
+{
+    tcg_target_long offset;
+
+    offset = (target - (tcg_target_long)s->code_ptr) / 4;
+
+    if (offset < -0x02000000 || offset >= 0x02000000) { /* out of 26bit rng */
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, target);
+        tcg_out_callr(s, TCG_REG_TMP);
+    } else {
+        tcg_out32(s, 0x94000000 | (offset & 0x03ffffff));
+    }
+}
+
+/* encode a logical immediate, mapping user parameter
+   M=set bits pattern length to S=M-1 */
+static inline unsigned int
+aarch64_limm(unsigned int m, unsigned int r)
+{
+    assert(m > 0);
+    return r << 16 | (m - 1) << 10;
+}
+
+/* test a register against an immediate bit pattern made of
+   M set bits rotated right by R.
+   Examples:
+   to test a 32/64 reg against 0x00000007, pass M = 3,  R = 0.
+   to test a 32/64 reg against 0x000000ff, pass M = 8,  R = 0.
+   to test a 32bit reg against 0xff000000, pass M = 8,  R = 8.
+   to test a 32bit reg against 0xff0000ff, pass M = 16, R = 8.
+ */
+static inline void tcg_out_tst(TCGContext *s, int ext, TCGReg rn,
+                               unsigned int m, unsigned int r)
+{
+    /* using TST alias of ANDS XZR, Xn,#bimm64 0x7200001f */
+    unsigned int base = ext ? 0xf240001f : 0x7200001f;
+    tcg_out32(s, base | aarch64_limm(m, r) | rn << 5);
+}
+
+/* and a register with a bit pattern, similarly to TST, no flags change */
+static inline void tcg_out_andi(TCGContext *s, int ext, TCGReg rd, TCGReg rn,
+                                unsigned int m, unsigned int r)
+{
+    /* using AND 0x12000000 */
+    unsigned int base = ext ? 0x92400000 : 0x12000000;
+    tcg_out32(s, base | aarch64_limm(m, r) | rn << 5 | rd);
+}
+
+static inline void tcg_out_ret(TCGContext *s)
+{
+    /* emit RET { LR } */
+    tcg_out32(s, 0xd65f03c0);
+}
+
+void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
+{
+    tcg_target_long target, offset;
+    target = (tcg_target_long)addr;
+    offset = (target - (tcg_target_long)jmp_addr) / 4;
+
+    if (offset < -0x02000000 || offset >= 0x02000000) {
+        /* out of 26bit range */
+        tcg_abort();
+    }
+
+    patch_reloc((uint8_t *)jmp_addr, R_AARCH64_JUMP26, target, 0);
+    flush_icache_range(jmp_addr, jmp_addr + 4);
+}
+
+static inline void tcg_out_goto_label(TCGContext *s, int label_index)
+{
+    TCGLabel *l = &s->labels[label_index];
+
+    if (!l->has_value) {
+        tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, label_index, 0);
+        tcg_out_goto_noaddr(s);
+    } else {
+        tcg_out_goto(s, l->u.value);
+    }
+}
+
+static inline void tcg_out_goto_label_cond(TCGContext *s,
+                                           TCGCond c, int label_index)
+{
+    TCGLabel *l = &s->labels[label_index];
+
+    if (!l->has_value) {
+        tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, label_index, 0);
+        tcg_out_goto_cond_noaddr(s, c);
+    } else {
+        tcg_out_goto_cond(s, c, l->u.value);
+    }
+}
+
+static inline void tcg_out_rev(TCGContext *s, int ext, TCGReg rd, TCGReg rm)
+{
+    /* using REV 0x5ac00800 */
+    unsigned int base = ext ? 0xdac00c00 : 0x5ac00800;
+    tcg_out32(s, base | rm << 5 | rd);
+}
+
+static inline void tcg_out_rev16(TCGContext *s, int ext, TCGReg rd, TCGReg rm)
+{
+    /* using REV16 0x5ac00400 */
+    unsigned int base = ext ? 0xdac00400 : 0x5ac00400;
+    tcg_out32(s, base | rm << 5 | rd);
+}
+
+static inline void tcg_out_sxt(TCGContext *s, int ext, int s_bits,
+                               TCGReg rd, TCGReg rn)
+{
+    /* using ALIASes SXTB 0x13001c00, SXTH 0x13003c00, SXTW 0x93407c00
+       of SBFM Xd, Xn, #0, #7|15|31 */
+    int bits = 8 * (1 << s_bits) - 1;
+    tcg_out_sbfm(s, ext, rd, rn, 0, bits);
+}
+
+static inline void tcg_out_uxt(TCGContext *s, int s_bits,
+                               TCGReg rd, TCGReg rn)
+{
+    /* using ALIASes UXTB 0x53001c00, UXTH 0x53003c00
+       of UBFM Wd, Wn, #0, #7|15 */
+    int bits = 8 * (1 << s_bits) - 1;
+    tcg_out_ubfm(s, 0, rd, rn, 0, bits);
+}
+
+#ifdef CONFIG_SOFTMMU
+#include "exec/softmmu_defs.h"
+
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
+};
+
+#else /* !CONFIG_SOFTMMU */
+
+static void tcg_out_qemu_ld_direct(TCGContext *s, int opc, TCGReg data_r,
+                                   TCGReg addr_r, TCGReg off_r)
+{
+    switch (opc) {
+    case 0:
+        tcg_out_ldst_r(s, LDST_8, LDST_LD, data_r, addr_r, off_r);
+        break;
+    case 0 | 4:
+        tcg_out_ldst_r(s, LDST_8, LDST_LD_S_X, data_r, addr_r, off_r);
+        break;
+    case 1:
+        tcg_out_ldst_r(s, LDST_16, LDST_LD, data_r, addr_r, off_r);
+        if (TCG_LDST_BSWAP) {
+            tcg_out_rev16(s, 0, data_r, data_r);
+        }
+        break;
+    case 1 | 4:
+        if (TCG_LDST_BSWAP) {
+            tcg_out_ldst_r(s, LDST_16, LDST_LD, data_r, addr_r, off_r);
+            tcg_out_rev16(s, 0, data_r, data_r);
+            tcg_out_sxt(s, 1, 1, data_r, data_r);
+        } else {
+            tcg_out_ldst_r(s, LDST_16, LDST_LD_S_X, data_r, addr_r, off_r);
+        }
+        break;
+    case 2:
+        tcg_out_ldst_r(s, LDST_32, LDST_LD, data_r, addr_r, off_r);
+        if (TCG_LDST_BSWAP) {
+            tcg_out_rev(s, 0, data_r, data_r);
+        }
+        break;
+    case 2 | 4:
+        if (TCG_LDST_BSWAP) {
+            tcg_out_ldst_r(s, LDST_32, LDST_LD, data_r, addr_r, off_r);
+            tcg_out_rev(s, 0, data_r, data_r);
+            tcg_out_sxt(s, 1, 2, data_r, data_r);
+        } else {
+            tcg_out_ldst_r(s, LDST_32, LDST_LD_S_X, data_r, addr_r, off_r);
+        }
+        break;
+    case 3:
+        tcg_out_ldst_r(s, LDST_64, LDST_LD, data_r, addr_r, off_r);
+        if (TCG_LDST_BSWAP) {
+            tcg_out_rev(s, 1, data_r, data_r);
+        }
+        break;
+    default:
+        tcg_abort();
+    }
+}
+
+static void tcg_out_qemu_st_direct(TCGContext *s, int opc, TCGReg data_r,
+                                   TCGReg addr_r, TCGReg off_r)
+{
+    switch (opc) {
+    case 0:
+        tcg_out_ldst_r(s, LDST_8, LDST_ST, data_r, addr_r, off_r);
+        break;
+    case 1:
+        if (TCG_LDST_BSWAP) {
+            tcg_out_rev16(s, 0, TCG_REG_TMP, data_r);
+            tcg_out_ldst_r(s, LDST_16, LDST_ST, TCG_REG_TMP, addr_r, off_r);
+        } else {
+            tcg_out_ldst_r(s, LDST_16, LDST_ST, data_r, addr_r, off_r);
+        }
+        break;
+    case 2:
+        if (TCG_LDST_BSWAP) {
+            tcg_out_rev(s, 0, TCG_REG_TMP, data_r);
+            tcg_out_ldst_r(s, LDST_32, LDST_ST, TCG_REG_TMP, addr_r, off_r);
+        } else {
+            tcg_out_ldst_r(s, LDST_32, LDST_ST, data_r, addr_r, off_r);
+        }
+        break;
+    case 3:
+        if (TCG_LDST_BSWAP) {
+            tcg_out_rev(s, 1, TCG_REG_TMP, data_r);
+            tcg_out_ldst_r(s, LDST_64, LDST_ST, TCG_REG_TMP, addr_r, off_r);
+        } else {
+            tcg_out_ldst_r(s, LDST_64, LDST_ST, data_r, addr_r, off_r);
+        }
+        break;
+    default:
+        tcg_abort();
+    }
+}
+#endif /* CONFIG_SOFTMMU */
+
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+{
+    TCGReg addr_reg, data_reg;
+#ifdef CONFIG_SOFTMMU
+    int mem_index, s_bits;
+#endif
+    data_reg = args[0];
+    addr_reg = args[1];
+
+#ifdef CONFIG_SOFTMMU
+    mem_index = args[2];
+    s_bits = opc & 3;
+
+    /* TODO: insert TLB lookup here */
+
+    /* all arguments passed via registers */
+    tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
+    tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, addr_reg);
+    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, mem_index);
+    tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
+                 (tcg_target_long)qemu_ld_helpers[s_bits]);
+    tcg_out_callr(s, TCG_REG_TMP);
+
+    if (opc & 0x04) { /* sign extend */
+        tcg_out_sxt(s, 1, s_bits, data_reg, TCG_REG_X0);
+    } else {
+        tcg_out_movr(s, 1, data_reg, TCG_REG_X0);
+    }
+
+#else /* !CONFIG_SOFTMMU */
+    tcg_out_qemu_ld_direct(s, opc, data_reg, addr_reg,
+                           GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
+#endif /* CONFIG_SOFTMMU */
+}
+
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+{
+    TCGReg addr_reg, data_reg;
+#ifdef CONFIG_SOFTMMU
+    int mem_index, s_bits;
+#endif
+    data_reg = args[0];
+    addr_reg = args[1];
+
+#ifdef CONFIG_SOFTMMU
+    mem_index = args[2];
+    s_bits = opc & 3;
+
+    /* TODO: insert TLB lookup here */
+
+    /* all arguments passed via registers */
+    tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
+    tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, addr_reg);
+    tcg_out_movr(s, 1, TCG_REG_X2, data_reg);
+    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, mem_index);
+    tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
+                 (tcg_target_long)qemu_st_helpers[s_bits]);
+    tcg_out_callr(s, TCG_REG_TMP);
+
+#else /* !CONFIG_SOFTMMU */
+    tcg_out_qemu_st_direct(s, opc, data_reg, addr_reg,
+                           GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
+#endif /* CONFIG_SOFTMMU */
+}
+
+static uint8_t *tb_ret_addr;
+
+/* callee stack use example:
+   stp     x29, x30, [sp,#-32]!
+   mov     x29, sp
+   stp     x1, x2, [sp,#16]
+   ...
+   ldp     x1, x2, [sp,#16]
+   ldp     x29, x30, [sp],#32
+   ret
+*/
+
+/* push r1 and r2, and alloc stack space for a total of
+   alloc_n elements (1 element=16 bytes, must be between 1 and 31. */
+static inline void tcg_out_push_pair(TCGContext *s, TCGReg addr,
+                                     TCGReg r1, TCGReg r2, int alloc_n)
+{
+    /* using indexed scaled simm7 STP 0x28800000 | (ext) | 0x01000000 (pre-idx)
+       | alloc_n * (-1) << 16 | r2 << 10 | addr << 5 | r1 */
+    assert(alloc_n > 0 && alloc_n < 0x20);
+    alloc_n = (-alloc_n) & 0x3f;
+    tcg_out32(s, 0xa9800000 | alloc_n << 16 | r2 << 10 | addr << 5 | r1);
+}
+
+/* dealloc stack space for a total of alloc_n elements and pop r1, r2.  */
+static inline void tcg_out_pop_pair(TCGContext *s, TCGReg addr,
+                                    TCGReg r1, TCGReg r2, int alloc_n)
+{
+    /* using indexed scaled simm7 LDP 0x28c00000 | (ext) | nothing (post-idx)
+       | alloc_n << 16 | r2 << 10 | addr << 5 | r1 */
+    assert(alloc_n > 0 && alloc_n < 0x20);
+    tcg_out32(s, 0xa8c00000 | alloc_n << 16 | r2 << 10 | addr << 5 | r1);
+}
+
+static inline void tcg_out_store_pair(TCGContext *s, TCGReg addr,
+                                      TCGReg r1, TCGReg r2, int idx)
+{
+    /* using register pair offset simm7 STP 0x29000000 | (ext)
+       | idx << 16 | r2 << 10 | addr << 5 | r1 */
+    assert(idx > 0 && idx < 0x20);
+    tcg_out32(s, 0xa9000000 | idx << 16 | r2 << 10 | addr << 5 | r1);
+}
+
+static inline void tcg_out_load_pair(TCGContext *s, TCGReg addr,
+                                     TCGReg r1, TCGReg r2, int idx)
+{
+    /* using register pair offset simm7 LDP 0x29400000 | (ext)
+       | idx << 16 | r2 << 10 | addr << 5 | r1 */
+    assert(idx > 0 && idx < 0x20);
+    tcg_out32(s, 0xa9400000 | idx << 16 | r2 << 10 | addr << 5 | r1);
+}
+
+static void tcg_out_op(TCGContext *s, TCGOpcode opc,
+                       const TCGArg *args, const int *const_args)
+{
+    /* ext will be set in the switch below, which will fall through to the
+       common code. It triggers the use of extended regs where appropriate. */
+    int ext = 0;
+
+    switch (opc) {
+    case INDEX_op_exit_tb:
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, args[0]);
+        tcg_out_goto(s, (tcg_target_long)tb_ret_addr);
+        break;
+
+    case INDEX_op_goto_tb:
+#ifndef USE_DIRECT_JUMP
+#error "USE_DIRECT_JUMP required for aarch64"
+#endif
+        assert(s->tb_jmp_offset != NULL); /* consistency for USE_DIRECT_JUMP */
+        s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+        /* actual branch destination will be patched by
+           aarch64_tb_set_jmp_target later, beware retranslation. */
+        tcg_out_goto_noaddr(s);
+        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
+        break;
+
+    case INDEX_op_call:
+        if (const_args[0]) {
+            tcg_out_call(s, args[0]);
+        } else {
+            tcg_out_callr(s, args[0]);
+        }
+        break;
+
+    case INDEX_op_br:
+        tcg_out_goto_label(s, args[0]);
+        break;
+
+    case INDEX_op_ld_i32:
+    case INDEX_op_ld_i64:
+    case INDEX_op_st_i32:
+    case INDEX_op_st_i64:
+    case INDEX_op_ld8u_i32:
+    case INDEX_op_ld8s_i32:
+    case INDEX_op_ld16u_i32:
+    case INDEX_op_ld16s_i32:
+    case INDEX_op_ld8u_i64:
+    case INDEX_op_ld8s_i64:
+    case INDEX_op_ld16u_i64:
+    case INDEX_op_ld16s_i64:
+    case INDEX_op_ld32u_i64:
+    case INDEX_op_ld32s_i64:
+    case INDEX_op_st8_i32:
+    case INDEX_op_st8_i64:
+    case INDEX_op_st16_i32:
+    case INDEX_op_st16_i64:
+    case INDEX_op_st32_i64:
+        tcg_out_ldst(s, aarch64_ldst_get_data(opc), aarch64_ldst_get_type(opc),
+                     args[0], args[1], args[2]);
+        break;
+
+    case INDEX_op_mov_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_mov_i32:
+        tcg_out_movr(s, ext, args[0], args[1]);
+        break;
+
+    case INDEX_op_movi_i64:
+        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
+        break;
+    case INDEX_op_movi_i32:
+        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
+        break;
+
+    case INDEX_op_add_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_add_i32:
+        tcg_out_arith(s, ARITH_ADD, ext, args[0], args[1], args[2], 0);
+        break;
+
+    case INDEX_op_sub_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_sub_i32:
+        tcg_out_arith(s, ARITH_SUB, ext, args[0], args[1], args[2], 0);
+        break;
+
+    case INDEX_op_and_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_and_i32:
+        tcg_out_arith(s, ARITH_AND, ext, args[0], args[1], args[2], 0);
+        break;
+
+    case INDEX_op_or_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_or_i32:
+        tcg_out_arith(s, ARITH_OR, ext, args[0], args[1], args[2], 0);
+        break;
+
+    case INDEX_op_xor_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_xor_i32:
+        tcg_out_arith(s, ARITH_XOR, ext, args[0], args[1], args[2], 0);
+        break;
+
+    case INDEX_op_mul_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_mul_i32:
+        tcg_out_mul(s, ext, args[0], args[1], args[2]);
+        break;
+
+    case INDEX_op_shl_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_shl_i32:
+        if (const_args[2]) {    /* LSL / UBFM Wd, Wn, (32 - m) */
+            tcg_out_shl(s, ext, args[0], args[1], args[2]);
+        } else {                /* LSL / LSLV */
+            tcg_out_shiftrot_reg(s, SRR_SHL, ext, args[0], args[1], args[2]);
+        }
+        break;
+
+    case INDEX_op_shr_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_shr_i32:
+        if (const_args[2]) {    /* LSR / UBFM Wd, Wn, m, 31 */
+            tcg_out_shr(s, ext, args[0], args[1], args[2]);
+        } else {                /* LSR / LSRV */
+            tcg_out_shiftrot_reg(s, SRR_SHR, ext, args[0], args[1], args[2]);
+        }
+        break;
+
+    case INDEX_op_sar_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_sar_i32:
+        if (const_args[2]) {    /* ASR / SBFM Wd, Wn, m, 31 */
+            tcg_out_sar(s, ext, args[0], args[1], args[2]);
+        } else {                /* ASR / ASRV */
+            tcg_out_shiftrot_reg(s, SRR_SAR, ext, args[0], args[1], args[2]);
+        }
+        break;
+
+    case INDEX_op_rotr_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_rotr_i32:
+        if (const_args[2]) {    /* ROR / EXTR Wd, Wm, Wm, m */
+            tcg_out_rotr(s, ext, args[0], args[1], args[2]);
+        } else {                /* ROR / RORV */
+            tcg_out_shiftrot_reg(s, SRR_ROR, ext, args[0], args[1], args[2]);
+        }
+        break;
+
+    case INDEX_op_rotl_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_rotl_i32:     /* same as rotate right by (32 - m) */
+        if (const_args[2]) {    /* ROR / EXTR Wd, Wm, Wm, 32 - m */
+            tcg_out_rotl(s, ext, args[0], args[1], args[2]);
+        } else {
+            tcg_out_arith(s, ARITH_SUB, 0,
+                          TCG_REG_TMP, TCG_REG_XZR, args[2], 0);
+            tcg_out_shiftrot_reg(s, SRR_ROR, ext,
+                                 args[0], args[1], TCG_REG_TMP);
+        }
+        break;
+
+    case INDEX_op_brcond_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_brcond_i32: /* CMP 0, 1, cond(2), label 3 */
+        tcg_out_cmp(s, ext, args[0], args[1], 0);
+        tcg_out_goto_label_cond(s, args[2], args[3]);
+        break;
+
+    case INDEX_op_setcond_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_setcond_i32:
+        tcg_out_cmp(s, ext, args[1], args[2], 0);
+        tcg_out_cset(s, 0, args[0], args[3]);
+        break;
+
+    case INDEX_op_qemu_ld8u:
+        tcg_out_qemu_ld(s, args, 0 | 0);
+        break;
+    case INDEX_op_qemu_ld8s:
+        tcg_out_qemu_ld(s, args, 4 | 0);
+        break;
+    case INDEX_op_qemu_ld16u:
+        tcg_out_qemu_ld(s, args, 0 | 1);
+        break;
+    case INDEX_op_qemu_ld16s:
+        tcg_out_qemu_ld(s, args, 4 | 1);
+        break;
+    case INDEX_op_qemu_ld32u:
+        tcg_out_qemu_ld(s, args, 0 | 2);
+        break;
+    case INDEX_op_qemu_ld32s:
+        tcg_out_qemu_ld(s, args, 4 | 2);
+        break;
+    case INDEX_op_qemu_ld32:
+        tcg_out_qemu_ld(s, args, 0 | 2);
+        break;
+    case INDEX_op_qemu_ld64:
+        tcg_out_qemu_ld(s, args, 0 | 3);
+        break;
+    case INDEX_op_qemu_st8:
+        tcg_out_qemu_st(s, args, 0);
+        break;
+    case INDEX_op_qemu_st16:
+        tcg_out_qemu_st(s, args, 1);
+        break;
+    case INDEX_op_qemu_st32:
+        tcg_out_qemu_st(s, args, 2);
+        break;
+    case INDEX_op_qemu_st64:
+        tcg_out_qemu_st(s, args, 3);
+        break;
+
+    case INDEX_op_bswap64_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_bswap32_i64:
+    case INDEX_op_bswap32_i32:
+        tcg_out_rev(s, ext, args[0], args[1]);
+        break;
+    case INDEX_op_bswap16_i64:
+    case INDEX_op_bswap16_i32:
+        tcg_out_rev16(s, 0, args[0], args[1]);
+        break;
+
+    case INDEX_op_ext8s_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_ext8s_i32:
+        tcg_out_sxt(s, ext, 0, args[0], args[1]);
+        break;
+    case INDEX_op_ext16s_i64:
+        ext = 1; /* fall through */
+    case INDEX_op_ext16s_i32:
+        tcg_out_sxt(s, ext, 1, args[0], args[1]);
+        break;
+    case INDEX_op_ext32s_i64:
+        tcg_out_sxt(s, 1, 2, args[0], args[1]);
+        break;
+    case INDEX_op_ext8u_i64:
+    case INDEX_op_ext8u_i32:
+        tcg_out_uxt(s, 0, args[0], args[1]);
+        break;
+    case INDEX_op_ext16u_i64:
+    case INDEX_op_ext16u_i32:
+        tcg_out_uxt(s, 1, args[0], args[1]);
+        break;
+    case INDEX_op_ext32u_i64:
+        tcg_out_movr(s, 0, args[0], args[1]);
+        break;
+
+    default:
+        tcg_abort(); /* opcode not implemented */
+    }
+}
+
+static const TCGTargetOpDef aarch64_op_defs[] = {
+    { INDEX_op_exit_tb, { } },
+    { INDEX_op_goto_tb, { } },
+    { INDEX_op_call, { "ri" } },
+    { INDEX_op_br, { } },
+
+    { INDEX_op_mov_i32, { "r", "r" } },
+    { INDEX_op_mov_i64, { "r", "r" } },
+
+    { INDEX_op_movi_i32, { "r" } },
+    { INDEX_op_movi_i64, { "r" } },
+
+    { INDEX_op_ld8u_i32, { "r", "r" } },
+    { INDEX_op_ld8s_i32, { "r", "r" } },
+    { INDEX_op_ld16u_i32, { "r", "r" } },
+    { INDEX_op_ld16s_i32, { "r", "r" } },
+    { INDEX_op_ld_i32, { "r", "r" } },
+    { INDEX_op_ld8u_i64, { "r", "r" } },
+    { INDEX_op_ld8s_i64, { "r", "r" } },
+    { INDEX_op_ld16u_i64, { "r", "r" } },
+    { INDEX_op_ld16s_i64, { "r", "r" } },
+    { INDEX_op_ld32u_i64, { "r", "r" } },
+    { INDEX_op_ld32s_i64, { "r", "r" } },
+    { INDEX_op_ld_i64, { "r", "r" } },
+
+    { INDEX_op_st8_i32, { "r", "r" } },
+    { INDEX_op_st16_i32, { "r", "r" } },
+    { INDEX_op_st_i32, { "r", "r" } },
+    { INDEX_op_st8_i64, { "r", "r" } },
+    { INDEX_op_st16_i64, { "r", "r" } },
+    { INDEX_op_st32_i64, { "r", "r" } },
+    { INDEX_op_st_i64, { "r", "r" } },
+
+    { INDEX_op_add_i32, { "r", "r", "r" } },
+    { INDEX_op_add_i64, { "r", "r", "r" } },
+    { INDEX_op_sub_i32, { "r", "r", "r" } },
+    { INDEX_op_sub_i64, { "r", "r", "r" } },
+    { INDEX_op_mul_i32, { "r", "r", "r" } },
+    { INDEX_op_mul_i64, { "r", "r", "r" } },
+    { INDEX_op_and_i32, { "r", "r", "r" } },
+    { INDEX_op_and_i64, { "r", "r", "r" } },
+    { INDEX_op_or_i32, { "r", "r", "r" } },
+    { INDEX_op_or_i64, { "r", "r", "r" } },
+    { INDEX_op_xor_i32, { "r", "r", "r" } },
+    { INDEX_op_xor_i64, { "r", "r", "r" } },
+
+    { INDEX_op_shl_i32, { "r", "r", "ri" } },
+    { INDEX_op_shr_i32, { "r", "r", "ri" } },
+    { INDEX_op_sar_i32, { "r", "r", "ri" } },
+    { INDEX_op_rotl_i32, { "r", "r", "ri" } },
+    { INDEX_op_rotr_i32, { "r", "r", "ri" } },
+    { INDEX_op_shl_i64, { "r", "r", "ri" } },
+    { INDEX_op_shr_i64, { "r", "r", "ri" } },
+    { INDEX_op_sar_i64, { "r", "r", "ri" } },
+    { INDEX_op_rotl_i64, { "r", "r", "ri" } },
+    { INDEX_op_rotr_i64, { "r", "r", "ri" } },
+
+    { INDEX_op_brcond_i32, { "r", "r" } },
+    { INDEX_op_setcond_i32, { "r", "r", "r" } },
+    { INDEX_op_brcond_i64, { "r", "r" } },
+    { INDEX_op_setcond_i64, { "r", "r", "r" } },
+
+    { INDEX_op_qemu_ld8u, { "r", "l" } },
+    { INDEX_op_qemu_ld8s, { "r", "l" } },
+    { INDEX_op_qemu_ld16u, { "r", "l" } },
+    { INDEX_op_qemu_ld16s, { "r", "l" } },
+    { INDEX_op_qemu_ld32u, { "r", "l" } },
+    { INDEX_op_qemu_ld32s, { "r", "l" } },
+
+    { INDEX_op_qemu_ld32, { "r", "l" } },
+    { INDEX_op_qemu_ld64, { "r", "l" } },
+
+    { INDEX_op_qemu_st8, { "l", "l" } },
+    { INDEX_op_qemu_st16, { "l", "l" } },
+    { INDEX_op_qemu_st32, { "l", "l" } },
+    { INDEX_op_qemu_st64, { "l", "l" } },
+
+    { INDEX_op_bswap16_i32, { "r", "r" } },
+    { INDEX_op_bswap32_i32, { "r", "r" } },
+    { INDEX_op_bswap16_i64, { "r", "r" } },
+    { INDEX_op_bswap32_i64, { "r", "r" } },
+    { INDEX_op_bswap64_i64, { "r", "r" } },
+
+    { INDEX_op_ext8s_i32, { "r", "r" } },
+    { INDEX_op_ext16s_i32, { "r", "r" } },
+    { INDEX_op_ext8u_i32, { "r", "r" } },
+    { INDEX_op_ext16u_i32, { "r", "r" } },
+
+    { INDEX_op_ext8s_i64, { "r", "r" } },
+    { INDEX_op_ext16s_i64, { "r", "r" } },
+    { INDEX_op_ext32s_i64, { "r", "r" } },
+    { INDEX_op_ext8u_i64, { "r", "r" } },
+    { INDEX_op_ext16u_i64, { "r", "r" } },
+    { INDEX_op_ext32u_i64, { "r", "r" } },
+
+    { -1 },
+};
+
+static void tcg_target_init(TCGContext *s)
+{
+#if !defined(CONFIG_USER_ONLY)
+    /* fail safe */
+    if ((1ULL << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) {
+        tcg_abort();
+    }
+#endif
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
+
+    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
+                     (1 << TCG_REG_X0) | (1 << TCG_REG_X1) |
+                     (1 << TCG_REG_X2) | (1 << TCG_REG_X3) |
+                     (1 << TCG_REG_X4) | (1 << TCG_REG_X5) |
+                     (1 << TCG_REG_X6) | (1 << TCG_REG_X7) |
+                     (1 << TCG_REG_X8) | (1 << TCG_REG_X9) |
+                     (1 << TCG_REG_X10) | (1 << TCG_REG_X11) |
+                     (1 << TCG_REG_X12) | (1 << TCG_REG_X13) |
+                     (1 << TCG_REG_X14) | (1 << TCG_REG_X15) |
+                     (1 << TCG_REG_X16) | (1 << TCG_REG_X17) |
+                     (1 << TCG_REG_X18));
+
+    tcg_regset_clear(s->reserved_regs);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
+
+    tcg_add_target_add_op_defs(aarch64_op_defs);
+}
+
+static inline void tcg_out_addi(TCGContext *s, int ext,
+                                TCGReg rd, TCGReg rn, unsigned int aimm)
+{
+    /* add immediate aimm unsigned 12bit value (we use LSL 0 - no shift) */
+    /* using ADD 0x11000000 | (ext) | (aimm << 10) | (rn << 5) | rd */
+    unsigned int base = ext ? 0x91000000 : 0x11000000;
+    assert(aimm <= 0xfff);
+    tcg_out32(s, base | (aimm << 10) | (rn << 5) | rd);
+}
+
+static inline void tcg_out_subi(TCGContext *s, int ext,
+                                TCGReg rd, TCGReg rn, unsigned int aimm)
+{
+    /* sub immediate aimm unsigned 12bit value (we use LSL 0 - no shift) */
+    /* using SUB 0x51000000 | (ext) | (aimm << 10) | (rn << 5) | rd */
+    unsigned int base = ext ? 0xd1000000 : 0x51000000;
+    assert(aimm <= 0xfff);
+    tcg_out32(s, base | (aimm << 10) | (rn << 5) | rd);
+}
+
+static void tcg_target_qemu_prologue(TCGContext *s)
+{
+    /* NB: frame sizes are in 16 byte stack units! */
+    int frame_size_callee_saved, frame_size_tcg_locals;
+    TCGReg r;
+
+    /* save pairs             (FP, LR) and (X19, X20) .. (X27, X28) */
+    frame_size_callee_saved = (1) + (TCG_REG_X28 - TCG_REG_X19) / 2 + 1;
+
+    /* frame size requirement for TCG local variables */
+    frame_size_tcg_locals = TCG_STATIC_CALL_ARGS_SIZE
+        + CPU_TEMP_BUF_NLONGS * sizeof(long)
+        + (TCG_TARGET_STACK_ALIGN - 1);
+    frame_size_tcg_locals &= ~(TCG_TARGET_STACK_ALIGN - 1);
+    frame_size_tcg_locals /= TCG_TARGET_STACK_ALIGN;
+
+    /* push (FP, LR) and update sp */
+    tcg_out_push_pair(s, TCG_REG_SP,
+                      TCG_REG_FP, TCG_REG_LR, frame_size_callee_saved);
+
+    /* FP -> callee_saved */
+    tcg_out_movr_sp(s, 1, TCG_REG_FP, TCG_REG_SP);
+
+    /* store callee-preserved regs x19..x28 using FP -> callee_saved */
+    for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
+        int idx = (r - TCG_REG_X19) / 2 + 1;
+        tcg_out_store_pair(s, TCG_REG_FP, r, r + 1, idx);
+    }
+
+    /* make stack space for TCG locals */
+    tcg_out_subi(s, 1, TCG_REG_SP, TCG_REG_SP,
+                 frame_size_tcg_locals * TCG_TARGET_STACK_ALIGN);
+    /* inform TCG about how to find TCG locals with register, offset, size */
+    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
+                  CPU_TEMP_BUF_NLONGS * sizeof(long));
+
+#if defined(CONFIG_USE_GUEST_BASE)
+    if (GUEST_BASE) {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, GUEST_BASE);
+        tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
+    }
+#endif
+
+    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+    tcg_out_gotor(s, tcg_target_call_iarg_regs[1]);
+
+    tb_ret_addr = s->code_ptr;
+
+    /* remove TCG locals stack space */
+    tcg_out_addi(s, 1, TCG_REG_SP, TCG_REG_SP,
+                 frame_size_tcg_locals * TCG_TARGET_STACK_ALIGN);
+
+    /* restore registers x19..x28.
+       FP must be preserved, so it still points to callee_saved area */
+    for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
+        int idx = (r - TCG_REG_X19) / 2 + 1;
+        tcg_out_load_pair(s, TCG_REG_FP, r, r + 1, idx);
+    }
+
+    /* pop (FP, LR), restore SP to previous frame, return */
+    tcg_out_pop_pair(s, TCG_REG_SP,
+                     TCG_REG_FP, TCG_REG_LR, frame_size_callee_saved);
+    tcg_out_ret(s);
+}
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
new file mode 100644
index 0000000..97e4a5b
--- /dev/null
+++ b/tcg/aarch64/tcg-target.h
@@ -0,0 +1,99 @@
+/*
+ * Initial TCG Implementation for aarch64
+ *
+ * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
+ * Written by Claudio Fontana
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.
+ *
+ * See the COPYING file in the top-level directory for details.
+ */
+
+#ifndef TCG_TARGET_AARCH64
+#define TCG_TARGET_AARCH64 1
+
+#undef TCG_TARGET_WORDS_BIGENDIAN
+#undef TCG_TARGET_STACK_GROWSUP
+
+typedef enum {
+    TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, TCG_REG_X4,
+    TCG_REG_X5, TCG_REG_X6, TCG_REG_X7, TCG_REG_X8, TCG_REG_X9,
+    TCG_REG_X10, TCG_REG_X11, TCG_REG_X12, TCG_REG_X13, TCG_REG_X14,
+    TCG_REG_X15, TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19,
+    TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23, TCG_REG_X24,
+    TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, TCG_REG_X28,
+    TCG_REG_FP,  /* frame pointer */
+    TCG_REG_LR, /* link register */
+    TCG_REG_SP,  /* stack pointer or zero register */
+    TCG_REG_XZR = TCG_REG_SP /* same register number */
+    /* program counter is not directly accessible! */
+} TCGReg;
+
+#define TCG_TARGET_NB_REGS 32
+
+/* used for function call generation */
+#define TCG_REG_CALL_STACK              TCG_REG_SP
+#define TCG_TARGET_STACK_ALIGN          16
+#define TCG_TARGET_CALL_ALIGN_ARGS      1
+#define TCG_TARGET_CALL_STACK_OFFSET    0
+
+/* optional instructions */
+#define TCG_TARGET_HAS_div_i32          0
+#define TCG_TARGET_HAS_ext8s_i32        1
+#define TCG_TARGET_HAS_ext16s_i32       1
+#define TCG_TARGET_HAS_ext8u_i32        1
+#define TCG_TARGET_HAS_ext16u_i32       1
+#define TCG_TARGET_HAS_bswap16_i32      1
+#define TCG_TARGET_HAS_bswap32_i32      1
+#define TCG_TARGET_HAS_not_i32          0
+#define TCG_TARGET_HAS_neg_i32          0
+#define TCG_TARGET_HAS_rot_i32          1
+#define TCG_TARGET_HAS_andc_i32         0
+#define TCG_TARGET_HAS_orc_i32          0
+#define TCG_TARGET_HAS_eqv_i32          0
+#define TCG_TARGET_HAS_nand_i32         0
+#define TCG_TARGET_HAS_nor_i32          0
+#define TCG_TARGET_HAS_deposit_i32      0
+#define TCG_TARGET_HAS_movcond_i32      0
+#define TCG_TARGET_HAS_add2_i32         0
+#define TCG_TARGET_HAS_sub2_i32         0
+#define TCG_TARGET_HAS_mulu2_i32        0
+#define TCG_TARGET_HAS_muls2_i32        0
+
+#define TCG_TARGET_HAS_div_i64          0
+#define TCG_TARGET_HAS_ext8s_i64        1
+#define TCG_TARGET_HAS_ext16s_i64       1
+#define TCG_TARGET_HAS_ext32s_i64       1
+#define TCG_TARGET_HAS_ext8u_i64        1
+#define TCG_TARGET_HAS_ext16u_i64       1
+#define TCG_TARGET_HAS_ext32u_i64       1
+#define TCG_TARGET_HAS_bswap16_i64      1
+#define TCG_TARGET_HAS_bswap32_i64      1
+#define TCG_TARGET_HAS_bswap64_i64      1
+#define TCG_TARGET_HAS_not_i64          0
+#define TCG_TARGET_HAS_neg_i64          0
+#define TCG_TARGET_HAS_rot_i64          1
+#define TCG_TARGET_HAS_andc_i64         0
+#define TCG_TARGET_HAS_orc_i64          0
+#define TCG_TARGET_HAS_eqv_i64          0
+#define TCG_TARGET_HAS_nand_i64         0
+#define TCG_TARGET_HAS_nor_i64          0
+#define TCG_TARGET_HAS_deposit_i64      0
+#define TCG_TARGET_HAS_movcond_i64      0
+#define TCG_TARGET_HAS_add2_i64         0
+#define TCG_TARGET_HAS_sub2_i64         0
+#define TCG_TARGET_HAS_mulu2_i64        0
+#define TCG_TARGET_HAS_muls2_i64        0
+
+enum {
+    TCG_AREG0 = TCG_REG_X19,
+};
+
+static inline void flush_icache_range(tcg_target_ulong start,
+                                      tcg_target_ulong stop)
+{
+    __builtin___clear_cache((char *)start, (char *)stop);
+}
+
+#endif /* TCG_TARGET_AARCH64 */
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 3d43412..6be736b 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -2053,12 +2053,6 @@
 
 static void tcg_target_init(TCGContext *s)
 {
-#if !defined(CONFIG_USER_ONLY)
-    /* fail safe */
-    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
-        tcg_abort();
-#endif
-
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
                      (1 << TCG_REG_R0) |
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 9eec06c..9e95477 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -2283,12 +2283,6 @@
     }
 #endif
 
-#if !defined(CONFIG_USER_ONLY)
-    /* fail safe */
-    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
-        tcg_abort();
-#endif
-
     if (TCG_TARGET_REG_BITS == 64) {
         tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
         tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 7d6f777..f229f1c 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -2324,13 +2324,6 @@
 
 static void tcg_target_init(TCGContext *s)
 {
-#if !defined(CONFIG_USER_ONLY)
-    /* fail safe */
-    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) {
-        tcg_abort();
-    }
-#endif
-
     query_facilities();
 
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 365e995..7e2eb94 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -64,6 +64,7 @@
 };
 
 enum {
+    DEV     = 0x10,
     LBA     = 0x40,
 };
 
@@ -76,6 +77,7 @@
 enum {
     CMD_READ_DMA    = 0xc8,
     CMD_WRITE_DMA   = 0xca,
+    CMD_FLUSH_CACHE = 0xe7,
     CMD_IDENTIFY    = 0xec,
 
     CMDF_ABORT      = 0x100,
@@ -394,7 +396,7 @@
 
     /* Read in the IDENTIFY buffer and check registers */
     data = inb(IDE_BASE + reg_device);
-    g_assert_cmpint(data & 0x10, ==, 0);
+    g_assert_cmpint(data & DEV, ==, 0);
 
     for (i = 0; i < 256; i++) {
         data = inb(IDE_BASE + reg_status);
@@ -423,6 +425,46 @@
     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();
+}
+
 int main(int argc, char **argv)
 {
     const char *arch = qtest_get_arch();
@@ -453,6 +495,8 @@
     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);
+
     ret = g_test_run();
 
     /* Cleanup */
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index 72db13f..d2f0efe 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -108,15 +108,15 @@
 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/translate-all.c b/translate-all.c
index 40b8f3d..df7c697 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -460,6 +460,8 @@
 # define MAX_CODE_GEN_BUFFER_SIZE  (2ul * 1024 * 1024 * 1024)
 #elif defined(__sparc__)
 # define MAX_CODE_GEN_BUFFER_SIZE  (2ul * 1024 * 1024 * 1024)
+#elif defined(__aarch64__)
+# define MAX_CODE_GEN_BUFFER_SIZE  (128ul * 1024 * 1024)
 #elif defined(__arm__)
 # define MAX_CODE_GEN_BUFFER_SIZE  (16u * 1024 * 1024)
 #elif defined(__s390x__)
diff --git a/ui/console.c b/ui/console.c
index b30853f..28bba6d 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1788,6 +1788,10 @@
     s->chr = chr;
     chr->opaque = s;
     chr->chr_set_echo = text_console_set_echo;
+    /* console/chardev init sometimes completes elsewhere in a 2nd
+     * stage, so defer OPENED events until they are fully initialized
+     */
+    chr->explicit_be_open = true;
 
     if (display_state) {
         text_console_do_init(chr, display_state);
diff --git a/ui/gtk.c b/ui/gtk.c
index 3bc2842..50a6993 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1119,6 +1119,8 @@
 
     chr = g_malloc0(sizeof(*chr));
     chr->chr_write = gd_vc_chr_write;
+    /* defer OPENED events until our vc is fully initialized */
+    chr->explicit_be_open = true;
 
     vcs[nb_vcs++] = chr;
 
@@ -1158,8 +1160,7 @@
     GIOChannel *chan;
     GtkWidget *scrolled_window;
     GtkAdjustment *vadjustment;
-    int master_fd, slave_fd, ret;
-    struct termios tty;
+    int master_fd, slave_fd;
 
     snprintf(buffer, sizeof(buffer), "vc%d", index);
     snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index);
@@ -1179,13 +1180,8 @@
 
     vc->terminal = vte_terminal_new();
 
-    ret = openpty(&master_fd, &slave_fd, NULL, NULL, NULL);
-    g_assert(ret != -1);
-
-    /* Set raw attributes on the pty. */
-    tcgetattr(slave_fd, &tty);
-    cfmakeraw(&tty);
-    tcsetattr(slave_fd, TCSAFLUSH, &tty);
+    master_fd = qemu_openpty_raw(&slave_fd, NULL);
+    g_assert(master_fd != -1);
 
 #if VTE_CHECK_VERSION(0, 26, 0)
     pty = vte_pty_new_foreign(master_fd, NULL);
@@ -1433,7 +1429,7 @@
     .dpy_cursor_define = gd_cursor_define,
 };
 
-void gtk_display_init(DisplayState *ds)
+void gtk_display_init(DisplayState *ds, bool full_screen)
 {
     GtkDisplayState *s = g_malloc0(sizeof(*s));
     char *filename;
@@ -1469,7 +1465,7 @@
 
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA"));
 
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu-icon.bmp");
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu_logo_no_text.svg");
     if (filename) {
         GError *error = NULL;
         GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, &error);
@@ -1509,6 +1505,10 @@
 
     gtk_widget_show_all(s->window);
 
+    if (full_screen) {
+        gtk_menu_item_activate(GTK_MENU_ITEM(s->full_screen_item));
+    }
+
     register_displaychangelistener(&s->dcl);
 
     global_state = s;
diff --git a/user-exec.c b/user-exec.c
index 71bd6c5..fa7f1f1 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -448,6 +448,21 @@
                              &uc->uc_sigmask, puc);
 }
 
+#elif defined(__aarch64__)
+
+int cpu_signal_handler(int host_signum, void *pinfo,
+                       void *puc)
+{
+    siginfo_t *info = pinfo;
+    struct ucontext *uc = puc;
+    uint64_t pc;
+    int is_write = 0; /* XXX how to determine? */
+
+    pc = uc->uc_mcontext.pc;
+    return handle_cpu_signal(pc, (uint64_t)info->si_addr,
+                             is_write, &uc->uc_sigmask, puc);
+}
+
 #elif defined(__mc68000)
 
 int cpu_signal_handler(int host_signum, void *pinfo,
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 4a1bd4e..dc72ab0 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -1,6 +1,6 @@
 util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
 util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o event_notifier-win32.o
-util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o
+util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o qemu-openpty.o
 util-obj-y += envlist.o path.o host-utils.o cache-utils.o module.o
 util-obj-y += bitmap.o bitops.o hbitmap.o
 util-obj-y += fifo8.o
diff --git a/util/cutils.c b/util/cutils.c
index a165819..0116fcd 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -107,6 +107,27 @@
     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;
@@ -267,6 +288,10 @@
         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;
 }
diff --git a/util/qemu-openpty.c b/util/qemu-openpty.c
new file mode 100644
index 0000000..4febfe9
--- /dev/null
+++ b/util/qemu-openpty.c
@@ -0,0 +1,135 @@
+/*
+ * qemu-openpty.c
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * Wrapper function qemu_openpty() implementation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * This is not part of oslib-posix.c because this function
+ * uses openpty() which often in -lutil, and if we add this
+ * dependency to oslib-posix.o, every app will have to be
+ * linked with -lutil.
+ */
+
+#include "config-host.h"
+#include "qemu-common.h"
+
+#if defined(__GLIBC__)
+# include <pty.h>
+#elif defined CONFIG_BSD
+# include <termios.h>
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#  include <libutil.h>
+# else
+#  include <util.h>
+# endif
+#elif defined CONFIG_SOLARIS
+# include <termios.h>
+# include <stropts.h>
+#endif
+
+#ifdef __sun__
+/* Once Solaris has openpty(), this is going to be removed. */
+static int openpty(int *amaster, int *aslave, char *name,
+                   struct termios *termp, struct winsize *winp)
+{
+        const char *slave;
+        int mfd = -1, sfd = -1;
+
+        *amaster = *aslave = -1;
+
+        mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
+        if (mfd < 0)
+                goto err;
+
+        if (grantpt(mfd) == -1 || unlockpt(mfd) == -1)
+                goto err;
+
+        if ((slave = ptsname(mfd)) == NULL)
+                goto err;
+
+        if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1)
+                goto err;
+
+        if (ioctl(sfd, I_PUSH, "ptem") == -1 ||
+            (termp != NULL && tcgetattr(sfd, termp) < 0))
+                goto err;
+
+        if (amaster)
+                *amaster = mfd;
+        if (aslave)
+                *aslave = sfd;
+        if (winp)
+                ioctl(sfd, TIOCSWINSZ, winp);
+
+        return 0;
+
+err:
+        if (sfd != -1)
+                close(sfd);
+        close(mfd);
+        return -1;
+}
+
+static void cfmakeraw (struct termios *termios_p)
+{
+        termios_p->c_iflag &=
+                ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+        termios_p->c_oflag &= ~OPOST;
+        termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+        termios_p->c_cflag &= ~(CSIZE|PARENB);
+        termios_p->c_cflag |= CS8;
+
+        termios_p->c_cc[VMIN] = 0;
+        termios_p->c_cc[VTIME] = 0;
+}
+#endif
+
+int qemu_openpty_raw(int *aslave, char *pty_name)
+{
+    int amaster;
+    struct termios tty;
+#if defined(__OpenBSD__) || defined(__DragonFly__)
+    char pty_buf[PATH_MAX];
+#define q_ptsname(x) pty_buf
+#else
+    char *pty_buf = NULL;
+#define q_ptsname(x) ptsname(x)
+#endif
+
+    if (openpty(&amaster, aslave, pty_buf, NULL, NULL) < 0) {
+        return -1;
+    }
+
+    /* Set raw attributes on the pty. */
+    tcgetattr(*aslave, &tty);
+    cfmakeraw(&tty);
+    tcsetattr(*aslave, TCSAFLUSH, &tty);
+
+    if (pty_name) {
+        strcpy(pty_name, q_ptsname(amaster));
+    }
+
+    return amaster;
+}
diff --git a/vl.c b/vl.c
index 47ab45d..9f8fd6e 100644
--- a/vl.c
+++ b/vl.c
@@ -610,6 +610,7 @@
 
     { RUN_STATE_GUEST_PANICKED, RUN_STATE_PAUSED },
     { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_GUEST_PANICKED, RUN_STATE_DEBUG },
 
     { RUN_STATE_MAX, RUN_STATE_MAX },
 };
@@ -3523,7 +3524,6 @@
             case QEMU_OPTION_full_screen:
                 full_screen = 1;
                 break;
-#ifdef CONFIG_SDL
             case QEMU_OPTION_no_frame:
                 no_frame = 1;
                 break;
@@ -3536,14 +3536,11 @@
             case QEMU_OPTION_no_quit:
                 no_quit = 1;
                 break;
+#ifdef CONFIG_SDL
             case QEMU_OPTION_sdl:
                 display_type = DT_SDL;
                 break;
 #else
-            case QEMU_OPTION_no_frame:
-            case QEMU_OPTION_alt_grab:
-            case QEMU_OPTION_ctrl_grab:
-            case QEMU_OPTION_no_quit:
             case QEMU_OPTION_sdl:
                 fprintf(stderr, "SDL support is disabled\n");
                 exit(1);
@@ -4084,6 +4081,15 @@
 #endif
     }
 
+    if ((no_frame || alt_grab || ctrl_grab) && display_type != DT_SDL) {
+        fprintf(stderr, "-no-frame, -alt-grab and -ctrl-grab are only valid "
+                        "for SDL, ignoring option\n");
+    }
+    if (no_quit && (display_type != DT_GTK && display_type != DT_SDL)) {
+        fprintf(stderr, "-no-quit is only valid for GTK and SDL, "
+                        "ignoring option\n");
+    }
+
 #if defined(CONFIG_GTK)
     if (display_type == DT_GTK) {
         early_gtk_display_init();
@@ -4347,7 +4353,7 @@
 #endif
 #if defined(CONFIG_GTK)
     case DT_GTK:
-        gtk_display_init(ds);
+        gtk_display_init(ds, full_screen);
         break;
 #endif
     default:
diff --git a/xen-all.c b/xen-all.c
index bc105f1..1a1d7bb 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -389,7 +389,7 @@
     if (state->log_for_dirtybit == physmap) {
         state->log_for_dirtybit = NULL;
     }
-    free(physmap);
+    g_free(physmap);
 
     return 0;
 }
@@ -1030,7 +1030,7 @@
                 xen_domid, entries[i]);
         value = xs_read(state->xenstore, 0, path, &len);
         if (value == NULL) {
-            free(physmap);
+            g_free(physmap);
             continue;
         }
         physmap->start_addr = strtoull(value, NULL, 16);
@@ -1041,7 +1041,7 @@
                 xen_domid, entries[i]);
         value = xs_read(state->xenstore, 0, path, &len);
         if (value == NULL) {
-            free(physmap);
+            g_free(physmap);
             continue;
         }
         physmap->size = strtoull(value, NULL, 16);
@@ -1069,12 +1069,14 @@
     state->xce_handle = xen_xc_evtchn_open(NULL, 0);
     if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
         perror("xen: event channel open");
+        g_free(state);
         return -errno;
     }
 
     state->xenstore = xs_daemon_open();
     if (state->xenstore == NULL) {
         perror("xen: xenstore open");
+        g_free(state);
         return -errno;
     }