summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.mailmap16
-rw-r--r--Makefile9
-rw-r--r--Makefile.target4
-rwxr-xr-xQMP/qmp126
-rw-r--r--README4
-rw-r--r--balloon.c28
-rw-r--r--balloon.h3
-rw-r--r--blockdev.c89
-rw-r--r--blockdev.h4
-rw-r--r--bsd-user/bsdload.c2
-rw-r--r--bsd-user/elfload.c5
-rwxr-xr-xconfigure10
-rw-r--r--console.h2
-rw-r--r--cpus.c96
-rw-r--r--docs/writing-qmp-commands.txt642
-rw-r--r--exec.c6
-rw-r--r--hmp-commands.hx36
-rw-r--r--hmp.c148
-rw-r--r--hmp.h12
-rw-r--r--hw/a9mpcore.c189
-rw-r--r--hw/arm11mpcore.c130
-rw-r--r--hw/arm_gic.c75
-rw-r--r--hw/arm_mptimer.c332
-rw-r--r--hw/arm_timer.c41
-rw-r--r--hw/ccid-card-emulated.c25
-rw-r--r--hw/e1000.c11
-rw-r--r--hw/eepro100.c7
-rw-r--r--hw/hw.h8
-rw-r--r--hw/ide/pci.c4
-rw-r--r--hw/lsi53c895a.c4
-rw-r--r--hw/mpcore.c283
-rw-r--r--hw/realview_gic.c25
-rw-r--r--hw/rtl8139.c8
-rw-r--r--hw/syborg.c113
-rw-r--r--hw/syborg.h18
-rw-r--r--hw/syborg_fb.c554
-rw-r--r--hw/syborg_interrupt.c233
-rw-r--r--hw/syborg_keyboard.c215
-rw-r--r--hw/syborg_pointer.c220
-rw-r--r--hw/syborg_rtc.c134
-rw-r--r--hw/syborg_serial.c329
-rw-r--r--hw/syborg_timer.c224
-rw-r--r--hw/syborg_virtio.c307
-rw-r--r--hw/usb-ehci.c6
-rw-r--r--hw/usb-net.c5
-rw-r--r--hw/usb-uhci.c17
-rw-r--r--migration-exec.c9
-rw-r--r--migration-tcp.c7
-rw-r--r--migration-unix.c7
-rw-r--r--migration.c32
-rw-r--r--migration.h7
-rw-r--r--monitor.c201
-rw-r--r--monitor.h3
-rw-r--r--net.c10
-rw-r--r--net.h1
-rw-r--r--net/socket.c88
-rw-r--r--qapi-schema-guest.json6
-rw-r--r--qapi-schema-test.json6
-rw-r--r--qapi-schema.json267
-rw-r--r--qapi/qmp-core.h4
-rw-r--r--qapi/qmp-dispatch.c4
-rw-r--r--qapi/qmp-registry.c56
-rw-r--r--qemu-ga.c37
-rw-r--r--qemu-thread-posix.c33
-rw-r--r--qemu-thread-win32.c107
-rw-r--r--qemu-thread-win32.h5
-rw-r--r--qemu-thread.h8
-rw-r--r--qerror.c8
-rw-r--r--qerror.h6
-rw-r--r--qga/guest-agent-commands.c24
-rw-r--r--qmp-commands.hx77
-rw-r--r--qmp.c37
-rw-r--r--savevm.c65
-rw-r--r--target-cris/cpu.h2
-rw-r--r--target-cris/helper.c1
-rw-r--r--target-cris/translate_v10.c72
-rw-r--r--target-i386/translate.c11
-rw-r--r--test-qmp-input-visitor.c270
-rw-r--r--test-qmp-output-visitor.c423
-rw-r--r--test-visitor.c338
-rw-r--r--ui/vnc-jobs-async.c2
81 files changed, 3413 insertions, 3580 deletions
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000000..9797802aaa
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,16 @@
+# This mailmap just translates the weird addresses from the original import into git
+# into proper addresses so that they are counted properly in git shortlog output.
+#
+Andrzej Zaborowski <balrogg@gmail.com> balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>
+Anthony Liguori <aliguori@us.ibm.com> aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
+Aurelien Jarno <aurelien@aurel32.net> aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>
+Blue Swirl <blauwirbel@gmail.com> blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
+Edgar E. Iglesias <edgar.iglesias@gmail.com> edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>
+Fabrice Bellard <fabrice@bellard.org> bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
+Jocelyn Mayer <l_indien@magic.fr> j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
+Paul Brook <paul@codesourcery.com> pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
+Thiemo Seufer <ths@networkno.de> ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
+malc <av1474@comtv.ru> malc <malc@c046a42c-6fe2-441c-8c8c-71466251a162>
+# There is also a:
+#    (no author) <(no author)@c046a42c-6fe2-441c-8c8c-71466251a162>
+# for the cvs2svn initialization commit e63c3dc74bf.
diff --git a/Makefile b/Makefile
index 301c75e7e5..2c030552a1 100644
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
-test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
@@ -202,8 +202,11 @@ qmp-commands.h qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -m -o "." < $<, "  GEN   $@")
 
-test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
+test-qmp-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
 test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
 test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
diff --git a/Makefile.target b/Makefile.target
index 7369a89e55..8be9b9a596 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -342,6 +342,7 @@ obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
 obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
 obj-arm-y += versatile_pci.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
 obj-arm-y += arm-semi.o
@@ -359,9 +360,6 @@ obj-arm-y += mst_fpga.o mainstone.o
 obj-arm-y += z2.o
 obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
 obj-arm-y += framebuffer.o
-obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
-obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
-obj-arm-y += syborg_virtio.o
 obj-arm-y += vexpress.o
 obj-arm-y += strongarm.o
 obj-arm-y += collie.o
diff --git a/QMP/qmp b/QMP/qmp
new file mode 100755
index 0000000000..1db3c7ffeb
--- /dev/null
+++ b/QMP/qmp
@@ -0,0 +1,126 @@
+#!/usr/bin/python
+#
+# QMP command line tool
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+#  Anthony Liguori <aliguori@us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2 or later.
+# See the COPYING file in the top-level directory.
+
+import sys, os
+from qmp import QEMUMonitorProtocol
+
+def print_response(rsp, prefix=[]):
+    if type(rsp) == list:
+        i = 0
+        for item in rsp:
+            if prefix == []:
+                prefix = ['item']
+            print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)])
+            i += 1
+    elif type(rsp) == dict:
+        for key in rsp.keys():
+            print_response(rsp[key], prefix + [key])
+    else:
+        if len(prefix):
+            print '%s: %s' % ('.'.join(prefix), rsp)
+        else:
+            print '%s' % (rsp)
+
+def main(args):
+    path = None
+
+    # Use QMP_PATH if it's set
+    if os.environ.has_key('QMP_PATH'):
+        path = os.environ['QMP_PATH']
+
+    while len(args):
+        arg = args[0]
+
+        if arg.startswith('--'):
+            arg = arg[2:]
+            if arg.find('=') == -1:
+                value = True
+            else:
+                arg, value = arg.split('=', 1)
+
+            if arg in ['path']:
+                if type(value) == str:
+                    path = value
+            elif arg in ['help']:
+                os.execlp('man', 'man', 'qmp')
+            else:
+                print 'Unknown argument "%s"' % arg
+
+            args = args[1:]
+        else:
+            break
+
+    if not path:
+        print "QMP path isn't set, use --path=qmp-monitor-address or set QMP_PATH"
+        return 1
+
+    if len(args):
+        command, args = args[0], args[1:]
+    else:
+        print 'No command found'
+        print 'Usage: "qmp [--path=qmp-monitor-address] qmp-cmd arguments"'
+        return 1
+
+    if command in ['help']:
+        os.execlp('man', 'man', 'qmp')
+
+    srv = QEMUMonitorProtocol(path)
+    srv.connect()
+
+    def do_command(srv, cmd, **kwds):
+        rsp = srv.cmd(cmd, kwds)
+        if rsp.has_key('error'):
+            raise Exception(rsp['error']['desc'])
+        return rsp['return']
+
+    commands = map(lambda x: x['name'], do_command(srv, 'query-commands'))
+
+    srv.close()
+
+    if command not in commands:
+        fullcmd = 'qmp-%s' % command
+        try:
+            os.environ['QMP_PATH'] = path
+            os.execvp(fullcmd, [fullcmd] + args)
+        except OSError, (errno, msg):
+            if errno == 2:
+                print 'Command "%s" not found.' % (fullcmd)
+                return 1
+            raise
+        return 0
+
+    srv = QEMUMonitorProtocol(path)
+    srv.connect()
+
+    arguments = {}
+    for arg in args:
+        if not arg.startswith('--'):
+            print 'Unknown argument "%s"' % arg
+            return 1
+
+        arg = arg[2:]
+        if arg.find('=') == -1:
+            value = True
+        else:
+            arg, value = arg.split('=', 1)
+
+        if arg in ['help']:
+            os.execlp('man', 'man', 'qmp-%s' % command)
+            return 1
+
+        arguments[arg] = value
+
+    rsp = do_command(srv, command, **arguments)
+    print_response(rsp)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
diff --git a/README b/README
index dfd56f24bb..c77d12642d 100644
--- a/README
+++ b/README
@@ -1,3 +1,3 @@
-Read the documentation in qemu-doc.html.
+Read the documentation in qemu-doc.html or on http://wiki.qemu.org
 
-Fabrice Bellard.
+- QEMU team
diff --git a/balloon.c b/balloon.c
index e1cd5fac4c..0166744aa8 100644
--- a/balloon.c
+++ b/balloon.c
@@ -100,31 +100,19 @@ BalloonInfo *qmp_query_balloon(Error **errp)
     return info;
 }
 
-/**
- * do_balloon(): Request VM to change its memory allocation
- */
-int do_balloon(Monitor *mon, const QDict *params,
-	       MonitorCompletion cb, void *opaque)
+void qmp_balloon(int64_t value, Error **errp)
 {
-    int64_t target;
-    int ret;
-
     if (kvm_enabled() && !kvm_has_sync_mmu()) {
-        qerror_report(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
-        return -1;
+        error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+        return;
     }
 
-    target = qdict_get_int(params, "value");
-    if (target <= 0) {
+    if (value <= 0) {
         qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size");
-        return -1;
+        return;
     }
-    ret = qemu_balloon(target);
-    if (ret == 0) {
-        qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
-        return -1;
+    
+    if (qemu_balloon(value) == 0) {
+        error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
     }
-
-    cb(opaque, NULL);
-    return 0;
 }
diff --git a/balloon.h b/balloon.h
index b36abeadf0..b60fd5d9f2 100644
--- a/balloon.h
+++ b/balloon.h
@@ -24,7 +24,4 @@ int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
 			     QEMUBalloonStatus *stat_func, void *opaque);
 void qemu_remove_balloon_handler(void *opaque);
 
-int do_balloon(Monitor *mon, const QDict *params,
-               MonitorCompletion cb, void *opaque);
-
 #endif
diff --git a/blockdev.c b/blockdev.c
index dbf0251a77..c832782d03 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -15,6 +15,7 @@
 #include "qemu-config.h"
 #include "sysemu.h"
 #include "block_int.h"
+#include "qmp-commands.h"
 
 static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
 
@@ -600,28 +601,20 @@ void do_commit(Monitor *mon, const QDict *qdict)
     }
 }
 
-int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
+                                bool has_format, const char *format,
+                                Error **errp)
 {
-    const char *device = qdict_get_str(qdict, "device");
-    const char *filename = qdict_get_try_str(qdict, "snapshot-file");
-    const char *format = qdict_get_try_str(qdict, "format");
     BlockDriverState *bs;
     BlockDriver *drv, *old_drv, *proto_drv;
     int ret = 0;
     int flags;
     char old_filename[1024];
 
-    if (!filename) {
-        qerror_report(QERR_MISSING_PARAMETER, "snapshot-file");
-        ret = -1;
-        goto out;
-    }
-
     bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, device);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
     pstrcpy(old_filename, sizeof(old_filename), bs->filename);
@@ -629,35 +622,34 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     old_drv = bs->drv;
     flags = bs->open_flags;
 
-    if (!format) {
+    if (!has_format) {
         format = "qcow2";
     }
 
     drv = bdrv_find_format(format);
     if (!drv) {
-        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+        return;
     }
 
-    proto_drv = bdrv_find_protocol(filename);
+    proto_drv = bdrv_find_protocol(snapshot_file);
     if (!proto_drv) {
-        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+        return;
     }
 
-    ret = bdrv_img_create(filename, format, bs->filename,
+    ret = bdrv_img_create(snapshot_file, format, bs->filename,
                           bs->drv->format_name, NULL, -1, flags);
     if (ret) {
-        goto out;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
 
     bdrv_drain_all();
     bdrv_flush(bs);
 
     bdrv_close(bs);
-    ret = bdrv_open(bs, filename, flags, drv);
+    ret = bdrv_open(bs, snapshot_file, flags, drv);
     /*
      * If reopening the image file we just created fails, fall back
      * and try to re-open the original image. If that fails too, we
@@ -666,17 +658,11 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     if (ret != 0) {
         ret = bdrv_open(bs, old_filename, flags, old_drv);
         if (ret != 0) {
-            qerror_report(QERR_OPEN_FILE_FAILED, old_filename);
+            error_set(errp, QERR_OPEN_FILE_FAILED, old_filename);
         } else {
-            qerror_report(QERR_OPEN_FILE_FAILED, filename);
+            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
         }
     }
-out:
-    if (ret) {
-        ret = -1;
-    }
-
-    return ret;
 }
 
 static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
@@ -710,28 +696,25 @@ int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return eject_device(mon, bs, force);
 }
 
-int do_block_set_passwd(Monitor *mon, const QDict *qdict,
-                        QObject **ret_data)
+void qmp_block_passwd(const char *device, const char *password, Error **errp)
 {
     BlockDriverState *bs;
     int err;
 
-    bs = bdrv_find(qdict_get_str(qdict, "device"));
+    bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
-    err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
+    err = bdrv_set_key(bs, password);
     if (err == -EINVAL) {
-        qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
+        return;
     } else if (err < 0) {
-        qerror_report(QERR_INVALID_PASSWORD);
-        return -1;
+        error_set(errp, QERR_INVALID_PASSWORD);
+        return;
     }
-
-    return 0;
 }
 
 int do_change_block(Monitor *mon, const char *device,
@@ -863,27 +846,23 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
  * existing QERR_ macro mess is cleaned up.  A good example for better
  * error reports can be found in the qemu-img resize code.
  */
-int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_block_resize(const char *device, int64_t size, Error **errp)
 {
-    const char *device = qdict_get_str(qdict, "device");
-    int64_t size = qdict_get_int(qdict, "size");
     BlockDriverState *bs;
 
     bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, device);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
     if (size < 0) {
-        qerror_report(QERR_UNDEFINED_ERROR);
-        return -1;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
 
     if (bdrv_truncate(bs, size)) {
-        qerror_report(QERR_UNDEFINED_ERROR);
-        return -1;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
-
-    return 0;
 }
diff --git a/blockdev.h b/blockdev.h
index 1b48a75499..f1b639660d 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -59,13 +59,9 @@ DriveInfo *add_init_drive(const char *opts);
 
 void do_commit(Monitor *mon, const QDict *qdict);
 int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_change_block(Monitor *mon, const char *device,
                     const char *filename, const char *fmt);
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_block_set_io_throttle(Monitor *mon,
                              const QDict *qdict, QObject **ret_data);
-int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 #endif
diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c
index 6d9bb6fb4e..2abc7136e0 100644
--- a/bsd-user/bsdload.c
+++ b/bsd-user/bsdload.c
@@ -196,7 +196,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
 
     /* Something went wrong, return the inode and free the argument pages*/
     for (i=0 ; i<MAX_ARG_PAGES ; i++) {
-        free(bprm.page[i]);
+        g_free(bprm.page[i]);
     }
     return(retval);
 }
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 1ef1f972fc..12888840a4 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -641,8 +641,7 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
                 offset = p % TARGET_PAGE_SIZE;
                 pag = (char *)page[p/TARGET_PAGE_SIZE];
                 if (!pag) {
-                    pag = (char *)malloc(TARGET_PAGE_SIZE);
-                    memset(pag, 0, TARGET_PAGE_SIZE);
+                    pag = g_try_malloc0(TARGET_PAGE_SIZE);
                     page[p/TARGET_PAGE_SIZE] = pag;
                     if (!pag)
                         return 0;
@@ -696,7 +695,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
             info->rss++;
             /* FIXME - check return value of memcpy_to_target() for failure */
             memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
-            free(bprm->page[i]);
+            g_free(bprm->page[i]);
         }
         stack_base += TARGET_PAGE_SIZE;
     }
diff --git a/configure b/configure
index 4bcb8efe29..6fd580e3a6 100755
--- a/configure
+++ b/configure
@@ -1116,7 +1116,7 @@ fi
 
 if test "$pie" = ""; then
   case "$cpu-$targetos" in
-    i386-Linux|x86_64-Linux)
+    i386-Linux|x86_64-Linux|i386-OpenBSD|x86_64-OpenBSD)
       ;;
     *)
       pie="no"
@@ -1528,9 +1528,6 @@ EOF
   if compile_prog "$sdl_cflags" "$sdl_libs" ; then
     sdl_libs="$sdl_libs -lX11"
   fi
-  if test "$mingw32" = "yes" ; then
-    sdl_libs="`echo $sdl_libs | sed s/-mwindows//g` -mconsole"
-  fi
   libs_softmmu="$sdl_libs $libs_softmmu"
 fi
 
@@ -2748,8 +2745,9 @@ if test "$softmmu" = yes ; then
     fi
     if [ "$check_utests" = "yes" ]; then
       checks="check-qint check-qstring check-qdict check-qlist"
-      checks="check-qfloat check-qjson test-coroutine $checks"
+      checks="check-qfloat check-qjson $checks"
     fi
+    test_progs="$checks test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
@@ -3235,7 +3233,7 @@ if test "$trace_default" = "yes"; then
 fi
 
 echo "TOOLS=$tools" >> $config_host_mak
-echo "CHECKS=$checks" >> $config_host_mak
+echo "CHECKS=$test_progs" >> $config_host_mak
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
diff --git a/console.h b/console.h
index 6ac4ed31ec..9466886b59 100644
--- a/console.h
+++ b/console.h
@@ -74,8 +74,6 @@ struct MouseTransformInfo {
     int a[7];
 };
 
-void do_info_mice_print(Monitor *mon, const QObject *data);
-void do_info_mice(Monitor *mon, QObject **ret_data);
 void do_mouse_set(Monitor *mon, const QDict *qdict);
 
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
diff --git a/cpus.c b/cpus.c
index a53276ac32..a060c6056e 100644
--- a/cpus.c
+++ b/cpus.c
@@ -910,7 +910,8 @@ static void qemu_tcg_init_vcpu(void *_env)
         env->halt_cond = g_malloc0(sizeof(QemuCond));
         qemu_cond_init(env->halt_cond);
         tcg_halt_cond = env->halt_cond;
-        qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env);
+        qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env,
+                           QEMU_THREAD_DETACHED);
         while (env->created == 0) {
             qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
         }
@@ -926,7 +927,8 @@ static void qemu_kvm_start_vcpu(CPUState *env)
     env->thread = g_malloc0(sizeof(QemuThread));
     env->halt_cond = g_malloc0(sizeof(QemuCond));
     qemu_cond_init(env->halt_cond);
-    qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env);
+    qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env,
+                       QEMU_THREAD_DETACHED);
     while (env->created == 0) {
         qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
     }
@@ -1136,3 +1138,93 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 
     return head;
 }
+
+void qmp_memsave(int64_t addr, int64_t size, const char *filename,
+                 bool has_cpu, int64_t cpu_index, Error **errp)
+{
+    FILE *f;
+    uint32_t l;
+    CPUState *env;
+    uint8_t buf[1024];
+
+    if (!has_cpu) {
+        cpu_index = 0;
+    }
+
+    for (env = first_cpu; env; env = env->next_cpu) {
+        if (cpu_index == env->cpu_index) {
+            break;
+        }
+    }
+
+    if (env == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+                  "a CPU number");
+        return;
+    }
+
+    f = fopen(filename, "wb");
+    if (!f) {
+        error_set(errp, QERR_OPEN_FILE_FAILED, filename);
+        return;
+    }
+
+    while (size != 0) {
+        l = sizeof(buf);
+        if (l > size)
+            l = size;
+        cpu_memory_rw_debug(env, addr, buf, l, 0);
+        if (fwrite(buf, 1, l, f) != l) {
+            error_set(errp, QERR_IO_ERROR);
+            goto exit;
+        }
+        addr += l;
+        size -= l;
+    }
+
+exit:
+    fclose(f);
+}
+
+void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
+                  Error **errp)
+{
+    FILE *f;
+    uint32_t l;
+    uint8_t buf[1024];
+
+    f = fopen(filename, "wb");
+    if (!f) {
+        error_set(errp, QERR_OPEN_FILE_FAILED, filename);
+        return;
+    }
+
+    while (size != 0) {
+        l = sizeof(buf);
+        if (l > size)
+            l = size;
+        cpu_physical_memory_rw(addr, buf, l, 0);
+        if (fwrite(buf, 1, l, f) != l) {
+            error_set(errp, QERR_IO_ERROR);
+            goto exit;
+        }
+        addr += l;
+        size -= l;
+    }
+
+exit:
+    fclose(f);
+}
+
+void qmp_inject_nmi(Error **errp)
+{
+#if defined(TARGET_I386)
+    CPUState *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu_interrupt(env, CPU_INTERRUPT_NMI);
+    }
+#else
+    error_set(errp, QERR_UNSUPPORTED);
+#endif
+}
diff --git a/docs/writing-qmp-commands.txt b/docs/writing-qmp-commands.txt
new file mode 100644
index 0000000000..0472fc3914
--- /dev/null
+++ b/docs/writing-qmp-commands.txt
@@ -0,0 +1,642 @@
+= How to write QMP commands using the QAPI framework =
+
+This document is a step-by-step guide on how to write new QMP commands using
+the QAPI framework. It also shows how to implement new style HMP commands.
+
+This document doesn't discuss QMP protocol level details, nor does it dive
+into the QAPI framework implementation.
+
+For an in-depth introduction to the QAPI framework, please refer to
+docs/qapi-code-gen.txt. For documentation about the QMP protocol, please
+check the files in QMP/.
+
+== Overview ==
+
+Generally speaking, the following steps should be taken in order to write a
+new QMP command.
+
+1. Write the command's and type(s) specification in the QAPI schema file
+   (qapi-schema.json in the root source directory)
+
+2. Write the QMP command itself, which is a regular C function. Preferably,
+   the command should be exported by some QEMU subsystem. But it can also be
+   added to the qmp.c file
+
+3. At this point the command can be tested under the QMP protocol
+
+4. Write the HMP command equivalent. This is not required and should only be
+   done if it does make sense to have the functionality in HMP. The HMP command
+   is implemented in terms of the QMP command
+
+The following sections will demonstrate each of the steps above. We will start
+very simple and get more complex as we progress.
+
+=== Testing ===
+
+For all the examples in the next sections, the test setup is the same and is
+shown here.
+
+First, QEMU should be started as:
+
+# /path/to/your/source/qemu [...] \
+    -chardev socket,id=qmp,port=4444,host=localhost,server \
+    -mon chardev=qmp,mode=control,pretty=on
+
+Then, in a different terminal:
+
+$ telnet localhost 4444
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+{
+    "QMP": {
+        "version": {
+            "qemu": {
+                "micro": 50, 
+                "minor": 15, 
+                "major": 0
+            }, 
+            "package": ""
+        }, 
+        "capabilities": [
+        ]
+    }
+}
+
+The above output is the QMP server saying you're connected. The server is
+actually in capabilities negotiation mode. To enter in command mode type:
+
+{ "execute": "qmp_capabilities" }
+
+Then the server should respond:
+
+{
+    "return": {
+    }
+}
+
+Which is QMP's way of saying "the latest command executed OK and didn't return
+any data". Now you're ready to enter the QMP example commands as explained in
+the following sections.
+
+== Writing a command that doesn't return data ==
+
+That's the most simple QMP command that can be written. Usually, this kind of
+command carries some meaningful action in QEMU but here it will just print
+"Hello, world" to the standard output.
+
+Our command will be called "hello-world". It takes no arguments, nor does it
+return any data.
+
+The first step is to add the following line to the bottom of the
+qapi-schema.json file:
+
+{ 'command': 'hello-world' }
+
+The "command" keyword defines a new QMP command. It's an JSON object. All
+schema entries are JSON objects. The line above will instruct the QAPI to
+generate any prototypes and the necessary code to marshal and unmarshal
+protocol data.
+
+The next step is to write the "hello-world" implementation. As explained
+earlier, it's preferable for commands to live in QEMU subsystems. But
+"hello-world" doesn't pertain to any, so we put its implementation in qmp.c:
+
+void qmp_hello_world(Error **errp)
+{
+    printf("Hello, world!\n");
+}
+
+There are a few things to be noticed:
+
+1. QMP command implementation functions must be prefixed with "qmp_"
+2. qmp_hello_world() returns void, this is in accordance with the fact that the
+   command doesn't return any data
+3. It takes an "Error **" argument. This is required. Later we will see how to
+   return errors and take additional arguments. The Error argument should not
+   be touched if the command doesn't return errors
+4. We won't add the function's prototype. That's automatically done by the QAPI
+5. Printing to the terminal is discouraged for QMP commands, we do it here
+   because it's the easiest way to demonstrate a QMP command
+
+Now a little hack is needed. As we're still using the old QMP server we need
+to add the new command to its internal dispatch table. This step won't be
+required in the near future. Open the qmp-commands.hx file and add the
+following in the botton:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_hello_world,
+    },
+
+You're done. Now build qemu, run it as suggested in the "Testing" section,
+and then type the following QMP command:
+
+{ "execute": "hello-world" }
+
+Then check the terminal running qemu and look for the "Hello, world" string. If
+you don't see it then something went wrong.
+
+=== Arguments ===
+
+Let's add an argument called "message" to our "hello-world" command. The new
+argument will contain the string to be printed to stdout. It's an optional
+argument, if it's not present we print our default "Hello, World" string.
+
+The first change we have to do is to modify the command specification in the
+schema file to the following:
+
+{ 'command': 'hello-world', 'data': { '*message': 'str' } }
+
+Notice the new 'data' member in the schema. It's an JSON object whose each
+element is an argument to the command in question. Also notice the asterisk,
+it's used to mark the argument optional (that means that you shouldn't use it
+for mandatory arguments). Finally, 'str' is the argument's type, which
+stands for "string". The QAPI also supports integers, booleans, enumerations
+and user defined types.
+
+Now, let's update our C implementation in qmp.c:
+
+void qmp_hello_world(bool has_message, const char *message, Error **errp)
+{
+    if (has_message) {
+        printf("%s\n", message);
+    } else {
+        printf("Hello, world\n");
+    }
+}
+
+There are two important details to be noticed:
+
+1. All optional arguments are accompanied by a 'has_' boolean, which is set
+   if the optional argument is present or false otherwise
+2. The C implementation signature must follow the schema's argument ordering,
+   which is defined by the "data" member
+
+The last step is to update the qmp-commands.hx file:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "message:s?",
+        .mhandler.cmd_new = qmp_marshal_input_hello_world,
+    },
+
+Notice that the "args_type" member got our "message" argument. The character
+"s" stands for "string" and "?" means it's optional. This too must be ordered
+according to the C implementation and schema file. You can look for more
+examples in the qmp-commands.hx file if you need to define more arguments.
+
+Again, this step won't be required in the future.
+
+Time to test our new version of the "hello-world" command. Build qemu, run it as
+described in the "Testing" section and then send two commands:
+
+{ "execute": "hello-world" }
+{
+    "return": {
+    }
+}
+
+{ "execute": "hello-world", "arguments": { "message": "We love qemu" } }
+{
+    "return": {
+    }
+}
+
+You should see "Hello, world" and "we love qemu" in the terminal running qemu,
+if you don't see these strings, then something went wrong.
+
+=== Errors ===
+
+QMP commands should use the error interface exported by the error.h header
+file. The basic function used to set an error is the error_set() one.
+
+Let's say we don't accept the string "message" to contain the word "love". If
+it does contain it, we want the "hello-world" command to the return the
+InvalidParameter error.
+
+Only one change is required, and it's in the C implementation:
+
+void qmp_hello_world(bool has_message, const char *message, Error **errp)
+{
+    if (has_message) {
+        if (strstr(message, "love")) {
+            error_set(errp, QERR_INVALID_PARAMETER, "message");
+            return;
+        }
+        printf("%s\n", message);
+    } else {
+        printf("Hello, world\n");
+    }
+}
+
+Let's test it. Build qemu, run it as defined in the "Testing" section, and
+then issue the following command:
+
+{ "execute": "hello-world", "arguments": { "message": "we love qemu" } }
+
+The QMP server's response should be:
+
+{
+    "error": {
+        "class": "InvalidParameter",
+        "desc": "Invalid parameter 'message'",
+        "data": {
+            "name": "message"
+        }
+    }
+}
+
+Which is the InvalidParameter error.
+
+When you have to return an error but you're unsure what error to return or
+which arguments an error takes, you should look at the qerror.h file. Note
+that you might be required to add new errors if needed.
+
+FIXME: describe better the error API and how to add new errors.
+
+=== Command Documentation ===
+
+There's only one step missing to make "hello-world"'s implementation complete,
+and that's its documentation in the schema file.
+
+This is very important. No QMP command will be accepted in QEMU without proper
+documentation.
+
+There are many examples of such documentation in the schema file already, but
+here goes "hello-world"'s new entry for the qapi-schema.json file:
+
+##
+# @hello-world
+#
+# Print a client provided string to the standard output stream.
+#
+# @message: #optional string to be printed
+#
+# Returns: Nothing on success.
+#          If @message contains "love", InvalidParameter
+#
+# Notes: if @message is not provided, the "Hello, world" string will
+#        be printed instead
+#
+# Since: <next qemu stable release, eg. 1.0>
+##
+{ 'command': 'hello-world', 'data': { '*message': 'str' } }
+
+Please, note that the "Returns" clause is optional if a command doesn't return
+any data nor any errors.
+
+=== Implementing the HMP command ===
+
+Now that the QMP command is in place, we can also make it available in the human
+monitor (HMP).
+
+With the introduction of the QAPI, HMP commands make QMP calls. Most of the
+time HMP commands are simple wrappers. All HMP commands implementation exist in
+the hmp.c file.
+
+Here's the implementation of the "hello-world" HMP command:
+
+void hmp_hello_world(Monitor *mon, const QDict *qdict)
+{
+    const char *message = qdict_get_try_str(qdict, "message");
+    Error *errp = NULL;
+
+    qmp_hello_world(!!message, message, &errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "%s\n", error_get_pretty(errp));
+        error_free(errp);
+        return;
+    }
+}
+
+Also, you have to add the function's prototype to the hmp.h file.
+
+There are three important points to be noticed:
+
+1. The "mon" and "qdict" arguments are mandatory for all HMP functions. The
+   former is the monitor object. The latter is how the monitor passes
+   arguments entered by the user to the command implementation
+2. hmp_hello_world() performs error checking. In this example we just print
+   the error description to the user, but we could do more, like taking
+   different actions depending on the error qmp_hello_world() returns
+3. The "errp" variable must be initialized to NULL before performing the
+   QMP call
+
+There's one last step to actually make the command available to monitor users,
+we should add it to the hmp-commands.hx file:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "message:s?",
+        .params     = "hello-world [message]",
+        .help       = "Print message to the standard output",
+        .mhandler.cmd = hmp_hello_world,
+    },
+
+STEXI
+@item hello_world @var{message}
+@findex hello_world
+Print message to the standard output
+ETEXI
+
+To test this you have to open a user monitor and issue the "hello-world"
+command. It might be instructive to check the command's documentation with
+HMP's "help" command.
+
+Please, check the "-monitor" command-line option to know how to open a user
+monitor.
+
+== Writing a command that returns data ==
+
+A QMP command is capable of returning any data the QAPI supports like integers,
+strings, booleans, enumerations and user defined types.
+
+In this section we will focus on user defined types. Please, check the QAPI
+documentation for information about the other types.
+
+=== User Defined Types ===
+
+For this example we will write the query-alarm-clock command, which returns
+information about QEMU's timer alarm. For more information about it, please
+check the "-clock" command-line option.
+
+We want to return two pieces of information. The first one is the alarm clock's
+name. The second one is when the next alarm will fire. The former information is
+returned as a string, the latter is an integer in nanoseconds (which is not
+very useful in practice, as the timer has probably already fired when the
+information reaches the client).
+
+The best way to return that data is to create a new QAPI type, as shown below:
+
+##
+# @QemuAlarmClock
+#
+# QEMU alarm clock information.
+#
+# @clock-name: The alarm clock method's name.
+#
+# @next-deadline: #optional The time (in nanoseconds) the next alarm will fire.
+#
+# Since: 1.0
+##
+{ 'type': 'QemuAlarmClock',
+  'data': { 'clock-name': 'str', '*next-deadline': 'int' } }
+
+The "type" keyword defines a new QAPI type. Its "data" member contains the
+type's members. In this example our members are the "clock-name" and the
+"next-deadline" one, which is optional.
+
+Now let's define the query-alarm-clock command:
+
+##
+# @query-alarm-clock
+#
+# Return information about QEMU's alarm clock.
+#
+# Returns a @QemuAlarmClock instance describing the alarm clock method
+# being currently used by QEMU (this is usually set by the '-clock'
+# command-line option).
+#
+# Since: 1.0
+##
+{ 'command': 'query-alarm-clock', 'returns': 'QemuAlarmClock' }
+
+Notice the "returns" keyword. As its name suggests, it's used to define the
+data returned by a command.
+
+It's time to implement the qmp_query_alarm_clock() function, you can put it
+in the qemu-timer.c file:
+
+QemuAlarmClock *qmp_query_alarm_clock(Error **errp)
+{
+    QemuAlarmClock *clock;
+    int64_t deadline;
+
+    clock = g_malloc0(sizeof(*clock));
+
+    deadline = qemu_next_alarm_deadline();
+    if (deadline > 0) {
+        clock->has_next_deadline = true;
+        clock->next_deadline = deadline;
+    }
+    clock->clock_name = g_strdup(alarm_timer->name);
+
+    return clock;
+}
+
+There are a number of things to be noticed:
+
+1. The QemuAlarmClock type is automatically generated by the QAPI framework,
+   its members correspond to the type's specification in the schema file
+2. As specified in the schema file, the function returns a QemuAlarmClock
+   instance and takes no arguments (besides the "errp" one, which is mandatory
+   for all QMP functions)
+3. The "clock" variable (which will point to our QAPI type instance) is
+   allocated by the regular g_malloc0() function. Note that we chose to
+   initialize the memory to zero. This is recomended for all QAPI types, as
+   it helps avoiding bad surprises (specially with booleans)
+4. Remember that "next_deadline" is optional? All optional members have a
+   'has_TYPE_NAME' member that should be properly set by the implementation,
+   as shown above
+5. Even static strings, such as "alarm_timer->name", should be dynamically
+   allocated by the implementation. This is so because the QAPI also generates
+   a function to free its types and it cannot distinguish between dynamically
+   or statically allocated strings
+6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
+   otherwise qemu won't build
+
+The last step is to add the correspoding entry in the qmp-commands.hx file:
+
+    {
+        .name       = "query-alarm-clock",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_alarm_clock,
+    },
+
+Time to test the new command. Build qemu, run it as described in the "Testing"
+section and try this:
+
+{ "execute": "query-alarm-clock" }
+{
+    "return": {
+        "next-deadline": 2368219,
+        "clock-name": "dynticks"
+    }
+}
+
+==== The HMP command ====
+
+Here's the HMP counterpart of the query-alarm-clock command:
+
+void hmp_info_alarm_clock(Monitor *mon)
+{
+    QemuAlarmClock *clock;
+    Error *errp = NULL;
+
+    clock = qmp_query_alarm_clock(&errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "Could not query alarm clock information\n");
+        error_free(errp);
+        return;
+    }
+
+    monitor_printf(mon, "Alarm clock method in use: '%s'\n", clock->clock_name);
+    if (clock->has_next_deadline) {
+        monitor_printf(mon, "Next alarm will fire in %" PRId64 " nanoseconds\n",
+                       clock->next_deadline);
+    }
+
+   qapi_free_QemuAlarmClock(clock); 
+}
+
+It's important to notice that hmp_info_alarm_clock() calls
+qapi_free_QemuAlarmClock() to free the data returned by qmp_query_alarm_clock().
+For user defined types, the QAPI will generate a qapi_free_QAPI_TYPE_NAME()
+function and that's what you have to use to free the types you define and
+qapi_free_QAPI_TYPE_NAMEList() for list types (explained in the next section).
+If the QMP call returns a string, then you should g_free() to free it.
+
+Also note that hmp_info_alarm_clock() performs error handling. That's not
+strictly required if you're sure the QMP function doesn't return errors, but
+it's good practice to always check for errors.
+
+Another important detail is that HMP's "info" commands don't go into the
+hmp-commands.hx. Instead, they go into the info_cmds[] table, which is defined
+in the monitor.c file. The entry for the "info alarmclock" follows:
+
+    {
+        .name       = "alarmclock",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show information about the alarm clock",
+        .mhandler.info = hmp_info_alarm_clock,
+    },
+
+To test this, run qemu and type "info alarmclock" in the user monitor.
+
+=== Returning Lists ===
+
+For this example, we're going to return all available methods for the timer
+alarm, which is pretty much what the command-line option "-clock ?" does,
+except that we're also going to inform which method is in use.
+
+This first step is to define a new type:
+
+##
+# @TimerAlarmMethod
+#
+# Timer alarm method information.
+#
+# @method-name: The method's name.
+#
+# @current: true if this alarm method is currently in use, false otherwise
+#
+# Since: 1.0
+##
+{ 'type': 'TimerAlarmMethod',
+  'data': { 'method-name': 'str', 'current': 'bool' } }
+
+The command will be called "query-alarm-methods", here is its schema
+specification:
+
+##
+# @query-alarm-methods
+#
+# Returns information about available alarm methods.
+#
+# Returns: a list of @TimerAlarmMethod for each method
+#
+# Since: 1.0
+##
+{ 'command': 'query-alarm-methods', 'returns': ['TimerAlarmMethod'] }
+
+Notice the syntax for returning lists "'returns': ['TimerAlarmMethod']", this
+should be read as "returns a list of TimerAlarmMethod instances".
+
+The C implementation follows:
+
+TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
+{
+    TimerAlarmMethodList *method_list = NULL;
+    const struct qemu_alarm_timer *p;
+    bool current = true;
+
+    for (p = alarm_timers; p->name; p++) {
+        TimerAlarmMethodList *info = g_malloc0(sizeof(*info));
+        info->value = g_malloc0(sizeof(*info->value));
+        info->value->method_name = g_strdup(p->name);
+        info->value->current = current;
+
+        current = false;
+
+        info->next = method_list;
+        method_list = info;
+    }
+
+    return method_list;
+}
+
+The most important difference from the previous examples is the
+TimerAlarmMethodList type, which is automatically generated by the QAPI from
+the TimerAlarmMethod type.
+
+Each list node is represented by a TimerAlarmMethodList instance. We have to
+allocate it, and that's done inside the for loop: the "info" pointer points to
+an allocated node. We also have to allocate the node's contents, which is
+stored in its "value" member. In our example, the "value" member is a pointer
+to an TimerAlarmMethod instance.
+
+Notice that the "current" variable is used as "true" only in the first
+interation of the loop. That's because the alarm timer method in use is the
+first element of the alarm_timers array. Also notice that QAPI lists are handled
+by hand and we return the head of the list.
+
+To test this you have to add the corresponding qmp-commands.hx entry:
+
+    {
+        .name       = "query-alarm-methods",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_alarm_methods,
+    },
+
+Now Build qemu, run it as explained in the "Testing" section and try our new
+command:
+
+{ "execute": "query-alarm-methods" }
+{
+    "return": [
+        {
+            "current": false, 
+            "method-name": "unix"
+        }, 
+        {
+            "current": true, 
+            "method-name": "dynticks"
+        }
+    ]
+}
+
+The HMP counterpart is a bit more complex than previous examples because it
+has to traverse the list, it's shown below for reference:
+
+void hmp_info_alarm_methods(Monitor *mon)
+{
+    TimerAlarmMethodList *method_list, *method;
+    Error *errp = NULL;
+
+    method_list = qmp_query_alarm_methods(&errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "Could not query alarm methods\n");
+        error_free(errp);
+        return;
+    }
+
+    for (method = method_list; method; method = method->next) {
+        monitor_printf(mon, "%c %s\n", method->value->current ? '*' : ' ',
+                                       method->value->method_name);
+    }
+
+    qapi_free_TimerAlarmMethodList(method_list);
+}
diff --git a/exec.c b/exec.c
index 6b92198e62..d8b2180170 100644
--- a/exec.c
+++ b/exec.c
@@ -1603,8 +1603,10 @@ void cpu_set_log(int log_flags)
             static char logfile_buf[4096];
             setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
         }
-#elif !defined(_WIN32)
-        /* Win32 doesn't support line-buffering and requires size >= 2 */
+#elif defined(_WIN32)
+        /* Win32 doesn't support line-buffering, so use unbuffered output. */
+        setvbuf(logfile, NULL, _IONBF, 0);
+#else
         setvbuf(logfile, NULL, _IOLBF, 0);
 #endif
         log_append = 1;
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 54b2abf458..14838b7fae 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -57,8 +57,7 @@ ETEXI
         .args_type  = "device:B,size:o",
         .params     = "device size",
         .help       = "resize a block image",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_resize,
+        .mhandler.cmd = hmp_block_resize,
     },
 
 STEXI
@@ -304,8 +303,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "resume emulation",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_cont,
+        .mhandler.cmd = hmp_cont,
     },
 
 STEXI
@@ -689,8 +687,7 @@ ETEXI
         .args_type  = "val:l,size:i,filename:s",
         .params     = "addr size file",
         .help       = "save to disk virtual memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_memory_save,
+        .mhandler.cmd = hmp_memsave,
     },
 
 STEXI
@@ -704,8 +701,7 @@ ETEXI
         .args_type  = "val:l,size:i,filename:s",
         .params     = "addr size file",
         .help       = "save to disk physical memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_physical_memory_save,
+        .mhandler.cmd = hmp_pmemsave,
     },
 
 STEXI
@@ -739,8 +735,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "inject an NMI on all guest's CPUs",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_inject_nmi,
+        .mhandler.cmd = hmp_inject_nmi,
     },
 #endif
 STEXI
@@ -776,8 +771,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "cancel the current VM migration",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_cancel,
+        .mhandler.cmd = hmp_migrate_cancel,
     },
 
 STEXI
@@ -792,8 +786,7 @@ ETEXI
         .params     = "value",
         .help       = "set maximum speed (in bytes) for migrations. "
 	"Defaults to MB if no size suffix is specified, ie. B/K/M/G/T",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_speed,
+        .mhandler.cmd = hmp_migrate_set_speed,
     },
 
 STEXI
@@ -807,8 +800,7 @@ ETEXI
         .args_type  = "value:T",
         .params     = "value",
         .help       = "set maximum tolerated downtime (in seconds) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_downtime,
+        .mhandler.cmd = hmp_migrate_set_downtime,
     },
 
 STEXI
@@ -845,7 +837,7 @@ ETEXI
                       "If format is specified, the snapshot file will\n\t\t\t"
                       "be created in that format. Otherwise the\n\t\t\t"
                       "snapshot will be internal! (currently unsupported)",
-        .mhandler.cmd_new = do_snapshot_blkdev,
+        .mhandler.cmd = hmp_snapshot_blkdev,
     },
 
 STEXI
@@ -1026,9 +1018,7 @@ ETEXI
         .args_type  = "value:M",
         .params     = "target",
         .help       = "request VM to change its memory allocation (in MB)",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_async = do_balloon,
-        .flags      = MONITOR_CMD_ASYNC,
+        .mhandler.cmd = hmp_balloon,
     },
 
 STEXI
@@ -1042,8 +1032,7 @@ ETEXI
         .args_type  = "name:s,up:b",
         .params     = "name on|off",
         .help       = "change the link status of a network adapter",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_set_link,
+        .mhandler.cmd = hmp_set_link,
     },
 
 STEXI
@@ -1203,8 +1192,7 @@ ETEXI
         .args_type  = "device:B,password:s",
         .params     = "block_passwd device password",
         .help       = "set the password of encrypted block devices",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_set_passwd,
+        .mhandler.cmd = hmp_block_passwd,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index dfab7ad9bb..e7659d5ffc 100644
--- a/hmp.c
+++ b/hmp.c
@@ -14,6 +14,14 @@
 #include "hmp.h"
 #include "qmp-commands.h"
 
+static void hmp_handle_error(Monitor *mon, Error **errp)
+{
+    if (error_is_set(errp)) {
+        monitor_printf(mon, "%s\n", error_get_pretty(*errp));
+        error_free(*errp);
+    }
+}
+
 void hmp_info_name(Monitor *mon)
 {
     NameInfo *info;
@@ -531,3 +539,143 @@ void hmp_cpu(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "invalid CPU index\n");
     }
 }
+
+void hmp_memsave(Monitor *mon, const QDict *qdict)
+{
+    uint32_t size = qdict_get_int(qdict, "size");
+    const char *filename = qdict_get_str(qdict, "filename");
+    uint64_t addr = qdict_get_int(qdict, "val");
+    Error *errp = NULL;
+
+    qmp_memsave(addr, size, filename, true, monitor_get_cpu_index(), &errp);
+    hmp_handle_error(mon, &errp);
+}
+
+void hmp_pmemsave(Monitor *mon, const QDict *qdict)
+{
+    uint32_t size = qdict_get_int(qdict, "size");
+    const char *filename = qdict_get_str(qdict, "filename");
+    uint64_t addr = qdict_get_int(qdict, "val");
+    Error *errp = NULL;
+
+    qmp_pmemsave(addr, size, filename, &errp);
+    hmp_handle_error(mon, &errp);
+}
+
+static void hmp_cont_cb(void *opaque, int err)
+{
+    Monitor *mon = opaque;
+
+    if (!err) {
+        hmp_cont(mon, NULL);
+    }
+}
+
+void hmp_cont(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+
+    qmp_cont(&errp);
+    if (error_is_set(&errp)) {
+        if (error_is_type(errp, QERR_DEVICE_ENCRYPTED)) {
+            const char *device;
+
+            /* The device is encrypted. Ask the user for the password
+               and retry */
+
+            device = error_get_field(errp, "device");
+            assert(device != NULL);
+
+            monitor_read_block_device_key(mon, device, hmp_cont_cb, mon);
+            error_free(errp);
+            return;
+        }
+        hmp_handle_error(mon, &errp);
+    }
+}
+
+void hmp_inject_nmi(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+
+    qmp_inject_nmi(&errp);
+    hmp_handle_error(mon, &errp);
+}
+
+void hmp_set_link(Monitor *mon, const QDict *qdict)
+{
+    const char *name = qdict_get_str(qdict, "name");
+    int up = qdict_get_bool(qdict, "up");
+    Error *errp = NULL;
+
+    qmp_set_link(name, up, &errp);
+    hmp_handle_error(mon, &errp);
+}
+
+void hmp_block_passwd(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    const char *password = qdict_get_str(qdict, "password");
+    Error *errp = NULL;
+
+    qmp_block_passwd(device, password, &errp);
+    hmp_handle_error(mon, &errp);
+}
+
+void hmp_balloon(Monitor *mon, const QDict *qdict)
+{
+    int64_t value = qdict_get_int(qdict, "value");
+    Error *errp = NULL;
+
+    qmp_balloon(value, &errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "balloon: %s\n", error_get_pretty(errp));
+        error_free(errp);
+    }
+}
+
+void hmp_block_resize(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    int64_t size = qdict_get_int(qdict, "size");
+    Error *errp = NULL;
+
+    qmp_block_resize(device, size, &errp);
+    hmp_handle_error(mon, &errp);
+}
+
+void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    const char *filename = qdict_get_try_str(qdict, "snapshot-file");
+    const char *format = qdict_get_try_str(qdict, "format");
+    Error *errp = NULL;
+
+    if (!filename) {
+        /* In the future, if 'snapshot-file' is not specified, the snapshot
+           will be taken internally. Today it's actually required. */
+        error_set(&errp, QERR_MISSING_PARAMETER, "snapshot-file");
+        hmp_handle_error(mon, &errp);
+        return;
+    }
+
+    qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp);
+    hmp_handle_error(mon, &errp);
+}
+
+void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
+{
+    qmp_migrate_cancel(NULL);
+}
+
+void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict)
+{
+    double value = qdict_get_double(qdict, "value");
+    qmp_migrate_set_downtime(value, NULL);
+}
+
+void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
+{
+    int64_t value = qdict_get_int(qdict, "value");
+    qmp_migrate_set_speed(value, NULL);
+}
diff --git a/hmp.h b/hmp.h
index 4422578448..093242d626 100644
--- a/hmp.h
+++ b/hmp.h
@@ -37,5 +37,17 @@ void hmp_stop(Monitor *mon, const QDict *qdict);
 void hmp_system_reset(Monitor *mon, const QDict *qdict);
 void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
+void hmp_memsave(Monitor *mon, const QDict *qdict);
+void hmp_pmemsave(Monitor *mon, const QDict *qdict);
+void hmp_cont(Monitor *mon, const QDict *qdict);
+void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
+void hmp_set_link(Monitor *mon, const QDict *qdict);
+void hmp_block_passwd(Monitor *mon, const QDict *qdict);
+void hmp_balloon(Monitor *mon, const QDict *qdict);
+void hmp_block_resize(Monitor *mon, const QDict *qdict);
+void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
+void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 6f108f4ce2..cd2985f421 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -2,28 +2,197 @@
  * Cortex-A9MPCore internal peripheral emulation.
  *
  * Copyright (c) 2009 CodeSourcery.
- * Written by Paul Brook
+ * Copyright (c) 2011 Linaro Limited.
+ * Written by Paul Brook, Peter Maydell.
  *
  * This code is licensed under the GPL.
  */
 
-/* 64 external IRQ lines.  */
+#include "sysbus.h"
+
+/* Configuration for arm_gic.c:
+ * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ */
 #define GIC_NIRQ 96
-#include "mpcore.c"
+#define NCPU 4
+
+static inline int
+gic_get_current_cpu(void)
+{
+  return cpu_single_env->cpu_index;
+}
+
+#include "arm_gic.c"
+
+/* A9MP private memory region.  */
+
+typedef struct a9mp_priv_state {
+    gic_state gic;
+    uint32_t scu_control;
+    uint32_t old_timer_status[8];
+    uint32_t num_cpu;
+    qemu_irq *timer_irq;
+    MemoryRegion scu_iomem;
+    MemoryRegion ptimer_iomem;
+    MemoryRegion container;
+    DeviceState *mptimer;
+} a9mp_priv_state;
+
+static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
+                            unsigned size)
+{
+    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    switch (offset) {
+    case 0x00: /* Control */
+        return s->scu_control;
+    case 0x04: /* Configuration */
+        return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
+    case 0x08: /* CPU Power Status */
+        return 0;
+    case 0x0c: /* Invalidate All Registers In Secure State */
+        return 0;
+    case 0x40: /* Filtering Start Address Register */
+    case 0x44: /* Filtering End Address Register */
+        /* RAZ/WI, like an implementation with only one AXI master */
+        return 0;
+    case 0x50: /* SCU Access Control Register */
+    case 0x54: /* SCU Non-secure Access Control Register */
+        /* unimplemented, fall through */
+    default:
+        return 0;
+    }
+}
+
+static void a9_scu_write(void *opaque, target_phys_addr_t offset,
+                         uint64_t value, unsigned size)
+{
+    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    switch (offset) {
+    case 0x00: /* Control */
+        s->scu_control = value & 1;
+        break;
+    case 0x4: /* Configuration: RO */
+        break;
+    case 0x0c: /* Invalidate All Registers In Secure State */
+        /* no-op as we do not implement caches */
+        break;
+    case 0x40: /* Filtering Start Address Register */
+    case 0x44: /* Filtering End Address Register */
+        /* RAZ/WI, like an implementation with only one AXI master */
+        break;
+    case 0x8: /* CPU Power Status */
+    case 0x50: /* SCU Access Control Register */
+    case 0x54: /* SCU Non-secure Access Control Register */
+        /* unimplemented, fall through */
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps a9_scu_ops = {
+    .read = a9_scu_read,
+    .write = a9_scu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void a9mpcore_timer_irq_handler(void *opaque, int irq, int level)
+{
+    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    if (level && !s->old_timer_status[irq]) {
+        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
+    }
+    s->old_timer_status[irq] = level;
+}
+
+static void a9mp_priv_reset(DeviceState *dev)
+{
+    a9mp_priv_state *s = FROM_SYSBUSGIC(a9mp_priv_state, sysbus_from_qdev(dev));
+    int i;
+    s->scu_control = 0;
+    for (i = 0; i < ARRAY_SIZE(s->old_timer_status); i++) {
+        s->old_timer_status[i] = 0;
+    }
+}
+
+static int a9mp_priv_init(SysBusDevice *dev)
+{
+    a9mp_priv_state *s = FROM_SYSBUSGIC(a9mp_priv_state, dev);
+    SysBusDevice *busdev;
+    int i;
+
+    if (s->num_cpu > NCPU) {
+        hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
+    }
+
+    gic_init(&s->gic, s->num_cpu);
+
+    s->mptimer = qdev_create(NULL, "arm_mptimer");
+    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
+    qdev_init_nofail(s->mptimer);
+    busdev = sysbus_from_qdev(s->mptimer);
+
+    /* Memory map (addresses are offsets from PERIPHBASE):
+     *  0x0000-0x00ff -- Snoop Control Unit
+     *  0x0100-0x01ff -- GIC CPU interface
+     *  0x0200-0x02ff -- Global Timer
+     *  0x0300-0x05ff -- nothing
+     *  0x0600-0x06ff -- private timers and watchdogs
+     *  0x0700-0x0fff -- nothing
+     *  0x1000-0x1fff -- GIC Distributor
+     *
+     * We should implement the global timer but don't currently do so.
+     */
+    memory_region_init(&s->container, "a9mp-priv-container", 0x2000);
+    memory_region_init_io(&s->scu_iomem, &a9_scu_ops, s, "a9mp-scu", 0x100);
+    memory_region_add_subregion(&s->container, 0, &s->scu_iomem);
+    /* GIC CPU interface */
+    memory_region_add_subregion(&s->container, 0x100, &s->gic.cpuiomem[0]);
+    /* Note that the A9 exposes only the "timer/watchdog for this core"
+     * memory region, not the "timer/watchdog for core X" ones 11MPcore has.
+     */
+    memory_region_add_subregion(&s->container, 0x600,
+                                sysbus_mmio_get_region(busdev, 0));
+    memory_region_add_subregion(&s->container, 0x620,
+                                sysbus_mmio_get_region(busdev, 1));
+    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+
+    sysbus_init_mmio(dev, &s->container);
+
+    /* Wire up the interrupt from each watchdog and timer. */
+    s->timer_irq = qemu_allocate_irqs(a9mpcore_timer_irq_handler,
+                                      s, (s->num_cpu + 1) * 2);
+    for (i = 0; i < s->num_cpu * 2; i++) {
+        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_a9mp_priv = {
+    .name = "a9mpcore_priv",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(scu_control, a9mp_priv_state),
+        VMSTATE_UINT32_ARRAY(old_timer_status, a9mp_priv_state, 8),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-static SysBusDeviceInfo mpcore_priv_info = {
-    .init = mpcore_priv_init,
+static SysBusDeviceInfo a9mp_priv_info = {
+    .init = a9mp_priv_init,
     .qdev.name  = "a9mpcore_priv",
-    .qdev.size  = sizeof(mpcore_priv_state),
+    .qdev.size  = sizeof(a9mp_priv_state),
+    .qdev.vmsd = &vmstate_a9mp_priv,
+    .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
 
-static void a9mpcore_register_devices(void)
+static void a9mp_register_devices(void)
 {
-    sysbus_register_withprop(&mpcore_priv_info);
+    sysbus_register_withprop(&a9mp_priv_info);
 }
 
-device_init(a9mpcore_register_devices)
+device_init(a9mp_register_devices)
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 32ecf98309..bc0457e58b 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -7,11 +7,139 @@
  * This code is licensed under the GPL.
  */
 
+#include "sysbus.h"
+#include "qemu-timer.h"
+
 /* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
    (+ 32 internal).  However my test chip only exposes/reports 32.
    More importantly Linux falls over if more than 32 are present!  */
 #define GIC_NIRQ 64
-#include "mpcore.c"
+
+#define NCPU 4
+
+static inline int
+gic_get_current_cpu(void)
+{
+  return cpu_single_env->cpu_index;
+}
+
+#include "arm_gic.c"
+
+/* MPCore private memory region.  */
+
+typedef struct mpcore_priv_state {
+    gic_state gic;
+    uint32_t scu_control;
+    int iomemtype;
+    uint32_t old_timer_status[8];
+    uint32_t num_cpu;
+    qemu_irq *timer_irq;
+    MemoryRegion iomem;
+    MemoryRegion container;
+    DeviceState *mptimer;
+} mpcore_priv_state;
+
+/* Per-CPU private memory mapped IO.  */
+
+static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
+{
+    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    int id;
+    offset &= 0xff;
+    /* SCU */
+    switch (offset) {
+    case 0x00: /* Control.  */
+        return s->scu_control;
+    case 0x04: /* Configuration.  */
+        id = ((1 << s->num_cpu) - 1) << 4;
+        return id | (s->num_cpu - 1);
+    case 0x08: /* CPU status.  */
+        return 0;
+    case 0x0c: /* Invalidate all.  */
+        return 0;
+    default:
+        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
+    }
+}
+
+static void mpcore_scu_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
+{
+    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    offset &= 0xff;
+    /* SCU */
+    switch (offset) {
+    case 0: /* Control register.  */
+        s->scu_control = value & 1;
+        break;
+    case 0x0c: /* Invalidate all.  */
+        /* This is a no-op as cache is not emulated.  */
+        break;
+    default:
+        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
+    }
+}
+
+static const MemoryRegionOps mpcore_scu_ops = {
+    .read = mpcore_scu_read,
+    .write = mpcore_scu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void mpcore_timer_irq_handler(void *opaque, int irq, int level)
+{
+    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    if (level && !s->old_timer_status[irq]) {
+        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
+    }
+    s->old_timer_status[irq] = level;
+}
+
+static void mpcore_priv_map_setup(mpcore_priv_state *s)
+{
+    int i;
+    SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
+    memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
+    memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
+    memory_region_add_subregion(&s->container, 0, &s->iomem);
+    /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
+     * at 0x200, 0x300...
+     */
+    for (i = 0; i < (s->num_cpu + 1); i++) {
+        target_phys_addr_t offset = 0x100 + (i * 0x100);
+        memory_region_add_subregion(&s->container, offset, &s->gic.cpuiomem[i]);
+    }
+    /* Add the regions for timer and watchdog for "current CPU" and
+     * for each specific CPU.
+     */
+    s->timer_irq = qemu_allocate_irqs(mpcore_timer_irq_handler,
+                                      s, (s->num_cpu + 1) * 2);
+    for (i = 0; i < (s->num_cpu + 1) * 2; i++) {
+        /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
+        target_phys_addr_t offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20;
+        memory_region_add_subregion(&s->container, offset,
+                                    sysbus_mmio_get_region(busdev, i));
+    }
+    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+    /* Wire up the interrupt from each watchdog and timer. */
+    for (i = 0; i < s->num_cpu * 2; i++) {
+        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+    }
+}
+
+static int mpcore_priv_init(SysBusDevice *dev)
+{
+    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
+
+    gic_init(&s->gic, s->num_cpu);
+    s->mptimer = qdev_create(NULL, "arm_mptimer");
+    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
+    qdev_init_nofail(s->mptimer);
+    mpcore_priv_map_setup(s);
+    sysbus_init_mmio(dev, &s->container);
+    return 0;
+}
 
 /* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
    controllers.  The output of these, plus some of the raw input lines
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 1a896fbcb3..9b521195a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -103,7 +103,14 @@ typedef struct gic_state
     int num_cpu;
 #endif
 
-    MemoryRegion iomem;
+    MemoryRegion iomem; /* Distributor */
+#ifndef NVIC
+    /* This is just so we can have an opaque pointer which identifies
+     * both this GIC and which CPU interface we should be accessing.
+     */
+    struct gic_state *backref[NCPU];
+    MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
+#endif
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -633,6 +640,54 @@ static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
     }
     gic_update(s);
 }
+
+/* Wrappers to read/write the GIC CPU interface for the current CPU */
+static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
+                                 unsigned size)
+{
+    gic_state *s = (gic_state *)opaque;
+    return gic_cpu_read(s, gic_get_current_cpu(), addr & 0xff);
+}
+
+static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
+                              uint64_t value, unsigned size)
+{
+    gic_state *s = (gic_state *)opaque;
+    gic_cpu_write(s, gic_get_current_cpu(), addr & 0xff, value);
+}
+
+/* Wrappers to read/write the GIC CPU interface for a specific CPU.
+ * These just decode the opaque pointer into gic_state* + cpu id.
+ */
+static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
+{
+    gic_state **backref = (gic_state **)opaque;
+    gic_state *s = *backref;
+    int id = (backref - s->backref);
+    return gic_cpu_read(s, id, addr & 0xff);
+}
+
+static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t value, unsigned size)
+{
+    gic_state **backref = (gic_state **)opaque;
+    gic_state *s = *backref;
+    int id = (backref - s->backref);
+    gic_cpu_write(s, id, addr & 0xff, value);
+}
+
+static const MemoryRegionOps gic_thiscpu_ops = {
+    .read = gic_thiscpu_read,
+    .write = gic_thiscpu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const MemoryRegionOps gic_cpu_ops = {
+    .read = gic_do_cpu_read,
+    .write = gic_do_cpu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
 #endif
 
 static void gic_reset(gic_state *s)
@@ -752,6 +807,24 @@ static void gic_init(gic_state *s)
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
     memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
+#ifndef NVIC
+    /* Memory regions for the CPU interfaces (NVIC doesn't have these):
+     * a region for "CPU interface for this core", then a region for
+     * "CPU interface for core 0", "for core 1", ...
+     * NB that the memory region size of 0x100 applies for the 11MPCore
+     * and also cores following the GIC v1 spec (ie A9).
+     * GIC v2 defines a larger memory region (0x1000) so this will need
+     * to be extended when we implement A15.
+     */
+    memory_region_init_io(&s->cpuiomem[0], &gic_thiscpu_ops, s,
+                          "gic_cpu", 0x100);
+    for (i = 0; i < NUM_CPU(s); i++) {
+        s->backref[i] = s;
+        memory_region_init_io(&s->cpuiomem[i+1], &gic_cpu_ops, &s->backref[i],
+                              "gic_cpu", 0x100);
+    }
+#endif
+
     gic_reset(s);
     register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
 }
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
new file mode 100644
index 0000000000..455a0aa55a
--- /dev/null
+++ b/hw/arm_mptimer.c
@@ -0,0 +1,332 @@
+/*
+ * Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited
+ * Written by Paul Brook, Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysbus.h"
+#include "qemu-timer.h"
+
+/* This device implements the per-cpu private timer and watchdog block
+ * which is used in both the ARM11MPCore and Cortex-A9MP.
+ */
+
+#define MAX_CPUS 4
+
+/* State of a single timer or watchdog block */
+typedef struct {
+    uint32_t count;
+    uint32_t load;
+    uint32_t control;
+    uint32_t status;
+    int64_t tick;
+    QEMUTimer *timer;
+    qemu_irq irq;
+    MemoryRegion iomem;
+} timerblock;
+
+typedef struct {
+    SysBusDevice busdev;
+    uint32_t num_cpu;
+    timerblock timerblock[MAX_CPUS * 2];
+    MemoryRegion iomem[2];
+} arm_mptimer_state;
+
+static inline int get_current_cpu(arm_mptimer_state *s)
+{
+    if (cpu_single_env->cpu_index >= s->num_cpu) {
+        hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
+                 s->num_cpu, cpu_single_env->cpu_index);
+    }
+    return cpu_single_env->cpu_index;
+}
+
+static inline void timerblock_update_irq(timerblock *tb)
+{
+    qemu_set_irq(tb->irq, tb->status);
+}
+
+/* Return conversion factor from mpcore timer ticks to qemu timer ticks.  */
+static inline uint32_t timerblock_scale(timerblock *tb)
+{
+    return (((tb->control >> 8) & 0xff) + 1) * 10;
+}
+
+static void timerblock_reload(timerblock *tb, int restart)
+{
+    if (tb->count == 0) {
+        return;
+    }
+    if (restart) {
+        tb->tick = qemu_get_clock_ns(vm_clock);
+    }
+    tb->tick += (int64_t)tb->count * timerblock_scale(tb);
+    qemu_mod_timer(tb->timer, tb->tick);
+}
+
+static void timerblock_tick(void *opaque)
+{
+    timerblock *tb = (timerblock *)opaque;
+    tb->status = 1;
+    if (tb->control & 2) {
+        tb->count = tb->load;
+        timerblock_reload(tb, 0);
+    } else {
+        tb->count = 0;
+    }
+    timerblock_update_irq(tb);
+}
+
+static uint64_t timerblock_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
+{
+    timerblock *tb = (timerblock *)opaque;
+    int64_t val;
+    addr &= 0x1f;
+    switch (addr) {
+    case 0: /* Load */
+        return tb->load;
+    case 4: /* Counter.  */
+        if (((tb->control & 1) == 0) || (tb->count == 0)) {
+            return 0;
+        }
+        /* Slow and ugly, but hopefully won't happen too often.  */
+        val = tb->tick - qemu_get_clock_ns(vm_clock);
+        val /= timerblock_scale(tb);
+        if (val < 0) {
+            val = 0;
+        }
+        return val;
+    case 8: /* Control.  */
+        return tb->control;
+    case 12: /* Interrupt status.  */
+        return tb->status;
+    default:
+        return 0;
+    }
+}
+
+static void timerblock_write(void *opaque, target_phys_addr_t addr,
+                             uint64_t value, unsigned size)
+{
+    timerblock *tb = (timerblock *)opaque;
+    int64_t old;
+    addr &= 0x1f;
+    switch (addr) {
+    case 0: /* Load */
+        tb->load = value;
+        /* Fall through.  */
+    case 4: /* Counter.  */
+        if ((tb->control & 1) && tb->count) {
+            /* Cancel the previous timer.  */
+            qemu_del_timer(tb->timer);
+        }
+        tb->count = value;
+        if (tb->control & 1) {
+            timerblock_reload(tb, 1);
+        }
+        break;
+    case 8: /* Control.  */
+        old = tb->control;
+        tb->control = value;
+        if (((old & 1) == 0) && (value & 1)) {
+            if (tb->count == 0 && (tb->control & 2)) {
+                tb->count = tb->load;
+            }
+            timerblock_reload(tb, 1);
+        }
+        break;
+    case 12: /* Interrupt status.  */
+        tb->status &= ~value;
+        timerblock_update_irq(tb);
+        break;
+    }
+}
+
+/* Wrapper functions to implement the "read timer/watchdog for
+ * the current CPU" memory regions.
+ */
+static uint64_t arm_thistimer_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
+{
+    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    int id = get_current_cpu(s);
+    return timerblock_read(&s->timerblock[id * 2], addr, size);
+}
+
+static void arm_thistimer_write(void *opaque, target_phys_addr_t addr,
+                                uint64_t value, unsigned size)
+{
+    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    int id = get_current_cpu(s);
+    timerblock_write(&s->timerblock[id * 2], addr, value, size);
+}
+
+static uint64_t arm_thiswdog_read(void *opaque, target_phys_addr_t addr,
+                                  unsigned size)
+{
+    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    int id = get_current_cpu(s);
+    return timerblock_read(&s->timerblock[id * 2 + 1], addr, size);
+}
+
+static void arm_thiswdog_write(void *opaque, target_phys_addr_t addr,
+                               uint64_t value, unsigned size)
+{
+    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    int id = get_current_cpu(s);
+    timerblock_write(&s->timerblock[id * 2 + 1], addr, value, size);
+}
+
+static const MemoryRegionOps arm_thistimer_ops = {
+    .read = arm_thistimer_read,
+    .write = arm_thistimer_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const MemoryRegionOps arm_thiswdog_ops = {
+    .read = arm_thiswdog_read,
+    .write = arm_thiswdog_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const MemoryRegionOps timerblock_ops = {
+    .read = timerblock_read,
+    .write = timerblock_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void timerblock_reset(timerblock *tb)
+{
+    tb->count = 0;
+    tb->load = 0;
+    tb->control = 0;
+    tb->status = 0;
+    tb->tick = 0;
+}
+
+static void arm_mptimer_reset(DeviceState *dev)
+{
+    arm_mptimer_state *s =
+        FROM_SYSBUS(arm_mptimer_state, sysbus_from_qdev(dev));
+    int i;
+    /* We reset every timer in the array, not just the ones we're using,
+     * because vmsave will look at every array element.
+     */
+    for (i = 0; i < ARRAY_SIZE(s->timerblock); i++) {
+        timerblock_reset(&s->timerblock[i]);
+    }
+}
+
+static int arm_mptimer_init(SysBusDevice *dev)
+{
+    arm_mptimer_state *s = FROM_SYSBUS(arm_mptimer_state, dev);
+    int i;
+    if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) {
+        hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS);
+    }
+    /* We implement one timer and one watchdog block per CPU, and
+     * expose multiple MMIO regions:
+     *  * region 0 is "timer for this core"
+     *  * region 1 is "watchdog for this core"
+     *  * region 2 is "timer for core 0"
+     *  * region 3 is "watchdog for core 0"
+     *  * region 4 is "timer for core 1"
+     *  * region 5 is "watchdog for core 1"
+     * and so on.
+     * The outgoing interrupt lines are
+     *  * timer for core 0
+     *  * watchdog for core 0
+     *  * timer for core 1
+     *  * watchdog for core 1
+     * and so on.
+     */
+    memory_region_init_io(&s->iomem[0], &arm_thistimer_ops, s,
+                          "arm_mptimer_timer", 0x20);
+    sysbus_init_mmio(dev, &s->iomem[0]);
+    memory_region_init_io(&s->iomem[1], &arm_thiswdog_ops, s,
+                          "arm_mptimer_wdog", 0x20);
+    sysbus_init_mmio(dev, &s->iomem[1]);
+    for (i = 0; i < (s->num_cpu * 2); i++) {
+        timerblock *tb = &s->timerblock[i];
+        tb->timer = qemu_new_timer_ns(vm_clock, timerblock_tick, tb);
+        sysbus_init_irq(dev, &tb->irq);
+        memory_region_init_io(&tb->iomem, &timerblock_ops, tb,
+                              "arm_mptimer_timerblock", 0x20);
+        sysbus_init_mmio(dev, &tb->iomem);
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_timerblock = {
+    .name = "arm_mptimer_timerblock",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(count, timerblock),
+        VMSTATE_UINT32(load, timerblock),
+        VMSTATE_UINT32(control, timerblock),
+        VMSTATE_UINT32(status, timerblock),
+        VMSTATE_INT64(tick, timerblock),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_arm_mptimer = {
+    .name = "arm_mptimer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(timerblock, arm_mptimer_state, (MAX_CPUS * 2),
+                             1, vmstate_timerblock, timerblock),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo arm_mptimer_info = {
+    .init = arm_mptimer_init,
+    .qdev.name = "arm_mptimer",
+    .qdev.size = sizeof(arm_mptimer_state),
+    .qdev.vmsd = &vmstate_arm_mptimer,
+    .qdev.reset = arm_mptimer_reset,
+    .qdev.no_user = 1,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-cpu", arm_mptimer_state, num_cpu, 0),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
+
+static void arm_mptimer_register_devices(void)
+{
+    sysbus_register_withprop(&arm_mptimer_info);
+}
+
+device_init(arm_mptimer_register_devices)
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 518bad20ae..0a5b9d2cd3 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -170,9 +170,9 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
 }
 
 /* ARM PrimeCell SP804 dual timer module.
-   Docs for this device don't seem to be publicly available.  This
-   implementation is based on guesswork, the linux kernel sources and the
-   Integrator/CP timer modules.  */
+ * Docs at
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
+*/
 
 typedef struct {
     SysBusDevice busdev;
@@ -182,6 +182,13 @@ typedef struct {
     qemu_irq irq;
 } sp804_state;
 
+static const uint8_t sp804_ids[] = {
+    /* Timer ID */
+    0x04, 0x18, 0x14, 0,
+    /* PrimeCell ID */
+    0xd, 0xf0, 0x05, 0xb1
+};
+
 /* Merge the IRQs from the two component devices.  */
 static void sp804_set_irq(void *opaque, int irq, int level)
 {
@@ -196,12 +203,27 @@ static uint64_t sp804_read(void *opaque, target_phys_addr_t offset,
 {
     sp804_state *s = (sp804_state *)opaque;
 
-    /* ??? Don't know the PrimeCell ID for this device.  */
     if (offset < 0x20) {
         return arm_timer_read(s->timer[0], offset);
-    } else {
+    }
+    if (offset < 0x40) {
         return arm_timer_read(s->timer[1], offset - 0x20);
     }
+
+    /* TimerPeriphID */
+    if (offset >= 0xfe0 && offset <= 0xffc) {
+        return sp804_ids[(offset - 0xfe0) >> 2];
+    }
+
+    switch (offset) {
+    /* Integration Test control registers, which we won't support */
+    case 0xf00: /* TimerITCR */
+    case 0xf04: /* TimerITOP (strictly write only but..) */
+        return 0;
+    }
+
+    hw_error("%s: Bad offset %x\n", __func__, (int)offset);
+    return 0;
 }
 
 static void sp804_write(void *opaque, target_phys_addr_t offset,
@@ -211,9 +233,16 @@ static void sp804_write(void *opaque, target_phys_addr_t offset,
 
     if (offset < 0x20) {
         arm_timer_write(s->timer[0], offset, value);
-    } else {
+        return;
+    }
+
+    if (offset < 0x40) {
         arm_timer_write(s->timer[1], offset - 0x20, value);
+        return;
     }
+
+    /* Technically we could be writing to the Test Registers, but not likely */
+    hw_error("%s: Bad offset %x\n", __func__, (int)offset);
 }
 
 static const MemoryRegionOps sp804_ops = {
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 092301b541..2d2ebce852 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -120,6 +120,7 @@ struct EmulatedState {
     uint8_t  atr_length;
     QSIMPLEQ_HEAD(event_list, EmulEvent) event_list;
     QemuMutex event_list_mutex;
+    QemuThread event_thread_id;
     VReader *reader;
     QSIMPLEQ_HEAD(guest_apdu_list, EmulEvent) guest_apdu_list;
     QemuMutex vreader_mutex; /* and guest_apdu_list mutex */
@@ -127,8 +128,7 @@ struct EmulatedState {
     QemuCond handle_apdu_cond;
     int      pipe[2];
     int      quit_apdu_thread;
-    QemuMutex apdu_thread_quit_mutex;
-    QemuCond apdu_thread_quit_cond;
+    QemuThread apdu_thread_id;
 };
 
 static void emulated_apdu_from_guest(CCIDCardState *base,
@@ -271,9 +271,6 @@ static void *handle_apdu_thread(void* arg)
         }
         qemu_mutex_unlock(&card->vreader_mutex);
     }
-    qemu_mutex_lock(&card->apdu_thread_quit_mutex);
-    qemu_cond_signal(&card->apdu_thread_quit_cond);
-    qemu_mutex_unlock(&card->apdu_thread_quit_mutex);
     return NULL;
 }
 
@@ -489,7 +486,6 @@ static uint32_t parse_enumeration(char *str,
 static int emulated_initfn(CCIDCardState *base)
 {
     EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
-    QemuThread thread_id;
     VCardEmulError ret;
     EnumTable *ptable;
 
@@ -541,8 +537,10 @@ static int emulated_initfn(CCIDCardState *base)
         printf("%s: failed to initialize vcard\n", EMULATED_DEV_NAME);
         return -1;
     }
-    qemu_thread_create(&thread_id, event_thread, card);
-    qemu_thread_create(&thread_id, handle_apdu_thread, card);
+    qemu_thread_create(&card->event_thread_id, event_thread, card,
+                       QEMU_THREAD_JOINABLE);
+    qemu_thread_create(&card->apdu_thread_id, handle_apdu_thread, card,
+                       QEMU_THREAD_JOINABLE);
     return 0;
 }
 
@@ -552,15 +550,14 @@ static int emulated_exitfn(CCIDCardState *base)
     VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL);
 
     vevent_queue_vevent(vevent); /* stop vevent thread */
-    qemu_mutex_lock(&card->apdu_thread_quit_mutex);
+    qemu_thread_join(&card->event_thread_id);
+
     card->quit_apdu_thread = 1; /* stop handle_apdu thread */
     qemu_cond_signal(&card->handle_apdu_cond);
-    qemu_cond_wait(&card->apdu_thread_quit_cond,
-                      &card->apdu_thread_quit_mutex);
-    /* handle_apdu thread stopped, can destroy all of it's mutexes */
+    qemu_thread_join(&card->apdu_thread_id);
+
+    /* threads exited, can destroy all condvars/mutexes */
     qemu_cond_destroy(&card->handle_apdu_cond);
-    qemu_cond_destroy(&card->apdu_thread_quit_cond);
-    qemu_mutex_destroy(&card->apdu_thread_quit_mutex);
     qemu_mutex_destroy(&card->handle_apdu_mutex);
     qemu_mutex_destroy(&card->vreader_mutex);
     qemu_mutex_destroy(&card->event_list_mutex);
diff --git a/hw/e1000.c b/hw/e1000.c
index 986ed9cf79..a29c944df4 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -507,7 +507,7 @@ txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp)
                 ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);
     dp->upper.data = cpu_to_le32(txd_upper);
     pci_dma_write(&s->dev, base + ((char *)&dp->upper - (char *)dp),
-                  (void *)&dp->upper, sizeof(dp->upper));
+                  &dp->upper, sizeof(dp->upper));
     return E1000_ICR_TXDW;
 }
 
@@ -534,7 +534,7 @@ start_xmit(E1000State *s)
     while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
         base = tx_desc_base(s) +
                sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
-        pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc));
+        pci_dma_read(&s->dev, base, &desc, sizeof(desc));
 
         DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],
                (void *)(intptr_t)desc.buffer_addr, desc.lower.data,
@@ -714,7 +714,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
             desc_size = s->rxbuf_size;
         }
         base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH];
-        pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc));
+        pci_dma_read(&s->dev, base, &desc, sizeof(desc));
         desc.special = vlan_special;
         desc.status |= (vlan_status | E1000_RXD_STAT_DD);
         if (desc.buffer_addr) {
@@ -724,8 +724,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
                     copy_size = s->rxbuf_size;
                 }
                 pci_dma_write(&s->dev, le64_to_cpu(desc.buffer_addr),
-                                 (void *)(buf + desc_offset + vlan_offset),
-                                 copy_size);
+                              buf + desc_offset + vlan_offset, copy_size);
             }
             desc_offset += desc_size;
             desc.length = cpu_to_le16(desc_size);
@@ -739,7 +738,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
         } else { // as per intel docs; skip descriptors with null buf addr
             DBGOUT(RX, "Null RX descriptor!!\n");
         }
-        pci_dma_write(&s->dev, base, (void *)&desc, sizeof(desc));
+        pci_dma_write(&s->dev, base, &desc, sizeof(desc));
 
         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
             s->mac_reg[RDH] = 0;
diff --git a/hw/eepro100.c b/hw/eepro100.c
index e430f56b29..6a162f607f 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -713,8 +713,7 @@ static void dump_statistics(EEPRO100State * s)
      * values which really matter.
      * Number of data should check configuration!!!
      */
-    pci_dma_write(&s->dev, s->statsaddr,
-                  (uint8_t *) &s->statistics, s->stats_size);
+    pci_dma_write(&s->dev, s->statsaddr, &s->statistics, s->stats_size);
     stl_le_pci_dma(&s->dev, s->statsaddr + 0,
                    s->statistics.tx_good_frames);
     stl_le_pci_dma(&s->dev, s->statsaddr + 36,
@@ -732,7 +731,7 @@ static void dump_statistics(EEPRO100State * s)
 
 static void read_cb(EEPRO100State *s)
 {
-    pci_dma_read(&s->dev, s->cb_address, (uint8_t *) &s->tx, sizeof(s->tx));
+    pci_dma_read(&s->dev, s->cb_address, &s->tx, sizeof(s->tx));
     s->tx.status = le16_to_cpu(s->tx.status);
     s->tx.command = le16_to_cpu(s->tx.command);
     s->tx.link = le32_to_cpu(s->tx.link);
@@ -1715,7 +1714,7 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
     /* !!! */
     eepro100_rx_t rx;
     pci_dma_read(&s->dev, s->ru_base + s->ru_offset,
-                 (uint8_t *) &rx, sizeof(eepro100_rx_t));
+                 &rx, sizeof(eepro100_rx_t));
     uint16_t rfd_command = le16_to_cpu(rx.command);
     uint16_t rfd_size = le16_to_cpu(rx.size);
 
diff --git a/hw/hw.h b/hw/hw.h
index ed20f5a27a..efa04d1340 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -27,7 +27,13 @@ typedef int (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
 typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf,
                                     int64_t pos, int size);
 
-/* Close a file and return an error code */
+/* Close a file
+ *
+ * Return negative error number on error, 0 or positive value on success.
+ *
+ * The meaning of return value on success depends on the specific back-end being
+ * used.
+ */
 typedef int (QEMUFileCloseFunc)(void *opaque);
 
 /* Called to determine if the file has exceeded it's bandwidth allocation.  The
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 5078c0b565..cb3de6537b 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -71,7 +71,7 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
             if (bm->cur_prd_last ||
                 (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
                 return s->io_buffer_size != 0;
-            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8);
+            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, &prd, 8);
             bm->cur_addr += 8;
             prd.addr = le32_to_cpu(prd.addr);
             prd.size = le32_to_cpu(prd.size);
@@ -113,7 +113,7 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write)
             if (bm->cur_prd_last ||
                 (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
                 return 0;
-            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8);
+            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, &prd, 8);
             bm->cur_addr += 8;
             prd.addr = le32_to_cpu(prd.addr);
             prd.size = le32_to_cpu(prd.size);
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index fcc27d726f..0d3a1016df 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -392,7 +392,7 @@ static inline uint32_t read_dword(LSIState *s, uint32_t addr)
 {
     uint32_t buf;
 
-    pci_dma_read(&s->dev, addr, (uint8_t *)&buf, 4);
+    pci_dma_read(&s->dev, addr, &buf, 4);
     return cpu_to_le32(buf);
 }
 
@@ -1079,7 +1079,7 @@ again:
 
             /* 32-bit Table indirect */
             offset = sxt24(addr);
-            pci_dma_read(&s->dev, s->dsa + offset, (uint8_t *)buf, 8);
+            pci_dma_read(&s->dev, s->dsa + offset, buf, 8);
             /* byte count is stored in bits 0:23 only */
             s->dbc = cpu_to_le32(buf[0]) & 0xffffff;
             s->rbc = s->dbc;
diff --git a/hw/mpcore.c b/hw/mpcore.c
deleted file mode 100644
index 4357d12217..0000000000
--- a/hw/mpcore.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * ARM MPCore internal peripheral emulation (common code).
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "sysbus.h"
-#include "qemu-timer.h"
-
-#define NCPU 4
-
-static inline int
-gic_get_current_cpu(void)
-{
-  return cpu_single_env->cpu_index;
-}
-
-#include "arm_gic.c"
-
-/* MPCore private memory region.  */
-
-typedef struct {
-    uint32_t count;
-    uint32_t load;
-    uint32_t control;
-    uint32_t status;
-    uint32_t old_status;
-    int64_t tick;
-    QEMUTimer *timer;
-    struct mpcore_priv_state *mpcore;
-    int id; /* Encodes both timer/watchdog and CPU.  */
-} mpcore_timer_state;
-
-typedef struct mpcore_priv_state {
-    gic_state gic;
-    uint32_t scu_control;
-    int iomemtype;
-    mpcore_timer_state timer[8];
-    uint32_t num_cpu;
-    MemoryRegion iomem;
-    MemoryRegion container;
-} mpcore_priv_state;
-
-/* Per-CPU Timers.  */
-
-static inline void mpcore_timer_update_irq(mpcore_timer_state *s)
-{
-    if (s->status & ~s->old_status) {
-        gic_set_pending_private(&s->mpcore->gic, s->id >> 1, 29 + (s->id & 1));
-    }
-    s->old_status = s->status;
-}
-
-/* Return conversion factor from mpcore timer ticks to qemu timer ticks.  */
-static inline uint32_t mpcore_timer_scale(mpcore_timer_state *s)
-{
-    return (((s->control >> 8) & 0xff) + 1) * 10;
-}
-
-static void mpcore_timer_reload(mpcore_timer_state *s, int restart)
-{
-    if (s->count == 0)
-        return;
-    if (restart)
-        s->tick = qemu_get_clock_ns(vm_clock);
-    s->tick += (int64_t)s->count * mpcore_timer_scale(s);
-    qemu_mod_timer(s->timer, s->tick);
-}
-
-static void mpcore_timer_tick(void *opaque)
-{
-    mpcore_timer_state *s = (mpcore_timer_state *)opaque;
-    s->status = 1;
-    if (s->control & 2) {
-        s->count = s->load;
-        mpcore_timer_reload(s, 0);
-    } else {
-        s->count = 0;
-    }
-    mpcore_timer_update_irq(s);
-}
-
-static uint32_t mpcore_timer_read(mpcore_timer_state *s, int offset)
-{
-    int64_t val;
-    switch (offset) {
-    case 0: /* Load */
-        return s->load;
-        /* Fall through.  */
-    case 4: /* Counter.  */
-        if (((s->control & 1) == 0) || (s->count == 0))
-            return 0;
-        /* Slow and ugly, but hopefully won't happen too often.  */
-        val = s->tick - qemu_get_clock_ns(vm_clock);
-        val /= mpcore_timer_scale(s);
-        if (val < 0)
-            val = 0;
-        return val;
-    case 8: /* Control.  */
-        return s->control;
-    case 12: /* Interrupt status.  */
-        return s->status;
-    default:
-        return 0;
-    }
-}
-
-static void mpcore_timer_write(mpcore_timer_state *s, int offset,
-                               uint32_t value)
-{
-    int64_t old;
-    switch (offset) {
-    case 0: /* Load */
-        s->load = value;
-        /* Fall through.  */
-    case 4: /* Counter.  */
-        if ((s->control & 1) && s->count) {
-            /* Cancel the previous timer.  */
-            qemu_del_timer(s->timer);
-        }
-        s->count = value;
-        if (s->control & 1) {
-            mpcore_timer_reload(s, 1);
-        }
-        break;
-    case 8: /* Control.  */
-        old = s->control;
-        s->control = value;
-        if (((old & 1) == 0) && (value & 1)) {
-            if (s->count == 0 && (s->control & 2))
-                s->count = s->load;
-            mpcore_timer_reload(s, 1);
-        }
-        break;
-    case 12: /* Interrupt status.  */
-        s->status &= ~value;
-        mpcore_timer_update_irq(s);
-        break;
-    }
-}
-
-static void mpcore_timer_init(mpcore_priv_state *mpcore,
-                              mpcore_timer_state *s, int id)
-{
-    s->id = id;
-    s->mpcore = mpcore;
-    s->timer = qemu_new_timer_ns(vm_clock, mpcore_timer_tick, s);
-}
-
-
-/* Per-CPU private memory mapped IO.  */
-
-static uint64_t mpcore_priv_read(void *opaque, target_phys_addr_t offset,
-                                 unsigned size)
-{
-    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
-    int id;
-    offset &= 0xfff;
-    if (offset < 0x100) {
-        /* SCU */
-        switch (offset) {
-        case 0x00: /* Control.  */
-            return s->scu_control;
-        case 0x04: /* Configuration.  */
-            id = ((1 << s->num_cpu) - 1) << 4;
-            return id | (s->num_cpu - 1);
-        case 0x08: /* CPU status.  */
-            return 0;
-        case 0x0c: /* Invalidate all.  */
-            return 0;
-        default:
-            goto bad_reg;
-        }
-    } else if (offset < 0x600) {
-        /* Interrupt controller.  */
-        if (offset < 0x200) {
-            id = gic_get_current_cpu();
-        } else {
-            id = (offset - 0x200) >> 8;
-            if (id >= s->num_cpu) {
-                return 0;
-            }
-        }
-        return gic_cpu_read(&s->gic, id, offset & 0xff);
-    } else if (offset < 0xb00) {
-        /* Timers.  */
-        if (offset < 0x700) {
-            id = gic_get_current_cpu();
-        } else {
-            id = (offset - 0x700) >> 8;
-            if (id >= s->num_cpu) {
-                return 0;
-            }
-        }
-        id <<= 1;
-        if (offset & 0x20)
-          id++;
-        return mpcore_timer_read(&s->timer[id], offset & 0xf);
-    }
-bad_reg:
-    hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
-    return 0;
-}
-
-static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
-                              uint64_t value, unsigned size)
-{
-    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
-    int id;
-    offset &= 0xfff;
-    if (offset < 0x100) {
-        /* SCU */
-        switch (offset) {
-        case 0: /* Control register.  */
-            s->scu_control = value & 1;
-            break;
-        case 0x0c: /* Invalidate all.  */
-            /* This is a no-op as cache is not emulated.  */
-            break;
-        default:
-            goto bad_reg;
-        }
-    } else if (offset < 0x600) {
-        /* Interrupt controller.  */
-        if (offset < 0x200) {
-            id = gic_get_current_cpu();
-        } else {
-            id = (offset - 0x200) >> 8;
-        }
-        if (id < s->num_cpu) {
-            gic_cpu_write(&s->gic, id, offset & 0xff, value);
-        }
-    } else if (offset < 0xb00) {
-        /* Timers.  */
-        if (offset < 0x700) {
-            id = gic_get_current_cpu();
-        } else {
-            id = (offset - 0x700) >> 8;
-        }
-        if (id < s->num_cpu) {
-            id <<= 1;
-            if (offset & 0x20)
-              id++;
-            mpcore_timer_write(&s->timer[id], offset & 0xf, value);
-        }
-        return;
-    }
-    return;
-bad_reg:
-    hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
-}
-
-static const MemoryRegionOps mpcore_priv_ops = {
-    .read = mpcore_priv_read,
-    .write = mpcore_priv_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mpcore_priv_map_setup(mpcore_priv_state *s)
-{
-    memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
-    memory_region_init_io(&s->iomem, &mpcore_priv_ops, s, "mpcode-priv",
-                          0x1000);
-    memory_region_add_subregion(&s->container, 0, &s->iomem);
-    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
-}
-
-static int mpcore_priv_init(SysBusDevice *dev)
-{
-    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
-    int i;
-
-    gic_init(&s->gic, s->num_cpu);
-    mpcore_priv_map_setup(s);
-    sysbus_init_mmio(dev, &s->container);
-    for (i = 0; i < s->num_cpu * 2; i++) {
-        mpcore_timer_init(s, &s->timer[i], i);
-    }
-    return 0;
-}
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 479f939553..8c4d509ee7 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -23,36 +23,13 @@ gic_get_current_cpu(void)
 
 typedef struct {
     gic_state gic;
-    MemoryRegion iomem;
     MemoryRegion container;
 } RealViewGICState;
 
-static uint64_t realview_gic_cpu_read(void *opaque, target_phys_addr_t offset,
-                                      unsigned size)
-{
-    gic_state *s = (gic_state *)opaque;
-    return gic_cpu_read(s, gic_get_current_cpu(), offset);
-}
-
-static void realview_gic_cpu_write(void *opaque, target_phys_addr_t offset,
-                                   uint64_t value, unsigned size)
-{
-    gic_state *s = (gic_state *)opaque;
-    gic_cpu_write(s, gic_get_current_cpu(), offset, value);
-}
-
-static const MemoryRegionOps realview_gic_cpu_ops = {
-    .read = realview_gic_cpu_read,
-    .write = realview_gic_cpu_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
 static void realview_gic_map_setup(RealViewGICState *s)
 {
     memory_region_init(&s->container, "realview-gic-container", 0x2000);
-    memory_region_init_io(&s->iomem, &realview_gic_cpu_ops, &s->gic,
-                          "realview-gic", 0x1000);
-    memory_region_add_subregion(&s->container, 0, &s->iomem);
+    memory_region_add_subregion(&s->container, 0, &s->gic.cpuiomem[0]);
     memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
 }
 
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 8aace9a4ec..0ae9f5774b 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -991,13 +991,13 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
 
-        pci_dma_read(&s->dev, cplus_rx_ring_desc, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc, &val, 4);
         rxdw0 = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+4, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+4, &val, 4);
         rxdw1 = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+8, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+8, &val, 4);
         rxbufLO = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+12, (uint8_t *)&val, 4);
+        pci_dma_read(&s->dev, cplus_rx_ring_desc+12, &val, 4);
         rxbufHI = le32_to_cpu(val);
 
         DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
diff --git a/hw/syborg.c b/hw/syborg.c
deleted file mode 100644
index 248de54c4e..0000000000
--- a/hw/syborg.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Syborg (Symbian Virtual Platform) reference board
- *
- * Copyright (c) 2009 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "boards.h"
-#include "arm-misc.h"
-#include "net.h"
-#include "exec-memory.h"
-
-static struct arm_boot_info syborg_binfo;
-
-static void syborg_init(ram_addr_t ram_size,
-                        const char *boot_device,
-                        const char *kernel_filename, const char *kernel_cmdline,
-                        const char *initrd_filename, const char *cpu_model)
-{
-    CPUState *env;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_pic;
-    qemu_irq pic[64];
-    DeviceState *dev;
-    int i;
-
-    if (!cpu_model)
-        cpu_model = "cortex-a8";
-    env = cpu_init(cpu_model);
-    if (!env) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-
-    /* RAM at address zero. */
-    memory_region_init_ram(ram, NULL, "syborg.ram", ram_size);
-    memory_region_add_subregion(sysmem, 0, ram);
-
-    cpu_pic = arm_pic_init_cpu(env);
-    dev = sysbus_create_simple("syborg,interrupt", 0xC0000000,
-                               cpu_pic[ARM_PIC_CPU_IRQ]);
-    for (i = 0; i < 64; i++) {
-        pic[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    sysbus_create_simple("syborg,rtc", 0xC0001000, NULL);
-
-    dev = qdev_create(NULL, "syborg,timer");
-    qdev_prop_set_uint32(dev, "frequency", 1000000);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xC0002000);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[1]);
-
-    sysbus_create_simple("syborg,keyboard", 0xC0003000, pic[2]);
-    sysbus_create_simple("syborg,pointer", 0xC0004000, pic[3]);
-    sysbus_create_simple("syborg,framebuffer", 0xC0005000, pic[4]);
-    sysbus_create_simple("syborg,serial", 0xC0006000, pic[5]);
-    sysbus_create_simple("syborg,serial", 0xC0007000, pic[6]);
-    sysbus_create_simple("syborg,serial", 0xC0008000, pic[7]);
-    sysbus_create_simple("syborg,serial", 0xC0009000, pic[8]);
-
-    if (nd_table[0].vlan || nd_table[0].netdev) {
-        DeviceState *dev;
-        SysBusDevice *s;
-
-        qemu_check_nic_model(&nd_table[0], "virtio");
-        dev = qdev_create(NULL, "syborg,virtio-net");
-        qdev_set_nic_properties(dev, &nd_table[0]);
-        qdev_init_nofail(dev);
-        s = sysbus_from_qdev(dev);
-        sysbus_mmio_map(s, 0, 0xc000c000);
-        sysbus_connect_irq(s, 0, pic[9]);
-    }
-
-    syborg_binfo.ram_size = ram_size;
-    syborg_binfo.kernel_filename = kernel_filename;
-    syborg_binfo.kernel_cmdline = kernel_cmdline;
-    syborg_binfo.initrd_filename = initrd_filename;
-    syborg_binfo.board_id = 0;
-    arm_load_kernel(env, &syborg_binfo);
-}
-
-static QEMUMachine syborg_machine = {
-    .name = "syborg",
-    .desc = "Syborg (Symbian Virtual Platform)",
-    .init = syborg_init,
-};
-
-static void syborg_machine_init(void)
-{
-    qemu_register_machine(&syborg_machine);
-}
-
-machine_init(syborg_machine_init);
diff --git a/hw/syborg.h b/hw/syborg.h
deleted file mode 100644
index b82ce4a502..0000000000
--- a/hw/syborg.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _SYBORG_H
-#define _SYBORG_H
-
-#define SYBORG_ID_PLATFORM    0xc51d1000
-#define SYBORG_ID_INT         0xc51d0000
-#define SYBORG_ID_SERIAL      0xc51d0001
-#define SYBORG_ID_KEYBOARD    0xc51d0002
-#define SYBORG_ID_TIMER       0xc51d0003
-#define SYBORG_ID_RTC         0xc51d0004
-#define SYBORG_ID_MOUSE       0xc51d0005
-#define SYBORG_ID_TOUCHSCREEN 0xc51d0006
-#define SYBORG_ID_FRAMEBUFFER 0xc51d0007
-#define SYBORG_ID_HOSTFS      0xc51d0008
-#define SYBORG_ID_SNAPSHOT    0xc51d0009
-#define SYBORG_ID_VIRTIO      0xc51d000a
-#define SYBORG_ID_NAND        0xc51d000b
-
-#endif
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
deleted file mode 100644
index b87d7e6d10..0000000000
--- a/hw/syborg_fb.c
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * Syborg Framebuffer
- *
- * Copyright (c) 2009 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "console.h"
-#include "syborg.h"
-#include "framebuffer.h"
-
-//#define DEBUG_SYBORG_FB
-
-#ifdef DEBUG_SYBORG_FB
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_fb: " fmt , ## __VA_ARGS__); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
-    FB_ID               = 0,
-    FB_BASE             = 1,
-    FB_HEIGHT           = 2,
-    FB_WIDTH            = 3,
-    FB_ORIENTATION      = 4,
-    FB_BLANK            = 5,
-    FB_INT_MASK         = 6,
-    FB_INTERRUPT_CAUSE  = 7,
-    FB_BPP              = 8,
-    FB_COLOR_ORDER      = 9,
-    FB_BYTE_ORDER       = 10,
-    FB_PIXEL_ORDER      = 11,
-    FB_ROW_PITCH        = 12,
-    FB_ENABLED          = 13,
-    FB_PALETTE_START    = 0x400 >> 2,
-    FB_PALETTE_END   = FB_PALETTE_START+256-1,
-};
-
-#define FB_INT_VSYNC            (1U << 0)
-#define FB_INT_BASE_UPDATE_DONE (1U << 1)
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    DisplayState *ds;
-    /*QEMUConsole *console;*/
-    uint32_t need_update : 1;
-    uint32_t need_int : 1;
-    uint32_t enabled : 1;
-    uint32_t int_status;
-    uint32_t int_enable;
-    qemu_irq irq;
-
-    uint32_t base;
-    uint32_t pitch;
-    uint32_t rows;
-    uint32_t cols;
-    int blank;
-    int bpp;
-    int rgb; /* 0 = BGR, 1 = RGB */
-    int endian; /* 0 = Little, 1 = Big */
-    uint32_t raw_palette[256];
-    uint32_t palette[256];
-} SyborgFBState;
-
-enum {
-    BPP_SRC_1,
-    BPP_SRC_2,
-    BPP_SRC_4,
-    BPP_SRC_8,
-    BPP_SRC_16,
-    BPP_SRC_32,
-    /* TODO: Implement these.  */
-    BPP_SRC_15 = -1,
-    BPP_SRC_24 = -2
-};
-
-#include "pixel_ops.h"
-
-#define BITS 8
-#include "pl110_template.h"
-#define BITS 15
-#include "pl110_template.h"
-#define BITS 16
-#include "pl110_template.h"
-#define BITS 24
-#include "pl110_template.h"
-#define BITS 32
-#include "pl110_template.h"
-
-/* Update interrupts.  */
-static void syborg_fb_update(SyborgFBState *s)
-{
-    if ((s->int_status & s->int_enable) != 0) {
-        DPRINTF("Raise IRQ\n");
-        qemu_irq_raise(s->irq);
-    } else {
-        DPRINTF("Lower IRQ\n");
-        qemu_irq_lower(s->irq);
-    }
-}
-
-static int syborg_fb_enabled(const SyborgFBState *s)
-{
-    return s->enabled;
-}
-
-static void syborg_fb_update_palette(SyborgFBState *s)
-{
-    int n, i;
-    uint32_t raw;
-    unsigned int r, g, b;
-
-    switch (s->bpp) {
-    case BPP_SRC_1: n = 2; break;
-    case BPP_SRC_2: n = 4; break;
-    case BPP_SRC_4: n = 16; break;
-    case BPP_SRC_8: n = 256; break;
-    default: return;
-    }
-
-    for (i = 0; i < n; i++) {
-        raw = s->raw_palette[i];
-        r = (raw >> 16) & 0xff;
-        g = (raw >> 8) & 0xff;
-        b = raw & 0xff;
-        switch (ds_get_bits_per_pixel(s->ds)) {
-        case 8:
-            s->palette[i] = rgb_to_pixel8(r, g, b);
-            break;
-        case 15:
-            s->palette[i] = rgb_to_pixel15(r, g, b);
-            break;
-        case 16:
-            s->palette[i] = rgb_to_pixel16(r, g, b);
-            break;
-        case 24:
-        case 32:
-            s->palette[i] = rgb_to_pixel32(r, g, b);
-            break;
-        default:
-            abort();
-        }
-    }
-
-}
-
-static void syborg_fb_update_display(void *opaque)
-{
-    SyborgFBState *s = (SyborgFBState *)opaque;
-    drawfn* fntable;
-    drawfn fn;
-    int dest_width;
-    int src_width;
-    int bpp_offset;
-    int first;
-    int last;
-
-    if (!syborg_fb_enabled(s))
-        return;
-
-    switch (ds_get_bits_per_pixel(s->ds)) {
-    case 0:
-        return;
-    case 8:
-        fntable = pl110_draw_fn_8;
-        dest_width = 1;
-        break;
-    case 15:
-        fntable = pl110_draw_fn_15;
-        dest_width = 2;
-        break;
-    case 16:
-        fntable = pl110_draw_fn_16;
-        dest_width = 2;
-        break;
-    case 24:
-        fntable = pl110_draw_fn_24;
-        dest_width = 3;
-        break;
-    case 32:
-        fntable = pl110_draw_fn_32;
-        dest_width = 4;
-        break;
-    default:
-        fprintf(stderr, "syborg_fb: Bad color depth\n");
-        exit(1);
-    }
-
-    if (s->need_int) {
-        s->int_status |= FB_INT_BASE_UPDATE_DONE;
-        syborg_fb_update(s);
-        s->need_int = 0;
-    }
-
-    if (s->rgb) {
-        bpp_offset = 24;
-    } else {
-        bpp_offset = 0;
-    }
-    if (s->endian) {
-        bpp_offset += 8;
-    }
-    /* Our bpp constants mostly match the PL110/PL111 but
-     * not for the 16 bit case
-     */
-    switch (s->bpp) {
-    case BPP_SRC_16:
-        bpp_offset += 6;
-        break;
-    default:
-        bpp_offset += s->bpp;
-    }
-    fn = fntable[bpp_offset];
-
-    if (s->pitch) {
-        src_width = s->pitch;
-    } else {
-        src_width = s->cols;
-        switch (s->bpp) {
-        case BPP_SRC_1:
-            src_width >>= 3;
-            break;
-        case BPP_SRC_2:
-            src_width >>= 2;
-            break;
-        case BPP_SRC_4:
-            src_width >>= 1;
-            break;
-        case BPP_SRC_8:
-            break;
-        case BPP_SRC_15:
-        case BPP_SRC_16:
-            src_width <<= 1;
-            break;
-        case BPP_SRC_24:
-            src_width *= 3;
-            break;
-        case BPP_SRC_32:
-            src_width <<= 2;
-            break;
-        }
-    }
-    dest_width *= s->cols;
-    first = 0;
-    /* TODO: Implement blanking.  */
-    if (!s->blank) {
-        if (s->need_update && s->bpp <= BPP_SRC_8) {
-            syborg_fb_update_palette(s);
-        }
-        framebuffer_update_display(s->ds,
-                                   s->base, s->cols, s->rows,
-                                   src_width, dest_width, 0,
-                                   s->need_update,
-                                   fn, s->palette,
-                                   &first, &last);
-        if (first >= 0) {
-            dpy_update(s->ds, 0, first, s->cols, last - first + 1);
-        }
-
-        s->int_status |= FB_INT_VSYNC;
-        syborg_fb_update(s);
-    }
-
-    s->need_update = 0;
-}
-
-static void syborg_fb_invalidate_display(void * opaque)
-{
-    SyborgFBState *s = (SyborgFBState *)opaque;
-    s->need_update = 1;
-}
-
-static uint64_t syborg_fb_read(void *opaque, target_phys_addr_t offset,
-                               unsigned size)
-{
-    SyborgFBState *s = opaque;
-
-    DPRINTF("read reg %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case FB_ID:
-        return SYBORG_ID_FRAMEBUFFER;
-
-    case FB_BASE:
-        return s->base;
-
-    case FB_HEIGHT:
-        return s->rows;
-
-    case FB_WIDTH:
-        return s->cols;
-
-    case FB_ORIENTATION:
-        return 0;
-
-    case FB_BLANK:
-        return s->blank;
-
-    case FB_INT_MASK:
-        return s->int_enable;
-
-    case FB_INTERRUPT_CAUSE:
-        return s->int_status;
-
-    case FB_BPP:
-        switch (s->bpp) {
-        case BPP_SRC_1: return 1;
-        case BPP_SRC_2: return 2;
-        case BPP_SRC_4: return 4;
-        case BPP_SRC_8: return 8;
-        case BPP_SRC_15: return 15;
-        case BPP_SRC_16: return 16;
-        case BPP_SRC_24: return 24;
-        case BPP_SRC_32: return 32;
-        default: return 0;
-        }
-
-    case FB_COLOR_ORDER:
-        return s->rgb;
-
-    case FB_BYTE_ORDER:
-        return s->endian;
-
-    case FB_PIXEL_ORDER:
-        return 0;
-
-    case FB_ROW_PITCH:
-        return s->pitch;
-
-    case FB_ENABLED:
-        return s->enabled;
-
-    default:
-        if ((offset >> 2) >= FB_PALETTE_START
-            && (offset >> 2) <= FB_PALETTE_END) {
-            return s->raw_palette[(offset >> 2) - FB_PALETTE_START];
-        } else {
-            cpu_abort (cpu_single_env, "syborg_fb_read: Bad offset %x\n",
-                         (int)offset);
-        }
-        return 0;
-    }
-}
-
-static void syborg_fb_write(void *opaque, target_phys_addr_t offset,
-                            uint64_t val, unsigned size)
-{
-    SyborgFBState *s = opaque;
-
-    DPRINTF("write reg %d = %d\n", (int)offset, val);
-    s->need_update = 1;
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case FB_BASE:
-        s->base = val;
-        s->need_int = 1;
-        s->need_update = 1;
-        syborg_fb_update(s);
-        break;
-
-    case FB_HEIGHT:
-        s->rows = val;
-        break;
-
-    case FB_WIDTH:
-        s->cols = val;
-        break;
-
-    case FB_ORIENTATION:
-        /* TODO: Implement rotation.  */
-        break;
-
-    case FB_BLANK:
-        s->blank = val & 1;
-        break;
-
-    case FB_INT_MASK:
-        s->int_enable = val;
-        syborg_fb_update(s);
-        break;
-
-    case FB_INTERRUPT_CAUSE:
-        s->int_status &= ~val;
-        syborg_fb_update(s);
-        break;
-
-    case FB_BPP:
-        switch (val) {
-        case 1: val = BPP_SRC_1; break;
-        case 2: val = BPP_SRC_2; break;
-        case 4: val = BPP_SRC_4; break;
-        case 8: val = BPP_SRC_8; break;
-        /* case 15: val = BPP_SRC_15; break; */
-        case 16: val = BPP_SRC_16; break;
-        /* case 24: val = BPP_SRC_24; break; */
-        case 32: val = BPP_SRC_32; break;
-        default: val = s->bpp; break;
-        }
-        s->bpp = val;
-        break;
-
-    case FB_COLOR_ORDER:
-        s->rgb = (val != 0);
-        break;
-
-    case FB_BYTE_ORDER:
-        s->endian = (val != 0);
-        break;
-
-    case FB_PIXEL_ORDER:
-        /* TODO: Implement this.  */
-        break;
-
-    case FB_ROW_PITCH:
-        s->pitch = val;
-        break;
-
-    case FB_ENABLED:
-        s->enabled = val;
-        break;
-
-    default:
-        if ((offset >> 2) >= FB_PALETTE_START
-            && (offset >> 2) <= FB_PALETTE_END) {
-            s->raw_palette[(offset >> 2) - FB_PALETTE_START] = val;
-        } else {
-            cpu_abort (cpu_single_env, "syborg_fb_write: Bad offset %x\n",
-                      (int)offset);
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps syborg_fb_ops = {
-    .read = syborg_fb_read,
-    .write = syborg_fb_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_fb_save(QEMUFile *f, void *opaque)
-{
-    SyborgFBState *s = opaque;
-    int i;
-
-    qemu_put_be32(f, s->need_int);
-    qemu_put_be32(f, s->int_status);
-    qemu_put_be32(f, s->int_enable);
-    qemu_put_be32(f, s->enabled);
-    qemu_put_be32(f, s->base);
-    qemu_put_be32(f, s->pitch);
-    qemu_put_be32(f, s->rows);
-    qemu_put_be32(f, s->cols);
-    qemu_put_be32(f, s->bpp);
-    qemu_put_be32(f, s->rgb);
-    for (i = 0; i < 256; i++) {
-        qemu_put_be32(f, s->raw_palette[i]);
-    }
-}
-
-static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgFBState *s = opaque;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->need_int = qemu_get_be32(f);
-    s->int_status = qemu_get_be32(f);
-    s->int_enable = qemu_get_be32(f);
-    s->enabled = qemu_get_be32(f);
-    s->base = qemu_get_be32(f);
-    s->pitch = qemu_get_be32(f);
-    s->rows = qemu_get_be32(f);
-    s->cols = qemu_get_be32(f);
-    s->bpp = qemu_get_be32(f);
-    s->rgb = qemu_get_be32(f);
-    for (i = 0; i < 256; i++) {
-        s->raw_palette[i] = qemu_get_be32(f);
-    }
-    s->need_update = 1;
-
-    return 0;
-}
-
-static int syborg_fb_init(SysBusDevice *dev)
-{
-    SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_fb_ops, s,
-                          "framebuffer", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    s->ds = graphic_console_init(syborg_fb_update_display,
-                                 syborg_fb_invalidate_display,
-                                 NULL, NULL, s);
-
-    if (s->cols != 0 && s->rows != 0) {
-        qemu_console_resize(s->ds, s->cols, s->rows);
-    }
-
-    if (!s->cols)
-        s->cols = ds_get_width(s->ds);
-    if (!s->rows)
-        s->rows = ds_get_height(s->ds);
-
-    register_savevm(&dev->qdev, "syborg_framebuffer", -1, 1,
-                    syborg_fb_save, syborg_fb_load, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_fb_info = {
-    .init = syborg_fb_init,
-    .qdev.name  = "syborg,framebuffer",
-    .qdev.size  = sizeof(SyborgFBState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("width",  SyborgFBState, cols, 0),
-        DEFINE_PROP_UINT32("height", SyborgFBState, rows, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_fb_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_fb_info);
-}
-
-device_init(syborg_fb_register_devices)
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
deleted file mode 100644
index 93e81c8660..0000000000
--- a/hw/syborg_interrupt.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Syborg interrupt controller.
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "syborg.h"
-
-//#define DEBUG_SYBORG_INT
-
-#ifdef DEBUG_SYBORG_INT
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_int: " fmt , ## __VA_ARGS__); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_int: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_int: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-enum {
-    INT_ID            = 0,
-    INT_STATUS        = 1, /* number of pending interrupts */
-    INT_CURRENT       = 2, /* next interrupt to be serviced */
-    INT_DISABLE_ALL   = 3,
-    INT_DISABLE       = 4,
-    INT_ENABLE        = 5,
-    INT_TOTAL         = 6
-};
-
-typedef struct {
-    unsigned level:1;
-    unsigned enabled:1;
-} syborg_int_flags;
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    int pending_count;
-    uint32_t num_irqs;
-    syborg_int_flags *flags;
-    qemu_irq parent_irq;
-} SyborgIntState;
-
-static void syborg_int_update(SyborgIntState *s)
-{
-    DPRINTF("pending %d\n", s->pending_count);
-    qemu_set_irq(s->parent_irq, s->pending_count > 0);
-}
-
-static void syborg_int_set_irq(void *opaque, int irq, int level)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-
-    if (s->flags[irq].level == level)
-        return;
-
-    s->flags[irq].level = level;
-    if (s->flags[irq].enabled) {
-        if (level)
-            s->pending_count++;
-        else
-            s->pending_count--;
-        syborg_int_update(s);
-    }
-}
-
-static uint64_t syborg_int_read(void *opaque, target_phys_addr_t offset,
-                                unsigned size)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-    int i;
-
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case INT_ID:
-        return SYBORG_ID_INT;
-    case INT_STATUS:
-        DPRINTF("read status=%d\n", s->pending_count);
-        return s->pending_count;
-
-    case INT_CURRENT:
-        for (i = 0; i < s->num_irqs; i++) {
-            if (s->flags[i].level & s->flags[i].enabled) {
-                DPRINTF("read current=%d\n", i);
-                return i;
-            }
-        }
-        DPRINTF("read current=none\n");
-        return 0xffffffffu;
-
-    default:
-        cpu_abort(cpu_single_env, "syborg_int_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_int_write(void *opaque, target_phys_addr_t offset,
-                             uint64_t value, unsigned size)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-    int i;
-    offset &= 0xfff;
-
-    DPRINTF("syborg_int_write offset=%d val=%d\n", (int)offset, (int)value);
-    switch (offset >> 2) {
-    case INT_DISABLE_ALL:
-        s->pending_count = 0;
-        for (i = 0; i < s->num_irqs; i++)
-            s->flags[i].enabled = 0;
-        break;
-
-    case INT_DISABLE:
-        if (value >= s->num_irqs)
-            break;
-        if (s->flags[value].enabled) {
-            if (s->flags[value].enabled)
-                s->pending_count--;
-            s->flags[value].enabled = 0;
-        }
-        break;
-
-    case INT_ENABLE:
-      if (value >= s->num_irqs)
-          break;
-      if (!(s->flags[value].enabled)) {
-          if(s->flags[value].level)
-              s->pending_count++;
-          s->flags[value].enabled = 1;
-      }
-      break;
-
-    default:
-        cpu_abort(cpu_single_env, "syborg_int_write: Bad offset %x\n",
-                  (int)offset);
-        return;
-    }
-    syborg_int_update(s);
-}
-
-static const MemoryRegionOps syborg_int_ops = {
-    .read = syborg_int_read,
-    .write = syborg_int_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_int_save(QEMUFile *f, void *opaque)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-    int i;
-
-    qemu_put_be32(f, s->num_irqs);
-    qemu_put_be32(f, s->pending_count);
-    for (i = 0; i < s->num_irqs; i++) {
-        qemu_put_be32(f, s->flags[i].enabled
-                         | ((unsigned)s->flags[i].level << 1));
-    }
-}
-
-static int syborg_int_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgIntState *s = (SyborgIntState *)opaque;
-    uint32_t val;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    val = qemu_get_be32(f);
-    if (val != s->num_irqs)
-        return -EINVAL;
-    s->pending_count = qemu_get_be32(f);
-    for (i = 0; i < s->num_irqs; i++) {
-        val = qemu_get_be32(f);
-        s->flags[i].enabled = val & 1;
-        s->flags[i].level = (val >> 1) & 1;
-    }
-    return 0;
-}
-
-static int syborg_int_init(SysBusDevice *dev)
-{
-    SyborgIntState *s = FROM_SYSBUS(SyborgIntState, dev);
-
-    sysbus_init_irq(dev, &s->parent_irq);
-    qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs);
-    memory_region_init_io(&s->iomem, &syborg_int_ops, s,
-                          "interrupt", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    s->flags = g_malloc0(s->num_irqs * sizeof(syborg_int_flags));
-
-    register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save,
-                    syborg_int_load, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_int_info = {
-    .init = syborg_int_init,
-    .qdev.name  = "syborg,interrupt",
-    .qdev.size  = sizeof(SyborgIntState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("num-interrupts", SyborgIntState, num_irqs, 64),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_interrupt_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_int_info);
-}
-
-device_init(syborg_interrupt_register_devices)
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
deleted file mode 100644
index 942a7dc800..0000000000
--- a/hw/syborg_keyboard.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Syborg keyboard controller.
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "console.h"
-#include "syborg.h"
-
-//#define DEBUG_SYBORG_KEYBOARD
-
-#ifdef DEBUG_SYBORG_KEYBOARD
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_keyboard: " fmt , ##args); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \
-} while (0)
-#endif
-
-enum {
-    KBD_ID          = 0,
-    KBD_DATA        = 1,
-    KBD_FIFO_COUNT  = 2,
-    KBD_INT_ENABLE  = 3,
-    KBD_FIFO_SIZE   = 4
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t int_enabled;
-    int extension_bit;
-    uint32_t fifo_size;
-    uint32_t *key_fifo;
-    uint32_t read_pos, read_count;
-    qemu_irq irq;
-} SyborgKeyboardState;
-
-static void syborg_keyboard_update(SyborgKeyboardState *s)
-{
-    int level = s->read_count && s->int_enabled;
-    DPRINTF("Update IRQ %d\n", level);
-    qemu_set_irq(s->irq, level);
-}
-
-static uint64_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset,
-                                    unsigned size)
-{
-    SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
-    int c;
-
-    DPRINTF("reg read %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case KBD_ID:
-        return SYBORG_ID_KEYBOARD;
-    case KBD_FIFO_COUNT:
-        return s->read_count;
-    case KBD_DATA:
-        if (s->read_count == 0) {
-            c = -1;
-            DPRINTF("FIFO underflow\n");
-        } else {
-            c = s->key_fifo[s->read_pos];
-            DPRINTF("FIFO read 0x%x\n", c);
-            s->read_count--;
-            s->read_pos++;
-            if (s->read_pos == s->fifo_size)
-                s->read_pos = 0;
-        }
-        syborg_keyboard_update(s);
-        return c;
-    case KBD_INT_ENABLE:
-        return s->int_enabled;
-    case KBD_FIFO_SIZE:
-        return s->fifo_size;
-    default:
-        cpu_abort(cpu_single_env, "syborg_keyboard_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset,
-                                  uint64_t value, unsigned size)
-{
-    SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
-
-    DPRINTF("reg write %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case KBD_INT_ENABLE:
-        s->int_enabled = value;
-        syborg_keyboard_update(s);
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_keyboard_write: Bad offset %x\n",
-                  (int)offset);
-    }
-}
-
-static const MemoryRegionOps syborg_keyboard_ops = {
-    .read = syborg_keyboard_read,
-    .write = syborg_keyboard_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_keyboard_event(void *opaque, int keycode)
-{
-    SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
-    int slot;
-    uint32_t val;
-
-    /* Strip off 0xe0 prefixes and reconstruct the full scancode.  */
-    if (keycode == 0xe0 && !s->extension_bit) {
-        DPRINTF("Extension bit\n");
-        s->extension_bit = 0x80;
-        return;
-    }
-    val = (keycode & 0x7f) | s->extension_bit;
-    if (keycode & 0x80)
-        val |= 0x80000000u;
-    s->extension_bit = 0;
-
-    DPRINTF("FIFO push 0x%x\n", val);
-    slot = s->read_pos + s->read_count;
-    if (slot >= s->fifo_size)
-        slot -= s->fifo_size;
-
-    if (s->read_count < s->fifo_size) {
-        s->read_count++;
-        s->key_fifo[slot] = val;
-    } else {
-        fprintf(stderr, "syborg_keyboard error! FIFO overflow\n");
-    }
-
-    syborg_keyboard_update(s);
-}
-
-static const VMStateDescription vmstate_syborg_keyboard = {
-    .name = "syborg_keyboard",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_EQUAL(fifo_size, SyborgKeyboardState),
-        VMSTATE_UINT32(int_enabled, SyborgKeyboardState),
-        VMSTATE_UINT32(read_pos, SyborgKeyboardState),
-        VMSTATE_UINT32(read_count, SyborgKeyboardState),
-        VMSTATE_VARRAY_UINT32(key_fifo, SyborgKeyboardState, fifo_size, 1,
-                              vmstate_info_uint32, uint32),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_keyboard_init(SysBusDevice *dev)
-{
-    SyborgKeyboardState *s = FROM_SYSBUS(SyborgKeyboardState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_keyboard_ops, s,
-                              "keyboard", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    if (s->fifo_size <= 0) {
-        fprintf(stderr, "syborg_keyboard: fifo too small\n");
-        s->fifo_size = 16;
-    }
-    s->key_fifo = g_malloc0(s->fifo_size * sizeof(s->key_fifo[0]));
-
-    qemu_add_kbd_event_handler(syborg_keyboard_event, s);
-
-    vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_keyboard_info = {
-    .init = syborg_keyboard_init,
-    .qdev.name  = "syborg,keyboard",
-    .qdev.size  = sizeof(SyborgKeyboardState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("fifo-size", SyborgKeyboardState, fifo_size, 16),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_keyboard_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_keyboard_info);
-}
-
-device_init(syborg_keyboard_register_devices)
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
deleted file mode 100644
index bb75fa42c8..0000000000
--- a/hw/syborg_pointer.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Syborg pointing device (mouse/touchscreen)
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "console.h"
-#include "syborg.h"
-
-enum {
-    POINTER_ID          = 0,
-    POINTER_LATCH       = 1,
-    POINTER_FIFO_COUNT  = 2,
-    POINTER_X           = 3,
-    POINTER_Y           = 4,
-    POINTER_Z           = 5,
-    POINTER_BUTTONS     = 6,
-    POINTER_INT_ENABLE  = 7,
-    POINTER_FIFO_SIZE   = 8
-};
-
-typedef struct {
-    int x, y, z, pointer_buttons;
-} event_data;
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    int int_enabled;
-    uint32_t fifo_size;
-    event_data *event_fifo;
-    int read_pos, read_count;
-    qemu_irq irq;
-    uint32_t absolute;
-} SyborgPointerState;
-
-static void syborg_pointer_update(SyborgPointerState *s)
-{
-    qemu_set_irq(s->irq, s->read_count && s->int_enabled);
-}
-
-static uint64_t syborg_pointer_read(void *opaque, target_phys_addr_t offset,
-                                    unsigned size)
-{
-    SyborgPointerState *s = (SyborgPointerState *)opaque;
-
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case POINTER_ID:
-        return s->absolute ? SYBORG_ID_TOUCHSCREEN : SYBORG_ID_MOUSE;
-    case POINTER_FIFO_COUNT:
-        return s->read_count;
-    case POINTER_X:
-        return s->event_fifo[s->read_pos].x;
-    case POINTER_Y:
-        return s->event_fifo[s->read_pos].y;
-    case POINTER_Z:
-        return s->event_fifo[s->read_pos].z;
-    case POINTER_BUTTONS:
-        return s->event_fifo[s->read_pos].pointer_buttons;
-    case POINTER_INT_ENABLE:
-        return s->int_enabled;
-    case POINTER_FIFO_SIZE:
-        return s->fifo_size;
-    default:
-        cpu_abort(cpu_single_env, "syborg_pointer_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_pointer_write(void *opaque, target_phys_addr_t offset,
-                                 uint64_t value, unsigned size)
-{
-    SyborgPointerState *s = (SyborgPointerState *)opaque;
-
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case POINTER_LATCH:
-        if (s->read_count > 0) {
-            s->read_count--;
-            if (++s->read_pos == s->fifo_size)
-                s->read_pos = 0;
-        }
-        break;
-    case POINTER_INT_ENABLE:
-        s->int_enabled = value;
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_pointer_write: Bad offset %x\n",
-                  (int)offset);
-    }
-    syborg_pointer_update(s);
-}
-
-static const MemoryRegionOps syborg_pointer_ops = {
-    .read = syborg_pointer_read,
-    .write = syborg_pointer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_pointer_event(void *opaque, int dx, int dy, int dz,
-                                 int buttons_state)
-{
-    SyborgPointerState *s = (SyborgPointerState *)opaque;
-    int slot = s->read_pos + s->read_count;
-
-    /* This first FIFO entry is used to store current register state.  */
-    if (s->read_count < s->fifo_size - 1) {
-        s->read_count++;
-        slot++;
-    }
-
-    if (slot >= s->fifo_size)
-          slot -= s->fifo_size;
-
-    if (s->read_count == s->fifo_size && !s->absolute) {
-        /* Merge existing entries.  */
-        s->event_fifo[slot].x += dx;
-        s->event_fifo[slot].y += dy;
-        s->event_fifo[slot].z += dz;
-    } else {
-        s->event_fifo[slot].x = dx;
-        s->event_fifo[slot].y = dy;
-        s->event_fifo[slot].z = dz;
-    }
-    s->event_fifo[slot].pointer_buttons = buttons_state;
-
-    syborg_pointer_update(s);
-}
-
-static const VMStateDescription vmstate_event_data = {
-    .name = "dbma_channel",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_INT32(x, event_data),
-        VMSTATE_INT32(y, event_data),
-        VMSTATE_INT32(z, event_data),
-        VMSTATE_INT32(pointer_buttons, event_data),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_syborg_pointer = {
-    .name = "syborg_pointer",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_EQUAL(fifo_size, SyborgPointerState),
-        VMSTATE_UINT32_EQUAL(absolute, SyborgPointerState),
-        VMSTATE_INT32(int_enabled, SyborgPointerState),
-        VMSTATE_INT32(read_pos, SyborgPointerState),
-        VMSTATE_INT32(read_count, SyborgPointerState),
-        VMSTATE_STRUCT_VARRAY_UINT32(event_fifo, SyborgPointerState, fifo_size,
-                                     1, vmstate_event_data, event_data),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_pointer_init(SysBusDevice *dev)
-{
-    SyborgPointerState *s = FROM_SYSBUS(SyborgPointerState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_pointer_ops, s,
-                          "pointer", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    if (s->fifo_size <= 0) {
-        fprintf(stderr, "syborg_pointer: fifo too small\n");
-        s->fifo_size = 16;
-    }
-    s->event_fifo = g_malloc0(s->fifo_size * sizeof(s->event_fifo[0]));
-
-    qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
-                                 "Syborg Pointer");
-
-    vmstate_register(&dev->qdev, -1, &vmstate_syborg_pointer, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_pointer_info = {
-    .init = syborg_pointer_init,
-    .qdev.name  = "syborg,pointer",
-    .qdev.size  = sizeof(SyborgPointerState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("fifo-size", SyborgPointerState, fifo_size, 16),
-        DEFINE_PROP_UINT32("absolute",  SyborgPointerState, absolute,   1),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_pointer_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_pointer_info);
-}
-
-device_init(syborg_pointer_register_devices)
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
deleted file mode 100644
index b5f34798b6..0000000000
--- a/hw/syborg_rtc.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Syborg RTC
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "qemu-timer.h"
-#include "syborg.h"
-
-enum {
-    RTC_ID        = 0,
-    RTC_LATCH     = 1,
-    RTC_DATA_LOW  = 2,
-    RTC_DATA_HIGH = 3
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    int64_t offset;
-    int64_t data;
-    qemu_irq irq;
-} SyborgRTCState;
-
-static uint64_t syborg_rtc_read(void *opaque, target_phys_addr_t offset,
-                                unsigned size)
-{
-    SyborgRTCState *s = (SyborgRTCState *)opaque;
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case RTC_ID:
-        return SYBORG_ID_RTC;
-    case RTC_DATA_LOW:
-        return (uint32_t)s->data;
-    case RTC_DATA_HIGH:
-        return (uint32_t)(s->data >> 32);
-    default:
-        cpu_abort(cpu_single_env, "syborg_rtc_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_rtc_write(void *opaque, target_phys_addr_t offset,
-                             uint64_t value, unsigned size)
-{
-    SyborgRTCState *s = (SyborgRTCState *)opaque;
-    uint64_t now;
-
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case RTC_LATCH:
-        now = qemu_get_clock_ns(vm_clock);
-        if (value >= 4) {
-            s->offset = s->data - now;
-        } else {
-            s->data = now + s->offset;
-            while (value) {
-                s->data /= 1000;
-                value--;
-            }
-        }
-        break;
-    case RTC_DATA_LOW:
-        s->data = (s->data & ~(uint64_t)0xffffffffu) | value;
-        break;
-    case RTC_DATA_HIGH:
-        s->data = (s->data & 0xffffffffu) | ((uint64_t)value << 32);
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_rtc_write: Bad offset %x\n",
-                  (int)offset);
-        break;
-    }
-}
-
-static const MemoryRegionOps syborg_rtc_ops = {
-    .read = syborg_rtc_read,
-    .write = syborg_rtc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_syborg_rtc = {
-    .name = "syborg_keyboard",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_INT64(offset, SyborgRTCState),
-        VMSTATE_INT64(data, SyborgRTCState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_rtc_init(SysBusDevice *dev)
-{
-    SyborgRTCState *s = FROM_SYSBUS(SyborgRTCState, dev);
-    struct tm tm;
-
-    memory_region_init_io(&s->iomem, &syborg_rtc_ops, s, "rtc", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    qemu_get_timedate(&tm, 0);
-    s->offset = (uint64_t)mktime(&tm) * 1000000000;
-
-    vmstate_register(&dev->qdev, -1, &vmstate_syborg_rtc, s);
-    return 0;
-}
-
-static void syborg_rtc_register_devices(void)
-{
-    sysbus_register_dev("syborg,rtc", sizeof(SyborgRTCState), syborg_rtc_init);
-}
-
-device_init(syborg_rtc_register_devices)
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
deleted file mode 100644
index 6f339fa7a6..0000000000
--- a/hw/syborg_serial.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Syborg serial port
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "qemu-char.h"
-#include "syborg.h"
-
-//#define DEBUG_SYBORG_SERIAL
-
-#ifdef DEBUG_SYBORG_SERIAL
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_serial: " fmt , ##args); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_serial: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_serial: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
-    SERIAL_ID           = 0,
-    SERIAL_DATA         = 1,
-    SERIAL_FIFO_COUNT   = 2,
-    SERIAL_INT_ENABLE   = 3,
-    SERIAL_DMA_TX_ADDR  = 4,
-    SERIAL_DMA_TX_COUNT = 5, /* triggers dma */
-    SERIAL_DMA_RX_ADDR  = 6,
-    SERIAL_DMA_RX_COUNT = 7, /* triggers dma */
-    SERIAL_FIFO_SIZE    = 8
-};
-
-#define SERIAL_INT_FIFO   (1u << 0)
-#define SERIAL_INT_DMA_TX (1u << 1)
-#define SERIAL_INT_DMA_RX (1u << 2)
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t int_enable;
-    uint32_t fifo_size;
-    uint32_t *read_fifo;
-    int read_pos;
-    int read_count;
-    CharDriverState *chr;
-    qemu_irq irq;
-    uint32_t dma_tx_ptr;
-    uint32_t dma_rx_ptr;
-    uint32_t dma_rx_size;
-} SyborgSerialState;
-
-static void syborg_serial_update(SyborgSerialState *s)
-{
-    int level;
-    level = 0;
-    if ((s->int_enable & SERIAL_INT_FIFO) && s->read_count)
-        level = 1;
-    if (s->int_enable & SERIAL_INT_DMA_TX)
-        level = 1;
-    if ((s->int_enable & SERIAL_INT_DMA_RX) && s->dma_rx_size == 0)
-        level = 1;
-
-    qemu_set_irq(s->irq, level);
-}
-
-static uint32_t fifo_pop(SyborgSerialState *s)
-{
-    const uint32_t c = s->read_fifo[s->read_pos];
-    s->read_count--;
-    s->read_pos++;
-    if (s->read_pos == s->fifo_size)
-        s->read_pos = 0;
-
-    DPRINTF("FIFO pop %x (%d)\n", c, s->read_count);
-    return c;
-}
-
-static void fifo_push(SyborgSerialState *s, uint32_t new_value)
-{
-    int slot;
-
-    DPRINTF("FIFO push %x (%d)\n", new_value, s->read_count);
-    slot = s->read_pos + s->read_count;
-    if (slot >= s->fifo_size)
-          slot -= s->fifo_size;
-    s->read_fifo[slot] = new_value;
-    s->read_count++;
-}
-
-static void do_dma_tx(SyborgSerialState *s, uint32_t count)
-{
-    unsigned char ch;
-
-    if (count == 0)
-        return;
-
-    if (s->chr != NULL) {
-        /* optimize later. Now, 1 byte per iteration */
-        while (count--) {
-            cpu_physical_memory_read(s->dma_tx_ptr, &ch, 1);
-            qemu_chr_fe_write(s->chr, &ch, 1);
-            s->dma_tx_ptr++;
-        }
-    } else {
-        s->dma_tx_ptr += count;
-    }
-    /* QEMU char backends do not have a nonblocking mode, so we transmit all
-       the data immediately and the interrupt status will be unchanged.  */
-}
-
-/* Initiate RX DMA, and transfer data from the FIFO.  */
-static void dma_rx_start(SyborgSerialState *s, uint32_t len)
-{
-    uint32_t dest;
-    unsigned char ch;
-
-    dest = s->dma_rx_ptr;
-    if (s->read_count < len) {
-        s->dma_rx_size = len - s->read_count;
-        len = s->read_count;
-    } else {
-        s->dma_rx_size = 0;
-    }
-
-    while (len--) {
-        ch = fifo_pop(s);
-        cpu_physical_memory_write(dest, &ch, 1);
-        dest++;
-    }
-    s->dma_rx_ptr = dest;
-    syborg_serial_update(s);
-}
-
-static uint64_t syborg_serial_read(void *opaque, target_phys_addr_t offset,
-                                   unsigned size)
-{
-    SyborgSerialState *s = (SyborgSerialState *)opaque;
-    uint32_t c;
-
-    offset &= 0xfff;
-    DPRINTF("read 0x%x\n", (int)offset);
-    switch(offset >> 2) {
-    case SERIAL_ID:
-        return SYBORG_ID_SERIAL;
-    case SERIAL_DATA:
-        if (s->read_count > 0)
-            c = fifo_pop(s);
-        else
-            c = -1;
-        syborg_serial_update(s);
-        return c;
-    case SERIAL_FIFO_COUNT:
-        return s->read_count;
-    case SERIAL_INT_ENABLE:
-        return s->int_enable;
-    case SERIAL_DMA_TX_ADDR:
-        return s->dma_tx_ptr;
-    case SERIAL_DMA_TX_COUNT:
-        return 0;
-    case SERIAL_DMA_RX_ADDR:
-        return s->dma_rx_ptr;
-    case SERIAL_DMA_RX_COUNT:
-        return s->dma_rx_size;
-    case SERIAL_FIFO_SIZE:
-        return s->fifo_size;
-
-    default:
-        cpu_abort(cpu_single_env, "syborg_serial_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_serial_write(void *opaque, target_phys_addr_t offset,
-                                uint64_t value, unsigned size)
-{
-    SyborgSerialState *s = (SyborgSerialState *)opaque;
-    unsigned char ch;
-
-    offset &= 0xfff;
-    DPRINTF("Write 0x%x=0x%x\n", (int)offset, value);
-    switch (offset >> 2) {
-    case SERIAL_DATA:
-        ch = value;
-        if (s->chr)
-            qemu_chr_fe_write(s->chr, &ch, 1);
-        break;
-    case SERIAL_INT_ENABLE:
-        s->int_enable = value;
-        syborg_serial_update(s);
-        break;
-    case SERIAL_DMA_TX_ADDR:
-        s->dma_tx_ptr = value;
-        break;
-    case SERIAL_DMA_TX_COUNT:
-        do_dma_tx(s, value);
-        break;
-    case SERIAL_DMA_RX_ADDR:
-        /* For safety, writes to this register cancel any pending DMA.  */
-        s->dma_rx_size = 0;
-        s->dma_rx_ptr = value;
-        break;
-    case SERIAL_DMA_RX_COUNT:
-        dma_rx_start(s, value);
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_serial_write: Bad offset %x\n",
-                  (int)offset);
-        break;
-    }
-}
-
-static int syborg_serial_can_receive(void *opaque)
-{
-    SyborgSerialState *s = (SyborgSerialState *)opaque;
-
-    if (s->dma_rx_size)
-        return s->dma_rx_size;
-    return s->fifo_size - s->read_count;
-}
-
-static void syborg_serial_receive(void *opaque, const uint8_t *buf, int size)
-{
-    SyborgSerialState *s = (SyborgSerialState *)opaque;
-
-    if (s->dma_rx_size) {
-        /* Place it in the DMA buffer.  */
-        cpu_physical_memory_write(s->dma_rx_ptr, buf, size);
-        s->dma_rx_size -= size;
-        s->dma_rx_ptr += size;
-    } else {
-        while (size--)
-            fifo_push(s, *buf);
-    }
-
-    syborg_serial_update(s);
-}
-
-static void syborg_serial_event(void *opaque, int event)
-{
-    /* TODO: Report BREAK events?  */
-}
-
-static const MemoryRegionOps syborg_serial_ops = {
-    .read = syborg_serial_read,
-    .write = syborg_serial_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_syborg_serial = {
-    .name = "syborg_serial",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_EQUAL(fifo_size, SyborgSerialState),
-        VMSTATE_UINT32(int_enable, SyborgSerialState),
-        VMSTATE_INT32(read_pos, SyborgSerialState),
-        VMSTATE_INT32(read_count, SyborgSerialState),
-        VMSTATE_UINT32(dma_tx_ptr, SyborgSerialState),
-        VMSTATE_UINT32(dma_rx_ptr, SyborgSerialState),
-        VMSTATE_UINT32(dma_rx_size, SyborgSerialState),
-        VMSTATE_VARRAY_UINT32(read_fifo, SyborgSerialState, fifo_size, 1,
-                              vmstate_info_uint32, uint32),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_serial_init(SysBusDevice *dev)
-{
-    SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_serial_ops, s,
-                          "serial", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    s->chr = qdev_init_chardev(&dev->qdev);
-    if (s->chr) {
-        qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
-                              syborg_serial_receive, syborg_serial_event, s);
-    }
-    if (s->fifo_size <= 0) {
-        fprintf(stderr, "syborg_serial: fifo too small\n");
-        s->fifo_size = 16;
-    }
-    s->read_fifo = g_malloc0(s->fifo_size * sizeof(s->read_fifo[0]));
-
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_serial_info = {
-    .init = syborg_serial_init,
-    .qdev.name  = "syborg,serial",
-    .qdev.size  = sizeof(SyborgSerialState),
-    .qdev.vmsd  = &vmstate_syborg_serial,
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("fifo-size", SyborgSerialState, fifo_size, 16),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_serial_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_serial_info);
-}
-
-device_init(syborg_serial_register_devices)
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
deleted file mode 100644
index 1498f01a62..0000000000
--- a/hw/syborg_timer.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Syborg Interval Timer.
- *
- * Copyright (c) 2008 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "sysbus.h"
-#include "qemu-timer.h"
-#include "syborg.h"
-
-//#define DEBUG_SYBORG_TIMER
-
-#ifdef DEBUG_SYBORG_TIMER
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_timer: " fmt , ##args); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_timer: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_timer: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
-    TIMER_ID          = 0,
-    TIMER_RUNNING     = 1,
-    TIMER_ONESHOT     = 2,
-    TIMER_LIMIT       = 3,
-    TIMER_VALUE       = 4,
-    TIMER_INT_ENABLE  = 5,
-    TIMER_INT_STATUS  = 6,
-    TIMER_FREQ        = 7
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    ptimer_state *timer;
-    int running;
-    int oneshot;
-    uint32_t limit;
-    uint32_t freq;
-    uint32_t int_level;
-    uint32_t int_enabled;
-    qemu_irq irq;
-} SyborgTimerState;
-
-static void syborg_timer_update(SyborgTimerState *s)
-{
-    /* Update interrupt.  */
-    if (s->int_level && s->int_enabled) {
-        qemu_irq_raise(s->irq);
-    } else {
-        qemu_irq_lower(s->irq);
-    }
-}
-
-static void syborg_timer_tick(void *opaque)
-{
-    SyborgTimerState *s = (SyborgTimerState *)opaque;
-    //DPRINTF("Timer Tick\n");
-    s->int_level = 1;
-    if (s->oneshot)
-        s->running = 0;
-    syborg_timer_update(s);
-}
-
-static uint64_t syborg_timer_read(void *opaque, target_phys_addr_t offset,
-                                  unsigned size)
-{
-    SyborgTimerState *s = (SyborgTimerState *)opaque;
-
-    DPRINTF("Reg read %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case TIMER_ID:
-        return SYBORG_ID_TIMER;
-    case TIMER_RUNNING:
-        return s->running;
-    case TIMER_ONESHOT:
-        return s->oneshot;
-    case TIMER_LIMIT:
-        return s->limit;
-    case TIMER_VALUE:
-        return ptimer_get_count(s->timer);
-    case TIMER_INT_ENABLE:
-        return s->int_enabled;
-    case TIMER_INT_STATUS:
-        return s->int_level;
-    case TIMER_FREQ:
-        return s->freq;
-    default:
-        cpu_abort(cpu_single_env, "syborg_timer_read: Bad offset %x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void syborg_timer_write(void *opaque, target_phys_addr_t offset,
-                               uint64_t value, unsigned size)
-{
-    SyborgTimerState *s = (SyborgTimerState *)opaque;
-
-    DPRINTF("Reg write %d\n", (int)offset);
-    offset &= 0xfff;
-    switch (offset >> 2) {
-    case TIMER_RUNNING:
-        if (value == s->running)
-            break;
-        s->running = value;
-        if (value) {
-            ptimer_run(s->timer, s->oneshot);
-        } else {
-            ptimer_stop(s->timer);
-        }
-        break;
-    case TIMER_ONESHOT:
-        if (s->running) {
-            ptimer_stop(s->timer);
-        }
-        s->oneshot = value;
-        if (s->running) {
-            ptimer_run(s->timer, s->oneshot);
-        }
-        break;
-    case TIMER_LIMIT:
-        s->limit = value;
-        ptimer_set_limit(s->timer, value, 1);
-        break;
-    case TIMER_VALUE:
-        ptimer_set_count(s->timer, value);
-        break;
-    case TIMER_INT_ENABLE:
-        s->int_enabled = value;
-        syborg_timer_update(s);
-        break;
-    case TIMER_INT_STATUS:
-        s->int_level &= ~value;
-        syborg_timer_update(s);
-        break;
-    default:
-        cpu_abort(cpu_single_env, "syborg_timer_write: Bad offset %x\n",
-                  (int)offset);
-        break;
-    }
-}
-
-static const MemoryRegionOps syborg_timer_ops = {
-    .read = syborg_timer_read,
-    .write = syborg_timer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_syborg_timer = {
-    .name = "syborg_timer",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_INT32(running, SyborgTimerState),
-        VMSTATE_INT32(oneshot, SyborgTimerState),
-        VMSTATE_UINT32(limit, SyborgTimerState),
-        VMSTATE_UINT32(int_level, SyborgTimerState),
-        VMSTATE_UINT32(int_enabled, SyborgTimerState),
-        VMSTATE_PTIMER(timer, SyborgTimerState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int syborg_timer_init(SysBusDevice *dev)
-{
-    SyborgTimerState *s = FROM_SYSBUS(SyborgTimerState, dev);
-    QEMUBH *bh;
-
-    if (s->freq == 0) {
-        fprintf(stderr, "syborg_timer: Zero/unset frequency\n");
-        exit(1);
-    }
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->iomem, &syborg_timer_ops, s, "timer", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    bh = qemu_bh_new(syborg_timer_tick, s);
-    s->timer = ptimer_init(bh);
-    ptimer_set_freq(s->timer, s->freq);
-    vmstate_register(&dev->qdev, -1, &vmstate_syborg_timer, s);
-    return 0;
-}
-
-static SysBusDeviceInfo syborg_timer_info = {
-    .init = syborg_timer_init,
-    .qdev.name  = "syborg,timer",
-    .qdev.size  = sizeof(SyborgTimerState),
-    .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("frequency",SyborgTimerState, freq, 0),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_timer_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_timer_info);
-}
-
-device_init(syborg_timer_register_devices)
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
deleted file mode 100644
index 96a0ee651f..0000000000
--- a/hw/syborg_virtio.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Virtio Syborg bindings
- *
- * Copyright (c) 2009 CodeSourcery
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "syborg.h"
-#include "sysbus.h"
-#include "virtio.h"
-#include "virtio-net.h"
-
-//#define DEBUG_SYBORG_VIRTIO
-
-#ifdef DEBUG_SYBORG_VIRTIO
-#define DPRINTF(fmt, ...) \
-do { printf("syborg_virtio: " fmt , ## __VA_ARGS__); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__); \
-    exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
-    SYBORG_VIRTIO_ID             = 0,
-    SYBORG_VIRTIO_DEVTYPE        = 1,
-    SYBORG_VIRTIO_HOST_FEATURES  = 2,
-    SYBORG_VIRTIO_GUEST_FEATURES = 3,
-    SYBORG_VIRTIO_QUEUE_BASE     = 4,
-    SYBORG_VIRTIO_QUEUE_NUM      = 5,
-    SYBORG_VIRTIO_QUEUE_SEL      = 6,
-    SYBORG_VIRTIO_QUEUE_NOTIFY   = 7,
-    SYBORG_VIRTIO_STATUS         = 8,
-    SYBORG_VIRTIO_INT_ENABLE     = 9,
-    SYBORG_VIRTIO_INT_STATUS     = 10
-};
-
-#define SYBORG_VIRTIO_CONFIG 0x100
-
-/* Device independent interface.  */
-
-typedef struct {
-    SysBusDevice busdev;
-    VirtIODevice *vdev;
-    MemoryRegion iomem;
-    qemu_irq irq;
-    uint32_t int_enable;
-    uint32_t id;
-    NICConf nic;
-    uint32_t host_features;
-    virtio_net_conf net;
-} SyborgVirtIOProxy;
-
-static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-    uint32_t ret;
-
-    DPRINTF("readl 0x%x\n", (int)offset);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_readl(vdev, offset - SYBORG_VIRTIO_CONFIG);
-    }
-    switch(offset >> 2) {
-    case SYBORG_VIRTIO_ID:
-        ret = SYBORG_ID_VIRTIO;
-        break;
-    case SYBORG_VIRTIO_DEVTYPE:
-        ret = s->id;
-        break;
-    case SYBORG_VIRTIO_HOST_FEATURES:
-        ret = s->host_features;
-        break;
-    case SYBORG_VIRTIO_GUEST_FEATURES:
-        ret = vdev->guest_features;
-        break;
-    case SYBORG_VIRTIO_QUEUE_BASE:
-        ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
-        break;
-    case SYBORG_VIRTIO_QUEUE_NUM:
-        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
-        break;
-    case SYBORG_VIRTIO_QUEUE_SEL:
-        ret = vdev->queue_sel;
-        break;
-    case SYBORG_VIRTIO_STATUS:
-        ret = vdev->status;
-        break;
-    case SYBORG_VIRTIO_INT_ENABLE:
-        ret = s->int_enable;
-        break;
-    case SYBORG_VIRTIO_INT_STATUS:
-        ret = vdev->isr;
-        break;
-    default:
-        BADF("Bad read offset 0x%x\n", (int)offset);
-        return 0;
-    }
-    return ret;
-}
-
-static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("writel 0x%x = 0x%x\n", (int)offset, value);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_writel(vdev, offset - SYBORG_VIRTIO_CONFIG,
-                                    value);
-    }
-    switch (offset >> 2) {
-    case SYBORG_VIRTIO_GUEST_FEATURES:
-        virtio_set_features(vdev, value);
-        break;
-    case SYBORG_VIRTIO_QUEUE_BASE:
-        if (value == 0)
-            virtio_reset(vdev);
-        else
-            virtio_queue_set_addr(vdev, vdev->queue_sel, value);
-        break;
-    case SYBORG_VIRTIO_QUEUE_SEL:
-        if (value < VIRTIO_PCI_QUEUE_MAX)
-            vdev->queue_sel = value;
-        break;
-    case SYBORG_VIRTIO_QUEUE_NOTIFY:
-        if (value < VIRTIO_PCI_QUEUE_MAX) {
-            virtio_queue_notify(vdev, value);
-        }
-        break;
-    case SYBORG_VIRTIO_STATUS:
-        virtio_set_status(vdev, value & 0xFF);
-        if (vdev->status == 0)
-            virtio_reset(vdev);
-        break;
-    case SYBORG_VIRTIO_INT_ENABLE:
-        s->int_enable = value;
-        virtio_update_irq(vdev);
-        break;
-    case SYBORG_VIRTIO_INT_STATUS:
-        vdev->isr &= ~value;
-        virtio_update_irq(vdev);
-        break;
-    default:
-        BADF("Bad write offset 0x%x\n", (int)offset);
-        break;
-    }
-}
-
-static uint32_t syborg_virtio_readw(void *opaque, target_phys_addr_t offset)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("readw 0x%x\n", (int)offset);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_readw(vdev, offset - SYBORG_VIRTIO_CONFIG);
-    }
-    BADF("Bad halfword read offset 0x%x\n", (int)offset);
-    return -1;
-}
-
-static void syborg_virtio_writew(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("writew 0x%x = 0x%x\n", (int)offset, value);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_writew(vdev, offset - SYBORG_VIRTIO_CONFIG,
-                                    value);
-    }
-    BADF("Bad halfword write offset 0x%x\n", (int)offset);
-}
-
-static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("readb 0x%x\n", (int)offset);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG);
-    }
-    BADF("Bad byte read offset 0x%x\n", (int)offset);
-    return -1;
-}
-
-static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
-                                 uint32_t value)
-{
-    SyborgVirtIOProxy *s = opaque;
-    VirtIODevice *vdev = s->vdev;
-
-    DPRINTF("writeb 0x%x = 0x%x\n", (int)offset, value);
-    if (offset >= SYBORG_VIRTIO_CONFIG) {
-        return virtio_config_writeb(vdev, offset - SYBORG_VIRTIO_CONFIG,
-                                    value);
-    }
-    BADF("Bad byte write offset 0x%x\n", (int)offset);
-}
-
-static const MemoryRegionOps syborg_virtio_ops = {
-    .old_mmio = {
-        .read = { syborg_virtio_readb, syborg_virtio_readw, syborg_virtio_readl },
-        .write = { syborg_virtio_writeb, syborg_virtio_writew, syborg_virtio_writel },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
-{
-    SyborgVirtIOProxy *proxy = opaque;
-    int level;
-
-    level = proxy->int_enable & proxy->vdev->isr;
-    DPRINTF("IRQ %d\n", level);
-    qemu_set_irq(proxy->irq, level != 0);
-}
-
-static unsigned syborg_virtio_get_features(void *opaque)
-{
-    SyborgVirtIOProxy *proxy = opaque;
-    return proxy->host_features;
-}
-
-static VirtIOBindings syborg_virtio_bindings = {
-    .notify = syborg_virtio_update_irq,
-    .get_features = syborg_virtio_get_features,
-};
-
-static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
-{
-    proxy->vdev = vdev;
-
-    /* Don't support multiple vectors */
-    proxy->vdev->nvectors = 0;
-    sysbus_init_irq(&proxy->busdev, &proxy->irq);
-    memory_region_init_io(&proxy->iomem, &syborg_virtio_ops, proxy,
-                          "virtio", 0x1000);
-    sysbus_init_mmio(&proxy->busdev, &proxy->iomem);
-
-    proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
-
-    qemu_register_reset(virtio_reset, vdev);
-
-    virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
-    proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
-    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
-    return 0;
-}
-
-/* Device specific bindings.  */
-
-static int syborg_virtio_net_init(SysBusDevice *dev)
-{
-    VirtIODevice *vdev;
-    SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
-
-    vdev = virtio_net_init(&dev->qdev, &proxy->nic, &proxy->net);
-    return syborg_virtio_init(proxy, vdev);
-}
-
-static SysBusDeviceInfo syborg_virtio_net_info = {
-    .init = syborg_virtio_net_init,
-    .qdev.name  = "syborg,virtio-net",
-    .qdev.size  = sizeof(SyborgVirtIOProxy),
-    .qdev.props = (Property[]) {
-        DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
-        DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
-        DEFINE_PROP_UINT32("x-txtimer", SyborgVirtIOProxy,
-                           net.txtimer, TX_TIMER_INTERVAL),
-        DEFINE_PROP_INT32("x-txburst", SyborgVirtIOProxy,
-                          net.txburst, TX_BURST),
-        DEFINE_PROP_STRING("tx", SyborgVirtIOProxy, net.tx),
-        DEFINE_PROP_END_OF_LIST(),
-    }
-};
-
-static void syborg_virtio_register_devices(void)
-{
-    sysbus_register_withprop(&syborg_virtio_net_info);
-}
-
-device_init(syborg_virtio_register_devices)
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index a946e1d1fd..7c926c0d47 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1109,7 +1109,7 @@ static inline int get_dwords(EHCIState *ehci, uint32_t addr,
     int i;
 
     for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        pci_dma_read(&ehci->dev, addr, (uint8_t *)buf, sizeof(*buf));
+        pci_dma_read(&ehci->dev, addr, buf, sizeof(*buf));
         *buf = le32_to_cpu(*buf);
     }
 
@@ -1124,7 +1124,7 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
 
     for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint32_t tmp = cpu_to_le32(*buf);
-        pci_dma_write(&ehci->dev, addr, (uint8_t *)&tmp, sizeof(tmp));
+        pci_dma_write(&ehci->dev, addr, &tmp, sizeof(tmp));
     }
 
     return 1;
@@ -2157,7 +2157,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
         }
         list |= ((ehci->frindex & 0x1ff8) >> 1);
 
-        pci_dma_read(&ehci->dev, list, (uint8_t *) &entry, sizeof entry);
+        pci_dma_read(&ehci->dev, list, &entry, sizeof entry);
         entry = le32_to_cpu(entry);
 
         DPRINTF("PERIODIC state adv fr=%d.  [%08X] -> %08X\n",
diff --git a/hw/usb-net.c b/hw/usb-net.c
index a8b7c8dd76..f91fa32334 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1268,8 +1268,9 @@ static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t si
 
     if (is_rndis(s)) {
         msg = (struct rndis_packet_msg_type *) s->in_buf;
-        if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
+        if (s->rndis_state != RNDIS_DATA_INITIALIZED) {
             return -1;
+        }
         if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
             return -1;
 
@@ -1302,7 +1303,7 @@ static int usbnet_can_receive(VLANClientState *nc)
 {
     USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    if (is_rndis(s) && !s->rndis_state == RNDIS_DATA_INITIALIZED) {
+    if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) {
         return 1;
     }
 
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index f9e3ea5bfc..f8912e2b0b 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -876,7 +876,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
         uint32_t link = async->td;
         uint32_t int_mask = 0, val;
 
-        pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &td, sizeof(td));
+        pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td));
         le32_to_cpus(&td.link);
         le32_to_cpus(&td.ctrl);
         le32_to_cpus(&td.token);
@@ -888,8 +888,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
 
         /* update the status bits of the TD */
         val = cpu_to_le32(td.ctrl);
-        pci_dma_write(&s->dev, (link & ~0xf) + 4,
-                      (const uint8_t *)&val, sizeof(val));
+        pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
         uhci_async_free(s, async);
     } else {
         async->done = 1;
@@ -952,7 +951,7 @@ static void uhci_process_frame(UHCIState *s)
 
     DPRINTF("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
 
-    pci_dma_read(&s->dev, frame_addr, (uint8_t *)&link, 4);
+    pci_dma_read(&s->dev, frame_addr, &link, 4);
     le32_to_cpus(&link);
 
     int_mask = 0;
@@ -976,7 +975,7 @@ static void uhci_process_frame(UHCIState *s)
                 break;
             }
 
-            pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &qh, sizeof(qh));
+            pci_dma_read(&s->dev, link & ~0xf, &qh, sizeof(qh));
             le32_to_cpus(&qh.link);
             le32_to_cpus(&qh.el_link);
 
@@ -996,7 +995,7 @@ static void uhci_process_frame(UHCIState *s)
         }
 
         /* TD */
-        pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &td, sizeof(td));
+        pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td));
         le32_to_cpus(&td.link);
         le32_to_cpus(&td.ctrl);
         le32_to_cpus(&td.token);
@@ -1010,8 +1009,7 @@ static void uhci_process_frame(UHCIState *s)
         if (old_td_ctrl != td.ctrl) {
             /* update the status bits of the TD */
             val = cpu_to_le32(td.ctrl);
-            pci_dma_write(&s->dev, (link & ~0xf) + 4,
-                          (const uint8_t *)&val, sizeof(val));
+            pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
         }
 
         if (ret < 0) {
@@ -1039,8 +1037,7 @@ static void uhci_process_frame(UHCIState *s)
 	    /* update QH element link */
             qh.el_link = link;
             val = cpu_to_le32(qh.el_link);
-            pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4,
-                          (const uint8_t *)&val, sizeof(val));
+            pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4, &val, sizeof(val));
 
             if (!depth_first(link)) {
                /* done with this QH */
diff --git a/migration-exec.c b/migration-exec.c
index b7b1055e88..e14552ec01 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -50,12 +50,9 @@ static int exec_close(MigrationState *s)
         ret = qemu_fclose(s->opaque);
         s->opaque = NULL;
         s->fd = -1;
-        if (ret != -1 &&
-            WIFEXITED(ret)
-            && WEXITSTATUS(ret) == 0) {
-            ret = 0;
-        } else {
-            ret = -1;
+        if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) {
+            /* close succeeded, but non-zero exit code: */
+            ret = -EIO; /* fake errno value */
         }
     }
     return ret;
diff --git a/migration-tcp.c b/migration-tcp.c
index 5aa742c34b..cf6a9b83d6 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -40,12 +40,15 @@ static int socket_write(MigrationState *s, const void * buf, size_t size)
 
 static int tcp_close(MigrationState *s)
 {
+    int r = 0;
     DPRINTF("tcp_close\n");
     if (s->fd != -1) {
-        close(s->fd);
+        if (close(s->fd) < 0) {
+            r = -errno;
+        }
         s->fd = -1;
     }
-    return 0;
+    return r;
 }
 
 static void tcp_wait_for_connect(void *opaque)
diff --git a/migration-unix.c b/migration-unix.c
index 8596353d7d..dfcf2033c6 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -40,12 +40,15 @@ static int unix_write(MigrationState *s, const void * buf, size_t size)
 
 static int unix_close(MigrationState *s)
 {
+    int r = 0;
     DPRINTF("unix_close\n");
     if (s->fd != -1) {
-        close(s->fd);
+        if (close(s->fd) < 0) {
+            r = -errno;
+        }
         s->fd = -1;
     }
-    return 0;
+    return r;
 }
 
 static void unix_wait_for_connect(void *opaque)
diff --git a/migration.c b/migration.c
index 8280d7189a..412fdfe5bf 100644
--- a/migration.c
+++ b/migration.c
@@ -174,9 +174,7 @@ static int migrate_fd_cleanup(MigrationState *s)
 
     if (s->file) {
         DPRINTF("closing file\n");
-        if (qemu_fclose(s->file) != 0) {
-            ret = -1;
-        }
+        ret = qemu_fclose(s->file);
         s->file = NULL;
     } else {
         if (s->mon) {
@@ -468,37 +466,27 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
-int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate_cancel(Error **errp)
 {
     migrate_fd_cancel(migrate_get_current());
-    return 0;
 }
 
-int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate_set_speed(int64_t value, Error **errp)
 {
-    int64_t d;
     MigrationState *s;
 
-    d = qdict_get_int(qdict, "value");
-    if (d < 0) {
-        d = 0;
+    if (value < 0) {
+        value = 0;
     }
 
     s = migrate_get_current();
-    s->bandwidth_limit = d;
+    s->bandwidth_limit = value;
     qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
-
-    return 0;
 }
 
-int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
-                            QObject **ret_data)
+void qmp_migrate_set_downtime(double value, Error **errp)
 {
-    double d;
-
-    d = qdict_get_double(qdict, "value") * 1e9;
-    d = MAX(0, MIN(UINT64_MAX, d));
-    max_downtime = (uint64_t)d;
-
-    return 0;
+    value *= 1e9;
+    value = MAX(0, MIN(UINT64_MAX, value));
+    max_downtime = (uint64_t)value;
 }
diff --git a/migration.h b/migration.h
index 78a50d31ac..372b066b48 100644
--- a/migration.h
+++ b/migration.h
@@ -42,15 +42,8 @@ int qemu_start_incoming_migration(const char *uri);
 
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
-int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
-int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 uint64_t migrate_max_downtime(void);
 
-int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
-                            QObject **ret_data);
-
 void do_info_migrate_print(Monitor *mon, const QObject *data);
 
 void do_info_migrate(Monitor *mon, QObject **ret_data);
diff --git a/monitor.c b/monitor.c
index 1be222ee18..733440115f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -513,10 +513,10 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params,
 
 static void handle_user_command(Monitor *mon, const char *cmdline);
 
-static int do_hmp_passthrough(Monitor *mon, const QDict *params,
-                              QObject **ret_data)
+char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
+                                int64_t cpu_index, Error **errp)
 {
-    int ret = 0;
+    char *output = NULL;
     Monitor *old_mon, hmp;
     CharDriverState mchar;
 
@@ -527,25 +527,30 @@ static int do_hmp_passthrough(Monitor *mon, const QDict *params,
     old_mon = cur_mon;
     cur_mon = &hmp;
 
-    if (qdict_haskey(params, "cpu-index")) {
-        ret = monitor_set_cpu(qdict_get_int(params, "cpu-index"));
+    if (has_cpu_index) {
+        int ret = monitor_set_cpu(cpu_index);
         if (ret < 0) {
             cur_mon = old_mon;
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number");
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+                      "a CPU number");
             goto out;
         }
     }
 
-    handle_user_command(&hmp, qdict_get_str(params, "command-line"));
+    handle_user_command(&hmp, command_line);
     cur_mon = old_mon;
 
     if (qemu_chr_mem_osize(hmp.chr) > 0) {
-        *ret_data = QOBJECT(qemu_chr_mem_to_qs(hmp.chr));
+        QString *str = qemu_chr_mem_to_qs(hmp.chr);
+        output = g_strdup(qstring_get_str(str));
+        QDECREF(str);
+    } else {
+        output = g_strdup("");
     }
 
 out:
     qemu_chr_close_mem(hmp.chr);
-    return ret;
+    return output;
 }
 
 static int compare_cmd(const char *name, const char *list)
@@ -1073,65 +1078,6 @@ static void do_singlestep(Monitor *mon, const QDict *qdict)
     }
 }
 
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
-
-struct bdrv_iterate_context {
-    Monitor *mon;
-    int err;
-};
-
-static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
-{
-    bdrv_iostatus_reset(bs);
-}
-
-/**
- * do_cont(): Resume emulation.
- */
-static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    struct bdrv_iterate_context context = { mon, 0 };
-
-    if (runstate_check(RUN_STATE_INMIGRATE)) {
-        qerror_report(QERR_MIGRATION_EXPECTED);
-        return -1;
-    } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-               runstate_check(RUN_STATE_SHUTDOWN)) {
-        qerror_report(QERR_RESET_REQUIRED);
-        return -1;
-    }
-
-    bdrv_iterate(iostatus_bdrv_it, NULL);
-    bdrv_iterate(encrypted_bdrv_it, &context);
-    /* only resume the vm if all keys are set and valid */
-    if (!context.err) {
-        vm_start();
-        return 0;
-    } else {
-        return -1;
-    }
-}
-
-static void bdrv_key_cb(void *opaque, int err)
-{
-    Monitor *mon = opaque;
-
-    /* another key was set successfully, retry to continue */
-    if (!err)
-        do_cont(mon, NULL, NULL);
-}
-
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
-{
-    struct bdrv_iterate_context *context = opaque;
-
-    if (!context->err && bdrv_key_required(bs)) {
-        context->err = -EBUSY;
-        monitor_read_bdrv_key_start(context->mon, bs, bdrv_key_cb,
-                                    context->mon);
-    }
-}
-
 static void do_gdbserver(Monitor *mon, const QDict *qdict)
 {
     const char *device = qdict_get_try_str(qdict, "device");
@@ -1370,81 +1316,6 @@ static void do_print(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "\n");
 }
 
-static int do_memory_save(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    FILE *f;
-    uint32_t size = qdict_get_int(qdict, "size");
-    const char *filename = qdict_get_str(qdict, "filename");
-    target_long addr = qdict_get_int(qdict, "val");
-    uint32_t l;
-    CPUState *env;
-    uint8_t buf[1024];
-    int ret = -1;
-
-    env = mon_get_cpu();
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        qerror_report(QERR_OPEN_FILE_FAILED, filename);
-        return -1;
-    }
-    while (size != 0) {
-        l = sizeof(buf);
-        if (l > size)
-            l = size;
-        cpu_memory_rw_debug(env, addr, buf, l, 0);
-        if (fwrite(buf, 1, l, f) != l) {
-            monitor_printf(mon, "fwrite() error in do_memory_save\n");
-            goto exit;
-        }
-        addr += l;
-        size -= l;
-    }
-
-    ret = 0;
-
-exit:
-    fclose(f);
-    return ret;
-}
-
-static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
-                                    QObject **ret_data)
-{
-    FILE *f;
-    uint32_t l;
-    uint8_t buf[1024];
-    uint32_t size = qdict_get_int(qdict, "size");
-    const char *filename = qdict_get_str(qdict, "filename");
-    target_phys_addr_t addr = qdict_get_int(qdict, "val");
-    int ret = -1;
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        qerror_report(QERR_OPEN_FILE_FAILED, filename);
-        return -1;
-    }
-    while (size != 0) {
-        l = sizeof(buf);
-        if (l > size)
-            l = size;
-        cpu_physical_memory_read(addr, buf, l);
-        if (fwrite(buf, 1, l, f) != l) {
-            monitor_printf(mon, "fwrite() error in do_physical_memory_save\n");
-            goto exit;
-        }
-        fflush(f);
-        addr += l;
-        size -= l;
-    }
-
-    ret = 0;
-
-exit:
-    fclose(f);
-    return ret;
-}
-
 static void do_sum(Monitor *mon, const QDict *qdict)
 {
     uint32_t addr;
@@ -1796,16 +1667,6 @@ static void do_boot_set(Monitor *mon, const QDict *qdict)
     }
 }
 
-/**
- * do_system_powerdown(): Issue a machine powerdown
- */
-static int do_system_powerdown(Monitor *mon, const QDict *qdict,
-                               QObject **ret_data)
-{
-    qemu_system_powerdown_request();
-    return 0;
-}
-
 #if defined(TARGET_I386)
 static void print_pte(Monitor *mon, target_phys_addr_t addr,
                       target_phys_addr_t pte,
@@ -2348,25 +2209,6 @@ static void do_wav_capture(Monitor *mon, const QDict *qdict)
 }
 #endif
 
-#if defined(TARGET_I386)
-static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    CPUState *env;
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu_interrupt(env, CPU_INTERRUPT_NMI);
-    }
-
-    return 0;
-}
-#else
-static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    qerror_report(QERR_UNSUPPORTED);
-    return -1;
-}
-#endif
-
 static qemu_acl *find_acl(Monitor *mon, const char *name)
 {
     qemu_acl *acl = qemu_acl_find(name);
@@ -4943,3 +4785,18 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
 
     return err;
 }
+
+int monitor_read_block_device_key(Monitor *mon, const char *device,
+                                  BlockDriverCompletionFunc *completion_cb,
+                                  void *opaque)
+{
+    BlockDriverState *bs;
+
+    bs = bdrv_find(device);
+    if (!bs) {
+        monitor_printf(mon, "Device not found %s\n", device);
+        return -1;
+    }
+
+    return monitor_read_bdrv_key_start(mon, bs, completion_cb, opaque);
+}
diff --git a/monitor.h b/monitor.h
index e76795f1f3..052f1cb244 100644
--- a/monitor.h
+++ b/monitor.h
@@ -49,6 +49,9 @@ void monitor_resume(Monitor *mon);
 int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
                                 BlockDriverCompletionFunc *completion_cb,
                                 void *opaque);
+int monitor_read_block_device_key(Monitor *mon, const char *device,
+                                  BlockDriverCompletionFunc *completion_cb,
+                                  void *opaque);
 
 int monitor_get_fd(Monitor *mon, const char *fdname);
 
diff --git a/net.c b/net.c
index cb52050bfd..f7bebf8cc4 100644
--- a/net.c
+++ b/net.c
@@ -34,6 +34,7 @@
 #include "monitor.h"
 #include "qemu-common.h"
 #include "qemu_socket.h"
+#include "qmp-commands.h"
 #include "hw/qdev.h"
 #include "iov.h"
 
@@ -1258,12 +1259,10 @@ void do_info_network(Monitor *mon)
     }
 }
 
-int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_set_link(const char *name, bool up, Error **errp)
 {
     VLANState *vlan;
     VLANClientState *vc = NULL;
-    const char *name = qdict_get_str(qdict, "name");
-    int up = qdict_get_bool(qdict, "up");
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
@@ -1280,8 +1279,8 @@ int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
 done:
 
     if (!vc) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, name);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, name);
+        return;
     }
 
     vc->link_down = !up;
@@ -1300,7 +1299,6 @@ done:
     if (vc->peer && vc->peer->info->link_status_changed) {
         vc->peer->info->link_status_changed(vc->peer);
     }
-    return 0;
 }
 
 void net_cleanup(void)
diff --git a/net.h b/net.h
index 9f633f8432..c6b41905af 100644
--- a/net.h
+++ b/net.h
@@ -122,7 +122,6 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                         const char *default_model);
 
 void do_info_network(Monitor *mon);
-int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 /* NIC info */
 
diff --git a/net/socket.c b/net/socket.c
index 0f091645ed..aaf9be48e2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -161,10 +161,11 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
 #endif
 
     if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
-	fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n",
-		inet_ntoa(mcastaddr->sin_addr),
+        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
+                "does not contain a multicast address\n",
+                inet_ntoa(mcastaddr->sin_addr),
                 (int)ntohl(mcastaddr->sin_addr.s_addr));
-	return -1;
+        return -1;
 
     }
     fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
@@ -177,8 +178,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                    (const char *)&val, sizeof(val));
     if (ret < 0) {
-	perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
-	goto fail;
+        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
+        goto fail;
     }
 
     ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
@@ -198,8 +199,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                      (const char *)&imr, sizeof(struct ip_mreq));
     if (ret < 0) {
-	perror("setsockopt(IP_ADD_MEMBERSHIP)");
-	goto fail;
+        perror("setsockopt(IP_ADD_MEMBERSHIP)");
+        goto fail;
     }
 
     /* Force mcast msgs to loopback (eg. several QEMUs in same host */
@@ -207,8 +208,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
                    (const char *)&loop, sizeof(loop));
     if (ret < 0) {
-	perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
-	goto fail;
+        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
+        goto fail;
     }
 
     /* If a bind address is given, only send packets from that address */
@@ -260,37 +261,37 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
      */
 
     if (is_connected) {
-	if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
-	    /* must be bound */
-	    if (saddr.sin_addr.s_addr==0) {
-		fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, cannot setup multicast dst addr\n",
-			fd);
-		return NULL;
-	    }
-	    /* clone dgram socket */
-	    newfd = net_socket_mcast_create(&saddr, NULL);
-	    if (newfd < 0) {
-		/* error already reported by net_socket_mcast_create() */
-		close(fd);
-		return NULL;
-	    }
-	    /* clone newfd to fd, close newfd */
-	    dup2(newfd, fd);
-	    close(newfd);
-
-	} else {
-	    fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
-		    fd, strerror(errno));
-	    return NULL;
-	}
+        if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
+            /* must be bound */
+            if (saddr.sin_addr.s_addr == 0) {
+                fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
+                        "cannot setup multicast dst addr\n", fd);
+                goto err;
+            }
+            /* clone dgram socket */
+            newfd = net_socket_mcast_create(&saddr, NULL);
+            if (newfd < 0) {
+                /* error already reported by net_socket_mcast_create() */
+                goto err;
+            }
+            /* clone newfd to fd, close newfd */
+            dup2(newfd, fd);
+            close(newfd);
+
+        } else {
+            fprintf(stderr,
+                    "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
+                    fd, strerror(errno));
+            goto err;
+        }
     }
 
     nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name);
 
     snprintf(nc->info_str, sizeof(nc->info_str),
-	    "socket: fd=%d (%s mcast=%s:%d)",
-	    fd, is_connected ? "cloned" : "",
-	    inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+            "socket: fd=%d (%s mcast=%s:%d)",
+            fd, is_connected ? "cloned" : "",
+            inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
 
     s = DO_UPCAST(NetSocketState, nc, nc);
 
@@ -302,6 +303,10 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
     if (is_connected) s->dgram_dst=saddr;
 
     return s;
+
+err:
+    closesocket(fd);
+    return NULL;
 }
 
 static void net_socket_connect(void *opaque)
@@ -349,8 +354,10 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan,
 
     if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
         (socklen_t *)&optlen)< 0) {
-	fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd);
-	return NULL;
+        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
+                fd);
+        closesocket(fd);
+        return NULL;
     }
     switch(so_type) {
     case SOCK_DGRAM:
@@ -383,9 +390,7 @@ static void net_socket_accept(void *opaque)
         }
     }
     s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1);
-    if (!s1) {
-        closesocket(fd);
-    } else {
+    if (s1) {
         snprintf(s1->nc.info_str, sizeof(s1->nc.info_str),
                  "socket: connection from %s:%d",
                  inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
@@ -512,7 +517,7 @@ static int net_socket_mcast_init(VLANState *vlan,
 
     fd = net_socket_mcast_create(&saddr, param_localaddr);
     if (fd < 0)
-	return -1;
+        return -1;
 
     s = net_socket_fd_init(vlan, model, name, fd, 0);
     if (!s)
@@ -549,7 +554,6 @@ int net_init_socket(QemuOpts *opts,
         }
 
         if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) {
-            close(fd);
             return -1;
         }
     } else if (qemu_opt_get(opts, "listen")) {
diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json
index f4bcd1a532..5f8a18d4d8 100644
--- a/qapi-schema-guest.json
+++ b/qapi-schema-guest.json
@@ -43,7 +43,11 @@
 #
 # Since: 0.15.0
 ##
-{ 'type': 'GuestAgentInfo', 'data': {'version': 'str'} }
+{ 'type': 'GuestAgentCommandInfo',
+  'data': { 'name': 'str', 'enabled': 'bool' } }
+{ 'type': 'GuestAgentInfo',
+  'data': { 'version': 'str',
+            'supported_commands': ['GuestAgentCommandInfo'] } }
 { 'command': 'guest-info',
   'returns': 'GuestAgentInfo' }
 
diff --git a/qapi-schema-test.json b/qapi-schema-test.json
index 3acedad7ee..2b38919001 100644
--- a/qapi-schema-test.json
+++ b/qapi-schema-test.json
@@ -16,6 +16,12 @@
                       'dict': { 'userdef': 'UserDefOne', 'string': 'str' },
                       '*dict2': { 'userdef': 'UserDefOne', 'string': 'str' } } } }
 
+{ 'type': 'UserDefNested',
+  'data': { 'string0': 'str',
+            'dict1': { 'string1': 'str',
+                       'dict2': { 'userdef1': 'UserDefOne', 'string2': 'str' },
+                       '*dict3': { 'userdef2': 'UserDefOne', 'string3': 'str' } } } }
+
 # testing commands
 { 'command': 'user_def_cmd', 'data': {} }
 { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
diff --git a/qapi-schema.json b/qapi-schema.json
index fbbdbe0914..f358b490b0 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -901,3 +901,270 @@
 # Notes: Do not use this command.
 ##
 { 'command': 'cpu', 'data': {'index': 'int'} }
+
+##
+# @memsave:
+#
+# Save a portion of guest memory to a file.
+#
+# @val: the virtual address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# @cpu-index: #optional the index of the virtual CPU to use for translating the
+#                       virtual address (defaults to CPU 0)
+#
+# Returns: Nothing on success
+#          If @cpu is not a valid VCPU, InvalidParameterValue
+#          If @filename cannot be opened, OpenFileFailed
+#          If an I/O error occurs while writing the file, IOError
+#
+# Since: 0.14.0
+#
+# Notes: Errors were not reliably returned until 1.1
+##
+{ 'command': 'memsave',
+  'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
+
+##
+# @pmemsave:
+#
+# Save a portion of guest physical memory to a file.
+#
+# @val: the physical address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# Returns: Nothing on success
+#          If @filename cannot be opened, OpenFileFailed
+#          If an I/O error occurs while writing the file, IOError
+#
+# Since: 0.14.0
+#
+# Notes: Errors were not reliably returned until 1.1
+##
+{ 'command': 'pmemsave',
+  'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
+
+##
+# @cont:
+#
+# Resume guest VCPU execution.
+#
+# Since:  0.14.0
+#
+# Returns:  If successful, nothing
+#           If the QEMU is waiting for an incoming migration, MigrationExpected
+#           If QEMU was started with an encrypted block device and a key has
+#              not yet been set, DeviceEncrypted.
+#
+# Notes:  This command will succeed if the guest is currently running.
+##
+{ 'command': 'cont' }
+
+##
+# @inject-nmi:
+#
+# Injects an Non-Maskable Interrupt into all guest's VCPUs.
+#
+# Returns:  If successful, nothing
+#           If the Virtual Machine doesn't support NMI injection, Unsupported
+#
+# Since:  0.14.0
+#
+# Notes: Only x86 Virtual Machines support this command.
+##
+{ 'command': 'inject-nmi' }
+
+##
+# @set_link:
+#
+# Sets the link status of a virtual network adapter.
+#
+# @name: the device name of the virtual network adapter
+#
+# @up: true to set the link status to be up
+#
+# Returns: Nothing on success
+#          If @name is not a valid network device, DeviceNotFound
+#
+# Since: 0.14.0
+#
+# Notes: Not all network adapters support setting link status.  This command
+#        will succeed even if the network adapter does not support link status
+#        notification.
+##
+{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }
+
+##
+# @block_passwd:
+#
+# This command sets the password of a block device that has not been open
+# with a password and requires one.
+#
+# The two cases where this can happen are a block device is created through
+# QEMU's initial command line or a block device is changed through the legacy
+# @change interface.
+#
+# In the event that the block device is created through the initial command
+# line, the VM will start in the stopped state regardless of whether '-S' is
+# used.  The intention is for a management tool to query the block devices to
+# determine which ones are encrypted, set the passwords with this command, and
+# then start the guest with the @cont command.
+#
+# @device:   the name of the device to set the password on
+#
+# @password: the password to use for the device
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#          If @device is not encrypted, DeviceNotEncrypted
+#          If @password is not valid for this device, InvalidPassword
+#
+# Notes:  Not all block formats support encryption and some that do are not
+#         able to validate that a password is correct.  Disk corruption may
+#         occur if an invalid password is specified.
+#
+# Since: 0.14.0
+##
+{ 'command': 'block_passwd', 'data': {'device': 'str', 'password': 'str'} }
+
+##
+# @balloon:
+#
+# Request the balloon driver to change its balloon size.
+#
+# @value: the target size of the balloon in bytes
+#
+# Returns: Nothing on success
+#          If the balloon driver is enabled but not functional because the KVM
+#            kernel module cannot support it, KvmMissingCap
+#          If no balloon device is present, DeviceNotActive
+#
+# Notes: This command just issues a request to the guest.  When it returns,
+#        the balloon size may not have changed.  A guest can change the balloon
+#        size independent of this command.
+#
+# Since: 0.14.0
+##
+{ 'command': 'balloon', 'data': {'value': 'int'} }
+
+##
+# @block_resize
+#
+# Resize a block image while a guest is running.
+#
+# @device:  the name of the device to get the image resized
+#
+# @size:  new image size in bytes
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#
+# Notes: This command returns UndefinedError in a number of error conditions.
+#
+# Since: 0.14.0
+##
+{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
+
+##
+# @blockdev-snapshot-sync
+#
+# Generates a synchronous snapshot of a block device.
+#
+# @device:  the name of the device to generate the snapshot from.
+#
+# @snapshot-file: the target of the new image. If the file exists, or if it
+#                 is a device, the snapshot will be created in the existing
+#                 file/device. If does not exist, a new file will be created.
+#
+# @format: #optional the format of the snapshot image, default is 'qcow2'.
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#          If @snapshot-file can't be opened, OpenFileFailed
+#          If @format is invalid, InvalidBlockFormat
+#
+# Notes: One of the last steps taken by this command is to close the current
+#        image being used by @device and open the @snapshot-file one. If that
+#        fails, the command will try to reopen the original image file. If
+#        that also fails OpenFileFailed will be returned and the guest may get
+#        unexpected errors.
+#
+# Since 0.14.0
+##
+{ 'command': 'blockdev-snapshot-sync',
+  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
+
+##
+# @human-monitor-command:
+#
+# Execute a command on the human monitor and return the output.
+#
+# @command-line: the command to execute in the human monitor
+#
+# @cpu-index: #optional The CPU to use for commands that require an implicit CPU
+#
+# Returns: the output of the command as a string
+#
+# Since: 0.14.0
+#
+# Notes: This command only exists as a stop-gap.  It's use is highly
+#        discouraged.  The semantics of this command are not guaranteed.
+#
+#        Known limitations:
+#
+#        o This command is stateless, this means that commands that depend
+#          on state information (such as getfd) might not work
+#
+#       o Commands that prompt the user for data (eg. 'cont' when the block
+#         device is encrypted) don't currently work
+##
+{ 'command': 'human-monitor-command',
+  'data': {'command-line': 'str', '*cpu-index': 'int'},
+  'returns': 'str' } 
+
+##
+# @migrate_cancel
+#
+# Cancel the current executing migration process.
+#
+# Returns: nothing on success
+#
+# Notes: This command succeeds even if there is no migration process running.
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_cancel' }
+
+##
+# @migrate_set_downtime
+#
+# Set maximum tolerated downtime for migration.
+#
+# @value: maximum downtime in seconds
+#
+# Returns: nothing on success
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_set_downtime', 'data': {'value': 'number'} }
+
+##
+# @migrate_set_speed
+#
+# Set maximum speed for migration.
+#
+# @value: maximum speed in bytes.
+#
+# Returns: nothing on success
+#
+# Notes: A value lesser than zero will be automatically round up to zero.
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
diff --git a/qapi/qmp-core.h b/qapi/qmp-core.h
index f1c26e4b2e..3bb3acb589 100644
--- a/qapi/qmp-core.h
+++ b/qapi/qmp-core.h
@@ -31,11 +31,15 @@ typedef struct QmpCommand
     QmpCommandType type;
     QmpCommandFunc *fn;
     QTAILQ_ENTRY(QmpCommand) node;
+    bool enabled;
 } QmpCommand;
 
 void qmp_register_command(const char *name, QmpCommandFunc *fn);
 QmpCommand *qmp_find_command(const char *name);
 QObject *qmp_dispatch(QObject *request);
+void qmp_disable_command(const char *name);
+bool qmp_command_is_enabled(const char *name);
+char **qmp_get_command_list(void);
 
 #endif
 
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 558469325c..43f640a95e 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -79,6 +79,10 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
         error_set(errp, QERR_COMMAND_NOT_FOUND, command);
         return NULL;
     }
+    if (!cmd->enabled) {
+        error_set(errp, QERR_COMMAND_DISABLED, command);
+        return NULL;
+    }
 
     if (!qdict_haskey(dict, "arguments")) {
         args = qdict_new();
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 5ff99cff14..25c89ad098 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -14,7 +14,7 @@
 
 #include "qapi/qmp-core.h"
 
-static QTAILQ_HEAD(, QmpCommand) qmp_commands =
+static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
     QTAILQ_HEAD_INITIALIZER(qmp_commands);
 
 void qmp_register_command(const char *name, QmpCommandFunc *fn)
@@ -24,17 +24,63 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn)
     cmd->name = name;
     cmd->type = QCT_NORMAL;
     cmd->fn = fn;
+    cmd->enabled = true;
     QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
 }
 
 QmpCommand *qmp_find_command(const char *name)
 {
-    QmpCommand *i;
+    QmpCommand *cmd;
 
-    QTAILQ_FOREACH(i, &qmp_commands, node) {
-        if (strcmp(i->name, name) == 0) {
-            return i;
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        if (strcmp(cmd->name, name) == 0) {
+            return cmd;
         }
     }
     return NULL;
 }
+
+void qmp_disable_command(const char *name)
+{
+    QmpCommand *cmd;
+
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        if (strcmp(cmd->name, name) == 0) {
+            cmd->enabled = false;
+            return;
+        }
+    }
+}
+
+bool qmp_command_is_enabled(const char *name)
+{
+    QmpCommand *cmd;
+
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        if (strcmp(cmd->name, name) == 0) {
+            return cmd->enabled;
+        }
+    }
+
+    return false;
+}
+
+char **qmp_get_command_list(void)
+{
+    QmpCommand *cmd;
+    int count = 1;
+    char **list_head, **list;
+
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        count++;
+    }
+
+    list_head = list = g_malloc0(count * sizeof(char *));
+
+    QTAILQ_FOREACH(cmd, &qmp_commands, node) {
+        *list = strdup(cmd->name);
+        list++;
+    }
+
+    return list_head;
+}
diff --git a/qemu-ga.c b/qemu-ga.c
index 49320133c6..200bb1585f 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -27,6 +27,7 @@
 #include "signal.h"
 #include "qerror.h"
 #include "error_int.h"
+#include "qapi/qmp-core.h"
 
 #define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0"
 #define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
@@ -91,6 +92,8 @@ static void usage(const char *cmd)
 "  -v, --verbose     log extra debugging information\n"
 "  -V, --version     print version information and exit\n"
 "  -d, --daemonize   become a daemon\n"
+"  -b, --blacklist   comma-seperated list of RPCs to disable (no spaces, \"?\""
+"                    to list available RPCs)\n"
 "  -h, --help        display this help and exit\n"
 "\n"
 "Report bugs to <mdroth@linux.vnet.ibm.com>\n"
@@ -548,7 +551,7 @@ static void init_guest_agent(GAState *s)
 
 int main(int argc, char **argv)
 {
-    const char *sopt = "hVvdm:p:l:f:";
+    const char *sopt = "hVvdm:p:l:f:b:";
     const char *method = NULL, *path = NULL, *pidfile = QGA_PIDFILE_DEFAULT;
     const struct option lopt[] = {
         { "help", 0, NULL, 'h' },
@@ -559,13 +562,16 @@ int main(int argc, char **argv)
         { "method", 0, NULL, 'm' },
         { "path", 0, NULL, 'p' },
         { "daemonize", 0, NULL, 'd' },
+        { "blacklist", 0, NULL, 'b' },
         { NULL, 0, NULL, 0 }
     };
-    int opt_ind = 0, ch, daemonize = 0;
+    int opt_ind = 0, ch, daemonize = 0, i, j, len;
     GLogLevelFlags log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
     FILE *log_file = stderr;
     GAState *s;
 
+    module_call_init(MODULE_INIT_QAPI);
+
     while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
         switch (ch) {
         case 'm':
@@ -595,6 +601,32 @@ int main(int argc, char **argv)
         case 'd':
             daemonize = 1;
             break;
+        case 'b': {
+            char **list_head, **list;
+            if (*optarg == '?') {
+                list_head = list = qmp_get_command_list();
+                while (*list != NULL) {
+                    printf("%s\n", *list);
+                    g_free(*list);
+                    list++;
+                }
+                g_free(list_head);
+                return 0;
+            }
+            for (j = 0, i = 0, len = strlen(optarg); i < len; i++) {
+                if (optarg[i] == ',') {
+                    optarg[i] = 0;
+                    qmp_disable_command(&optarg[j]);
+                    g_debug("disabling command: %s", &optarg[j]);
+                    j = i + 1;
+                }
+            }
+            if (j < i) {
+                qmp_disable_command(&optarg[j]);
+                g_debug("disabling command: %s", &optarg[j]);
+            }
+            break;
+        }
         case 'h':
             usage(argv[0]);
             return 0;
@@ -624,7 +656,6 @@ int main(int argc, char **argv)
     ga_command_state_init_all(s->command_state);
     ga_state = s;
 
-    module_call_init(MODULE_INIT_QAPI);
     init_guest_agent(ga_state);
     register_signal_handlers();
 
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index ac3c0c9d14..9e1b5fbdaa 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -117,20 +117,33 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
 
 void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void*),
-                       void *arg)
+                       void *arg, int mode)
 {
+    sigset_t set, oldset;
     int err;
+    pthread_attr_t attr;
 
-    /* Leave signal handling to the iothread.  */
-    sigset_t set, oldset;
+    err = pthread_attr_init(&attr);
+    if (err) {
+        error_exit(err, __func__);
+    }
+    if (mode == QEMU_THREAD_DETACHED) {
+        err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+        if (err) {
+            error_exit(err, __func__);
+        }
+    }
 
+    /* Leave signal handling to the iothread.  */
     sigfillset(&set);
     pthread_sigmask(SIG_SETMASK, &set, &oldset);
-    err = pthread_create(&thread->thread, NULL, start_routine, arg);
+    err = pthread_create(&thread->thread, &attr, start_routine, arg);
     if (err)
         error_exit(err, __func__);
 
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+
+    pthread_attr_destroy(&attr);
 }
 
 void qemu_thread_get_self(QemuThread *thread)
@@ -147,3 +160,15 @@ void qemu_thread_exit(void *retval)
 {
     pthread_exit(retval);
 }
+
+void *qemu_thread_join(QemuThread *thread)
+{
+    int err;
+    void *ret;
+
+    err = pthread_join(thread->thread, &ret);
+    if (err) {
+        error_exit(err, __func__);
+    }
+    return ret;
+}
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index db8e744729..a13ffcca69 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -193,41 +193,78 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
 }
 
 struct QemuThreadData {
-    QemuThread *thread;
-    void *(*start_routine)(void *);
-    void *arg;
+    /* Passed to win32_start_routine.  */
+    void             *(*start_routine)(void *);
+    void             *arg;
+    short             mode;
+
+    /* Only used for joinable threads. */
+    bool              exited;
+    void             *ret;
+    CRITICAL_SECTION  cs;
 };
 
 static int qemu_thread_tls_index = TLS_OUT_OF_INDEXES;
 
 static unsigned __stdcall win32_start_routine(void *arg)
 {
-    struct QemuThreadData data = *(struct QemuThreadData *) arg;
-    QemuThread *thread = data.thread;
-
-    free(arg);
-    TlsSetValue(qemu_thread_tls_index, thread);
-
-    /*
-     * Use DuplicateHandle instead of assigning thread->thread in the
-     * creating thread to avoid races.  It's simpler this way than with
-     * synchronization.
-     */
-    DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
-                    GetCurrentProcess(), &thread->thread,
-                    0, FALSE, DUPLICATE_SAME_ACCESS);
-
-    qemu_thread_exit(data.start_routine(data.arg));
+    QemuThreadData *data = (QemuThreadData *) arg;
+    void *(*start_routine)(void *) = data->start_routine;
+    void *thread_arg = data->arg;
+
+    if (data->mode == QEMU_THREAD_DETACHED) {
+        g_free(data);
+        data = NULL;
+    } else {
+        InitializeCriticalSection(&data->cs);
+    }
+    TlsSetValue(qemu_thread_tls_index, data);
+    qemu_thread_exit(start_routine(thread_arg));
     abort();
 }
 
 void qemu_thread_exit(void *arg)
 {
-    QemuThread *thread = TlsGetValue(qemu_thread_tls_index);
-    thread->ret = arg;
-    CloseHandle(thread->thread);
-    thread->thread = NULL;
-    ExitThread(0);
+    QemuThreadData *data = TlsGetValue(qemu_thread_tls_index);
+    if (data) {
+        data->ret = arg;
+        EnterCriticalSection(&data->cs);
+        data->exited = true;
+        LeaveCriticalSection(&data->cs);
+    }
+    _endthreadex(0);
+}
+
+void *qemu_thread_join(QemuThread *thread)
+{
+    QemuThreadData *data;
+    void *ret;
+    HANDLE handle;
+
+    data = thread->data;
+    if (!data) {
+        return NULL;
+    }
+    /*
+     * Because multiple copies of the QemuThread can exist via
+     * qemu_thread_get_self, we need to store a value that cannot
+     * leak there.  The simplest, non racy way is to store the TID,
+     * discard the handle that _beginthreadex gives back, and
+     * get another copy of the handle here.
+     */
+    EnterCriticalSection(&data->cs);
+    if (!data->exited) {
+        handle = OpenThread(SYNCHRONIZE, FALSE, thread->tid);
+        LeaveCriticalSection(&data->cs);
+        WaitForSingleObject(handle, INFINITE);
+        CloseHandle(handle);
+    } else {
+        LeaveCriticalSection(&data->cs);
+    }
+    ret = data->ret;
+    DeleteCriticalSection(&data->cs);
+    g_free(data);
+    return ret;
 }
 
 static inline void qemu_thread_init(void)
@@ -243,39 +280,35 @@ static inline void qemu_thread_init(void)
 
 void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void *),
-                       void *arg)
+                       void *arg, int mode)
 {
     HANDLE hThread;
 
     struct QemuThreadData *data;
     qemu_thread_init();
     data = g_malloc(sizeof *data);
-    data->thread = thread;
     data->start_routine = start_routine;
     data->arg = arg;
+    data->mode = mode;
+    data->exited = false;
 
     hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
-                                      data, 0, NULL);
+                                      data, 0, &thread->tid);
     if (!hThread) {
         error_exit(GetLastError(), __func__);
     }
     CloseHandle(hThread);
+    thread->data = (mode == QEMU_THREAD_DETACHED) ? NULL : data;
 }
 
 void qemu_thread_get_self(QemuThread *thread)
 {
-    if (!thread->thread) {
-        /* In the main thread of the process.  Initialize the QemuThread
-           pointer in TLS, and use the dummy GetCurrentThread handle as
-           the identifier for qemu_thread_is_self.  */
-        qemu_thread_init();
-        TlsSetValue(qemu_thread_tls_index, thread);
-        thread->thread = GetCurrentThread();
-    }
+    qemu_thread_init();
+    thread->data = TlsGetValue(qemu_thread_tls_index);
+    thread->tid = GetCurrentThreadId();
 }
 
 int qemu_thread_is_self(QemuThread *thread)
 {
-    QemuThread *this_thread = TlsGetValue(qemu_thread_tls_index);
-    return this_thread->thread == thread->thread;
+    return GetCurrentThreadId() == thread->tid;
 }
diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h
index 878f86a910..2983490a58 100644
--- a/qemu-thread-win32.h
+++ b/qemu-thread-win32.h
@@ -13,9 +13,10 @@ struct QemuCond {
     HANDLE continue_event;
 };
 
+typedef struct QemuThreadData QemuThreadData;
 struct QemuThread {
-    HANDLE thread;
-    void *ret;
+    QemuThreadData *data;
+    unsigned tid;
 };
 
 #endif
diff --git a/qemu-thread.h b/qemu-thread.h
index e008b60028..a78a8f2524 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -13,6 +13,9 @@ typedef struct QemuThread QemuThread;
 #include "qemu-thread-posix.h"
 #endif
 
+#define QEMU_THREAD_JOINABLE 0
+#define QEMU_THREAD_DETACHED 1
+
 void qemu_mutex_init(QemuMutex *mutex);
 void qemu_mutex_destroy(QemuMutex *mutex);
 void qemu_mutex_lock(QemuMutex *mutex);
@@ -35,8 +38,9 @@ void qemu_cond_broadcast(QemuCond *cond);
 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
 
 void qemu_thread_create(QemuThread *thread,
-                       void *(*start_routine)(void*),
-                       void *arg);
+                        void *(*start_routine)(void *),
+                        void *arg, int mode);
+void *qemu_thread_join(QemuThread *thread);
 void qemu_thread_get_self(QemuThread *thread);
 int qemu_thread_is_self(QemuThread *thread);
 void qemu_thread_exit(void *retval);
diff --git a/qerror.c b/qerror.c
index d9ab3969d2..830c9c3ddf 100644
--- a/qerror.c
+++ b/qerror.c
@@ -65,6 +65,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "The command %(name) has not been found",
     },
     {
+        .error_fmt = QERR_COMMAND_DISABLED,
+        .desc      = "The command %(name) has been disabled for this instance",
+    },
+    {
         .error_fmt = QERR_DEVICE_ENCRYPTED,
         .desc      = "Device '%(device)' is encrypted",
     },
@@ -149,6 +153,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Password incorrect",
     },
     {
+        .error_fmt = QERR_IO_ERROR,
+        .desc      = "An IO error has occurred",
+    },
+    {
         .error_fmt = QERR_JSON_PARSING,
         .desc      = "Invalid JSON syntax",
     },
diff --git a/qerror.h b/qerror.h
index 161d654b75..688e700223 100644
--- a/qerror.h
+++ b/qerror.h
@@ -66,6 +66,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_COMMAND_NOT_FOUND \
     "{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
 
+#define QERR_COMMAND_DISABLED \
+    "{ 'class': 'CommandDisabled', 'data': { 'name': %s } }"
+
 #define QERR_DEVICE_ENCRYPTED \
     "{ 'class': 'DeviceEncrypted', 'data': { 'device': %s } }"
 
@@ -126,6 +129,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_INVALID_PASSWORD \
     "{ 'class': 'InvalidPassword', 'data': {} }"
 
+#define QERR_IO_ERROR \
+    "{ 'class': 'IOError', 'data': {} }"
+
 #define QERR_JSON_PARSING \
     "{ 'class': 'JSONParsing', 'data': {} }"
 
diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c
index 6da9904819..a09c8ca230 100644
--- a/qga/guest-agent-commands.c
+++ b/qga/guest-agent-commands.c
@@ -57,9 +57,33 @@ void qmp_guest_ping(Error **err)
 struct GuestAgentInfo *qmp_guest_info(Error **err)
 {
     GuestAgentInfo *info = g_malloc0(sizeof(GuestAgentInfo));
+    GuestAgentCommandInfo *cmd_info;
+    GuestAgentCommandInfoList *cmd_info_list;
+    char **cmd_list_head, **cmd_list;
 
     info->version = g_strdup(QGA_VERSION);
 
+    cmd_list_head = cmd_list = qmp_get_command_list();
+    if (*cmd_list_head == NULL) {
+        goto out;
+    }
+
+    while (*cmd_list) {
+        cmd_info = g_malloc0(sizeof(GuestAgentCommandInfo));
+        cmd_info->name = strdup(*cmd_list);
+        cmd_info->enabled = qmp_command_is_enabled(cmd_info->name);
+
+        cmd_info_list = g_malloc0(sizeof(GuestAgentCommandInfoList));
+        cmd_info_list->value = cmd_info;
+        cmd_info_list->next = info->supported_commands;
+        info->supported_commands = cmd_info_list;
+
+        g_free(*cmd_list);
+        cmd_list++;
+    }
+
+out:
+    g_free(cmd_list_head);
     return info;
 }
 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 94da2a8ef2..002e7e8bd9 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -199,10 +199,7 @@ EQMP
     {
         .name       = "cont",
         .args_type  = "",
-        .params     = "",
-        .help       = "resume emulation",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_cont,
+        .mhandler.cmd_new = qmp_marshal_input_cont,
     },
 
 SQMP
@@ -244,10 +241,7 @@ EQMP
     {
         .name       = "system_powerdown",
         .args_type  = "",
-        .params     = "",
-        .help       = "send system power down event",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_system_powerdown,
+        .mhandler.cmd_new = qmp_marshal_input_system_powerdown,
     },
 
 SQMP
@@ -355,11 +349,8 @@ EQMP
 
     {
         .name       = "memsave",
-        .args_type  = "val:l,size:i,filename:s",
-        .params     = "addr size file",
-        .help       = "save to disk virtual memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_memory_save,
+        .args_type  = "val:l,size:i,filename:s,cpu:i?",
+        .mhandler.cmd_new = qmp_marshal_input_memsave,
     },
 
 SQMP
@@ -373,6 +364,7 @@ Arguments:
 - "val": the starting address (json-int)
 - "size": the memory size, in bytes (json-int)
 - "filename": file path (json-string)
+- "cpu": virtual CPU index (json-int, optional)
 
 Example:
 
@@ -382,17 +374,12 @@ Example:
                             "filename": "/tmp/virtual-mem-dump" } }
 <- { "return": {} }
 
-Note: Depends on the current CPU.
-
 EQMP
 
     {
         .name       = "pmemsave",
         .args_type  = "val:l,size:i,filename:s",
-        .params     = "addr size file",
-        .help       = "save to disk physical memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_physical_memory_save,
+        .mhandler.cmd_new = qmp_marshal_input_pmemsave,
     },
 
 SQMP
@@ -420,10 +407,7 @@ EQMP
     {
         .name       = "inject-nmi",
         .args_type  = "",
-        .params     = "",
-        .help       = "",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_inject_nmi,
+        .mhandler.cmd_new = qmp_marshal_input_inject_nmi,
     },
 
 SQMP
@@ -487,10 +471,7 @@ EQMP
     {
         .name       = "migrate_cancel",
         .args_type  = "",
-        .params     = "",
-        .help       = "cancel the current VM migration",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_cancel,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_cancel,
     },
 
 SQMP
@@ -511,10 +492,7 @@ EQMP
     {
         .name       = "migrate_set_speed",
         .args_type  = "value:o",
-        .params     = "value",
-        .help       = "set maximum speed (in bytes) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_speed,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_set_speed,
     },
 
 SQMP
@@ -537,10 +515,7 @@ EQMP
     {
         .name       = "migrate_set_downtime",
         .args_type  = "value:T",
-        .params     = "value",
-        .help       = "set maximum tolerated downtime (in seconds) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_downtime,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_set_downtime,
     },
 
 SQMP
@@ -658,10 +633,7 @@ EQMP
     {
         .name       = "block_resize",
         .args_type  = "device:B,size:o",
-        .params     = "device size",
-        .help       = "resize a block image",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_resize,
+        .mhandler.cmd_new = qmp_marshal_input_block_resize,
     },
 
 SQMP
@@ -684,10 +656,8 @@ EQMP
 
     {
         .name       = "blockdev-snapshot-sync",
-        .args_type  = "device:B,snapshot-file:s?,format:s?",
-        .params     = "device [new-image-file] [format]",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_snapshot_blkdev,
+        .args_type  = "device:B,snapshot-file:s,format:s?",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_sync,
     },
 
 SQMP
@@ -719,11 +689,7 @@ EQMP
     {
         .name       = "balloon",
         .args_type  = "value:M",
-        .params     = "target",
-        .help       = "request VM to change its memory allocation (in MB)",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_async = do_balloon,
-        .flags      = MONITOR_CMD_ASYNC,
+        .mhandler.cmd_new = qmp_marshal_input_balloon,
     },
 
 SQMP
@@ -746,10 +712,7 @@ EQMP
     {
         .name       = "set_link",
         .args_type  = "name:s,up:b",
-        .params     = "name on|off",
-        .help       = "change the link status of a network adapter",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_set_link,
+        .mhandler.cmd_new = qmp_marshal_input_set_link,
     },
 
 SQMP
@@ -825,10 +788,7 @@ EQMP
     {
         .name       = "block_passwd",
         .args_type  = "device:B,password:s",
-        .params     = "block_passwd device password",
-        .help       = "set the password of encrypted block devices",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_set_passwd,
+        .mhandler.cmd_new = qmp_marshal_input_block_passwd,
     },
 
 SQMP
@@ -1001,10 +961,7 @@ EQMP
     {
         .name       = "human-monitor-command",
         .args_type  = "command-line:s,cpu-index:i?",
-        .params     = "",
-        .help       = "",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_hmp_passthrough,
+        .mhandler.cmd_new = qmp_marshal_input_human_monitor_command,
     },
 
 SQMP
diff --git a/qmp.c b/qmp.c
index 511dd624b5..d71ceb4e4d 100644
--- a/qmp.c
+++ b/qmp.c
@@ -117,3 +117,40 @@ SpiceInfo *qmp_query_spice(Error **errp)
     return NULL;
 };
 #endif
+
+static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    bdrv_iostatus_reset(bs);
+}
+
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    Error **err = opaque;
+
+    if (!error_is_set(err) && bdrv_key_required(bs)) {
+        error_set(err, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
+    }
+}
+
+void qmp_cont(Error **errp)
+{
+    Error *local_err = NULL;
+
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        error_set(errp, QERR_MIGRATION_EXPECTED);
+        return;
+    } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+               runstate_check(RUN_STATE_SHUTDOWN)) {
+        error_set(errp, QERR_RESET_REQUIRED);
+        return;
+    }
+
+    bdrv_iterate(iostatus_bdrv_it, NULL);
+    bdrv_iterate(encrypted_bdrv_it, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    vm_start();
+}
diff --git a/savevm.c b/savevm.c
index 1a21ab441f..b72f6c0d17 100644
--- a/savevm.c
+++ b/savevm.c
@@ -235,6 +235,9 @@ static int stdio_pclose(void *opaque)
     QEMUFileStdio *s = opaque;
     int ret;
     ret = pclose(s->stdio_file);
+    if (ret == -1) {
+        ret = -errno;
+    }
     g_free(s);
     return ret;
 }
@@ -242,9 +245,12 @@ static int stdio_pclose(void *opaque)
 static int stdio_fclose(void *opaque)
 {
     QEMUFileStdio *s = opaque;
-    fclose(s->stdio_file);
+    int ret = 0;
+    if (fclose(s->stdio_file) == EOF) {
+        ret = -errno;
+    }
     g_free(s);
-    return 0;
+    return ret;
 }
 
 QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
@@ -436,6 +442,22 @@ void qemu_file_set_error(QEMUFile *f, int ret)
     f->last_error = ret;
 }
 
+/** Sets last_error conditionally
+ *
+ * Sets last_error only if ret is negative _and_ no error
+ * was set before.
+ */
+static void qemu_file_set_if_error(QEMUFile *f, int ret)
+{
+    if (ret < 0 && !f->last_error) {
+        qemu_file_set_error(f, ret);
+    }
+}
+
+/** Flushes QEMUFile buffer
+ *
+ * In case of error, last_error is set.
+ */
 void qemu_fflush(QEMUFile *f)
 {
     if (!f->put_buffer)
@@ -448,7 +470,7 @@ void qemu_fflush(QEMUFile *f)
         if (len > 0)
             f->buf_offset += f->buf_index;
         else
-            f->last_error = -EINVAL;
+            qemu_file_set_error(f, -EINVAL);
         f->buf_index = 0;
     }
 }
@@ -479,15 +501,44 @@ static void qemu_fill_buffer(QEMUFile *f)
     } else if (len == 0) {
         f->last_error = -EIO;
     } else if (len != -EAGAIN)
-        f->last_error = len;
+        qemu_file_set_error(f, len);
 }
 
-int qemu_fclose(QEMUFile *f)
+/** Calls close function and set last_error if needed
+ *
+ * Internal function. qemu_fflush() must be called before this.
+ *
+ * Returns f->close() return value, or 0 if close function is not set.
+ */
+static int qemu_close(QEMUFile *f)
 {
     int ret = 0;
-    qemu_fflush(f);
-    if (f->close)
+    if (f->close) {
         ret = f->close(f->opaque);
+        qemu_file_set_if_error(f, ret);
+    }
+    return ret;
+}
+
+/** Closes the file
+ *
+ * Returns negative error value if any error happened on previous operations or
+ * while closing the file. Returns 0 or positive number on success.
+ *
+ * The meaning of return value on success depends on the specific backend
+ * being used.
+ */
+int qemu_fclose(QEMUFile *f)
+{
+    int ret;
+    qemu_fflush(f);
+    ret = qemu_close(f);
+    /* If any error was spotted before closing, we should report it
+     * instead of the close() return value.
+     */
+    if (f->last_error) {
+        ret = f->last_error;
+    }
     g_free(f);
     return ret;
 }
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 8ae0ce3ef3..453afbb66e 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -67,6 +67,8 @@
 #define Q_FLAG 0x80000000
 #define M_FLAG 0x40000000
 #define PFIX_FLAG 0x800      /* CRISv10 Only.  */
+#define F_FLAG_V10 0x400
+#define P_FLAG_V10 0x200
 #define S_FLAG 0x200
 #define R_FLAG 0x100
 #define P_FLAG 0x80
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 75f0035e6e..5bc6d810cb 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -157,6 +157,7 @@ static void do_interruptv10(CPUState *env)
 	/* Now that we are in kernel mode, load the handlers address.  */
 	env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
 	env->locked_irq = 1;
+	env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
 
 	qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
 		      __func__, env->pc, ex_vec, 
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 637ac2084a..95053b64fb 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -62,6 +62,65 @@ static inline void cris_illegal_insn(DisasContext *dc)
     t_gen_raise_exception(EXCP_BREAK);
 }
 
+static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val,
+                       unsigned int size, int mem_index)
+{
+    int l1 = gen_new_label();
+    TCGv taddr = tcg_temp_local_new();
+    TCGv tval = tcg_temp_local_new();
+    TCGv t1 = tcg_temp_local_new();
+    dc->postinc = 0;
+    cris_evaluate_flags(dc);
+
+    tcg_gen_mov_tl(taddr, addr);
+    tcg_gen_mov_tl(tval, val);
+
+    /* Store only if F flag isn't set */
+    tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10);
+    tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+    if (size == 1) {
+        tcg_gen_qemu_st8(tval, taddr, mem_index);
+    } else if (size == 2) {
+        tcg_gen_qemu_st16(tval, taddr, mem_index);
+    } else {
+        tcg_gen_qemu_st32(tval, taddr, mem_index);
+    }
+    gen_set_label(l1);
+    tcg_gen_shri_tl(t1, t1, 1);  /* shift F to P position */
+    tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/
+    tcg_temp_free(t1);
+    tcg_temp_free(tval);
+    tcg_temp_free(taddr);
+}
+
+static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val,
+                       unsigned int size)
+{
+    int mem_index = cpu_mmu_index(dc->env);
+
+    /* If we get a fault on a delayslot we must keep the jmp state in
+       the cpu-state to be able to re-execute the jmp.  */
+    if (dc->delayed_branch == 1) {
+        cris_store_direct_jmp(dc);
+    }
+
+    /* Conditional writes. We only support the kind were X is known
+       at translation time.  */
+    if (dc->flagx_known && dc->flags_x) {
+        gen_store_v10_conditional(dc, addr, val, size, mem_index);
+        return;
+    }
+
+    if (size == 1) {
+        tcg_gen_qemu_st8(val, addr, mem_index);
+    } else if (size == 2) {
+        tcg_gen_qemu_st16(val, addr, mem_index);
+    } else {
+        tcg_gen_qemu_st32(val, addr, mem_index);
+    }
+}
+
+
 /* Prefix flag and register are used to handle the more complex
    addressing modes.  */
 static void cris_set_prefix(DisasContext *dc)
@@ -313,7 +372,8 @@ static unsigned int dec10_setclrf(DisasContext *dc)
     if (set) {
         tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
     } else {
-        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
+        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS],
+                        ~(flags|F_FLAG_V10|P_FLAG_V10));
     }
 
     dc->flags_uptodate = 1;
@@ -723,7 +783,7 @@ static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size)
     LOG_DIS("move.%d $r%d, [$r%d]\n", dc->size, dc->src, dc->dst);
     addr = tcg_temp_new();
     crisv10_prepare_memaddr(dc, addr, size);
-    gen_store(dc, addr, cpu_R[dc->dst], size);
+    gen_store_v10(dc, addr, cpu_R[dc->dst], size);
     insn_len += crisv10_post_memaddr(dc, size);
 
     return insn_len;
@@ -767,10 +827,10 @@ static unsigned int dec10_ind_move_pr_m(DisasContext *dc)
         t0 = tcg_temp_new();
         cris_evaluate_flags(dc);
         tcg_gen_andi_tl(t0, cpu_PR[PR_CCS], ~PFIX_FLAG);
-        gen_store(dc, addr, t0, size);
+        gen_store_v10(dc, addr, t0, size);
         tcg_temp_free(t0);
     } else {
-        gen_store(dc, addr, cpu_PR[dc->dst], size);
+        gen_store_v10(dc, addr, cpu_PR[dc->dst], size);
     }
     t0 = tcg_temp_new();
     insn_len += crisv10_post_memaddr(dc, size);
@@ -793,9 +853,9 @@ static void dec10_movem_r_m(DisasContext *dc)
     tcg_gen_mov_tl(t0, addr);
     for (i = dc->dst; i >= 0; i--) {
         if ((pfix && dc->mode == CRISV10_MODE_AUTOINC) && dc->src == i) {
-            gen_store(dc, addr, t0, 4);
+            gen_store_v10(dc, addr, t0, 4);
         } else {
-            gen_store(dc, addr, cpu_R[i], 4);
+            gen_store_v10(dc, addr, cpu_R[i], 4);
         }
         tcg_gen_addi_tl(addr, addr, 4);
     }
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 1ef8d16ac7..8321bf39a5 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4870,20 +4870,23 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0);
             gen_extu(ot, t2);
             tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
+            label2 = gen_new_label();
             if (mod == 3) {
-                label2 = gen_new_label();
                 gen_op_mov_reg_v(ot, R_EAX, t0);
                 tcg_gen_br(label2);
                 gen_set_label(label1);
                 gen_op_mov_reg_v(ot, rm, t1);
-                gen_set_label(label2);
             } else {
-                tcg_gen_mov_tl(t1, t0);
+                /* perform no-op store cycle like physical cpu; must be
+                   before changing accumulator to ensure idempotency if
+                   the store faults and the instruction is restarted */
+                gen_op_st_v(ot + s->mem_index, t0, a0);
                 gen_op_mov_reg_v(ot, R_EAX, t0);
+                tcg_gen_br(label2);
                 gen_set_label(label1);
-                /* always store */
                 gen_op_st_v(ot + s->mem_index, t1, a0);
             }
+            gen_set_label(label2);
             tcg_gen_mov_tl(cpu_cc_src, t0);
             tcg_gen_mov_tl(cpu_cc_dst, t2);
             s->cc_op = CC_OP_SUBB + ot;
diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
new file mode 100644
index 0000000000..1f3ab031f7
--- /dev/null
+++ b/test-qmp-input-visitor.c
@@ -0,0 +1,270 @@
+/*
+ * QMP Input Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.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 <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void visitor_input_teardown(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static Visitor *visitor_input_test_init(TestInputVisitorData *data,
+                                        const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+static void test_visitor_in_int(TestInputVisitorData *data,
+                                const void *unused)
+{
+    int64_t res = 0, value = -42;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%d", value);
+
+    visit_type_int(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, value);
+}
+
+static void test_visitor_in_bool(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    bool res = false;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "true");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+}
+
+static void test_visitor_in_number(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    double res = 0, value = 3.14;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%f", value);
+
+    visit_type_number(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpfloat(res, ==, value);
+}
+
+static void test_visitor_in_string(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    char *res = NULL, *value = (char *) "Q E M U";
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%s", value);
+
+    visit_type_str(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpstr(res, ==, value);
+
+    g_free(res);
+}
+
+static void test_visitor_in_enum(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    Visitor *v;
+    EnumOne i;
+
+    for (i = 0; EnumOne_lookup[i]; i++) {
+        EnumOne res = -1;
+
+        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
+
+        visit_type_EnumOne(v, &res, NULL, &errp);
+        g_assert(!error_is_set(&errp));
+        g_assert_cmpint(i, ==, res);
+
+        visitor_input_teardown(data, NULL);
+    }
+
+    data->obj = NULL;
+    data->qiv = NULL;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_in_struct(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(p->integer, ==, -42);
+    g_assert(p->boolean == true);
+    g_assert_cmpstr(p->string, ==, "foo");
+
+    g_free(p->string);
+    g_free(p);
+}
+
+static void check_and_free_str(char *str, const char *cmp)
+{
+    g_assert_cmpstr(str, ==, cmp);
+    g_free(str);
+}
+
+static void test_visitor_in_struct_nested(TestInputVisitorData *data,
+                                          const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    check_and_free_str(udp->string0, "string0");
+    check_and_free_str(udp->dict1.string1, "string1");
+    g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
+    check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
+    check_and_free_str(udp->dict1.dict2.string2, "string2");
+    g_assert(udp->dict1.has_dict3 == false);
+
+    g_free(udp->dict1.dict2.userdef1);
+    g_free(udp);
+}
+
+static void test_visitor_in_list(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefOneList *item, *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+    int i;
+
+    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert(head != NULL);
+
+    for (i = 0, item = head; item; item = item->next, i++) {
+        char string[12];
+
+        snprintf(string, sizeof(string), "string%d", i);
+        g_assert_cmpstr(item->value->string, ==, string);
+        g_assert_cmpint(item->value->integer, ==, 42 + i);
+    }
+
+    qapi_free_UserDefOneList(head);
+}
+
+static void input_visitor_test_add(const char *testpath,
+                                   TestInputVisitorData *data,
+                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               visitor_input_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData in_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    input_visitor_test_add("/visitor/input/int",
+                           &in_visitor_data, test_visitor_in_int);
+    input_visitor_test_add("/visitor/input/bool",
+                           &in_visitor_data, test_visitor_in_bool);
+    input_visitor_test_add("/visitor/input/number",
+                           &in_visitor_data, test_visitor_in_number);
+    input_visitor_test_add("/visitor/input/string",
+                            &in_visitor_data, test_visitor_in_string);
+    input_visitor_test_add("/visitor/input/enum",
+                            &in_visitor_data, test_visitor_in_enum);
+    input_visitor_test_add("/visitor/input/struct",
+                            &in_visitor_data, test_visitor_in_struct);
+    input_visitor_test_add("/visitor/input/struct-nested",
+                            &in_visitor_data, test_visitor_in_struct_nested);
+    input_visitor_test_add("/visitor/input/list",
+                            &in_visitor_data, test_visitor_in_list);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
new file mode 100644
index 0000000000..c94c208125
--- /dev/null
+++ b/test-qmp-output-visitor.c
@@ -0,0 +1,423 @@
+/*
+ * QMP Output Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.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 <glib.h>
+
+#include "qapi/qmp-output-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestOutputVisitorData {
+    QmpOutputVisitor *qov;
+    Visitor *ov;
+} TestOutputVisitorData;
+
+static void visitor_output_setup(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    data->qov = qmp_output_visitor_new();
+    g_assert(data->qov != NULL);
+
+    data->ov = qmp_output_get_visitor(data->qov);
+    g_assert(data->ov != NULL);
+}
+
+static void visitor_output_teardown(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    qmp_output_visitor_cleanup(data->qov);
+    data->qov = NULL;
+    data->ov = NULL;
+}
+
+static void test_visitor_out_int(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    int64_t value = -42;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_int(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+    g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_bool(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    bool value = true;
+    QObject *obj;
+
+    visit_type_bool(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_number(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    double value = 3.14;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_number(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+    g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_string(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    char *string = (char *) "Q E M U";
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_no_string(TestOutputVisitorData *data,
+                                       const void *unused)
+{
+    char *string = NULL;
+    Error *errp = NULL;
+    QObject *obj;
+
+    /* A null string should return "" */
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_enum(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    QObject *obj;
+    EnumOne i;
+
+    for (i = 0; i < ENUM_ONE_MAX; i++) {
+        visit_type_EnumOne(data->ov, &i, "unused", &errp);
+        g_assert(!error_is_set(&errp));
+
+        obj = qmp_output_get_qobject(data->qov);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
+                        EnumOne_lookup[i]);
+        qobject_decref(obj);
+    }
+}
+
+static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
+                                         const void *unused)
+{
+    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+    Error *errp;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_out_struct(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    TestStruct test_struct = { .integer = 42,
+                               .boolean = false,
+                               .string = (char *) "foo"};
+    TestStruct *p = &test_struct;
+    Error *errp = NULL;
+    QObject *obj;
+    QDict *qdict;
+
+    visit_type_TestStruct(data->ov, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 3);
+    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
+    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
+    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
+
+    QDECREF(qdict);
+}
+
+static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    int64_t value = 42;
+    Error *errp = NULL;
+    UserDefNested *ud2;
+    QObject *obj;
+    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
+    const char *string = "user def string";
+    const char *strings[] = { "fourty two", "fourty three", "fourty four",
+                              "fourty five" };
+
+    ud2 = g_malloc0(sizeof(*ud2));
+    ud2->string0 = g_strdup(strings[0]);
+
+    ud2->dict1.string1 = g_strdup(strings[1]);
+    ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict2.userdef1->string = g_strdup(string);
+    ud2->dict1.dict2.userdef1->integer = value;
+    ud2->dict1.dict2.string2 = g_strdup(strings[2]);
+
+    ud2->dict1.has_dict3 = true;
+    ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict3.userdef2->string = g_strdup(string);
+    ud2->dict1.dict3.userdef2->integer = value;
+    ud2->dict1.dict3.string3 = g_strdup(strings[3]);
+
+    visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 2);
+    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
+
+    dict1 = qdict_get_qdict(qdict, "dict1");
+    g_assert_cmpint(qdict_size(dict1), ==, 3);
+    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
+
+    dict2 = qdict_get_qdict(dict1, "dict2");
+    g_assert_cmpint(qdict_size(dict2), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
+    userdef = qdict_get_qdict(dict2, "userdef1");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    dict3 = qdict_get_qdict(dict1, "dict3");
+    g_assert_cmpint(qdict_size(dict3), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
+    userdef = qdict_get_qdict(dict3, "userdef2");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    QDECREF(qdict);
+    qapi_free_UserDefNested(ud2);
+}
+
+typedef struct TestStructList
+{
+    TestStruct *value;
+    struct TestStructList *next;
+} TestStructList;
+
+static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
+                                      const char *name, Error **errp)
+{
+    GenericList *i, **head = (GenericList **)obj;
+
+    visit_start_list(v, name, errp);
+
+    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
+        TestStructList *native_i = (TestStructList *)i;
+        visit_type_TestStruct(v, &native_i->value, NULL, errp);
+    }
+
+    visit_end_list(v, errp);
+}
+
+static void test_visitor_out_list(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    char *value_str = (char *) "list value";
+    TestStructList *p, *head = NULL;
+    const int max_items = 10;
+    bool value_bool = true;
+    int value_int = 10;
+    Error *errp = NULL;
+    QListEntry *entry;
+    QObject *obj;
+    QList *qlist;
+    int i;
+
+    for (i = 0; i < max_items; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+        p->value->integer = value_int;
+        p->value->boolean = value_bool;
+        p->value->string = value_str;
+
+        p->next = head;
+        head = p;
+    }
+
+    visit_type_TestStructList(data->ov, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+    qlist = qobject_to_qlist(obj);
+    g_assert(!qlist_empty(qlist));
+
+    i = 0;
+    QLIST_FOREACH_ENTRY(qlist, entry) {
+        QDict *qdict;
+
+        g_assert(qobject_type(entry->value) == QTYPE_QDICT);
+        qdict = qobject_to_qdict(entry->value);
+        g_assert_cmpint(qdict_size(qdict), ==, 3);
+        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
+        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
+        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
+        i++;
+    }
+    g_assert_cmpint(i, ==, max_items);
+
+    QDECREF(qlist);
+
+    for (p = head; p;) {
+        TestStructList *tmp = p->next;
+        g_free(p->value);
+        g_free(p);
+        p = tmp;
+    }
+}
+
+static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
+                                            const void *unused)
+{
+    UserDefNestedList *p, *head = NULL;
+    const char string[] = "foo bar";
+    int i, max_count = 1024;
+
+    for (i = 0; i < max_count; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+
+        p->value->string0 = g_strdup(string);
+        p->value->dict1.string1 = g_strdup(string);
+        p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+        p->value->dict1.dict2.userdef1->string = g_strdup(string);
+        p->value->dict1.dict2.userdef1->integer = 42;
+        p->value->dict1.dict2.string2 = g_strdup(string);
+        p->value->dict1.has_dict3 = false;
+
+        p->next = head;
+        head = p;
+    }
+
+    qapi_free_UserDefNestedList(head);
+}
+
+static void output_visitor_test_add(const char *testpath,
+                                    TestOutputVisitorData *data,
+                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+               test_func, visitor_output_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestOutputVisitorData out_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    output_visitor_test_add("/visitor/output/int",
+                            &out_visitor_data, test_visitor_out_int);
+    output_visitor_test_add("/visitor/output/bool",
+                            &out_visitor_data, test_visitor_out_bool);
+    output_visitor_test_add("/visitor/output/number",
+                            &out_visitor_data, test_visitor_out_number);
+    output_visitor_test_add("/visitor/output/string",
+                            &out_visitor_data, test_visitor_out_string);
+    output_visitor_test_add("/visitor/output/no-string",
+                            &out_visitor_data, test_visitor_out_no_string);
+    output_visitor_test_add("/visitor/output/enum",
+                            &out_visitor_data, test_visitor_out_enum);
+    output_visitor_test_add("/visitor/output/enum-errors",
+                            &out_visitor_data, test_visitor_out_enum_errors);
+    output_visitor_test_add("/visitor/output/struct",
+                            &out_visitor_data, test_visitor_out_struct);
+    output_visitor_test_add("/visitor/output/struct-nested",
+                            &out_visitor_data, test_visitor_out_struct_nested);
+    output_visitor_test_add("/visitor/output/list",
+                            &out_visitor_data, test_visitor_out_list);
+    output_visitor_test_add("/visitor/output/list-qapi-free",
+                            &out_visitor_data, test_visitor_out_list_qapi_free);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/test-visitor.c b/test-visitor.c
deleted file mode 100644
index f90b711883..0000000000
--- a/test-visitor.c
+++ /dev/null
@@ -1,338 +0,0 @@
-#include <glib.h>
-#include "qapi/qmp-output-visitor.h"
-#include "qapi/qmp-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestStruct
-{
-    int64_t x;
-    int64_t y;
-} TestStruct;
-
-typedef struct TestStructList
-{
-    TestStruct *value;
-    struct TestStructList *next;
-} TestStructList;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), errp);
-    visit_type_int(v, &(*obj)->x, "x", errp);
-    visit_type_int(v, &(*obj)->y, "y", errp);
-    visit_end_struct(v, errp);
-}
-
-static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
-{
-    GenericList *i, **head = (GenericList **)obj;
-
-    visit_start_list(m, name, errp);
-
-    for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
-        TestStructList *native_i = (TestStructList *)i;
-        visit_type_TestStruct(m, &native_i->value, NULL, errp);
-    }
-
-    visit_end_list(m, errp);
-}
-
-/* test core visitor methods */
-static void test_visitor_core(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    TestStruct ts = { 42, 82 };
-    TestStruct *pts = &ts;
-    TestStructList *lts = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QList *qlist;
-    QDict *qdict;
-    QString *str;
-    int64_t value = 0;
-
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-
-    visit_type_TestStruct(v, &pts, NULL, &err);
-
-    obj = qmp_output_get_qobject(mo);
-
-    str = qobject_to_json(obj);
-
-    printf("%s\n", qstring_get_str(str));
-
-    QDECREF(str);
-
-    obj = QOBJECT(qint_from_int(0x42));
-
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    visit_type_int(v, &value, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(value == 0x42);
-
-    qobject_decref(obj);
-
-    obj = qobject_from_json("{'x': 42, 'y': 84}");
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    pts = NULL;
-
-    visit_type_TestStruct(v, &pts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(pts != NULL);
-    g_assert(pts->x == 42);
-    g_assert(pts->y == 84);
-
-    qobject_decref(obj);
-    g_free(pts);
-
-    /* test list input visitor */
-    obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    visit_type_TestStructList(v, &lts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(lts != NULL);
-    g_assert(lts->value->x == 42);
-    g_assert(lts->value->y == 84);
-
-    g_assert(lts->next != NULL);
-    g_assert(lts->next->value->x == 12);
-    g_assert(lts->next->value->y == 24);
-    g_assert(lts->next->next == NULL);
-
-    qobject_decref(obj);
-
-    /* test list output visitor */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_TestStructList(v, &lts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj)));
-
-    qlist = qobject_to_qlist(obj);
-    assert(qlist);
-    obj = qlist_pop(qlist);
-    qdict = qobject_to_qdict(obj);
-    assert(qdict);
-    assert(qdict_get_int(qdict, "x") == 42);
-    assert(qdict_get_int(qdict, "y") == 84);
-    qobject_decref(obj);
-
-    obj = qlist_pop(qlist);
-    qdict = qobject_to_qdict(obj);
-    assert(qdict);
-    assert(qdict_get_int(qdict, "x") == 12);
-    assert(qdict_get_int(qdict, "y") == 24);
-    qobject_decref(obj);
-
-    qmp_output_visitor_cleanup(mo);
-    QDECREF(qlist);
-}
-
-/* test deep nesting with refs to other user-defined types */
-static void test_nested_structs(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    UserDefOne ud1;
-    UserDefOne *ud1_p = &ud1, *ud1c_p = NULL;
-    UserDefTwo ud2;
-    UserDefTwo *ud2_p = &ud2, *ud2c_p = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    ud1.integer = 42;
-    ud1.string = strdup("forty two");
-
-    /* sanity check */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_UserDefOne(v, &ud1_p, "o_O", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    qobject_decref(obj);
-
-    ud2.string = strdup("forty three");
-    ud2.dict.string = strdup("forty four");
-    ud2.dict.dict.userdef = ud1_p;
-    ud2.dict.dict.string = strdup("forty five");
-    ud2.dict.has_dict2 = true;
-    ud2.dict.dict2.userdef = ud1_p;
-    ud2.dict.dict2.string = strdup("forty six");
-
-    /* c type -> qobject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_UserDefTwo(v, &ud2_p, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-
-    /* qobject -> c type, should match original struct */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_UserDefTwo(v, &ud2c_p, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(!g_strcmp0(ud2c_p->string, ud2.string));
-    g_assert(!g_strcmp0(ud2c_p->dict.string, ud2.dict.string));
-
-    ud1c_p = ud2c_p->dict.dict.userdef;
-    g_assert(ud1c_p->integer == ud1_p->integer);
-    g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
-
-    g_assert(!g_strcmp0(ud2c_p->dict.dict.string, ud2.dict.dict.string));
-
-    ud1c_p = ud2c_p->dict.dict2.userdef;
-    g_assert(ud1c_p->integer == ud1_p->integer);
-    g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
-
-    g_assert(!g_strcmp0(ud2c_p->dict.dict2.string, ud2.dict.dict2.string));
-    g_free(ud1.string);
-    g_free(ud2.string);
-    g_free(ud2.dict.string);
-    g_free(ud2.dict.dict.string);
-    g_free(ud2.dict.dict2.string);
-
-    qapi_free_UserDefTwo(ud2c_p);
-
-    qobject_decref(obj);
-}
-
-/* test enum values */
-static void test_enums(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    EnumOne enum1 = ENUM_ONE_VALUE2, enum1_cpy = ENUM_ONE_VALUE1;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    /* C type -> QObject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_EnumOne(v, &enum1, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-    g_assert(g_strcmp0(qstring_get_str(qobject_to_qstring(obj)), "value2") == 0);
-
-    /* QObject -> C type */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_EnumOne(v, &enum1_cpy, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    g_debug("enum1_cpy, enum1: %d, %d", enum1_cpy, enum1);
-    g_assert(enum1_cpy == enum1);
-
-    qobject_decref(obj);
-}
-
-/* test enum values nested in schema-defined structs */
-static void test_nested_enums(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    NestedEnumsOne *nested_enums, *nested_enums_cpy = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    nested_enums = g_malloc0(sizeof(NestedEnumsOne));
-    nested_enums->enum1 = ENUM_ONE_VALUE1;
-    nested_enums->enum2 = ENUM_ONE_VALUE2;
-    nested_enums->enum3 = ENUM_ONE_VALUE3;
-    nested_enums->enum4 = ENUM_ONE_VALUE3;
-    nested_enums->has_enum2 = false;
-    nested_enums->has_enum4 = true;
-
-    /* C type -> QObject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_NestedEnumsOne(v, &nested_enums, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-
-    /* QObject -> C type */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_NestedEnumsOne(v, &nested_enums_cpy, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    g_assert(nested_enums_cpy);
-    g_assert(nested_enums_cpy->enum1 == nested_enums->enum1);
-    g_assert(nested_enums_cpy->enum3 == nested_enums->enum3);
-    g_assert(nested_enums_cpy->enum4 == nested_enums->enum4);
-    g_assert(nested_enums_cpy->has_enum2 == false);
-    g_assert(nested_enums_cpy->has_enum4 == true);
-
-    qmp_output_visitor_cleanup(mo);
-    qmp_input_visitor_cleanup(mi);
-    qapi_free_NestedEnumsOne(nested_enums);
-    qapi_free_NestedEnumsOne(nested_enums_cpy);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/0.15/visitor_core", test_visitor_core);
-    g_test_add_func("/0.15/nested_structs", test_nested_structs);
-    g_test_add_func("/0.15/enums", test_enums);
-    g_test_add_func("/0.15/nested_enums", test_nested_enums);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index de5ea6b5d8..9b3016c129 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -318,7 +318,7 @@ void vnc_start_worker_thread(void)
         return ;
 
     q = vnc_queue_init();
-    qemu_thread_create(&q->thread, vnc_worker_thread, q);
+    qemu_thread_create(&q->thread, vnc_worker_thread, q, QEMU_THREAD_DETACHED);
     queue = q; /* Set global queue */
 }