summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore5
-rw-r--r--tests/Makefile.include110
-rw-r--r--tests/acpi-test-data/pc/DSDT.cphpbin6435 -> 6471 bytes
-rw-r--r--tests/acpi-test-data/pc/SRAT.cphpbin0 -> 304 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDT.cphpbin9197 -> 9233 bytes
-rw-r--r--tests/acpi-test-data/q35/SRAT.cphpbin0 -> 304 bytes
-rw-r--r--tests/bios-tables-test.c41
-rw-r--r--tests/boot-sector.c9
-rw-r--r--tests/boot-serial-test.c110
-rwxr-xr-xtests/check-block.sh13
-rw-r--r--tests/check-qom-interface.c1
-rw-r--r--tests/check-qom-proplist.c16
-rw-r--r--tests/crypto-tls-x509-helpers.h1
-rw-r--r--tests/docker/Makefile.include15
-rwxr-xr-xtests/docker/common.rc17
-rwxr-xr-xtests/docker/docker.py24
-rw-r--r--tests/docker/dockerfiles/centos6.docker6
-rwxr-xr-xtests/docker/dockerfiles/debian-bootstrap.pre32
-rw-r--r--tests/docker/dockerfiles/fedora.docker16
-rw-r--r--tests/docker/dockerfiles/min-glib.docker8
-rw-r--r--tests/docker/dockerfiles/ubuntu.docker4
-rwxr-xr-xtests/docker/run26
-rwxr-xr-xtests/docker/test-clang2
-rwxr-xr-xtests/docker/test-full2
-rwxr-xr-xtests/docker/test-mingw2
-rwxr-xr-xtests/docker/test-quick4
-rw-r--r--tests/e1000e-test.c2
-rw-r--r--tests/hd-geo-test.c4
-rw-r--r--tests/i440fx-test.c2
-rw-r--r--tests/ide-test.c2
-rw-r--r--tests/ivshmem-test.c2
-rw-r--r--tests/libqos/ahci.c2
-rw-r--r--tests/libqos/libqos-pc.c10
-rw-r--r--tests/libqos/libqos-spapr.c34
-rw-r--r--tests/libqos/libqos-spapr.h10
-rw-r--r--tests/libqos/libqos.c33
-rw-r--r--tests/libqos/libqos.h11
-rw-r--r--tests/libqos/malloc-spapr.c38
-rw-r--r--tests/libqos/malloc-spapr.h17
-rw-r--r--tests/libqos/pci-pc.c24
-rw-r--r--tests/libqos/pci-pc.h3
-rw-r--r--tests/libqos/pci-spapr.c288
-rw-r--r--tests/libqos/pci-spapr.h17
-rw-r--r--tests/libqos/pci.c22
-rw-r--r--tests/libqos/rtas.c116
-rw-r--r--tests/libqos/rtas.h15
-rw-r--r--tests/libqos/virtio.c8
-rw-r--r--tests/libqtest.c29
-rw-r--r--tests/libqtest.h32
-rw-r--r--tests/pc-cpu-test.c24
-rw-r--r--tests/postcopy-test.c7
-rw-r--r--tests/ptimer-test-stubs.c107
-rw-r--r--tests/ptimer-test.c568
-rw-r--r--tests/ptimer-test.h22
-rw-r--r--tests/pxe-test.c22
-rw-r--r--tests/q35-test.c2
-rwxr-xr-xtests/qemu-iotests/0302
-rwxr-xr-xtests/qemu-iotests/04179
-rwxr-xr-xtests/qemu-iotests/055159
-rw-r--r--tests/qemu-iotests/055.out4
-rwxr-xr-xtests/qemu-iotests/0574
-rwxr-xr-xtests/qemu-iotests/0676
-rw-r--r--tests/qemu-iotests/067.out211
-rwxr-xr-xtests/qemu-iotests/0718
-rwxr-xr-xtests/qemu-iotests/0812
-rw-r--r--tests/qemu-iotests/085.out6
-rwxr-xr-xtests/qemu-iotests/08766
-rw-r--r--tests/qemu-iotests/087.out12
-rwxr-xr-xtests/qemu-iotests/1174
-rwxr-xr-xtests/qemu-iotests/11891
-rw-r--r--tests/qemu-iotests/12417
-rw-r--r--tests/qemu-iotests/139178
-rw-r--r--tests/qemu-iotests/139.out4
-rwxr-xr-xtests/qemu-iotests/14124
-rw-r--r--tests/qemu-iotests/141.out24
-rwxr-xr-xtests/qemu-iotests/15880
-rw-r--r--tests/qemu-iotests/158.out36
-rwxr-xr-xtests/qemu-iotests/15970
-rw-r--r--tests/qemu-iotests/159.out87
-rwxr-xr-xtests/qemu-iotests/16072
-rw-r--r--tests/qemu-iotests/160.out51
-rwxr-xr-xtests/qemu-iotests/17067
-rw-r--r--tests/qemu-iotests/170.out15
-rw-r--r--tests/qemu-iotests/common.filter9
-rw-r--r--tests/qemu-iotests/common.rc5
-rw-r--r--tests/qemu-iotests/group4
-rw-r--r--tests/qemu-iotests/iotests.py20
-rw-r--r--tests/qom-test.c5
-rw-r--r--tests/rtas-test.c41
-rw-r--r--tests/rtl8139-test.c2
-rw-r--r--tests/tcg/README76
-rw-r--r--tests/tcg/cris/Makefile21
-rw-r--r--tests/tcg/cris/check_abs.c4
-rw-r--r--tests/tcg/cris/check_addc.c2
-rw-r--r--tests/tcg/cris/check_addcm.c4
-rw-r--r--tests/tcg/cris/check_addcv17.s65
-rw-r--r--tests/tcg/cris/check_bound.c6
-rw-r--r--tests/tcg/cris/check_ftag.c8
-rw-r--r--tests/tcg/cris/check_int64.c4
-rw-r--r--tests/tcg/cris/check_lz.c2
-rw-r--r--tests/tcg/cris/check_openpf4.c5
-rw-r--r--tests/tcg/cris/check_swap.c2
-rw-r--r--tests/tcg/cris/check_time1.c46
-rw-r--r--tests/tcg/cris/crisutils.h20
-rw-r--r--tests/tcg/cris/sys.c26
-rw-r--r--tests/tcg/cris/sys.h2
-rw-r--r--tests/tco-test.c2
-rw-r--r--tests/test-bufferiszero.c78
-rw-r--r--tests/test-coroutine.c49
-rw-r--r--tests/test-crypto-block.c2
-rw-r--r--tests/test-crypto-cipher.c43
-rw-r--r--tests/test-crypto-pbkdf.c54
-rw-r--r--tests/test-cutils.c24
-rw-r--r--tests/test-iov.c7
-rw-r--r--tests/test-qga.c26
-rw-r--r--tests/test-qht.c4
-rw-r--r--tests/test-qmp-commands.c15
-rw-r--r--tests/test-qmp-input-strict.c46
-rw-r--r--tests/test-replication.c575
-rw-r--r--tests/test-string-input-visitor.c1
-rw-r--r--tests/test-uuid.c177
-rw-r--r--tests/test-vmstate.c8
-rw-r--r--tests/test-x86-cpuid-compat.c171
-rw-r--r--tests/usb-hcd-ehci-test.c2
-rw-r--r--tests/usb-hcd-uhci-test.c24
-rw-r--r--tests/vhost-user-test.c245
-rw-r--r--tests/virtio-9p-test.c119
-rw-r--r--tests/virtio-blk-test.c2
-rw-r--r--tests/virtio-net-test.c2
-rw-r--r--tests/virtio-scsi-test.c2
130 files changed, 4644 insertions, 729 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index dbb52639f6..9f3d2ee038 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -12,7 +12,9 @@ rcutorture
 test-aio
 test-base64
 test-bitops
+test-blockjob
 test-blockjob-txn
+test-bufferiszero
 test-clone-visitor
 test-coroutine
 test-crypto-afsplit
@@ -63,16 +65,19 @@ test-qmp-introspect.[ch]
 test-qmp-marshal.c
 test-qmp-output-visitor
 test-rcu-list
+test-replication
 test-rfifolock
 test-string-input-visitor
 test-string-output-visitor
 test-thread-pool
 test-throttle
 test-timed-average
+test-uuid
 test-visitor-serialization
 test-vmstate
 test-write-threshold
 test-x86-cpuid
+test-x86-cpuid-compat
 test-xbzrle
 test-netfilter
 test-filter-mirror
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 14be4915b9..a77777cf9c 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -112,6 +112,10 @@ check-unit-y += tests/test-crypto-xts$(EXESUF)
 check-unit-y += tests/test-crypto-block$(EXESUF)
 gcov-files-test-logging-y = tests/test-logging.c
 check-unit-y += tests/test-logging$(EXESUF)
+check-unit-$(CONFIG_REPLICATION) += tests/test-replication$(EXESUF)
+check-unit-y += tests/test-bufferiszero$(EXESUF)
+gcov-files-check-bufferiszero-y = util/bufferiszero.c
+check-unit-y += tests/test-uuid$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -195,6 +199,7 @@ check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
 gcov-files-i386-y += hw/block/hd-geometry.c
 check-qtest-i386-y += tests/boot-order-test$(EXESUF)
 check-qtest-i386-y += tests/bios-tables-test$(EXESUF)
+check-qtest-i386-y += tests/boot-serial-test$(EXESUF)
 check-qtest-i386-y += tests/pxe-test$(EXESUF)
 check-qtest-i386-y += tests/rtc-test$(EXESUF)
 check-qtest-i386-y += tests/ipmi-kcs-test$(EXESUF)
@@ -238,42 +243,70 @@ check-qtest-i386-y += tests/test-netfilter$(EXESUF)
 check-qtest-i386-y += tests/test-filter-mirror$(EXESUF)
 check-qtest-i386-y += tests/test-filter-redirector$(EXESUF)
 check-qtest-i386-y += tests/postcopy-test$(EXESUF)
+check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF)
 check-qtest-x86_64-y += $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
+
+check-qtest-alpha-y = tests/boot-serial-test$(EXESUF)
+
 check-qtest-mips-y = tests/endianness-test$(EXESUF)
+
 check-qtest-mips64-y = tests/endianness-test$(EXESUF)
+
 check-qtest-mips64el-y = tests/endianness-test$(EXESUF)
+
 check-qtest-ppc-y = tests/endianness-test$(EXESUF)
-check-qtest-ppc64-y = tests/endianness-test$(EXESUF)
+check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
+check-qtest-ppc-y += tests/prom-env-test$(EXESUF)
+check-qtest-ppc-y += tests/drive_del-test$(EXESUF)
+check-qtest-ppc-y += tests/boot-serial-test$(EXESUF)
+
+check-qtest-ppc64-y = tests/spapr-phb-test$(EXESUF)
+gcov-files-ppc64-y = ppc64-softmmu/hw/ppc/spapr_pci.c
+check-qtest-ppc64-y += tests/endianness-test$(EXESUF)
+check-qtest-ppc64-y += tests/boot-order-test$(EXESUF)
+check-qtest-ppc64-y += tests/prom-env-test$(EXESUF)
+check-qtest-ppc64-y += tests/drive_del-test$(EXESUF)
+check-qtest-ppc64-y += tests/postcopy-test$(EXESUF)
+check-qtest-ppc64-y += tests/boot-serial-test$(EXESUF)
+check-qtest-ppc64-y += tests/rtas-test$(EXESUF)
+check-qtest-ppc64-y += tests/pxe-test$(EXESUF)
+check-qtest-ppc64-y += tests/usb-hcd-ohci-test$(EXESUF)
+gcov-files-ppc64-y += hw/usb/hcd-ohci.c
+check-qtest-ppc64-y += tests/usb-hcd-uhci-test$(EXESUF)
+gcov-files-ppc64-y += hw/usb/hcd-uhci.c
+check-qtest-ppc64-y += tests/usb-hcd-xhci-test$(EXESUF)
+gcov-files-ppc64-y += hw/usb/hcd-xhci.c
+
 check-qtest-sh4-y = tests/endianness-test$(EXESUF)
+
 check-qtest-sh4eb-y = tests/endianness-test$(EXESUF)
+
+check-qtest-sparc-y = tests/prom-env-test$(EXESUF)
+#check-qtest-sparc-y += tests/m48t59-test$(EXESUF)
+#gcov-files-sparc-y = hw/timer/m48t59.c
+
 check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
-#check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
 #check-qtest-sparc64-y += tests/m48t59-test$(EXESUF)
-gcov-files-sparc-y += hw/timer/m48t59.c
-gcov-files-sparc64-y += hw/timer/m48t59.c
+#gcov-files-sparc64-y += hw/timer/m48t59.c
+#Disabled for now, triggers a TCG bug on 32-bit hosts
+#check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
+
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 check-qtest-arm-y += tests/ds1338-test$(EXESUF)
 gcov-files-arm-y += hw/misc/tmp105.c
 check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
 gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
-check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
-check-qtest-ppc64-y += tests/boot-order-test$(EXESUF)
-check-qtest-ppc-y += tests/drive_del-test$(EXESUF)
-check-qtest-ppc64-y += tests/drive_del-test$(EXESUF)
-check-qtest-ppc64-y += tests/spapr-phb-test$(EXESUF)
-gcov-files-ppc64-y += ppc64-softmmu/hw/ppc/spapr_pci.c
-check-qtest-ppc-y += tests/prom-env-test$(EXESUF)
-check-qtest-ppc64-y += tests/prom-env-test$(EXESUF)
-check-qtest-sparc-y += tests/prom-env-test$(EXESUF)
-#Disabled for now, triggers a TCG bug on 32-bit hosts
-#check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
+
 check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
+
 check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
-check-qtest-ppc64-y += tests/postcopy-test$(EXESUF)
+
+check-qtest-s390x-y = tests/boot-serial-test$(EXESUF)
 
 check-qtest-generic-y += tests/qom-test$(EXESUF)
+check-qtest-generic-y += tests/ptimer-test$(EXESUF)
 
 qapi-schema += alternate-any.json
 qapi-schema += alternate-array.json
@@ -465,6 +498,7 @@ tests/test-qdist$(EXESUF): tests/test-qdist.o $(test-util-obj-y)
 tests/test-qht$(EXESUF): tests/test-qht.o $(test-util-obj-y)
 tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests/qht-bench$(EXESUF) $(test-util-obj-y)
 tests/qht-bench$(EXESUF): tests/qht-bench.o $(test-util-obj-y)
+tests/test-bufferiszero$(EXESUF): tests/test-bufferiszero.o $(test-util-obj-y)
 
 tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
 	hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
@@ -483,31 +517,34 @@ tests/test-base64$(EXESUF): tests/test-base64.o \
 
 tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
 
+tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
+	$(test-block-obj-y)
+
 tests/test-qapi-types.c tests/test-qapi-types.h :\
 $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
 		$(gen-out-type) -o tests -p "test-" $<, \
-		"  GEN   $@")
+		"GEN","$@")
 tests/test-qapi-visit.c tests/test-qapi-visit.h :\
 $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
 		$(gen-out-type) -o tests -p "test-" $<, \
-		"  GEN   $@")
+		"GEN","$@")
 tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
 $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
 		$(gen-out-type) -o tests -p "test-" $<, \
-		"  GEN   $@")
+		"GEN","$@")
 tests/test-qapi-event.c tests/test-qapi-event.h :\
 $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
 		$(gen-out-type) -o tests -p "test-" $<, \
-		"  GEN   $@")
+		"GEN","$@")
 tests/test-qmp-introspect.c tests/test-qmp-introspect.h :\
 $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \
 		$(gen-out-type) -o tests -p "test-" $<, \
-		"  GEN   $@")
+		"GEN","$@")
 
 tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
 tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
@@ -557,12 +594,16 @@ tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y)
 
 libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
 libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
+libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o
+libqos-spapr-obj-y += tests/libqos/libqos-spapr.o
+libqos-spapr-obj-y += tests/libqos/rtas.o
+libqos-spapr-obj-y += tests/libqos/pci-spapr.o
 libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
 libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
 libqos-pc-obj-y += tests/libqos/ahci.o
 libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
 libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
-libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o
+libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o
 libqos-virtio-obj-y = $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o
 
 tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o
@@ -571,6 +612,7 @@ tests/m48t59-test$(EXESUF): tests/m48t59-test.o
 tests/endianness-test$(EXESUF): tests/endianness-test.o
 tests/spapr-phb-test$(EXESUF): tests/spapr-phb-test.o $(libqos-obj-y)
 tests/prom-env-test$(EXESUF): tests/prom-env-test.o $(libqos-obj-y)
+tests/rtas-test$(EXESUF): tests/rtas-test.o $(libqos-spapr-obj-y)
 tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
 tests/ahci-test$(EXESUF): tests/ahci-test.o $(libqos-pc-obj-y)
@@ -578,6 +620,7 @@ tests/ipmi-kcs-test$(EXESUF): tests/ipmi-kcs-test.o
 tests/ipmi-bt-test$(EXESUF): tests/ipmi-bt-test.o
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
+tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y)
 tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
 	tests/boot-sector.o $(libqos-obj-y)
 tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
@@ -600,7 +643,7 @@ tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o $(libqos-virtio-obj-y)
 tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o $(libqos-pc-obj-y) $(libqos-virtio-obj-y)
 tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o $(libqos-pc-obj-y)
 tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o $(libqos-virtio-obj-y)
-tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o
+tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o $(libqos-virtio-obj-y)
 tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o
 tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o
 tests/tpci200-test$(EXESUF): tests/tpci200-test.o
@@ -622,18 +665,21 @@ tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y)
 tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
 tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o
 tests/postcopy-test$(EXESUF): tests/postcopy-test.o
-tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) $(test-io-obj-y)
+tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y)
 tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
 tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y)
 tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y)
 tests/test-netfilter$(EXESUF): tests/test-netfilter.o $(qtest-obj-y)
 tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-y)
 tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-obj-y)
+tests/test-x86-cpuid-compat$(EXESUF): tests/test-x86-cpuid-compat.o $(qtest-obj-y)
 tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
 tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
+tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o
+tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
 
 tests/migration/stress$(EXESUF): tests/migration/stress.o
-	$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"  LINK  $(TARGET_DIR)$@")
+	$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@")
 
 INITRD_WORK_DIR=tests/migration/initrd
 
@@ -696,7 +742,7 @@ $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y)
 	$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
 		QTEST_QEMU_IMG=qemu-img$(EXESUF) \
 		MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
-		gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER $@")
+		gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER","$@")
 	$(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y) $(gcov-files-generic-y); do \
 	  echo Gcov report for $$f:;\
 	  $(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
@@ -707,7 +753,7 @@ $(patsubst %, check-%, $(check-unit-y)): check-%: %
 	$(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,)
 	$(call quiet-command, \
 		MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
-		gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
+		gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER","$*")
 	$(if $(CONFIG_GCOV),@for f in $(gcov-files-$(subst tests/,,$*)-y) $(gcov-files-generic-y); do \
 	  echo Gcov report for $$f:;\
 	  $(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
@@ -718,18 +764,18 @@ $(patsubst %, check-%, $(check-unit-y)): check-%: %
 $(patsubst %, check-report-qtest-%.xml, $(QTEST_TARGETS)): check-report-qtest-%.xml: $(check-qtest-y)
 	$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
 		QTEST_QEMU_IMG=qemu-img$(EXESUF) \
-	  gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER $@")
+	  gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER","$@")
 
 check-report-unit.xml: $(check-unit-y)
-	$(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^, "GTESTER $@")
+	$(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^,"GTESTER","$@")
 
 # Reports and overall runs
 
 check-report.xml: $(patsubst %,check-report-qtest-%.xml, $(QTEST_TARGETS)) check-report-unit.xml
-	$(call quiet-command,$(SRC_PATH)/scripts/gtester-cat $^ > $@, "  GEN   $@")
+	$(call quiet-command,$(SRC_PATH)/scripts/gtester-cat $^ > $@,"GEN","$@")
 
 check-report.html: check-report.xml
-	$(call quiet-command,gtester-report $< > $@, "  GEN   $@")
+	$(call quiet-command,gtester-report $< > $@,"GEN","$@")
 
 
 # Other tests
@@ -749,7 +795,7 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
 		$(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py \
 		$^ >$*.test.out 2>$*.test.err; \
 		echo $$? >$*.test.exit, \
-		"  TEST  $*.out")
+		"TEST","$*.out")
 	@diff -q $(SRC_PATH)/$*.out $*.test.out
 	@# Sanitize error messages (make them independent of build directory)
 	@perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -q $(SRC_PATH)/$*.err -
diff --git a/tests/acpi-test-data/pc/DSDT.cphp b/tests/acpi-test-data/pc/DSDT.cphp
index e8b146208e..9f405cfd83 100644
--- a/tests/acpi-test-data/pc/DSDT.cphp
+++ b/tests/acpi-test-data/pc/DSDT.cphp
Binary files differdiff --git a/tests/acpi-test-data/pc/SRAT.cphp b/tests/acpi-test-data/pc/SRAT.cphp
new file mode 100644
index 0000000000..ff2137642f
--- /dev/null
+++ b/tests/acpi-test-data/pc/SRAT.cphp
Binary files differdiff --git a/tests/acpi-test-data/q35/DSDT.cphp b/tests/acpi-test-data/q35/DSDT.cphp
index 6cc28c6dae..a0ce6b3264 100644
--- a/tests/acpi-test-data/q35/DSDT.cphp
+++ b/tests/acpi-test-data/q35/DSDT.cphp
Binary files differdiff --git a/tests/acpi-test-data/q35/SRAT.cphp b/tests/acpi-test-data/q35/SRAT.cphp
new file mode 100644
index 0000000000..ff2137642f
--- /dev/null
+++ b/tests/acpi-test-data/q35/SRAT.cphp
Binary files differdiff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index de4019e57d..6ea2b6d00a 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -711,9 +711,12 @@ static void test_acpi_one(const char *params, test_data *data)
 {
     char *args;
 
-    args = g_strdup_printf("-net none -display none %s "
+    /* Disable kernel irqchip to be able to override apic irq0. */
+    args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
+                           "-net none -display none %s "
                            "-drive id=hd0,if=none,file=%s,format=raw "
                            "-device ide-hd,drive=hd0 ",
+                           data->machine, "kvm:tcg",
                            params ? params : "", disk);
 
     qtest_start(args);
@@ -758,7 +761,7 @@ static void test_acpi_piix4_tcg(void)
     data.machine = MACHINE_PC;
     data.required_struct_types = base_required_struct_types;
     data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
-    test_acpi_one("-machine accel=tcg", &data);
+    test_acpi_one(NULL, &data);
     free_test_data(&data);
 }
 
@@ -771,7 +774,7 @@ static void test_acpi_piix4_tcg_bridge(void)
     data.variant = ".bridge";
     data.required_struct_types = base_required_struct_types;
     data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
-    test_acpi_one("-machine accel=tcg -device pci-bridge,chassis_nr=1", &data);
+    test_acpi_one("-device pci-bridge,chassis_nr=1", &data);
     free_test_data(&data);
 }
 
@@ -783,7 +786,7 @@ static void test_acpi_q35_tcg(void)
     data.machine = MACHINE_Q35;
     data.required_struct_types = base_required_struct_types;
     data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
-    test_acpi_one("-machine q35,accel=tcg", &data);
+    test_acpi_one(NULL, &data);
     free_test_data(&data);
 }
 
@@ -796,7 +799,7 @@ static void test_acpi_q35_tcg_bridge(void)
     data.variant = ".bridge";
     data.required_struct_types = base_required_struct_types;
     data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
-    test_acpi_one("-machine q35,accel=tcg -device pci-bridge,chassis_nr=1",
+    test_acpi_one("-device pci-bridge,chassis_nr=1",
                   &data);
     free_test_data(&data);
 }
@@ -808,8 +811,8 @@ static void test_acpi_piix4_tcg_cphp(void)
     memset(&data, 0, sizeof(data));
     data.machine = MACHINE_PC;
     data.variant = ".cphp";
-    test_acpi_one("-machine accel=tcg"
-                  " -smp 2,cores=3,sockets=2,maxcpus=6",
+    test_acpi_one("-smp 2,cores=3,sockets=2,maxcpus=6"
+                  " -numa node -numa node",
                   &data);
     free_test_data(&data);
 }
@@ -821,8 +824,8 @@ static void test_acpi_q35_tcg_cphp(void)
     memset(&data, 0, sizeof(data));
     data.machine = MACHINE_Q35;
     data.variant = ".cphp";
-    test_acpi_one("-machine q35,accel=tcg"
-                  " -smp 2,cores=3,sockets=2,maxcpus=6",
+    test_acpi_one(" -smp 2,cores=3,sockets=2,maxcpus=6"
+                  " -numa node -numa node",
                   &data);
     free_test_data(&data);
 }
@@ -840,7 +843,7 @@ static void test_acpi_q35_tcg_ipmi(void)
     data.variant = ".ipmibt";
     data.required_struct_types = ipmi_required_struct_types;
     data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types);
-    test_acpi_one("-machine q35,accel=tcg -device ipmi-bmc-sim,id=bmc0"
+    test_acpi_one("-device ipmi-bmc-sim,id=bmc0"
                   " -device isa-ipmi-bt,bmc=bmc0",
                   &data);
     free_test_data(&data);
@@ -858,7 +861,7 @@ static void test_acpi_piix4_tcg_ipmi(void)
     data.variant = ".ipmikcs";
     data.required_struct_types = ipmi_required_struct_types;
     data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types);
-    test_acpi_one("-machine accel=tcg -device ipmi-bmc-sim,id=bmc0"
+    test_acpi_one("-device ipmi-bmc-sim,id=bmc0"
                   " -device isa-ipmi-kcs,irq=0,bmc=bmc0",
                   &data);
     free_test_data(&data);
@@ -876,14 +879,14 @@ int main(int argc, char *argv[])
     g_test_init(&argc, &argv, NULL);
 
     if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
-        qtest_add_func("acpi/piix4/tcg", test_acpi_piix4_tcg);
-        qtest_add_func("acpi/piix4/tcg/bridge", test_acpi_piix4_tcg_bridge);
-        qtest_add_func("acpi/q35/tcg", test_acpi_q35_tcg);
-        qtest_add_func("acpi/q35/tcg/bridge", test_acpi_q35_tcg_bridge);
-        qtest_add_func("acpi/piix4/tcg/ipmi", test_acpi_piix4_tcg_ipmi);
-        qtest_add_func("acpi/q35/tcg/ipmi", test_acpi_q35_tcg_ipmi);
-        qtest_add_func("acpi/piix4/tcg/cpuhp", test_acpi_piix4_tcg_cphp);
-        qtest_add_func("acpi/q35/tcg/cpuhp", test_acpi_q35_tcg_cphp);
+        qtest_add_func("acpi/piix4", test_acpi_piix4_tcg);
+        qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge);
+        qtest_add_func("acpi/q35", test_acpi_q35_tcg);
+        qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge);
+        qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi);
+        qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi);
+        qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp);
+        qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp);
     }
     ret = g_test_run();
     boot_sector_cleanup(disk);
diff --git a/tests/boot-sector.c b/tests/boot-sector.c
index 3ffe2987ff..e3193c0a12 100644
--- a/tests/boot-sector.c
+++ b/tests/boot-sector.c
@@ -77,6 +77,15 @@ int boot_sector_init(const char *fname)
         fprintf(stderr, "Couldn't open \"%s\": %s", fname, strerror(errno));
         return 1;
     }
+
+    /* For Open Firmware based system, we can use a Forth script instead */
+    if (strcmp(qtest_get_arch(), "ppc64") == 0) {
+        memset(boot_sector, ' ', sizeof boot_sector);
+        sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n",
+                LOW(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET,
+                HIGH(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
+    }
+
     fwrite(boot_sector, 1, sizeof boot_sector, f);
     fclose(f);
     return 0;
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
new file mode 100644
index 0000000000..d98c564a35
--- /dev/null
+++ b/tests/boot-serial-test.c
@@ -0,0 +1,110 @@
+/*
+ * Test serial output of some machines.
+ *
+ * Copyright 2016 Thomas Huth, Red Hat Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2
+ * or later. See the COPYING file in the top-level directory.
+ *
+ * This test is used to check that the serial output of the firmware
+ * (that we provide for some machines) contains an expected string.
+ * Thus we check that the firmware still boots at least to a certain
+ * point and so we know that the machine is not completely broken.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+typedef struct testdef {
+    const char *arch;       /* Target architecture */
+    const char *machine;    /* Name of the machine */
+    const char *extra;      /* Additional parameters */
+    const char *expect;     /* Expected string in the serial output */
+} testdef_t;
+
+static testdef_t tests[] = {
+    { "alpha", "clipper", "", "PCI:" },
+    { "ppc", "ppce500", "", "U-Boot" },
+    { "ppc", "prep", "", "Open Hack'Ware BIOS" },
+    { "ppc64", "ppce500", "", "U-Boot" },
+    { "ppc64", "prep", "", "Open Hack'Ware BIOS" },
+    { "ppc64", "pseries", "", "Open Firmware" },
+    { "i386", "isapc", "-cpu qemu32 -device sga", "SGABIOS" },
+    { "i386", "pc", "-device sga", "SGABIOS" },
+    { "i386", "q35", "-device sga", "SGABIOS" },
+    { "x86_64", "isapc", "-cpu qemu32 -device sga", "SGABIOS" },
+    { "x86_64", "q35", "-device sga", "SGABIOS" },
+    { "s390x", "s390-ccw-virtio",
+      "-nodefaults -device sclpconsole,chardev=serial0", "virtio device" },
+    { NULL }
+};
+
+static void check_guest_output(const testdef_t *test, int fd)
+{
+    bool output_ok = false;
+    int i, nbr, pos = 0;
+    char ch;
+
+    /* Poll serial output... Wait at most 60 seconds */
+    for (i = 0; i < 6000; ++i) {
+        while ((nbr = read(fd, &ch, 1)) == 1) {
+            if (ch == test->expect[pos]) {
+                pos += 1;
+                if (test->expect[pos] == '\0') {
+                    /* We've reached the end of the expected string! */
+                    output_ok = true;
+                    goto done;
+                }
+            } else {
+                pos = 0;
+            }
+        }
+        g_assert(nbr >= 0);
+        g_usleep(10000);
+    }
+
+done:
+    g_assert(output_ok);
+}
+
+static void test_machine(const void *data)
+{
+    const testdef_t *test = data;
+    char *args;
+    char tmpname[] = "/tmp/qtest-boot-serial-XXXXXX";
+    int fd;
+
+    fd = mkstemp(tmpname);
+    g_assert(fd != -1);
+
+    args = g_strdup_printf("-M %s,accel=tcg -chardev file,id=serial0,path=%s"
+                           " -serial chardev:serial0 %s", test->machine,
+                           tmpname, test->extra);
+
+    qtest_start(args);
+    unlink(tmpname);
+
+    check_guest_output(test, fd);
+    qtest_quit(global_qtest);
+
+    g_free(args);
+    close(fd);
+}
+
+int main(int argc, char *argv[])
+{
+    const char *arch = qtest_get_arch();
+    int i;
+
+    g_test_init(&argc, &argv, NULL);
+
+    for (i = 0; tests[i].arch != NULL; i++) {
+        if (strcmp(arch, tests[i].arch) == 0) {
+            char *name = g_strdup_printf("boot-serial/%s", tests[i].machine);
+            qtest_add_data_func(name, &tests[i], test_machine);
+            g_free(name);
+        }
+    }
+
+    return g_test_run();
+}
diff --git a/tests/check-block.sh b/tests/check-block.sh
index a37797a494..c3de3789c4 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -1,5 +1,10 @@
 #!/bin/sh
 
+FORMAT_LIST="raw qcow2 qed vmdk vpc"
+if [ "$#" -ne 0 ]; then
+    FORMAT_LIST="$@"
+fi
+
 export QEMU_PROG="$(pwd)/x86_64-softmmu/qemu-system-x86_64"
 export QEMU_IMG_PROG="$(pwd)/qemu-img"
 export QEMU_IO_PROG="$(pwd)/qemu-io"
@@ -12,10 +17,8 @@ fi
 cd tests/qemu-iotests
 
 ret=0
-./check -T -nocache -raw || ret=1
-./check -T -nocache -qcow2 || ret=1
-./check -T -nocache -qed|| ret=1
-./check -T -nocache -vmdk|| ret=1
-./check -T -nocache -vpc || ret=1
+for FMT in $FORMAT_LIST ; do
+    ./check -T -nocache -$FMT || ret=1
+done
 
 exit $ret
diff --git a/tests/check-qom-interface.c b/tests/check-qom-interface.c
index 719ddcf2e0..f87c9aaa8a 100644
--- a/tests/check-qom-interface.c
+++ b/tests/check-qom-interface.c
@@ -76,6 +76,7 @@ static void test_interface_impl(const char *type)
 
     g_assert(iobj);
     g_assert(ioc->test == PATTERN);
+    object_unref(obj);
 }
 
 static void interface_direct_test(void)
diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index 42defe7128..a16cefca73 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -230,6 +230,13 @@ struct DummyBackendClass {
 };
 
 
+static void dummy_dev_finalize(Object *obj)
+{
+    DummyDev *dev = DUMMY_DEV(obj);
+
+    object_unref(OBJECT(dev->bus));
+}
+
 static void dummy_dev_init(Object *obj)
 {
     DummyDev *dev = DUMMY_DEV(obj);
@@ -257,6 +264,13 @@ static void dummy_dev_class_init(ObjectClass *klass, void *opaque)
 }
 
 
+static void dummy_bus_finalize(Object *obj)
+{
+    DummyBus *bus = DUMMY_BUS(obj);
+
+    object_unref(OBJECT(bus->backend));
+}
+
 static void dummy_bus_init(Object *obj)
 {
 }
@@ -283,6 +297,7 @@ static const TypeInfo dummy_dev_info = {
     .parent        = TYPE_OBJECT,
     .instance_size = sizeof(DummyDev),
     .instance_init = dummy_dev_init,
+    .instance_finalize = dummy_dev_finalize,
     .class_size = sizeof(DummyDevClass),
     .class_init = dummy_dev_class_init,
 };
@@ -292,6 +307,7 @@ static const TypeInfo dummy_bus_info = {
     .parent        = TYPE_OBJECT,
     .instance_size = sizeof(DummyBus),
     .instance_init = dummy_bus_init,
+    .instance_finalize = dummy_bus_finalize,
     .class_size = sizeof(DummyBusClass),
     .class_init = dummy_bus_class_init,
 };
diff --git a/tests/crypto-tls-x509-helpers.h b/tests/crypto-tls-x509-helpers.h
index 356b49cd5a..a8faa92bc0 100644
--- a/tests/crypto-tls-x509-helpers.h
+++ b/tests/crypto-tls-x509-helpers.h
@@ -26,7 +26,6 @@
 
 #if !(defined WIN32) && \
     defined(CONFIG_TASN1) && \
-    defined(LIBGNUTLS_VERSION_NUMBER) && \
     (LIBGNUTLS_VERSION_NUMBER >= 0x020600)
 # define QCRYPTO_HAVE_TLS_TEST_SUPPORT
 #endif
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 4f4707dae0..b44daabbce 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -25,7 +25,7 @@ make-archive-maybe = $(if $(wildcard $1/*), \
 		else \
 			git archive -1 $$(git stash create) --format=tar.gz; \
 		fi) > $2, \
-		"  ARCHIVE $(notdir $2)"))
+		"ARCHIVE","$(notdir $2)"))
 
 CUR_TIME := $(shell date +%Y-%m-%d-%H.%M.%S.$$$$)
 DOCKER_SRC_COPY := docker-src.$(CUR_TIME)
@@ -36,7 +36,7 @@ $(DOCKER_SRC_COPY):
 	$(call make-archive-maybe, $(SRC_PATH)/dtc, $@/dtc.tgz)
 	$(call make-archive-maybe, $(SRC_PATH)/pixman, $@/pixman.tgz)
 	$(call quiet-command, cp $(SRC_PATH)/tests/docker/run $@/run, \
-		"  COPY RUNNER")
+		"COPY","RUNNER")
 
 docker-qemu-src: $(DOCKER_SRC_COPY)
 
@@ -44,11 +44,14 @@ docker-image: ${DOCKER_TARGETS}
 
 # General rule for building docker images
 docker-image-%: $(DOCKER_FILES_DIR)/%.docker
+	@if test "$@" = docker-image-debian-bootstrap -a -z "$(EXECUTABLE)"; then \
+		echo WARNING: EXECUTABLE is not set, debootstrap may fail. 2>&1 ; \
+	fi
 	$(call quiet-command,\
 		$(SRC_PATH)/tests/docker/docker.py build qemu:$* $< \
 		$(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \
 		$(if $(EXECUTABLE),--include-executable=$(EXECUTABLE)),\
-		"  BUILD $*")
+		"BUILD","$*")
 
 # Expand all the pre-requistes for each docker image and test combination
 $(foreach i,$(DOCKER_IMAGES), \
@@ -114,15 +117,15 @@ docker-run-%: docker-qemu-src
 				$(if $(DEBUG),-i,--net=none) \
 				-e TARGET_LIST=$(TARGET_LIST) \
 				-e EXTRA_CONFIGURE_OPTS=$(EXTRA_CONFIGURE_OPTS) \
-				-e V=$V -e J=$J -e DEBUG=$(DEBUG)\
+				-e V=$V -e J=$J -e DEBUG=$(DEBUG) -e SHOW_ENV=$(SHOW_ENV)\
 				-e CCACHE_DIR=/var/tmp/ccache \
-				-v $$(realpath $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \
+				-v $$(readlink -e $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \
 				-v $(DOCKER_CCACHE_DIR):/var/tmp/ccache:z \
 				qemu:$(IMAGE) \
 				/var/tmp/qemu/run \
 				$(CMD); \
 			fi \
-			, "  RUN $(CMD) in $(IMAGE)")))
+			,"RUN","$(CMD) in $(IMAGE)")))
 
 docker-clean:
 	$(call quiet-command, $(SRC_PATH)/tests/docker/docker.py clean)
diff --git a/tests/docker/common.rc b/tests/docker/common.rc
index 0c6d8d5ece..21657e87c6 100755
--- a/tests/docker/common.rc
+++ b/tests/docker/common.rc
@@ -11,6 +11,9 @@
 # or (at your option) any later version. See the COPYING file in
 # the top-level directory.
 
+BUILD_DIR=/var/tmp/qemu-build
+mkdir $BUILD_DIR
+
 requires()
 {
     for c in $@; do
@@ -23,11 +26,13 @@ requires()
 
 build_qemu()
 {
-    $QEMU_SRC/configure \
-        --enable-werror \
-        ${TARGET_LIST:+"--target-list=${TARGET_LIST}"} \
-        --prefix="$PWD/install" \
-        $EXTRA_CONFIGURE_OPTS \
-        "$@"
+    config_opts="--enable-werror \
+                 ${TARGET_LIST:+--target-list=${TARGET_LIST}} \
+                 --prefix=$PWD/install \
+                 $EXTRA_CONFIGURE_OPTS \
+                 $@"
+    echo "Configure options:"
+    echo $config_opts
+    $QEMU_SRC/configure $config_opts
     make $MAKEFLAGS
 }
diff --git a/tests/docker/docker.py b/tests/docker/docker.py
index 222a1053fe..37d83199e7 100755
--- a/tests/docker/docker.py
+++ b/tests/docker/docker.py
@@ -21,10 +21,15 @@ import uuid
 import argparse
 import tempfile
 import re
+import signal
 from tarfile import TarFile, TarInfo
 from StringIO import StringIO
 from shutil import copy, rmtree
 
+
+DEVNULL = open(os.devnull, 'wb')
+
+
 def _text_checksum(text):
     """Calculate a digest string unique to the text content"""
     return hashlib.sha1(text).hexdigest()
@@ -33,10 +38,12 @@ def _guess_docker_command():
     """ Guess a working docker command or raise exception if not found"""
     commands = [["docker"], ["sudo", "-n", "docker"]]
     for cmd in commands:
-        if subprocess.call(cmd + ["images"],
-                           stdout=subprocess.PIPE,
-                           stderr=subprocess.PIPE) == 0:
-            return cmd
+        try:
+            if subprocess.call(cmd + ["images"],
+                               stdout=DEVNULL, stderr=DEVNULL) == 0:
+                return cmd
+        except OSError:
+            pass
     commands_txt = "\n".join(["  " + " ".join(x) for x in commands])
     raise Exception("Cannot find working docker command. Tried:\n%s" % \
                     commands_txt)
@@ -95,10 +102,12 @@ class Docker(object):
         self._command = _guess_docker_command()
         self._instances = []
         atexit.register(self._kill_instances)
+        signal.signal(signal.SIGTERM, self._kill_instances)
+        signal.signal(signal.SIGHUP, self._kill_instances)
 
     def _do(self, cmd, quiet=True, infile=None, **kwargs):
         if quiet:
-            kwargs["stdout"] = subprocess.PIPE
+            kwargs["stdout"] = DEVNULL
         if infile:
             kwargs["stdin"] = infile
         return subprocess.call(self._command + cmd, **kwargs)
@@ -127,7 +136,7 @@ class Docker(object):
         self._do_kill_instances(False, False)
         return 0
 
-    def _kill_instances(self):
+    def _kill_instances(self, *args, **kwargs):
         return self._do_kill_instances(True)
 
     def _output(self, cmd, **kwargs):
@@ -236,8 +245,9 @@ class BuildCommand(SubCommand):
             # Is there a .pre file to run in the build context?
             docker_pre = os.path.splitext(args.dockerfile)[0]+".pre"
             if os.path.exists(docker_pre):
+                stdout = DEVNULL if args.quiet else None
                 rc = subprocess.call(os.path.realpath(docker_pre),
-                                     cwd=docker_dir)
+                                     cwd=docker_dir, stdout=stdout)
                 if rc == 3:
                     print "Skip"
                     return 0
diff --git a/tests/docker/dockerfiles/centos6.docker b/tests/docker/dockerfiles/centos6.docker
index 8f4fe46379..34e0d3b91e 100644
--- a/tests/docker/dockerfiles/centos6.docker
+++ b/tests/docker/dockerfiles/centos6.docker
@@ -1,6 +1,8 @@
 FROM centos:6
-RUN yum install -y \
+RUN yum install -y epel-release
+ENV PACKAGES libfdt-devel ccache \
     tar git make gcc g++ \
     zlib-devel glib2-devel SDL-devel pixman-devel \
     epel-release
-RUN yum install -y libfdt-devel ccache
+RUN yum install -y $PACKAGES
+RUN rpm -q $PACKAGES | sort > /packages.txt
diff --git a/tests/docker/dockerfiles/debian-bootstrap.pre b/tests/docker/dockerfiles/debian-bootstrap.pre
index 5d9c8d5ebc..7c76dce663 100755
--- a/tests/docker/dockerfiles/debian-bootstrap.pre
+++ b/tests/docker/dockerfiles/debian-bootstrap.pre
@@ -3,6 +3,8 @@
 # Simple wrapper for debootstrap, run in the docker build context
 #
 FAKEROOT=`which fakeroot 2> /dev/null`
+# debootstrap < 1.0.67 generates empty sources.list, see Debian#732255
+MIN_DEBOOTSTRAP_VERSION=1.0.67
 
 exit_and_skip()
 {
@@ -13,8 +15,21 @@ exit_and_skip()
 # fakeroot is needed to run the bootstrap stage
 #
 if [ -z $FAKEROOT ]; then
-    echo "Please install fakeroot to enable bootstraping"
+    echo "Please install fakeroot to enable bootstraping" >&2
     exit_and_skip
+
+fi
+
+if [ -z "${DEB_ARCH}" ]; then
+    echo "Please set DEB_ARCH to choose an architecture (e.g. armhf)" >&2
+    exit_and_skip
+
+fi
+
+if [ -z "${DEB_TYPE}" ]; then
+    echo "Please set DEB_TYPE to a Debian archive name (e.g. testing)" >&2
+    exit_and_skip
+
 fi
 
 # We check in order for
@@ -27,18 +42,27 @@ fi
 #
 
 if [ -z $DEBOOTSTRAP_DIR ]; then
+    NEED_DEBOOTSTRAP=false
     DEBOOTSTRAP=`which debootstrap 2> /dev/null`
     if [ -z $DEBOOTSTRAP ]; then
         echo "No debootstrap installed, attempting to install from SCM"
+        NEED_DEBOOTSTRAP=true
+    elif ! (echo "${MIN_DEBOOTSTRAP_VERSION}" ; "${DEBOOTSTRAP}" --version \
+            | cut -d ' ' -f 2) | sort -t . -n -k 1,1 -k 2,2 -k 3,3 -c &>/dev/null; then
+        echo "debootstrap too old, attempting to install from SCM"
+        NEED_DEBOOTSTRAP=true
+    fi
+    if $NEED_DEBOOTSTRAP; then
         DEBOOTSTRAP_SOURCE=https://anonscm.debian.org/git/d-i/debootstrap.git
         git clone ${DEBOOTSTRAP_SOURCE} ./debootstrap.git
         export DEBOOTSTRAP_DIR=./debootstrap.git
         DEBOOTSTRAP=./debootstrap.git/debootstrap
+        (cd "${DEBOOTSTRAP_DIR}" && "${FAKEROOT}" make )
     fi
 else
     DEBOOTSTRAP=${DEBOOTSTRAP_DIR}/debootstrap
     if [ ! -f $DEBOOTSTRAP ]; then
-        echo "Couldn't find script at ${DEBOOTSTRAP}"
+        echo "Couldn't find script at ${DEBOOTSTRAP}" >&2
         exit_and_skip
     fi
 fi
@@ -48,7 +72,7 @@ fi
 #
 BINFMT_DIR=/proc/sys/fs/binfmt_misc
 if [ ! -e $BINFMT_DIR ]; then
-   echo "binfmt_misc needs enabling for a QEMU bootstrap to work"
+   echo "binfmt_misc needs enabling for a QEMU bootstrap to work" >&2
    exit_and_skip
 else
     # DEB_ARCH and QEMU arch names are not totally aligned
@@ -76,7 +100,7 @@ else
         ;;
     esac
     if [ ! -e "${BINFMT_DIR}/$QEMU" ]; then
-        echo "No binfmt_misc rule to run $QEMU, can't bootstrap"
+        echo "No binfmt_misc rule to run $QEMU, can't bootstrap" >&2
         exit_and_skip
     fi
 fi
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 1d26a8e98a..478163b8d8 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -1,7 +1,17 @@
-FROM fedora:23
-RUN dnf install -y \
+FROM fedora:latest
+ENV PACKAGES \
     ccache git tar PyYAML sparse flex bison \
     glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \
     gcc gcc-c++ clang make perl which bc findutils \
-    mingw{32,64}-{pixman,glib2,gmp,SDL,pkg-config,gtk2,gtk3,gnutls,nettle,libtasn1,libjpeg-turbo,libpng,curl,libssh2,bzip2}
+    mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config \
+    mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1 \
+    mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2 \
+    mingw32-bzip2 \
+    mingw64-pixman mingw64-glib2 mingw64-gmp mingw64-SDL mingw64-pkg-config \
+    mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1 \
+    mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2 \
+    mingw64-bzip2
+
+RUN dnf install -y $PACKAGES
+RUN rpm -q $PACKAGES | sort > /packages.txt
 ENV FEATURES mingw clang pyyaml
diff --git a/tests/docker/dockerfiles/min-glib.docker b/tests/docker/dockerfiles/min-glib.docker
new file mode 100644
index 0000000000..9f542d5e9c
--- /dev/null
+++ b/tests/docker/dockerfiles/min-glib.docker
@@ -0,0 +1,8 @@
+FROM centos:6
+RUN yum install -y \
+    tar git make gcc g++ \
+    zlib-devel SDL-devel pixman-devel \
+    epel-release
+RUN yum install -y libfdt-devel ccache
+RUN yum downgrade -y http://vault.centos.org/6.0/os/x86_64/Packages/glib2-2.22.5-5.el6.x86_64.rpm
+RUN yum install -y http://vault.centos.org/6.0/os/x86_64/Packages/glib2-devel-2.22.5-5.el6.x86_64.rpm
diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker
index a8b88c318c..a360a050a2 100644
--- a/tests/docker/dockerfiles/ubuntu.docker
+++ b/tests/docker/dockerfiles/ubuntu.docker
@@ -2,10 +2,12 @@ FROM ubuntu:14.04
 RUN echo "deb http://archive.ubuntu.com/ubuntu/ trusty universe multiverse" >> \
     /etc/apt/sources.list
 RUN apt-get update
-RUN apt-get -y install flex bison \
+ENV PACKAGES flex bison \
     libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev \
     libseccomp-dev libgnutls-dev libssh2-1-dev  libspice-server-dev \
     libspice-protocol-dev libnss3-dev libfdt-dev \
     libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev \
     git make ccache python-yaml gcc clang sparse
+RUN apt-get -y install $PACKAGES
+RUN dpkg -l $PACKAGES | sort > /packages.txt
 ENV FEATURES clang pyyaml
diff --git a/tests/docker/run b/tests/docker/run
index d85d49afc1..c1e4513bce 100755
--- a/tests/docker/run
+++ b/tests/docker/run
@@ -40,20 +40,34 @@ for p in dtc pixman; do
     fi
 done
 
+if test -n "$SHOW_ENV"; then
+    if test -f /packages.txt; then
+        echo "Packages installed:"
+        cat /packages.txt
+        echo
+    fi
+    echo "Environment variables:"
+    env
+    echo
+fi
+
 export QEMU_SRC="$TEST_DIR/src"
 
 cd "$QEMU_SRC/tests/docker"
 
 CMD="$QEMU_SRC/tests/docker/$@"
 
-if test -n "$DEBUG"; then
-    echo "* Prepared to run command:"
-    echo "  $CMD"
-    echo "* Hit Ctrl-D to continue, or type 'exit 1' to abort"
-    echo
-    $SHELL
+if test -z "$DEBUG"; then
+    exec $CMD
 fi
 
+# DEBUG workflow
+echo "* Prepared to run command:"
+echo "  $CMD"
+echo "* Hit Ctrl-D to continue, or type 'exit 1' to abort"
+echo
+$SHELL
+
 if "$CMD"; then
     exit 0
 elif test -n "$DEBUG"; then
diff --git a/tests/docker/test-clang b/tests/docker/test-clang
index 60e4e976b3..16485e6b7e 100755
--- a/tests/docker/test-clang
+++ b/tests/docker/test-clang
@@ -15,6 +15,8 @@
 
 requires clang
 
+cd "$BUILD_DIR"
+
 OPTS="--enable-debug --cxx=clang++ --cc=clang --host-cc=clang"
 # -fsanitize=undefined is broken on Fedora 23, skip it for now
 # See also: https://bugzilla.redhat.com/show_bug.cgi?id=1263834
diff --git a/tests/docker/test-full b/tests/docker/test-full
index fd9b798947..05f0d491d1 100755
--- a/tests/docker/test-full
+++ b/tests/docker/test-full
@@ -13,5 +13,7 @@
 
 . common.rc
 
+cd "$BUILD_DIR"
+
 build_qemu
 make check $MAKEFLAGS
diff --git a/tests/docker/test-mingw b/tests/docker/test-mingw
index c03757add8..33968769f8 100755
--- a/tests/docker/test-mingw
+++ b/tests/docker/test-mingw
@@ -15,6 +15,8 @@
 
 requires mingw dtc
 
+cd "$BUILD_DIR"
+
 for prefix in x86_64-w64-mingw32- i686-w64-mingw32-; do
     TARGET_LIST=x86_64-softmmu,aarch64-softmmu \
         build_qemu --cross-prefix=$prefix \
diff --git a/tests/docker/test-quick b/tests/docker/test-quick
index 07cdc59a10..c465dc06d8 100755
--- a/tests/docker/test-quick
+++ b/tests/docker/test-quick
@@ -13,7 +13,9 @@
 
 . common.rc
 
-DEF_TARGET_LIST="$(echo {x86_64,aarch64}-softmmu)"
+cd "$BUILD_DIR"
+
+DEF_TARGET_LIST="x86_64-softmmu,aarch64-softmmu"
 TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \
 build_qemu
 make check $MAKEFLAGS
diff --git a/tests/e1000e-test.c b/tests/e1000e-test.c
index d497b0857c..3979b20bb0 100644
--- a/tests/e1000e-test.c
+++ b/tests/e1000e-test.c
@@ -390,7 +390,7 @@ static void data_test_init(e1000e_device *d)
     qtest_start(cmdline);
     g_free(cmdline);
 
-    test_bus = qpci_init_pc();
+    test_bus = qpci_init_pc(NULL);
     g_assert_nonnull(test_bus);
 
     test_alloc = pc_alloc_init();
diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c
index 12ee3929da..6176e81ab2 100644
--- a/tests/hd-geo-test.c
+++ b/tests/hd-geo-test.c
@@ -416,7 +416,9 @@ int main(int argc, char **argv)
     ret = g_test_run();
 
     for (i = 0; i < backend_last; i++) {
-        unlink(img_file_name[i]);
+        if (img_file_name[i]) {
+            unlink(img_file_name[i]);
+        }
     }
 
     return ret;
diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c
index 3542ad114e..da2d5a53f0 100644
--- a/tests/i440fx-test.c
+++ b/tests/i440fx-test.c
@@ -38,7 +38,7 @@ static QPCIBus *test_start_get_bus(const TestData *s)
     cmdline = g_strdup_printf("-smp %d", s->num_cpus);
     qtest_start(cmdline);
     g_free(cmdline);
-    return qpci_init_pc();
+    return qpci_init_pc(NULL);
 }
 
 static void test_i440fx_defaults(gconstpointer opaque)
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 1e51af2a94..a8a4081f78 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -143,7 +143,7 @@ static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
     uint16_t vendor_id, device_id;
 
     if (!pcibus) {
-        pcibus = qpci_init_pc();
+        pcibus = qpci_init_pc(NULL);
     }
 
     /* Find PCI device and verify it's the right one */
diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
index 0957ee7555..f36bfe7d0a 100644
--- a/tests/ivshmem-test.c
+++ b/tests/ivshmem-test.c
@@ -105,7 +105,7 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
     uint64_t barsize;
 
     s->qtest = qtest_start(cmd);
-    s->pcibus = qpci_init_pc();
+    s->pcibus = qpci_init_pc(NULL);
     s->dev = get_device(s->pcibus);
 
     s->reg_base = qpci_iomap(s->dev, 0, &barsize);
diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
index f3be5500e1..716ab7939e 100644
--- a/tests/libqos/ahci.c
+++ b/tests/libqos/ahci.c
@@ -128,7 +128,7 @@ QPCIDevice *get_ahci_device(uint32_t *fingerprint)
     uint32_t ahci_fingerprint;
     QPCIBus *pcibus;
 
-    pcibus = qpci_init_pc();
+    pcibus = qpci_init_pc(NULL);
 
     /* Find the AHCI PCI device and verify it's the right one. */
     ahci = qpci_device_find(pcibus, QPCI_DEVFN(0x1F, 0x02));
diff --git a/tests/libqos/libqos-pc.c b/tests/libqos/libqos-pc.c
index 72b5e3ba09..b554758802 100644
--- a/tests/libqos/libqos-pc.c
+++ b/tests/libqos/libqos-pc.c
@@ -1,10 +1,14 @@
 #include "qemu/osdep.h"
 #include "libqos/libqos-pc.h"
 #include "libqos/malloc-pc.h"
+#include "libqos/pci-pc.h"
 
 static QOSOps qos_ops = {
     .init_allocator = pc_alloc_init_flags,
-    .uninit_allocator = pc_alloc_uninit
+    .uninit_allocator = pc_alloc_uninit,
+    .qpci_init = qpci_init_pc,
+    .qpci_free = qpci_free_pc,
+    .shutdown = qtest_pc_shutdown,
 };
 
 QOSState *qtest_pc_vboot(const char *cmdline_fmt, va_list ap)
@@ -21,10 +25,12 @@ QOSState *qtest_pc_boot(const char *cmdline_fmt, ...)
     qs = qtest_vboot(&qos_ops, cmdline_fmt, ap);
     va_end(ap);
 
+    qtest_irq_intercept_in(global_qtest, "ioapic");
+
     return qs;
 }
 
 void qtest_pc_shutdown(QOSState *qs)
 {
-    return qtest_shutdown(qs);
+    return qtest_common_shutdown(qs);
 }
diff --git a/tests/libqos/libqos-spapr.c b/tests/libqos/libqos-spapr.c
new file mode 100644
index 0000000000..a37791e5d0
--- /dev/null
+++ b/tests/libqos/libqos-spapr.c
@@ -0,0 +1,34 @@
+#include "qemu/osdep.h"
+#include "libqos/libqos-spapr.h"
+#include "libqos/malloc-spapr.h"
+#include "libqos/pci-spapr.h"
+
+static QOSOps qos_ops = {
+    .init_allocator = spapr_alloc_init_flags,
+    .uninit_allocator = spapr_alloc_uninit,
+    .qpci_init = qpci_init_spapr,
+    .qpci_free = qpci_free_spapr,
+    .shutdown = qtest_spapr_shutdown,
+};
+
+QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap)
+{
+    return qtest_vboot(&qos_ops, cmdline_fmt, ap);
+}
+
+QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...)
+{
+    QOSState *qs;
+    va_list ap;
+
+    va_start(ap, cmdline_fmt);
+    qs = qtest_vboot(&qos_ops, cmdline_fmt, ap);
+    va_end(ap);
+
+    return qs;
+}
+
+void qtest_spapr_shutdown(QOSState *qs)
+{
+    return qtest_common_shutdown(qs);
+}
diff --git a/tests/libqos/libqos-spapr.h b/tests/libqos/libqos-spapr.h
new file mode 100644
index 0000000000..dcb5c43ad3
--- /dev/null
+++ b/tests/libqos/libqos-spapr.h
@@ -0,0 +1,10 @@
+#ifndef LIBQOS_SPAPR_H
+#define LIBQOS_SPAPR_H
+
+#include "libqos/libqos.h"
+
+QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap);
+QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...);
+void qtest_spapr_shutdown(QOSState *qs);
+
+#endif
diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c
index c7ba441d0b..7abb48254e 100644
--- a/tests/libqos/libqos.c
+++ b/tests/libqos/libqos.c
@@ -20,9 +20,13 @@ QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap)
     cmdline = g_strdup_vprintf(cmdline_fmt, ap);
     qs->qts = qtest_start(cmdline);
     qs->ops = ops;
-    qtest_irq_intercept_in(global_qtest, "ioapic");
-    if (ops && ops->init_allocator) {
-        qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
+    if (ops) {
+        if (ops->init_allocator) {
+            qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
+        }
+        if (ops->qpci_init && qs->alloc) {
+            qs->pcibus = ops->qpci_init(qs->alloc);
+        }
     }
 
     g_free(cmdline);
@@ -48,16 +52,31 @@ QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...)
 /**
  * Tear down the QEMU instance.
  */
-void qtest_shutdown(QOSState *qs)
+void qtest_common_shutdown(QOSState *qs)
 {
-    if (qs->alloc && qs->ops && qs->ops->uninit_allocator) {
-        qs->ops->uninit_allocator(qs->alloc);
-        qs->alloc = NULL;
+    if (qs->ops) {
+        if (qs->pcibus && qs->ops->qpci_free) {
+            qs->ops->qpci_free(qs->pcibus);
+            qs->pcibus = NULL;
+        }
+        if (qs->alloc && qs->ops->uninit_allocator) {
+            qs->ops->uninit_allocator(qs->alloc);
+            qs->alloc = NULL;
+        }
     }
     qtest_quit(qs->qts);
     g_free(qs);
 }
 
+void qtest_shutdown(QOSState *qs)
+{
+    if (qs->ops && qs->ops->shutdown) {
+        qs->ops->shutdown(qs);
+    } else {
+        qtest_common_shutdown(qs);
+    }
+}
+
 void set_context(QOSState *s)
 {
     global_qtest = s->qts;
diff --git a/tests/libqos/libqos.h b/tests/libqos/libqos.h
index 604980d125..231969766f 100644
--- a/tests/libqos/libqos.h
+++ b/tests/libqos/libqos.h
@@ -5,19 +5,26 @@
 #include "libqos/pci.h"
 #include "libqos/malloc-pc.h"
 
+typedef struct QOSState QOSState;
+
 typedef struct QOSOps {
     QGuestAllocator *(*init_allocator)(QAllocOpts);
     void (*uninit_allocator)(QGuestAllocator *);
+    QPCIBus *(*qpci_init)(QGuestAllocator *alloc);
+    void (*qpci_free)(QPCIBus *bus);
+    void (*shutdown)(QOSState *);
 } QOSOps;
 
-typedef struct QOSState {
+struct QOSState {
     QTestState *qts;
     QGuestAllocator *alloc;
+    QPCIBus *pcibus;
     QOSOps *ops;
-} QOSState;
+};
 
 QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap);
 QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...);
+void qtest_common_shutdown(QOSState *qs);
 void qtest_shutdown(QOSState *qs);
 bool have_qemu_img(void);
 void mkimg(const char *file, const char *fmt, unsigned size_mb);
diff --git a/tests/libqos/malloc-spapr.c b/tests/libqos/malloc-spapr.c
new file mode 100644
index 0000000000..006404af33
--- /dev/null
+++ b/tests/libqos/malloc-spapr.c
@@ -0,0 +1,38 @@
+/*
+ * libqos malloc support for SPAPR
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqos/malloc-spapr.h"
+
+#include "qemu-common.h"
+
+#define PAGE_SIZE 4096
+
+/* Memory must be a multiple of 256 MB,
+ * so we have at least 256MB
+ */
+#define SPAPR_MIN_SIZE 0x10000000
+
+void spapr_alloc_uninit(QGuestAllocator *allocator)
+{
+    alloc_uninit(allocator);
+}
+
+QGuestAllocator *spapr_alloc_init_flags(QAllocOpts flags)
+{
+    QGuestAllocator *s;
+
+    s = alloc_init_flags(flags, 1 << 20, SPAPR_MIN_SIZE);
+    alloc_set_page_size(s, PAGE_SIZE);
+
+    return s;
+}
+
+QGuestAllocator *spapr_alloc_init(void)
+{
+    return spapr_alloc_init_flags(ALLOC_NO_FLAGS);
+}
diff --git a/tests/libqos/malloc-spapr.h b/tests/libqos/malloc-spapr.h
new file mode 100644
index 0000000000..64d0e770d1
--- /dev/null
+++ b/tests/libqos/malloc-spapr.h
@@ -0,0 +1,17 @@
+/*
+ * libqos malloc support for SPAPR
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_MALLOC_SPAPR_H
+#define LIBQOS_MALLOC_SPAPR_H
+
+#include "libqos/malloc.h"
+
+QGuestAllocator *spapr_alloc_init(void);
+QGuestAllocator *spapr_alloc_init_flags(QAllocOpts flags);
+void spapr_alloc_uninit(QGuestAllocator *allocator);
+
+#endif
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index 1ae2d3780f..9600ed6e41 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -212,7 +212,7 @@ static void qpci_pc_iounmap(QPCIBus *bus, void *data)
     /* FIXME */
 }
 
-QPCIBus *qpci_init_pc(void)
+QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
 {
     QPCIBusPC *ret;
 
@@ -255,28 +255,6 @@ void qpci_free_pc(QPCIBus *bus)
     g_free(s);
 }
 
-void qpci_plug_device_test(const char *driver, const char *id,
-                           uint8_t slot, const char *opts)
-{
-    QDict *response;
-    char *cmd;
-
-    cmd = g_strdup_printf("{'execute': 'device_add',"
-                          " 'arguments': {"
-                          "   'driver': '%s',"
-                          "   'addr': '%d',"
-                          "   %s%s"
-                          "   'id': '%s'"
-                          "}}", driver, slot,
-                          opts ? opts : "", opts ? "," : "",
-                          id);
-    response = qmp(cmd);
-    g_free(cmd);
-    g_assert(response);
-    g_assert(!qdict_haskey(response, "error"));
-    QDECREF(response);
-}
-
 void qpci_unplug_acpi_device_test(const char *id, uint8_t slot)
 {
     QDict *response;
diff --git a/tests/libqos/pci-pc.h b/tests/libqos/pci-pc.h
index 26211790cd..9479b51642 100644
--- a/tests/libqos/pci-pc.h
+++ b/tests/libqos/pci-pc.h
@@ -14,8 +14,9 @@
 #define LIBQOS_PCI_PC_H
 
 #include "libqos/pci.h"
+#include "libqos/malloc.h"
 
-QPCIBus *qpci_init_pc(void);
+QPCIBus *qpci_init_pc(QGuestAllocator *alloc);
 void     qpci_free_pc(QPCIBus *bus);
 
 #endif
diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
new file mode 100644
index 0000000000..2f73badfd9
--- /dev/null
+++ b/tests/libqos/pci-spapr.c
@@ -0,0 +1,288 @@
+/*
+ * libqos PCI bindings for SPAPR
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "libqos/pci-spapr.h"
+#include "libqos/rtas.h"
+
+#include "hw/pci/pci_regs.h"
+
+#include "qemu-common.h"
+#include "qemu/host-utils.h"
+
+
+/* From include/hw/pci-host/spapr.h */
+
+#define SPAPR_PCI_BASE_BUID          0x800000020000000ULL
+
+#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
+
+#define SPAPR_PCI_WINDOW_BASE        0x10000000000ULL
+#define SPAPR_PCI_WINDOW_SPACING     0x1000000000ULL
+#define SPAPR_PCI_MMIO_WIN_OFF       0xA0000000
+#define SPAPR_PCI_MMIO_WIN_SIZE      (SPAPR_PCI_WINDOW_SPACING - \
+                                     SPAPR_PCI_MEM_WIN_BUS_OFFSET)
+#define SPAPR_PCI_IO_WIN_OFF         0x80000000
+#define SPAPR_PCI_IO_WIN_SIZE        0x10000
+
+/* index is the phb index */
+
+#define BUIDBASE(index)              (SPAPR_PCI_BASE_BUID + (index))
+#define PCIBASE(index)               (SPAPR_PCI_WINDOW_BASE + \
+                                      (index) * SPAPR_PCI_WINDOW_SPACING)
+#define IOBASE(index)                (PCIBASE(index) + SPAPR_PCI_IO_WIN_OFF)
+#define MMIOBASE(index)              (PCIBASE(index) + SPAPR_PCI_MMIO_WIN_OFF)
+
+typedef struct QPCIBusSPAPR {
+    QPCIBus bus;
+    QGuestAllocator *alloc;
+
+    uint64_t pci_hole_start;
+    uint64_t pci_hole_size;
+    uint64_t pci_hole_alloc;
+
+    uint32_t pci_iohole_start;
+    uint32_t pci_iohole_size;
+    uint32_t pci_iohole_alloc;
+} QPCIBusSPAPR;
+
+/*
+ * PCI devices are always little-endian
+ * SPAPR by default is big-endian
+ * so PCI accessors need to swap data endianness
+ */
+
+static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
+{
+    uint64_t port = (uintptr_t)addr;
+    uint8_t v;
+    if (port < SPAPR_PCI_IO_WIN_SIZE) {
+        v = readb(IOBASE(0) + port);
+    } else {
+        v = readb(MMIOBASE(0) + port);
+    }
+    return v;
+}
+
+static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
+{
+    uint64_t port = (uintptr_t)addr;
+    uint16_t v;
+    if (port < SPAPR_PCI_IO_WIN_SIZE) {
+        v = readw(IOBASE(0) + port);
+    } else {
+        v = readw(MMIOBASE(0) + port);
+    }
+    return bswap16(v);
+}
+
+static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
+{
+    uint64_t port = (uintptr_t)addr;
+    uint32_t v;
+    if (port < SPAPR_PCI_IO_WIN_SIZE) {
+        v = readl(IOBASE(0) + port);
+    } else {
+        v = readl(MMIOBASE(0) + port);
+    }
+    return bswap32(v);
+}
+
+static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
+{
+    uint64_t port = (uintptr_t)addr;
+    if (port < SPAPR_PCI_IO_WIN_SIZE) {
+        writeb(IOBASE(0) + port, value);
+    } else {
+        writeb(MMIOBASE(0) + port, value);
+    }
+}
+
+static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
+{
+    uint64_t port = (uintptr_t)addr;
+    value = bswap16(value);
+    if (port < SPAPR_PCI_IO_WIN_SIZE) {
+        writew(IOBASE(0) + port, value);
+    } else {
+        writew(MMIOBASE(0) + port, value);
+    }
+}
+
+static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
+{
+    uint64_t port = (uintptr_t)addr;
+    value = bswap32(value);
+    if (port < SPAPR_PCI_IO_WIN_SIZE) {
+        writel(IOBASE(0) + port, value);
+    } else {
+        writel(MMIOBASE(0) + port, value);
+    }
+}
+
+static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    uint32_t config_addr = (devfn << 8) | offset;
+    return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
+                                     config_addr, 1);
+}
+
+static uint16_t qpci_spapr_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    uint32_t config_addr = (devfn << 8) | offset;
+    return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
+                                     config_addr, 2);
+}
+
+static uint32_t qpci_spapr_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    uint32_t config_addr = (devfn << 8) | offset;
+    return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
+                                     config_addr, 4);
+}
+
+static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset,
+                                     uint8_t value)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    uint32_t config_addr = (devfn << 8) | offset;
+    qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
+                               config_addr, 1, value);
+}
+
+static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset,
+                                     uint16_t value)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    uint32_t config_addr = (devfn << 8) | offset;
+    qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
+                               config_addr, 2, value);
+}
+
+static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
+                                     uint32_t value)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    uint32_t config_addr = (devfn << 8) | offset;
+    qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
+                               config_addr, 4, value);
+}
+
+static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
+                              uint64_t *sizeptr)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    static const int bar_reg_map[] = {
+        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
+        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
+    };
+    int bar_reg;
+    uint32_t addr;
+    uint64_t size;
+    uint32_t io_type;
+
+    g_assert(barno >= 0 && barno <= 5);
+    bar_reg = bar_reg_map[barno];
+
+    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
+    addr = qpci_config_readl(dev, bar_reg);
+
+    io_type = addr & PCI_BASE_ADDRESS_SPACE;
+    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+        addr &= PCI_BASE_ADDRESS_IO_MASK;
+    } else {
+        addr &= PCI_BASE_ADDRESS_MEM_MASK;
+    }
+
+    size = (1ULL << ctzl(addr));
+    if (size == 0) {
+        return NULL;
+    }
+    if (sizeptr) {
+        *sizeptr = size;
+    }
+
+    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+        uint16_t loc;
+
+        g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
+                 <= s->pci_iohole_size);
+        s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
+        loc = s->pci_iohole_start + s->pci_iohole_alloc;
+        s->pci_iohole_alloc += size;
+
+        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
+
+        return (void *)(unsigned long)loc;
+    } else {
+        uint64_t loc;
+
+        g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
+                 <= s->pci_hole_size);
+        s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
+        loc = s->pci_hole_start + s->pci_hole_alloc;
+        s->pci_hole_alloc += size;
+
+        qpci_config_writel(dev, bar_reg, loc);
+
+        return (void *)(unsigned long)loc;
+    }
+}
+
+static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
+{
+    /* FIXME */
+}
+
+QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
+{
+    QPCIBusSPAPR *ret;
+
+    ret = g_malloc(sizeof(*ret));
+
+    ret->alloc = alloc;
+
+    ret->bus.io_readb = qpci_spapr_io_readb;
+    ret->bus.io_readw = qpci_spapr_io_readw;
+    ret->bus.io_readl = qpci_spapr_io_readl;
+
+    ret->bus.io_writeb = qpci_spapr_io_writeb;
+    ret->bus.io_writew = qpci_spapr_io_writew;
+    ret->bus.io_writel = qpci_spapr_io_writel;
+
+    ret->bus.config_readb = qpci_spapr_config_readb;
+    ret->bus.config_readw = qpci_spapr_config_readw;
+    ret->bus.config_readl = qpci_spapr_config_readl;
+
+    ret->bus.config_writeb = qpci_spapr_config_writeb;
+    ret->bus.config_writew = qpci_spapr_config_writew;
+    ret->bus.config_writel = qpci_spapr_config_writel;
+
+    ret->bus.iomap = qpci_spapr_iomap;
+    ret->bus.iounmap = qpci_spapr_iounmap;
+
+    ret->pci_hole_start = 0xC0000000;
+    ret->pci_hole_size = SPAPR_PCI_MMIO_WIN_SIZE;
+    ret->pci_hole_alloc = 0;
+
+    ret->pci_iohole_start = 0xc000;
+    ret->pci_iohole_size = SPAPR_PCI_IO_WIN_SIZE;
+    ret->pci_iohole_alloc = 0;
+
+    return &ret->bus;
+}
+
+void qpci_free_spapr(QPCIBus *bus)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+
+    g_free(s);
+}
diff --git a/tests/libqos/pci-spapr.h b/tests/libqos/pci-spapr.h
new file mode 100644
index 0000000000..4192126d86
--- /dev/null
+++ b/tests/libqos/pci-spapr.h
@@ -0,0 +1,17 @@
+/*
+ * libqos PCI bindings for SPAPR
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_PCI_SPAPR_H
+#define LIBQOS_PCI_SPAPR_H
+
+#include "libqos/malloc.h"
+#include "libqos/pci.h"
+
+QPCIBus *qpci_init_spapr(QGuestAllocator *alloc);
+void     qpci_free_spapr(QPCIBus *bus);
+
+#endif
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index ed78d91cea..c3f3382b7c 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -263,4 +263,24 @@ void qpci_iounmap(QPCIDevice *dev, void *data)
     dev->bus->iounmap(dev->bus, data);
 }
 
-
+void qpci_plug_device_test(const char *driver, const char *id,
+                           uint8_t slot, const char *opts)
+{
+    QDict *response;
+    char *cmd;
+
+    cmd = g_strdup_printf("{'execute': 'device_add',"
+                          " 'arguments': {"
+                          "   'driver': '%s',"
+                          "   'addr': '%d',"
+                          "   %s%s"
+                          "   'id': '%s'"
+                          "}}", driver, slot,
+                          opts ? opts : "", opts ? "," : "",
+                          id);
+    response = qmp(cmd);
+    g_free(cmd);
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+}
diff --git a/tests/libqos/rtas.c b/tests/libqos/rtas.c
new file mode 100644
index 0000000000..0269803ce0
--- /dev/null
+++ b/tests/libqos/rtas.c
@@ -0,0 +1,116 @@
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "libqos/rtas.h"
+
+static void qrtas_copy_args(uint64_t target_args, uint32_t nargs,
+                            uint32_t *args)
+{
+    int i;
+
+    for (i = 0; i < nargs; i++) {
+        writel(target_args + i * sizeof(uint32_t), args[i]);
+    }
+}
+
+static void qrtas_copy_ret(uint64_t target_ret, uint32_t nret, uint32_t *ret)
+{
+    int i;
+
+    for (i = 0; i < nret; i++) {
+        ret[i] = readl(target_ret + i * sizeof(uint32_t));
+    }
+}
+
+static uint64_t qrtas_call(QGuestAllocator *alloc, const char *name,
+                           uint32_t nargs, uint32_t *args,
+                           uint32_t nret, uint32_t *ret)
+{
+    uint64_t res;
+    uint64_t target_args, target_ret;
+
+    target_args = guest_alloc(alloc, nargs * sizeof(uint32_t));
+    target_ret = guest_alloc(alloc, nret * sizeof(uint32_t));
+
+    qrtas_copy_args(target_args, nargs, args);
+    res = qtest_rtas_call(global_qtest, name,
+                          nargs, target_args, nret, target_ret);
+    qrtas_copy_ret(target_ret, nret, ret);
+
+    guest_free(alloc, target_ret);
+    guest_free(alloc, target_args);
+
+    return res;
+}
+
+int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns)
+{
+    int res;
+    uint32_t ret[8];
+
+    res = qrtas_call(alloc, "get-time-of-day", 0, NULL, 8, ret);
+    if (res != 0) {
+        return res;
+    }
+
+    res = ret[0];
+    memset(tm, 0, sizeof(*tm));
+    tm->tm_year = ret[1] - 1900;
+    tm->tm_mon = ret[2] - 1;
+    tm->tm_mday = ret[3];
+    tm->tm_hour = ret[4];
+    tm->tm_min = ret[5];
+    tm->tm_sec = ret[6];
+    *ns = ret[7];
+
+    return res;
+}
+
+uint32_t qrtas_ibm_read_pci_config(QGuestAllocator *alloc, uint64_t buid,
+                                   uint32_t addr, uint32_t size)
+{
+    int res;
+    uint32_t args[4], ret[2];
+
+    args[0] = addr;
+    args[1] = buid >> 32;
+    args[2] = buid & 0xffffffff;
+    args[3] = size;
+    res = qrtas_call(alloc, "ibm,read-pci-config", 4, args, 2, ret);
+    if (res != 0) {
+        return -1;
+    }
+
+    if (ret[0] != 0) {
+        return -1;
+    }
+
+    return ret[1];
+}
+
+int qrtas_ibm_write_pci_config(QGuestAllocator *alloc, uint64_t buid,
+                               uint32_t addr, uint32_t size, uint32_t val)
+{
+    int res;
+    uint32_t args[5], ret[1];
+
+    args[0] = addr;
+    args[1] = buid >> 32;
+    args[2] = buid & 0xffffffff;
+    args[3] = size;
+    args[4] = val;
+    res = qrtas_call(alloc, "ibm,write-pci-config", 5, args, 1, ret);
+    if (res != 0) {
+        return -1;
+    }
+
+    if (ret[0] != 0) {
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/libqos/rtas.h b/tests/libqos/rtas.h
new file mode 100644
index 0000000000..498eb19230
--- /dev/null
+++ b/tests/libqos/rtas.h
@@ -0,0 +1,15 @@
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_RTAS_H
+#define LIBQOS_RTAS_H
+#include "libqos/malloc.h"
+
+int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns);
+uint32_t qrtas_ibm_read_pci_config(QGuestAllocator *alloc, uint64_t buid,
+                                   uint32_t addr, uint32_t size);
+int qrtas_ibm_write_pci_config(QGuestAllocator *alloc, uint64_t buid,
+                               uint32_t addr, uint32_t size, uint32_t val);
+#endif /* LIBQOS_RTAS_H */
diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c
index d8c2970de7..105bccecaa 100644
--- a/tests/libqos/virtio.c
+++ b/tests/libqos/virtio.c
@@ -147,7 +147,7 @@ void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr)
 
     for (i = 0; i < vq->size - 1; i++) {
         /* vq->desc[i].addr */
-        writew(vq->desc + (16 * i), 0);
+        writeq(vq->desc + (16 * i), 0);
         /* vq->desc[i].next */
         writew(vq->desc + (16 * i) + 14, i + 1);
     }
@@ -257,16 +257,16 @@ void qvirtqueue_kick(const QVirtioBus *bus, QVirtioDevice *d, QVirtQueue *vq,
                                                             uint32_t free_head)
 {
     /* vq->avail->idx */
-    uint16_t idx = readl(vq->avail + 2);
+    uint16_t idx = readw(vq->avail + 2);
     /* vq->used->flags */
     uint16_t flags;
     /* vq->used->avail_event */
     uint16_t avail_event;
 
     /* vq->avail->ring[idx % vq->size] */
-    writel(vq->avail + 4 + (2 * (idx % vq->size)), free_head);
+    writew(vq->avail + 4 + (2 * (idx % vq->size)), free_head);
     /* vq->avail->idx */
-    writel(vq->avail + 2, idx + 1);
+    writew(vq->avail + 2, idx + 1);
 
     /* Must read after idx is updated */
     flags = readw(vq->avail);
diff --git a/tests/libqtest.c b/tests/libqtest.c
index eb00f1392b..6f6bdf142f 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -751,6 +751,16 @@ void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size)
     g_strfreev(args);
 }
 
+uint64_t qtest_rtas_call(QTestState *s, const char *name,
+                         uint32_t nargs, uint64_t args,
+                         uint32_t nret, uint64_t ret)
+{
+    qtest_sendf(s, "rtas %s %u 0x%"PRIx64" %u 0x%"PRIx64"\n",
+                name, nargs, args, nret, ret);
+    qtest_rsp(s, 0);
+    return 0;
+}
+
 void qtest_add_func(const char *str, void (*fn)(void))
 {
     gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
@@ -758,6 +768,25 @@ void qtest_add_func(const char *str, void (*fn)(void))
     g_free(path);
 }
 
+void qtest_add_data_func_full(const char *str, void *data,
+                              void (*fn)(const void *),
+                              GDestroyNotify data_free_func)
+{
+    gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
+#if GLIB_CHECK_VERSION(2, 34, 0)
+    g_test_add_data_func_full(path, data, fn, data_free_func);
+#elif GLIB_CHECK_VERSION(2, 26, 0)
+    /* back-compat casts, remove this once we can require new-enough glib */
+    g_test_add_vtable(path, 0, data, NULL,
+                      (GTestFixtureFunc)fn, (GTestFixtureFunc) data_free_func);
+#else
+    /* back-compat casts, remove this once we can require new-enough glib */
+    g_test_add_vtable(path, 0, data, NULL,
+                      (void (*)(void)) fn, (void (*)(void)) data_free_func);
+#endif
+    g_free(path);
+}
+
 void qtest_add_data_func(const char *str, const void *data,
                          void (*fn)(const void *))
 {
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 37f37adbf7..f7402e0cc1 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -318,6 +318,21 @@ uint64_t qtest_readq(QTestState *s, uint64_t addr);
 void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size);
 
 /**
+ * qtest_rtas_call:
+ * @s: #QTestState instance to operate on.
+ * @name: name of the command to call.
+ * @nargs: Number of args.
+ * @args: Guest address to read args from.
+ * @nret: Number of return value.
+ * @ret: Guest address to write return values to.
+ *
+ * Call an RTAS function
+ */
+uint64_t qtest_rtas_call(QTestState *s, const char *name,
+                         uint32_t nargs, uint64_t args,
+                         uint32_t nret, uint64_t ret);
+
+/**
  * qtest_bufread:
  * @s: #QTestState instance to operate on.
  * @addr: Guest address to read from.
@@ -426,6 +441,23 @@ void qtest_add_data_func(const char *str, const void *data,
                          void (*fn)(const void *));
 
 /**
+ * qtest_add_data_func_full:
+ * @str: Test case path.
+ * @data: Test case data
+ * @fn: Test case function
+ * @data_free_func: GDestroyNotify for data
+ *
+ * Add a GTester testcase with the given name, data and function.
+ * The path is prefixed with the architecture under test, as
+ * returned by qtest_get_arch().
+ *
+ * @data is passed to @data_free_func() on test completion.
+ */
+void qtest_add_data_func_full(const char *str, void *data,
+                              void (*fn)(const void *),
+                              GDestroyNotify data_free_func);
+
+/**
  * qtest_add:
  * @testpath: Test case path
  * @Fixture: Fixture type
diff --git a/tests/pc-cpu-test.c b/tests/pc-cpu-test.c
index 4428cea5f1..c3a2633d3c 100644
--- a/tests/pc-cpu-test.c
+++ b/tests/pc-cpu-test.c
@@ -14,7 +14,7 @@
 #include "qapi/qmp/types.h"
 
 struct PCTestData {
-    const char *machine;
+    char *machine;
     const char *cpu_model;
     unsigned sockets;
     unsigned cores;
@@ -71,6 +71,14 @@ static void test_pc_without_cpu_add(gconstpointer data)
     g_free(args);
 }
 
+static void test_data_free(gpointer data)
+{
+    PCTestData *pc = data;
+
+    g_free(pc->machine);
+    g_free(pc);
+}
+
 static void add_pc_test_cases(void)
 {
     QDict *response, *minfo;
@@ -78,7 +86,8 @@ static void add_pc_test_cases(void)
     const QListEntry *p;
     QObject *qobj;
     QString *qstr;
-    const char *mname, *path;
+    const char *mname;
+    char *path;
     PCTestData *data;
 
     qtest_start("-machine none");
@@ -99,7 +108,7 @@ static void add_pc_test_cases(void)
             continue;
         }
         data = g_malloc(sizeof(PCTestData));
-        data->machine = mname;
+        data->machine = g_strdup(mname);
         data->cpu_model = "Haswell"; /* 1.3+ theoretically */
         data->sockets = 1;
         data->cores = 3;
@@ -119,14 +128,19 @@ static void add_pc_test_cases(void)
             path = g_strdup_printf("cpu/%s/init/%ux%ux%u&maxcpus=%u",
                                    mname, data->sockets, data->cores,
                                    data->threads, data->maxcpus);
-            qtest_add_data_func(path, data, test_pc_without_cpu_add);
+            qtest_add_data_func_full(path, data, test_pc_without_cpu_add,
+                                     test_data_free);
+            g_free(path);
         } else {
             path = g_strdup_printf("cpu/%s/add/%ux%ux%u&maxcpus=%u",
                                    mname, data->sockets, data->cores,
                                    data->threads, data->maxcpus);
-            qtest_add_data_func(path, data, test_pc_with_cpu_add);
+            qtest_add_data_func_full(path, data, test_pc_with_cpu_add,
+                                     test_data_free);
+            g_free(path);
         }
     }
+    QDECREF(response);
     qtest_end();
 }
 
diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c
index 229e9e901a..41ed1a976f 100644
--- a/tests/postcopy-test.c
+++ b/tests/postcopy-test.c
@@ -176,6 +176,7 @@ static void wait_for_serial(const char *side)
     int started = (strcmp(side, "src_serial") == 0 &&
                    strcmp(arch, "ppc64") == 0) ? 0 : 1;
 
+    g_free(serialpath);
     do {
         int readvalue = fgetc(serialfile);
 
@@ -203,7 +204,6 @@ static void wait_for_serial(const char *side)
         case 'B':
             /* It's alive! */
             fclose(serialfile);
-            g_free(serialpath);
             return;
 
         case EOF:
@@ -260,8 +260,8 @@ static uint64_t get_migration_pass(void)
     } else {
         rsp_ram = qdict_get_qdict(rsp_return, "ram");
         result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
-        QDECREF(rsp);
     }
+    QDECREF(rsp);
     return result;
 }
 
@@ -350,6 +350,7 @@ static void cleanup(const char *filename)
     char *path = g_strdup_printf("%s/%s", tmpfs, filename);
 
     unlink(path);
+    g_free(path);
 }
 
 static void test_migrate(void)
@@ -394,6 +395,8 @@ static void test_migrate(void)
         g_assert_not_reached();
     }
 
+    g_free(bootpath);
+
     from = qtest_start(cmd_src);
     g_free(cmd_src);
 
diff --git a/tests/ptimer-test-stubs.c b/tests/ptimer-test-stubs.c
new file mode 100644
index 0000000000..92a22fbb09
--- /dev/null
+++ b/tests/ptimer-test-stubs.c
@@ -0,0 +1,107 @@
+/*
+ * Stubs for the ptimer-test
+ *
+ * Author: Dmitry Osipenko <digetx@gmail.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 "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "sysemu/replay.h"
+
+#include "ptimer-test.h"
+
+struct QEMUBH {
+    QEMUBHFunc *cb;
+    void *opaque;
+};
+
+QEMUTimerListGroup main_loop_tlg;
+
+int64_t ptimer_test_time_ns;
+
+void timer_init_tl(QEMUTimer *ts,
+                   QEMUTimerList *timer_list, int scale,
+                   QEMUTimerCB *cb, void *opaque)
+{
+    ts->timer_list = timer_list;
+    ts->cb = cb;
+    ts->opaque = opaque;
+    ts->scale = scale;
+    ts->expire_time = -1;
+}
+
+void timer_mod(QEMUTimer *ts, int64_t expire_time)
+{
+    QEMUTimerList *timer_list = ts->timer_list;
+    QEMUTimer *t = &timer_list->active_timers;
+
+    while (t->next != NULL) {
+        if (t->next == ts) {
+            break;
+        }
+
+        t = t->next;
+    }
+
+    ts->expire_time = MAX(expire_time * ts->scale, 0);
+    ts->next = NULL;
+    t->next = ts;
+}
+
+void timer_del(QEMUTimer *ts)
+{
+    QEMUTimerList *timer_list = ts->timer_list;
+    QEMUTimer *t = &timer_list->active_timers;
+
+    while (t->next != NULL) {
+        if (t->next == ts) {
+            t->next = ts->next;
+            return;
+        }
+
+        t = t->next;
+    }
+}
+
+int64_t qemu_clock_get_ns(QEMUClockType type)
+{
+    return ptimer_test_time_ns;
+}
+
+int64_t qemu_clock_deadline_ns_all(QEMUClockType type)
+{
+    QEMUTimerList *timer_list = main_loop_tlg.tl[type];
+    QEMUTimer *t = timer_list->active_timers.next;
+    int64_t deadline = -1;
+
+    while (t != NULL) {
+        if (deadline == -1) {
+            deadline = t->expire_time;
+        } else {
+            deadline = MIN(deadline, t->expire_time);
+        }
+
+        t = t->next;
+    }
+
+    return deadline;
+}
+
+QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
+{
+    QEMUBH *bh = g_new(QEMUBH, 1);
+
+    bh->cb = cb;
+    bh->opaque = opaque;
+
+    return bh;
+}
+
+void replay_bh_schedule_event(QEMUBH *bh)
+{
+    bh->cb(bh->opaque);
+}
diff --git a/tests/ptimer-test.c b/tests/ptimer-test.c
new file mode 100644
index 0000000000..f207eeb0eb
--- /dev/null
+++ b/tests/ptimer-test.c
@@ -0,0 +1,568 @@
+/*
+ * QTest testcase for the ptimer
+ *
+ * Author: Dmitry Osipenko <digetx@gmail.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/gprintf.h>
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "hw/ptimer.h"
+
+#include "libqtest.h"
+#include "ptimer-test.h"
+
+static bool triggered;
+
+static void ptimer_trigger(void *opaque)
+{
+    triggered = true;
+}
+
+static void ptimer_test_expire_qemu_timers(int64_t expire_time,
+                                           QEMUClockType type)
+{
+    QEMUTimerList *timer_list = main_loop_tlg.tl[type];
+    QEMUTimer *t = timer_list->active_timers.next;
+
+    while (t != NULL) {
+        if (t->expire_time == expire_time) {
+            timer_del(t);
+
+            if (t->cb != NULL) {
+                t->cb(t->opaque);
+            }
+        }
+
+        t = t->next;
+    }
+}
+
+static void ptimer_test_set_qemu_time_ns(int64_t ns)
+{
+    ptimer_test_time_ns = ns;
+}
+
+static void qemu_clock_step(uint64_t ns)
+{
+    int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+    int64_t advanced_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns;
+
+    while (deadline != -1 && deadline <= advanced_time) {
+        ptimer_test_set_qemu_time_ns(deadline);
+        ptimer_test_expire_qemu_timers(deadline, QEMU_CLOCK_VIRTUAL);
+        deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+    }
+
+    ptimer_test_set_qemu_time_ns(advanced_time);
+}
+
+static void check_set_count(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_count(ptimer, 1000);
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 1000);
+    g_assert_false(triggered);
+}
+
+static void check_set_limit(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_limit(ptimer, 1000, 0);
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 1000);
+    g_assert_false(triggered);
+
+    ptimer_set_limit(ptimer, 2000, 1);
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 2000);
+    g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 2000);
+    g_assert_false(triggered);
+}
+
+static void check_oneshot(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_period(ptimer, 2000000);
+    ptimer_set_count(ptimer, 10);
+    ptimer_run(ptimer, 1);
+
+    qemu_clock_step(2000000 * 2 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+    g_assert_false(triggered);
+
+    ptimer_stop(ptimer);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000 * 11);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+    g_assert_false(triggered);
+
+    ptimer_run(ptimer, 1);
+
+    qemu_clock_step(2000000 * 7 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    qemu_clock_step(4000000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    ptimer_set_count(ptimer, 10);
+
+    qemu_clock_step(20000000 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
+    g_assert_false(triggered);
+
+    ptimer_set_limit(ptimer, 9, 1);
+
+    qemu_clock_step(20000000 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+    g_assert_false(triggered);
+
+    ptimer_run(ptimer, 1);
+
+    qemu_clock_step(2000000 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+    g_assert_false(triggered);
+
+    ptimer_set_count(ptimer, 20);
+
+    qemu_clock_step(2000000 * 19 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_true(triggered);
+
+    ptimer_stop(ptimer);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 * 12 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+}
+
+static void check_periodic(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_period(ptimer, 2000000);
+    ptimer_set_limit(ptimer, 10, 1);
+    ptimer_run(ptimer, 0);
+
+    qemu_clock_step(2000000 * 10 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+    g_assert_false(triggered);
+
+    ptimer_set_count(ptimer, 20);
+
+    qemu_clock_step(2000000 * 11 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000 * 10);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+    g_assert_true(triggered);
+
+    ptimer_stop(ptimer);
+    triggered = false;
+
+    qemu_clock_step(2000000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+    g_assert_false(triggered);
+
+    ptimer_set_count(ptimer, 3);
+    ptimer_run(ptimer, 0);
+
+    qemu_clock_step(2000000 * 3 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+    g_assert_false(triggered);
+
+    ptimer_set_count(ptimer, 0);
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 * 12 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+    g_assert_true(triggered);
+
+    ptimer_stop(ptimer);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 * 12 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+    g_assert_false(triggered);
+
+    ptimer_run(ptimer, 0);
+    ptimer_set_period(ptimer, 0);
+
+    qemu_clock_step(2000000 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+    g_assert_false(triggered);
+}
+
+static void check_on_the_fly_mode_change(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_period(ptimer, 2000000);
+    ptimer_set_limit(ptimer, 10, 1);
+    ptimer_run(ptimer, 1);
+
+    qemu_clock_step(2000000 * 9 + 100000);
+
+    ptimer_run(ptimer, 0);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 * 9);
+
+    ptimer_run(ptimer, 1);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000 * 3);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_true(triggered);
+}
+
+static void check_on_the_fly_period_change(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_period(ptimer, 2000000);
+    ptimer_set_limit(ptimer, 8, 1);
+    ptimer_run(ptimer, 1);
+
+    qemu_clock_step(2000000 * 4 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+    g_assert_false(triggered);
+
+    ptimer_set_period(ptimer, 4000000);
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+
+    qemu_clock_step(4000000 * 2 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    qemu_clock_step(4000000 * 2);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_true(triggered);
+}
+
+static void check_on_the_fly_freq_change(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_freq(ptimer, 500);
+    ptimer_set_limit(ptimer, 8, 1);
+    ptimer_run(ptimer, 1);
+
+    qemu_clock_step(2000000 * 4 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+    g_assert_false(triggered);
+
+    ptimer_set_freq(ptimer, 250);
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+
+    qemu_clock_step(2000000 * 4 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000 * 4);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_true(triggered);
+}
+
+static void check_run_with_period_0(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_count(ptimer, 99);
+    ptimer_run(ptimer, 1);
+
+    qemu_clock_step(10 * NANOSECONDS_PER_SECOND);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
+    g_assert_false(triggered);
+}
+
+static void check_run_with_delta_0(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_period(ptimer, 2000000);
+    ptimer_set_limit(ptimer, 99, 0);
+    ptimer_run(ptimer, 1);
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000 * 97);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000 * 2);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    ptimer_set_count(ptimer, 0);
+    ptimer_run(ptimer, 0);
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
+    g_assert_false(triggered);
+
+    qemu_clock_step(2000000 * 98);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 98);
+    g_assert_true(triggered);
+
+    ptimer_stop(ptimer);
+}
+
+static void check_periodic_with_load_0(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_period(ptimer, 2000000);
+    ptimer_run(ptimer, 0);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    ptimer_stop(ptimer);
+}
+
+static void check_oneshot_with_load_0(gconstpointer arg)
+{
+    const uint8_t *policy = arg;
+    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
+    ptimer_state *ptimer = ptimer_init(bh, *policy);
+
+    triggered = false;
+
+    ptimer_set_period(ptimer, 2000000);
+    ptimer_run(ptimer, 1);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_true(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 + 100000);
+
+    g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+    g_assert_false(triggered);
+
+    triggered = false;
+
+    qemu_clock_step(2000000 + 100000);
+
+    g_assert_false(triggered);
+}
+
+static void add_ptimer_tests(uint8_t policy)
+{
+    uint8_t *ppolicy = g_malloc(1);
+    char *policy_name = g_malloc(64);
+
+    *ppolicy = policy;
+
+    if (policy == PTIMER_POLICY_DEFAULT) {
+        g_sprintf(policy_name, "default");
+    }
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/set_count policy=%s", policy_name),
+        ppolicy, check_set_count);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/set_limit policy=%s", policy_name),
+        ppolicy, check_set_limit);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/oneshot policy=%s", policy_name),
+        ppolicy, check_oneshot);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/periodic policy=%s", policy_name),
+        ppolicy, check_periodic);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/on_the_fly_mode_change policy=%s", policy_name),
+        ppolicy, check_on_the_fly_mode_change);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/on_the_fly_period_change policy=%s", policy_name),
+        ppolicy, check_on_the_fly_period_change);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/on_the_fly_freq_change policy=%s", policy_name),
+        ppolicy, check_on_the_fly_freq_change);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/run_with_period_0 policy=%s", policy_name),
+        ppolicy, check_run_with_period_0);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/run_with_delta_0 policy=%s", policy_name),
+        ppolicy, check_run_with_delta_0);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/periodic_with_load_0 policy=%s", policy_name),
+        ppolicy, check_periodic_with_load_0);
+
+    qtest_add_data_func(
+        g_strdup_printf("/ptimer/oneshot_with_load_0 policy=%s", policy_name),
+        ppolicy, check_oneshot_with_load_0);
+}
+
+int main(int argc, char **argv)
+{
+    int i;
+
+    g_test_init(&argc, &argv, NULL);
+
+    for (i = 0; i < QEMU_CLOCK_MAX; i++) {
+        main_loop_tlg.tl[i] = g_new0(QEMUTimerList, 1);
+    }
+
+    add_ptimer_tests(PTIMER_POLICY_DEFAULT);
+
+    qtest_allowed = true;
+
+    return g_test_run();
+}
diff --git a/tests/ptimer-test.h b/tests/ptimer-test.h
new file mode 100644
index 0000000000..98d9b8f347
--- /dev/null
+++ b/tests/ptimer-test.h
@@ -0,0 +1,22 @@
+/*
+ * QTest testcase for the ptimer
+ *
+ * Author: Dmitry Osipenko <digetx@gmail.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.
+ *
+ */
+
+#ifndef PTIMER_TEST_H
+#define PTIMER_TEST_H
+
+extern bool qtest_allowed;
+
+extern int64_t ptimer_test_time_ns;
+
+struct QEMUTimerList {
+    QEMUTimer active_timers;
+};
+
+#endif
diff --git a/tests/pxe-test.c b/tests/pxe-test.c
index b2cc355a95..5d3ddbe5e9 100644
--- a/tests/pxe-test.c
+++ b/tests/pxe-test.c
@@ -21,14 +21,14 @@
 
 static const char *disk = "tests/pxe-test-disk.raw";
 
-static void test_pxe_one(const char *params)
+static void test_pxe_one(const char *params, bool ipv6)
 {
     char *args;
 
-    args = g_strdup_printf("-machine accel=tcg "
-                           "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s "
-                           "%s ",
-                           disk, params);
+    args = g_strdup_printf("-machine accel=tcg -nodefaults -boot order=n "
+                           "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s,"
+                           "ipv4=%s,ipv6=%s %s", disk, ipv6 ? "off" : "on",
+                           ipv6 ? "on" : "off", params);
 
     qtest_start(args);
     boot_sector_test();
@@ -38,12 +38,17 @@ static void test_pxe_one(const char *params)
 
 static void test_pxe_e1000(void)
 {
-    test_pxe_one("-device e1000,netdev=" NETNAME);
+    test_pxe_one("-device e1000,netdev=" NETNAME, false);
 }
 
 static void test_pxe_virtio_pci(void)
 {
-    test_pxe_one("-device virtio-net-pci,netdev=" NETNAME);
+    test_pxe_one("-device virtio-net-pci,netdev=" NETNAME, false);
+}
+
+static void test_pxe_spapr_vlan(void)
+{
+    test_pxe_one("-device spapr-vlan,netdev=" NETNAME, true);
 }
 
 int main(int argc, char *argv[])
@@ -60,6 +65,9 @@ int main(int argc, char *argv[])
     if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
         qtest_add_func("pxe/e1000", test_pxe_e1000);
         qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
+    } else if (strcmp(arch, "ppc64") == 0) {
+        qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
+        qtest_add_func("pxe/spapr-vlan", test_pxe_spapr_vlan);
     }
     ret = g_test_run();
     boot_sector_cleanup(disk);
diff --git a/tests/q35-test.c b/tests/q35-test.c
index 71538fc17c..763fe3d6ae 100644
--- a/tests/q35-test.c
+++ b/tests/q35-test.c
@@ -42,7 +42,7 @@ static void test_smram_lock(void)
     QPCIDevice *pcidev;
     QDict *response;
 
-    pcibus = qpci_init_pc();
+    pcibus = qpci_init_pc(NULL);
     g_assert(pcibus != NULL);
 
     pcidev = qpci_device_find(pcibus, 0);
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 3ac2443e5b..107049b50f 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -126,7 +126,7 @@ class TestSingleDrive(iotests.QMPTestCase):
 
     def test_device_not_found(self):
         result = self.vm.qmp('block-stream', device='nonexistent')
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
 
 class TestSmallerBackingFile(iotests.QMPTestCase):
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index cbf5e0ba5c..d1e1ad8bd2 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -38,7 +38,6 @@ class TestSingleDrive(iotests.QMPTestCase):
     image_len = 1 * 1024 * 1024 # MB
     qmp_cmd = 'drive-mirror'
     qmp_target = target_img
-    not_found_error = 'DeviceNotFound'
 
     def setUp(self):
         iotests.create_image(backing_img, self.image_len)
@@ -176,7 +175,7 @@ class TestSingleDrive(iotests.QMPTestCase):
 
         result = self.vm.qmp(self.qmp_cmd, device='ide1-cd0', sync='full',
                              target=self.qmp_target)
-        self.assert_qmp(result, 'error/class', self.not_found_error)
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_image_not_found(self):
         result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
@@ -186,12 +185,11 @@ class TestSingleDrive(iotests.QMPTestCase):
     def test_device_not_found(self):
         result = self.vm.qmp(self.qmp_cmd, device='nonexistent', sync='full',
                              target=self.qmp_target)
-        self.assert_qmp(result, 'error/class', self.not_found_error)
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
 class TestSingleBlockdev(TestSingleDrive):
     qmp_cmd = 'blockdev-mirror'
     qmp_target = 'node1'
-    not_found_error = 'GenericError'
 
     def setUp(self):
         TestSingleDrive.setUp(self)
@@ -784,7 +782,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
         self.vm.launch()
 
         #assemble the quorum block device from the individual files
-        args = { "options" : { "driver": "quorum", "id": "quorum0",
+        args = { "options" : { "driver": "quorum", "node-name": "quorum0",
                  "vote-threshold": 2, "children": [ "img0", "img1", "img2" ] } }
         if self.has_quorum():
             result = self.vm.qmp("blockdev-add", **args)
@@ -806,13 +804,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
 
         self.assert_no_active_block_jobs()
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             node_name="repair0",
-                             replaces="img1",
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', node_name="repair0", replaces="img1",
                              target=quorum_repair_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'return', {})
 
-        self.complete_and_wait(drive="quorum0")
+        self.complete_and_wait(drive="job0")
         self.assert_has_block_node("repair0", quorum_repair_img)
         # TODO: a better test requiring some QEMU infrastructure will be added
         #       to check that this file is really driven by quorum
@@ -826,13 +823,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
 
         self.assert_no_active_block_jobs()
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             node_name="repair0",
-                             replaces="img1",
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', node_name="repair0", replaces="img1",
                              target=quorum_repair_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'return', {})
 
-        self.cancel_and_wait(drive="quorum0", force=True)
+        self.cancel_and_wait(drive="job0", force=True)
         # here we check that the last registered quorum file has not been
         # swapped out and unref
         self.assert_has_block_node(None, quorum_img3)
@@ -844,13 +840,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
 
         self.assert_no_active_block_jobs()
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             node_name="repair0",
-                             replaces="img1",
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', node_name="repair0", replaces="img1",
                              target=quorum_repair_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'return', {})
 
-        self.wait_ready_and_cancel(drive="quorum0")
+        self.wait_ready_and_cancel(drive="job0")
         # here we check that the last registered quorum file has not been
         # swapped out and unref
         self.assert_has_block_node(None, quorum_img3)
@@ -864,13 +859,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
 
         self.assert_no_active_block_jobs()
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             node_name="repair0",
-                             replaces="img1",
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', node_name="repair0", replaces="img1",
                              target=quorum_repair_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'return', {})
 
-        result = self.vm.qmp('block-job-pause', device='quorum0')
+        result = self.vm.qmp('block-job-pause', device='job0')
         self.assert_qmp(result, 'return', {})
 
         time.sleep(1)
@@ -881,10 +875,10 @@ class TestRepairQuorum(iotests.QMPTestCase):
         result = self.vm.qmp('query-block-jobs')
         self.assert_qmp(result, 'return[0]/offset', offset)
 
-        result = self.vm.qmp('block-job-resume', device='quorum0')
+        result = self.vm.qmp('block-job-resume', device='job0')
         self.assert_qmp(result, 'return', {})
 
-        self.complete_and_wait(drive="quorum0")
+        self.complete_and_wait(drive="job0")
         self.vm.shutdown()
         self.assertTrue(iotests.compare_images(quorum_img2, quorum_repair_img),
                         'target image does not match source after mirroring')
@@ -896,7 +890,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
         if iotests.qemu_default_machine != 'pc':
             return
 
-        result = self.vm.qmp('drive-mirror', device='drive0', # CD-ROM
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='drive0', # CD-ROM
                              sync='full',
                              node_name='repair0',
                              replaces='img1',
@@ -907,28 +901,28 @@ class TestRepairQuorum(iotests.QMPTestCase):
         if not self.has_quorum():
             return
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             node_name='repair0',
-                             replaces='img1',
-                             mode='existing',
-                             target=quorum_repair_img, format=iotests.imgfmt)
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', node_name='repair0', replaces='img1',
+                             mode='existing', target=quorum_repair_img,
+                             format=iotests.imgfmt)
         self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_device_not_found(self):
         if not self.has_quorum():
             return
 
-        result = self.vm.qmp('drive-mirror', device='nonexistent', sync='full',
+        result = self.vm.qmp('drive-mirror', job_id='job0',
+                             device='nonexistent', sync='full',
                              node_name='repair0',
                              replaces='img1',
                              target=quorum_repair_img, format=iotests.imgfmt)
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_wrong_sync_mode(self):
         if not self.has_quorum():
             return
 
-        result = self.vm.qmp('drive-mirror', device='quorum0',
+        result = self.vm.qmp('drive-mirror', device='quorum0', job_id='job0',
                              node_name='repair0',
                              replaces='img1',
                              target=quorum_repair_img, format=iotests.imgfmt)
@@ -938,8 +932,8 @@ class TestRepairQuorum(iotests.QMPTestCase):
         if not self.has_quorum():
             return
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             replaces='img1',
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', replaces='img1',
                              target=quorum_repair_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'error/class', 'GenericError')
 
@@ -947,9 +941,8 @@ class TestRepairQuorum(iotests.QMPTestCase):
         if not self.has_quorum():
             return
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             node_name='repair0',
-                             replaces='img77',
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', node_name='repair0', replaces='img77',
                              target=quorum_repair_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'error/class', 'GenericError')
 
@@ -961,19 +954,17 @@ class TestRepairQuorum(iotests.QMPTestCase):
                              snapshot_file=quorum_snapshot_file,
                              snapshot_node_name="snap1");
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             node_name='repair0',
-                             replaces="img1",
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', node_name='repair0', replaces="img1",
                              target=quorum_repair_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'error/class', 'GenericError')
 
-        result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
-                             node_name='repair0',
-                             replaces="snap1",
+        result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
+                             sync='full', node_name='repair0', replaces="snap1",
                              target=quorum_repair_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'return', {})
 
-        self.complete_and_wait(drive="quorum0")
+        self.complete_and_wait('job0')
         self.assert_has_block_node("repair0", quorum_repair_img)
         # TODO: a better test requiring some QEMU infrastructure will be added
         #       to check that this file is really driven by quorum
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
index c8e3578702..1d3fd04b65 100755
--- a/tests/qemu-iotests/055
+++ b/tests/qemu-iotests/055
@@ -29,17 +29,24 @@ test_img = os.path.join(iotests.test_dir, 'test.img')
 target_img = os.path.join(iotests.test_dir, 'target.img')
 blockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img')
 
-class TestSingleDrive(iotests.QMPTestCase):
-    image_len = 64 * 1024 * 1024 # MB
+image_len = 64 * 1024 * 1024 # MB
+
+def setUpModule():
+    qemu_img('create', '-f', iotests.imgfmt, test_img, str(image_len))
+    qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x11 0 64k', test_img)
+    qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x00 64k 128k', test_img)
+    qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img)
+    qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img)
+    qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img)
+    qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img)
+
+def tearDownModule():
+    os.remove(test_img)
+
 
+class TestSingleDrive(iotests.QMPTestCase):
     def setUp(self):
-        # Write data to the image so we can compare later
-        qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleDrive.image_len))
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img)
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img)
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img)
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img)
-        qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
+        qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
 
         self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
         if iotests.qemu_default_machine == 'pc':
@@ -48,7 +55,6 @@ class TestSingleDrive(iotests.QMPTestCase):
 
     def tearDown(self):
         self.vm.shutdown()
-        os.remove(test_img)
         os.remove(blockdev_target_img)
         try:
             os.remove(target_img)
@@ -134,10 +140,7 @@ class TestSingleDrive(iotests.QMPTestCase):
 
     def do_test_device_not_found(self, cmd, **args):
         result = self.vm.qmp(cmd, **args)
-        if cmd == 'drive-backup':
-            self.assert_qmp(result, 'error/class', 'DeviceNotFound')
-        else:
-            self.assert_qmp(result, 'error/class', 'GenericError')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_device_not_found(self):
         self.do_test_device_not_found('drive-backup', device='nonexistent',
@@ -158,19 +161,14 @@ class TestSingleDrive(iotests.QMPTestCase):
         self.assert_qmp(result, 'error/class', 'GenericError')
 
 class TestSetSpeed(iotests.QMPTestCase):
-    image_len = 80 * 1024 * 1024 # MB
-
     def setUp(self):
-        qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSetSpeed.image_len))
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P1 0 512', test_img)
-        qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
+        qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
 
         self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
         self.vm.launch()
 
     def tearDown(self):
         self.vm.shutdown()
-        os.remove(test_img)
         os.remove(blockdev_target_img)
         try:
             os.remove(target_img)
@@ -246,15 +244,8 @@ class TestSetSpeed(iotests.QMPTestCase):
         self.do_test_set_speed_invalid('blockdev-backup',  'drive1')
 
 class TestSingleTransaction(iotests.QMPTestCase):
-    image_len = 64 * 1024 * 1024 # MB
-
     def setUp(self):
-        qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleTransaction.image_len))
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img)
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img)
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img)
-        qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img)
-        qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
+        qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
 
         self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
         if iotests.qemu_default_machine == 'pc':
@@ -263,7 +254,6 @@ class TestSingleTransaction(iotests.QMPTestCase):
 
     def tearDown(self):
         self.vm.shutdown()
-        os.remove(test_img)
         os.remove(blockdev_target_img)
         try:
             os.remove(target_img)
@@ -371,7 +361,7 @@ class TestSingleTransaction(iotests.QMPTestCase):
                           'sync': 'full' },
             }
         ])
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
         result = self.vm.qmp('transaction', actions=[{
                 'type': 'blockdev-backup',
@@ -451,5 +441,114 @@ class TestSingleTransaction(iotests.QMPTestCase):
         self.assert_qmp(result, 'error/class', 'GenericError')
         self.assert_no_active_block_jobs()
 
+
+class TestDriveCompression(iotests.QMPTestCase):
+    image_len = 64 * 1024 * 1024 # MB
+    fmt_supports_compression = [{'type': 'qcow2', 'args': ()},
+                                {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}]
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(blockdev_target_img)
+        try:
+            os.remove(target_img)
+        except OSError:
+            pass
+
+    def do_prepare_drives(self, fmt, args):
+        self.vm = iotests.VM().add_drive(test_img)
+
+        qemu_img('create', '-f', fmt, blockdev_target_img,
+                 str(TestDriveCompression.image_len), *args)
+        self.vm.add_drive(blockdev_target_img, format=fmt)
+
+        self.vm.launch()
+
+    def do_test_compress_complete(self, cmd, format, **args):
+        self.do_prepare_drives(format['type'], format['args'])
+
+        self.assert_no_active_block_jobs()
+
+        result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+        self.assert_qmp(result, 'return', {})
+
+        self.wait_until_completed()
+
+        self.vm.shutdown()
+        self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
+                                               iotests.imgfmt, format['type']),
+                        'target image does not match source after backup')
+
+    def test_complete_compress_drive_backup(self):
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_complete('drive-backup', format,
+                                           target=blockdev_target_img, mode='existing')
+
+    def test_complete_compress_blockdev_backup(self):
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_complete('blockdev-backup', format, target='drive1')
+
+    def do_test_compress_cancel(self, cmd, format, **args):
+        self.do_prepare_drives(format['type'], format['args'])
+
+        self.assert_no_active_block_jobs()
+
+        result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+        self.assert_qmp(result, 'return', {})
+
+        event = self.cancel_and_wait()
+        self.assert_qmp(event, 'data/type', 'backup')
+
+        self.vm.shutdown()
+
+    def test_compress_cancel_drive_backup(self):
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_cancel('drive-backup', format,
+                                         target=blockdev_target_img, mode='existing')
+
+    def test_compress_cancel_blockdev_backup(self):
+       for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_cancel('blockdev-backup', format, target='drive1')
+
+    def do_test_compress_pause(self, cmd, format, **args):
+        self.do_prepare_drives(format['type'], format['args'])
+
+        self.assert_no_active_block_jobs()
+
+        self.vm.pause_drive('drive0')
+        result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
+        self.assert_qmp(result, 'return', {})
+
+        result = self.vm.qmp('block-job-pause', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        self.vm.resume_drive('drive0')
+        time.sleep(1)
+        result = self.vm.qmp('query-block-jobs')
+        offset = self.dictpath(result, 'return[0]/offset')
+
+        time.sleep(1)
+        result = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(result, 'return[0]/offset', offset)
+
+        result = self.vm.qmp('block-job-resume', device='drive0')
+        self.assert_qmp(result, 'return', {})
+
+        self.wait_until_completed()
+
+        self.vm.shutdown()
+        self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
+                                               iotests.imgfmt, format['type']),
+                        'target image does not match source after backup')
+
+    def test_compress_pause_drive_backup(self):
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_pause('drive-backup', format,
+                                        target=blockdev_target_img, mode='existing')
+
+    def test_compress_pause_blockdev_backup(self):
+        for format in TestDriveCompression.fmt_supports_compression:
+            self.do_test_compress_pause('blockdev-backup', format, target='drive1')
+
 if __name__ == '__main__':
     iotests.main(supported_fmts=['raw', 'qcow2'])
diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out
index 42314e9c00..5ce2f9a2ed 100644
--- a/tests/qemu-iotests/055.out
+++ b/tests/qemu-iotests/055.out
@@ -1,5 +1,5 @@
-........................
+..............................
 ----------------------------------------------------------------------
-Ran 24 tests
+Ran 30 tests
 
 OK
diff --git a/tests/qemu-iotests/057 b/tests/qemu-iotests/057
index 9cdd582e39..9f0a5a3057 100755
--- a/tests/qemu-iotests/057
+++ b/tests/qemu-iotests/057
@@ -182,7 +182,7 @@ class TestSingleTransaction(ImageSnapshotTestCase):
                               'name': 'a' },
                   }]
         result = self.vm.qmp('transaction', actions = actions)
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_error_exist(self):
         self.createSnapshotInTransaction(1)
@@ -239,7 +239,7 @@ class TestSnapshotDelete(ImageSnapshotTestCase):
         result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
                               device = 'drive_error',
                               id = '0')
-        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+        self.assert_qmp(result, 'error/class', 'GenericError')
 
     def test_error_no_id_and_name(self):
         result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
index c1df48eded..a12125bd46 100755
--- a/tests/qemu-iotests/067
+++ b/tests/qemu-iotests/067
@@ -121,7 +121,7 @@ run_qemu <<EOF
   "arguments": {
       "options": {
         "driver": "$IMGFMT",
-        "id": "disk",
+        "node-name": "disk",
         "file": {
             "driver": "file",
             "filename": "$TEST_IMG"
@@ -129,13 +129,13 @@ run_qemu <<EOF
       }
     }
   }
-{ "execute": "query-block" }
+{ "execute": "query-named-block-nodes" }
 { "execute": "device_add",
    "arguments": { "driver": "virtio-blk", "drive": "disk",
                   "id": "virtio0" } }
 { "execute": "device_del", "arguments": { "id": "virtio0" } }
 { "execute": "system_reset" }
-{ "execute": "query-block" }
+{ "execute": "query-named-block-nodes" }
 { "execute": "quit" }
 EOF
 
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
index 7e25a49029..782eae27a0 100644
--- a/tests/qemu-iotests/067.out
+++ b/tests/qemu-iotests/067.out
@@ -258,49 +258,72 @@ Testing:
 {
     "return": [
         {
-            "device": "disk",
-            "locked": false,
-            "removable": true,
-            "inserted": {
-                "iops_rd": 0,
-                "detect_zeroes": "off",
-                "image": {
-                    "virtual-size": 134217728,
-                    "filename": "TEST_DIR/t.qcow2",
-                    "cluster-size": 65536,
-                    "format": "qcow2",
-                    "actual-size": SIZE,
-                    "format-specific": {
-                        "type": "qcow2",
-                        "data": {
-                            "compat": "1.1",
-                            "lazy-refcounts": false,
-                            "refcount-bits": 16,
-                            "corrupt": false
-                        }
-                    },
-                    "dirty-flag": false
-                },
-                "iops_wr": 0,
-                "ro": false,
-                "node-name": "NODE_NAME",
-                "backing_file_depth": 0,
-                "drv": "qcow2",
-                "iops": 0,
-                "bps_wr": 0,
-                "write_threshold": 0,
-                "encrypted": false,
-                "bps": 0,
-                "bps_rd": 0,
-                "cache": {
-                    "no-flush": false,
-                    "direct": false,
-                    "writeback": true
+            "iops_rd": 0,
+            "detect_zeroes": "off",
+            "image": {
+                "virtual-size": 134217728,
+                "filename": "TEST_DIR/t.qcow2",
+                "cluster-size": 65536,
+                "format": "qcow2",
+                "actual-size": SIZE,
+                "format-specific": {
+                    "type": "qcow2",
+                    "data": {
+                        "compat": "1.1",
+                        "lazy-refcounts": false,
+                        "refcount-bits": 16,
+                        "corrupt": false
+                    }
                 },
-                "file": "TEST_DIR/t.qcow2",
-                "encryption_key_missing": false
+                "dirty-flag": false
             },
-            "type": "unknown"
+            "iops_wr": 0,
+            "ro": false,
+            "node-name": "disk",
+            "backing_file_depth": 0,
+            "drv": "qcow2",
+            "iops": 0,
+            "bps_wr": 0,
+            "write_threshold": 0,
+            "encrypted": false,
+            "bps": 0,
+            "bps_rd": 0,
+            "cache": {
+                "no-flush": false,
+                "direct": false,
+                "writeback": true
+            },
+            "file": "TEST_DIR/t.qcow2",
+            "encryption_key_missing": false
+        },
+        {
+            "iops_rd": 0,
+            "detect_zeroes": "off",
+            "image": {
+                "virtual-size": 197120,
+                "filename": "TEST_DIR/t.qcow2",
+                "format": "file",
+                "actual-size": SIZE,
+                "dirty-flag": false
+            },
+            "iops_wr": 0,
+            "ro": false,
+            "node-name": "NODE_NAME",
+            "backing_file_depth": 0,
+            "drv": "file",
+            "iops": 0,
+            "bps_wr": 0,
+            "write_threshold": 0,
+            "encrypted": false,
+            "bps": 0,
+            "bps_rd": 0,
+            "cache": {
+                "no-flush": false,
+                "direct": false,
+                "writeback": true
+            },
+            "file": "TEST_DIR/t.qcow2",
+            "encryption_key_missing": false
         }
     ]
 }
@@ -319,50 +342,72 @@ Testing:
 {
     "return": [
         {
-            "io-status": "ok",
-            "device": "disk",
-            "locked": false,
-            "removable": true,
-            "inserted": {
-                "iops_rd": 0,
-                "detect_zeroes": "off",
-                "image": {
-                    "virtual-size": 134217728,
-                    "filename": "TEST_DIR/t.qcow2",
-                    "cluster-size": 65536,
-                    "format": "qcow2",
-                    "actual-size": SIZE,
-                    "format-specific": {
-                        "type": "qcow2",
-                        "data": {
-                            "compat": "1.1",
-                            "lazy-refcounts": false,
-                            "refcount-bits": 16,
-                            "corrupt": false
-                        }
-                    },
-                    "dirty-flag": false
+            "iops_rd": 0,
+            "detect_zeroes": "off",
+            "image": {
+                "virtual-size": 134217728,
+                "filename": "TEST_DIR/t.qcow2",
+                "cluster-size": 65536,
+                "format": "qcow2",
+                "actual-size": SIZE,
+                "format-specific": {
+                    "type": "qcow2",
+                    "data": {
+                        "compat": "1.1",
+                        "lazy-refcounts": false,
+                        "refcount-bits": 16,
+                        "corrupt": false
+                    }
                 },
-                "iops_wr": 0,
-                "ro": false,
-                "node-name": "NODE_NAME",
-                "backing_file_depth": 0,
-                "drv": "qcow2",
-                "iops": 0,
-                "bps_wr": 0,
-                "write_threshold": 0,
-                "encrypted": false,
-                "bps": 0,
-                "bps_rd": 0,
-                "cache": {
-                    "no-flush": false,
-                    "direct": false,
-                    "writeback": true
-                },
-                "file": "TEST_DIR/t.qcow2",
-                "encryption_key_missing": false
+                "dirty-flag": false
             },
-            "type": "unknown"
+            "iops_wr": 0,
+            "ro": false,
+            "node-name": "disk",
+            "backing_file_depth": 0,
+            "drv": "qcow2",
+            "iops": 0,
+            "bps_wr": 0,
+            "write_threshold": 0,
+            "encrypted": false,
+            "bps": 0,
+            "bps_rd": 0,
+            "cache": {
+                "no-flush": false,
+                "direct": false,
+                "writeback": true
+            },
+            "file": "TEST_DIR/t.qcow2",
+            "encryption_key_missing": false
+        },
+        {
+            "iops_rd": 0,
+            "detect_zeroes": "off",
+            "image": {
+                "virtual-size": 197120,
+                "filename": "TEST_DIR/t.qcow2",
+                "format": "file",
+                "actual-size": SIZE,
+                "dirty-flag": false
+            },
+            "iops_wr": 0,
+            "ro": false,
+            "node-name": "NODE_NAME",
+            "backing_file_depth": 0,
+            "drv": "file",
+            "iops": 0,
+            "bps_wr": 0,
+            "write_threshold": 0,
+            "encrypted": false,
+            "bps": 0,
+            "bps_rd": 0,
+            "cache": {
+                "no-flush": false,
+                "direct": false,
+                "writeback": true
+            },
+            "file": "TEST_DIR/t.qcow2",
+            "encryption_key_missing": false
         }
     ]
 }
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
index bdfd91fef1..6d0864cff6 100755
--- a/tests/qemu-iotests/071
+++ b/tests/qemu-iotests/071
@@ -118,7 +118,7 @@ run_qemu <<EOF
     "arguments": {
         "options": {
             "driver": "$IMGFMT",
-            "id": "drive0-debug",
+            "node-name": "drive0-debug",
             "file": {
                 "driver": "blkdebug",
                 "image": "drive0",
@@ -159,7 +159,7 @@ run_qemu <<EOF
     "arguments": {
         "options": {
             "driver": "blkverify",
-            "id": "drive0-verify",
+            "node-name": "drive0-verify",
             "test": "drive0",
             "raw": {
                 "driver": "file",
@@ -195,7 +195,7 @@ run_qemu <<EOF
     "arguments": {
         "options": {
             "driver": "blkverify",
-            "id": "drive0-verify",
+            "node-name": "drive0-verify",
             "test": {
                 "driver": "$IMGFMT",
                 "file": {
@@ -234,7 +234,7 @@ run_qemu <<EOF
     "arguments": {
         "options": {
             "driver": "$IMGFMT",
-            "id": "drive0-debug",
+            "node-name": "drive0-debug",
             "file": {
                 "driver": "blkdebug",
                 "image": "drive0",
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
index d89fabcdbd..0a809f3499 100755
--- a/tests/qemu-iotests/081
+++ b/tests/qemu-iotests/081
@@ -119,7 +119,7 @@ run_qemu <<EOF
     "arguments": {
         "options": {
             "driver": "quorum",
-            "id": "drive0-quorum",
+            "node-name": "drive0-quorum",
             "vote-threshold": 2,
             "children": [
                 {
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
index 01c78d6894..08e4bb7218 100644
--- a/tests/qemu-iotests/085.out
+++ b/tests/qemu-iotests/085.out
@@ -68,9 +68,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/
 
 === Invalid command - snapshot node used as active layer ===
 
-{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio0"}}
-{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio0"}}
-{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio1"}}
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use"}}
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use"}}
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use"}}
 
 === Invalid command - snapshot node used as backing hd ===
 
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
index e7bca37efc..b1ac71f2b8 100755
--- a/tests/qemu-iotests/087
+++ b/tests/qemu-iotests/087
@@ -77,50 +77,12 @@ echo
 echo === Duplicate ID ===
 echo
 
-run_qemu <<EOF
+run_qemu -drive driver=$IMGFMT,id=disk,node-name=test-node,file="$TEST_IMG" <<EOF
 { "execute": "qmp_capabilities" }
 { "execute": "blockdev-add",
   "arguments": {
       "options": {
         "driver": "$IMGFMT",
-        "id": "disk",
-        "node-name": "test-node",
-        "file": {
-            "driver": "file",
-            "filename": "$TEST_IMG"
-        }
-      }
-    }
-  }
-{ "execute": "blockdev-add",
-  "arguments": {
-      "options": {
-        "driver": "$IMGFMT",
-        "id": "disk",
-        "file": {
-            "driver": "file",
-            "filename": "$TEST_IMG"
-        }
-      }
-    }
-  }
-{ "execute": "blockdev-add",
-  "arguments": {
-      "options": {
-        "driver": "$IMGFMT",
-        "id": "test-node",
-        "file": {
-            "driver": "file",
-            "filename": "$TEST_IMG"
-        }
-      }
-    }
-  }
-{ "execute": "blockdev-add",
-  "arguments": {
-      "options": {
-        "driver": "$IMGFMT",
-        "id": "disk2",
         "node-name": "disk",
         "file": {
             "driver": "file",
@@ -133,7 +95,6 @@ run_qemu <<EOF
   "arguments": {
       "options": {
         "driver": "$IMGFMT",
-        "id": "disk2",
         "node-name": "test-node",
         "file": {
             "driver": "file",
@@ -142,19 +103,6 @@ run_qemu <<EOF
       }
     }
   }
-{ "execute": "blockdev-add",
-  "arguments": {
-      "options": {
-        "driver": "$IMGFMT",
-        "id": "disk3",
-        "node-name": "disk3",
-        "file": {
-            "driver": "file",
-            "filename": "$TEST_IMG"
-        }
-      }
-    }
-  }
 { "execute": "quit" }
 EOF
 
@@ -168,11 +116,11 @@ run_qemu <<EOF
   "arguments": {
       "options": {
         "driver": "$IMGFMT",
-        "id": "disk",
-        "aio": "native",
+        "node-name": "disk",
         "file": {
             "driver": "file",
-            "filename": "$TEST_IMG"
+            "filename": "$TEST_IMG",
+            "aio": "native"
         }
       }
     }
@@ -191,7 +139,7 @@ run_qemu -S <<EOF
   "arguments": {
       "options": {
         "driver": "$IMGFMT",
-        "id": "disk",
+        "node-name": "disk",
         "file": {
             "driver": "file",
             "filename": "$TEST_IMG"
@@ -208,7 +156,7 @@ run_qemu <<EOF
   "arguments": {
       "options": {
         "driver": "$IMGFMT",
-        "id": "disk",
+        "node-name": "disk",
         "file": {
             "driver": "file",
             "filename": "$TEST_IMG"
@@ -229,7 +177,7 @@ run_qemu -S <<EOF
 { "execute": "blockdev-add",
   "arguments": {
       "options": {
-        "id": "disk"
+        "node-name": "disk"
       }
     }
   }
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index a95c4b0be8..dc6baf9366 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -6,22 +6,18 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
 Testing:
 QMP_VERSION
 {"return": {}}
-{"error": {"class": "GenericError", "desc": "'id' and/or 'node-name' need to be specified for the root node"}}
+{"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 
 
 === Duplicate ID ===
 
-Testing:
+Testing: -drive driver=IMGFMT,id=disk,node-name=test-node,file=TEST_DIR/t.IMGFMT
 QMP_VERSION
 {"return": {}}
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Device with id 'disk' already exists"}}
-{"error": {"class": "GenericError", "desc": "Device name 'test-node' conflicts with an existing node name"}}
 {"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}}
 {"error": {"class": "GenericError", "desc": "Duplicate node name"}}
-{"error": {"class": "GenericError", "desc": "Device name 'disk3' conflicts with an existing node name"}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 
@@ -31,7 +27,7 @@ QMP_VERSION
 Testing:
 QMP_VERSION
 {"return": {}}
-{"error": {"class": "GenericError", "desc": "aio=native requires cache.direct=true"}}
+{"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 
@@ -60,7 +56,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
 Testing: -S
 QMP_VERSION
 {"return": {}}
-{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'driver', expected: string"}}
+{"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 
diff --git a/tests/qemu-iotests/117 b/tests/qemu-iotests/117
index 9385b3f8da..5b28039e17 100755
--- a/tests/qemu-iotests/117
+++ b/tests/qemu-iotests/117
@@ -52,14 +52,14 @@ _send_qemu_cmd $QEMU_HANDLE \
 
 _send_qemu_cmd $QEMU_HANDLE \
     "{ 'execute': 'blockdev-add',
-       'arguments': { 'options': { 'id': 'protocol',
+       'arguments': { 'options': { 'node-name': 'protocol',
                                    'driver': 'file',
                                    'filename': '$TEST_IMG' } } }" \
     'return'
 
 _send_qemu_cmd $QEMU_HANDLE \
     "{ 'execute': 'blockdev-add',
-       'arguments': { 'options': { 'id': 'format',
+       'arguments': { 'options': { 'node-name': 'format',
                                    'driver': '$IMGFMT',
                                    'file': 'protocol' } } }" \
     'return'
diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118
index 9e5951f645..e63a40fa94 100755
--- a/tests/qemu-iotests/118
+++ b/tests/qemu-iotests/118
@@ -62,6 +62,9 @@ class ChangeBaseClass(iotests.QMPTestCase):
             self.fail('Timeout while waiting for the tray to close')
 
 class GeneralChangeTestsBaseClass(ChangeBaseClass):
+
+    device_name = None
+
     def test_change(self):
         result = self.vm.qmp('change', device='drive0', target=new_img,
                                        arg=iotests.imgfmt)
@@ -76,9 +79,15 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
 
     def test_blockdev_change_medium(self):
-        result = self.vm.qmp('blockdev-change-medium', device='drive0',
-                                                       filename=new_img,
-                                                       format=iotests.imgfmt)
+        if self.device_name is not None:
+            result = self.vm.qmp('blockdev-change-medium',
+                                 id=self.device_name, filename=new_img,
+                                 format=iotests.imgfmt)
+        else:
+            result = self.vm.qmp('blockdev-change-medium',
+                                 device='drive0', filename=new_img,
+                                 format=iotests.imgfmt)
+
         self.assert_qmp(result, 'return', {})
 
         self.wait_for_open()
@@ -90,7 +99,10 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
 
     def test_eject(self):
-        result = self.vm.qmp('eject', device='drive0', force=True)
+        if self.device_name is not None:
+            result = self.vm.qmp('eject', id=self.device_name, force=True)
+        else:
+            result = self.vm.qmp('eject', device='drive0', force=True)
         self.assert_qmp(result, 'return', {})
 
         self.wait_for_open()
@@ -101,7 +113,10 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
         self.assert_qmp_absent(result, 'return[0]/inserted')
 
     def test_tray_eject_change(self):
-        result = self.vm.qmp('eject', device='drive0', force=True)
+        if self.device_name is not None:
+            result = self.vm.qmp('eject', id=self.device_name, force=True)
+        else:
+            result = self.vm.qmp('eject', device='drive0', force=True)
         self.assert_qmp(result, 'return', {})
 
         self.wait_for_open()
@@ -111,9 +126,12 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
             self.assert_qmp(result, 'return[0]/tray_open', True)
         self.assert_qmp_absent(result, 'return[0]/inserted')
 
-        result = self.vm.qmp('blockdev-change-medium', device='drive0',
-                                                       filename=new_img,
-                                                       format=iotests.imgfmt)
+        if self.device_name is not None:
+            result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
+                                 filename=new_img, format=iotests.imgfmt)
+        else:
+            result = self.vm.qmp('blockdev-change-medium', device='drive0',
+                                 filename=new_img, format=iotests.imgfmt)
         self.assert_qmp(result, 'return', {})
 
         self.wait_for_close()
@@ -124,7 +142,12 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
 
     def test_tray_open_close(self):
-        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+        if self.device_name is not None:
+            result = self.vm.qmp('blockdev-open-tray',
+                                 id=self.device_name, force=True)
+        else:
+            result = self.vm.qmp('blockdev-open-tray',
+                                 device='drive0', force=True)
         self.assert_qmp(result, 'return', {})
 
         self.wait_for_open()
@@ -137,7 +160,10 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
         else:
             self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
 
-        result = self.vm.qmp('blockdev-close-tray', device='drive0')
+        if self.device_name is not None:
+            result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
+        else:
+            result = self.vm.qmp('blockdev-close-tray', device='drive0')
         self.assert_qmp(result, 'return', {})
 
         if self.has_real_tray or not self.was_empty:
@@ -162,7 +188,10 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
             self.assert_qmp(result, 'return[0]/tray_open', True)
         self.assert_qmp_absent(result, 'return[0]/inserted')
 
-        result = self.vm.qmp('blockdev-close-tray', device='drive0')
+        if self.device_name is not None:
+            result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
+        else:
+            result = self.vm.qmp('blockdev-close-tray', device='drive0')
         self.assert_qmp(result, 'return', {})
 
         self.wait_for_close()
@@ -206,7 +235,12 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
                                                'driver': 'file'}})
         self.assert_qmp(result, 'return', {})
 
-        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+        if self.device_name is not None:
+            result = self.vm.qmp('blockdev-open-tray',
+                                 id=self.device_name, force=True)
+        else:
+            result = self.vm.qmp('blockdev-open-tray',
+                                 device='drive0', force=True)
         self.assert_qmp(result, 'return', {})
 
         self.wait_for_open()
@@ -219,7 +253,11 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
         else:
             self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
 
-        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
+        if self.device_name is not None:
+            result = self.vm.qmp('x-blockdev-remove-medium',
+                                 id=self.device_name)
+        else:
+            result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
         self.assert_qmp(result, 'return', {})
 
         result = self.vm.qmp('query-block')
@@ -227,8 +265,12 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
             self.assert_qmp(result, 'return[0]/tray_open', True)
         self.assert_qmp_absent(result, 'return[0]/inserted')
 
-        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
-                                                       node_name='new')
+        if self.device_name is not None:
+            result = self.vm.qmp('x-blockdev-insert-medium',
+                                 id=self.device_name, node_name='new')
+        else:
+            result = self.vm.qmp('x-blockdev-insert-medium',
+                                 device='drive0', node_name='new')
         self.assert_qmp(result, 'return', {})
 
         result = self.vm.qmp('query-block')
@@ -236,7 +278,10 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
             self.assert_qmp(result, 'return[0]/tray_open', True)
         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
 
-        result = self.vm.qmp('blockdev-close-tray', device='drive0')
+        if self.device_name is not None:
+            result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
+        else:
+            result = self.vm.qmp('blockdev-close-tray', device='drive0')
         self.assert_qmp(result, 'return', {})
 
         self.wait_for_close()
@@ -280,7 +325,13 @@ class TestInitiallyFilled(GeneralChangeTestsBaseClass):
     def setUp(self, media, interface):
         qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
         qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
-        self.vm = iotests.VM().add_drive(old_img, 'media=%s' % media, interface)
+        self.vm = iotests.VM()
+        if interface == 'ide':
+            self.device_name = 'qdev0'
+            self.vm.add_drive(old_img, 'media=%s' % media, 'none')
+            self.vm.add_device('ide-cd,drive=drive0,id=%s' % self.device_name)
+        else:
+            self.vm.add_drive(old_img, 'media=%s' % media, interface)
         self.vm.launch()
 
     def tearDown(self):
@@ -597,13 +648,9 @@ class TestBlockJobsAfterCycle(ChangeBaseClass):
         qemu_img('create', '-f', iotests.imgfmt, old_img, '1M')
 
         self.vm = iotests.VM()
+        self.vm.add_drive_raw("id=drive0,driver=null-co,if=none")
         self.vm.launch()
 
-        result = self.vm.qmp('blockdev-add',
-                             options={'id': 'drive0',
-                                      'driver': 'null-co'})
-        self.assert_qmp(result, 'return', {})
-
         result = self.vm.qmp('query-block')
         self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co')
 
diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124
index de7cdbe00e..2f0bc24cd0 100644
--- a/tests/qemu-iotests/124
+++ b/tests/qemu-iotests/124
@@ -49,8 +49,8 @@ def transaction_bitmap_clear(node, name, **kwargs):
 
 
 def transaction_drive_backup(device, target, **kwargs):
-    return transaction_action('drive-backup', device=device, target=target,
-                              **kwargs)
+    return transaction_action('drive-backup', job_id=device, device=device,
+                              target=target, **kwargs)
 
 
 class Bitmap:
@@ -177,7 +177,8 @@ class TestIncrementalBackupBase(iotests.QMPTestCase):
     def create_anchor_backup(self, drive=None):
         if drive is None:
             drive = self.drives[-1]
-        res = self.do_qmp_backup(device=drive['id'], sync='full',
+        res = self.do_qmp_backup(job_id=drive['id'],
+                                 device=drive['id'], sync='full',
                                  format=drive['fmt'], target=drive['backup'])
         self.assertTrue(res)
         self.files.append(drive['backup'])
@@ -188,7 +189,8 @@ class TestIncrementalBackupBase(iotests.QMPTestCase):
         if bitmap is None:
             bitmap = self.bitmaps[-1]
         _, reference = bitmap.last_target()
-        res = self.do_qmp_backup(device=bitmap.drive['id'], sync='full',
+        res = self.do_qmp_backup(job_id=bitmap.drive['id'],
+                                 device=bitmap.drive['id'], sync='full',
                                  format=bitmap.drive['fmt'], target=reference)
         self.assertTrue(res)
 
@@ -221,7 +223,8 @@ class TestIncrementalBackupBase(iotests.QMPTestCase):
             parent, _ = bitmap.last_target()
 
         target = self.prepare_backup(bitmap, parent)
-        res = self.do_qmp_backup(device=bitmap.drive['id'],
+        res = self.do_qmp_backup(job_id=bitmap.drive['id'],
+                                 device=bitmap.drive['id'],
                                  sync='incremental', bitmap=bitmap.name,
                                  format=bitmap.drive['fmt'], target=target,
                                  mode='existing')
@@ -414,7 +417,7 @@ class TestIncrementalBackup(TestIncrementalBackupBase):
 
         # Create a blkdebug interface to this img as 'drive1'
         result = self.vm.qmp('blockdev-add', options={
-            'id': drive1['id'],
+            'node-name': drive1['id'],
             'driver': drive1['fmt'],
             'file': {
                 'driver': 'blkdebug',
@@ -558,7 +561,7 @@ class TestIncrementalBackupBlkdebug(TestIncrementalBackupBase):
 
         drive0 = self.drives[0]
         result = self.vm.qmp('blockdev-add', options={
-            'id': drive0['id'],
+            'node-name': drive0['id'],
             'driver': drive0['fmt'],
             'file': {
                 'driver': 'blkdebug',
diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139
index a4b969499c..47a4c26e29 100644
--- a/tests/qemu-iotests/139
+++ b/tests/qemu-iotests/139
@@ -31,6 +31,7 @@ class TestBlockdevDel(iotests.QMPTestCase):
     def setUp(self):
         iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M')
         self.vm = iotests.VM()
+        self.vm.add_device("virtio-scsi-pci,id=virtio-scsi")
         self.vm.launch()
 
     def tearDown(self):
@@ -39,18 +40,6 @@ class TestBlockdevDel(iotests.QMPTestCase):
         if os.path.isfile(new_img):
             os.remove(new_img)
 
-    # Check whether a BlockBackend exists
-    def checkBlockBackend(self, backend, node, must_exist = True):
-        result = self.vm.qmp('query-block')
-        backends = filter(lambda x: x['device'] == backend, result['return'])
-        self.assertLessEqual(len(backends), 1)
-        self.assertEqual(must_exist, len(backends) == 1)
-        if must_exist:
-            if node:
-                self.assertEqual(backends[0]['inserted']['node-name'], node)
-            else:
-                self.assertFalse(backends[0].has_key('inserted'))
-
     # Check whether a BlockDriverState exists
     def checkBlockDriverState(self, node, must_exist = True):
         result = self.vm.qmp('query-named-block-nodes')
@@ -58,24 +47,6 @@ class TestBlockdevDel(iotests.QMPTestCase):
         self.assertLessEqual(len(nodes), 1)
         self.assertEqual(must_exist, len(nodes) == 1)
 
-    # Add a new BlockBackend (with its attached BlockDriverState)
-    def addBlockBackend(self, backend, node):
-        file_node = '%s_file' % node
-        self.checkBlockBackend(backend, node, False)
-        self.checkBlockDriverState(node, False)
-        self.checkBlockDriverState(file_node, False)
-        opts = {'driver': iotests.imgfmt,
-                'id': backend,
-                'node-name': node,
-                'file': {'driver': 'file',
-                         'node-name': file_node,
-                         'filename': base_img}}
-        result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts)
-        self.assert_qmp(result, 'return', {})
-        self.checkBlockBackend(backend, node)
-        self.checkBlockDriverState(node)
-        self.checkBlockDriverState(file_node)
-
     # Add a BlockDriverState without a BlockBackend
     def addBlockDriverState(self, node):
         file_node = '%s_file' % node
@@ -105,23 +76,6 @@ class TestBlockdevDel(iotests.QMPTestCase):
         self.assert_qmp(result, 'return', {})
         self.checkBlockDriverState(node)
 
-    # Delete a BlockBackend
-    def delBlockBackend(self, backend, node, expect_error = False,
-                        destroys_media = True):
-        self.checkBlockBackend(backend, node)
-        if node:
-            self.checkBlockDriverState(node)
-        result = self.vm.qmp('x-blockdev-del', id = backend)
-        if expect_error:
-            self.assert_qmp(result, 'error/class', 'GenericError')
-            if node:
-                self.checkBlockDriverState(node)
-        else:
-            self.assert_qmp(result, 'return', {})
-            if node:
-                self.checkBlockDriverState(node, not destroys_media)
-        self.checkBlockBackend(backend, node, must_exist = expect_error)
-
     # Delete a BlockDriverState
     def delBlockDriverState(self, node, expect_error = False):
         self.checkBlockDriverState(node)
@@ -133,51 +87,47 @@ class TestBlockdevDel(iotests.QMPTestCase):
         self.checkBlockDriverState(node, expect_error)
 
     # Add a device model
-    def addDeviceModel(self, device, backend):
+    def addDeviceModel(self, device, backend, driver = 'virtio-blk-pci'):
         result = self.vm.qmp('device_add', id = device,
-                             driver = 'virtio-blk-pci', drive = backend)
+                             driver = driver, drive = backend)
         self.assert_qmp(result, 'return', {})
 
     # Delete a device model
-    def delDeviceModel(self, device):
+    def delDeviceModel(self, device, is_virtio_blk = True):
         result = self.vm.qmp('device_del', id = device)
         self.assert_qmp(result, 'return', {})
 
         result = self.vm.qmp('system_reset')
         self.assert_qmp(result, 'return', {})
 
-        device_path = '/machine/peripheral/%s/virtio-backend' % device
-        event = self.vm.event_wait(name="DEVICE_DELETED",
-                                   match={'data': {'path': device_path}})
-        self.assertNotEqual(event, None)
+        if is_virtio_blk:
+            device_path = '/machine/peripheral/%s/virtio-backend' % device
+            event = self.vm.event_wait(name="DEVICE_DELETED",
+                                       match={'data': {'path': device_path}})
+            self.assertNotEqual(event, None)
 
         event = self.vm.event_wait(name="DEVICE_DELETED",
                                    match={'data': {'device': device}})
         self.assertNotEqual(event, None)
 
     # Remove a BlockDriverState
-    def ejectDrive(self, backend, node, expect_error = False,
+    def ejectDrive(self, device, node, expect_error = False,
                    destroys_media = True):
-        self.checkBlockBackend(backend, node)
         self.checkBlockDriverState(node)
-        result = self.vm.qmp('eject', device = backend)
+        result = self.vm.qmp('eject', id = device)
         if expect_error:
             self.assert_qmp(result, 'error/class', 'GenericError')
             self.checkBlockDriverState(node)
-            self.checkBlockBackend(backend, node)
         else:
             self.assert_qmp(result, 'return', {})
             self.checkBlockDriverState(node, not destroys_media)
-            self.checkBlockBackend(backend, None)
 
     # Insert a BlockDriverState
-    def insertDrive(self, backend, node):
-        self.checkBlockBackend(backend, None)
+    def insertDrive(self, device, node):
         self.checkBlockDriverState(node)
         result = self.vm.qmp('x-blockdev-insert-medium',
-                             device = backend, node_name = node)
+                             id = device, node_name = node)
         self.assert_qmp(result, 'return', {})
-        self.checkBlockBackend(backend, node)
         self.checkBlockDriverState(node)
 
     # Create a snapshot using 'blockdev-snapshot-sync'
@@ -204,26 +154,23 @@ class TestBlockdevDel(iotests.QMPTestCase):
         self.checkBlockDriverState(overlay)
 
     # Create a mirror
-    def createMirror(self, backend, node, new_node):
-        self.checkBlockBackend(backend, node)
+    def createMirror(self, node, new_node):
         self.checkBlockDriverState(new_node, False)
-        opts = {'device': backend,
+        opts = {'device': node,
+                'job-id': node,
                 'target': new_img,
                 'node-name': new_node,
                 'sync': 'top',
                 'format': iotests.imgfmt}
         result = self.vm.qmp('drive-mirror', conv_keys=False, **opts)
         self.assert_qmp(result, 'return', {})
-        self.checkBlockBackend(backend, node)
         self.checkBlockDriverState(new_node)
 
     # Complete an existing block job
-    def completeBlockJob(self, backend, node_before, node_after):
-        self.checkBlockBackend(backend, node_before)
-        result = self.vm.qmp('block-job-complete', device=backend)
+    def completeBlockJob(self, id, node_before, node_after):
+        result = self.vm.qmp('block-job-complete', device=id)
         self.assert_qmp(result, 'return', {})
-        self.wait_until_completed(backend)
-        self.checkBlockBackend(backend, node_after)
+        self.wait_until_completed(id)
 
     # Add a BlkDebug node
     # Note that the purpose of this is to test the x-blockdev-del
@@ -297,89 +244,78 @@ class TestBlockdevDel(iotests.QMPTestCase):
     # The tests start here #
     ########################
 
-    def testWrongParameters(self):
-        self.addBlockBackend('drive0', 'node0')
-        result = self.vm.qmp('x-blockdev-del')
-        self.assert_qmp(result, 'error/class', 'GenericError')
-        result = self.vm.qmp('x-blockdev-del', id='drive0', node_name='node0')
-        self.assert_qmp(result, 'error/class', 'GenericError')
-        self.delBlockBackend('drive0', 'node0')
-
-    def testBlockBackend(self):
-        self.addBlockBackend('drive0', 'node0')
-        # You cannot delete a BDS that is attached to a backend
-        self.delBlockDriverState('node0', expect_error = True)
-        self.delBlockBackend('drive0', 'node0')
-
     def testBlockDriverState(self):
         self.addBlockDriverState('node0')
         # You cannot delete a file BDS directly
         self.delBlockDriverState('node0_file', expect_error = True)
         self.delBlockDriverState('node0')
 
-    def testEject(self):
-        self.addBlockBackend('drive0', 'node0')
-        self.ejectDrive('drive0', 'node0')
-        self.delBlockBackend('drive0', None)
-
     def testDeviceModel(self):
-        self.addBlockBackend('drive0', 'node0')
-        self.addDeviceModel('device0', 'drive0')
-        self.ejectDrive('drive0', 'node0', expect_error = True)
-        self.delBlockBackend('drive0', 'node0', expect_error = True)
+        self.addBlockDriverState('node0')
+        self.addDeviceModel('device0', 'node0')
+        self.ejectDrive('device0', 'node0', expect_error = True)
+        self.delBlockDriverState('node0', expect_error = True)
         self.delDeviceModel('device0')
-        self.delBlockBackend('drive0', 'node0')
+        self.delBlockDriverState('node0')
 
     def testAttachMedia(self):
         # This creates a BlockBackend and removes its media
-        self.addBlockBackend('drive0', 'node0')
-        self.ejectDrive('drive0', 'node0')
-        # This creates a new BlockDriverState and inserts it into the backend
+        self.addBlockDriverState('node0')
+        self.addDeviceModel('device0', 'node0', 'scsi-cd')
+        self.ejectDrive('device0', 'node0', destroys_media = False)
+        self.delBlockDriverState('node0')
+
+        # This creates a new BlockDriverState and inserts it into the device
         self.addBlockDriverState('node1')
-        self.insertDrive('drive0', 'node1')
-        # The backend can't be removed: the new BDS has an extra reference
-        self.delBlockBackend('drive0', 'node1', expect_error = True)
+        self.insertDrive('device0', 'node1')
+        # The node can't be removed: the new device has an extra reference
         self.delBlockDriverState('node1', expect_error = True)
         # The BDS still exists after being ejected, but now it can be removed
-        self.ejectDrive('drive0', 'node1', destroys_media = False)
+        self.ejectDrive('device0', 'node1', destroys_media = False)
         self.delBlockDriverState('node1')
-        self.delBlockBackend('drive0', None)
+        self.delDeviceModel('device0', False)
 
     def testSnapshotSync(self):
-        self.addBlockBackend('drive0', 'node0')
+        self.addBlockDriverState('node0')
+        self.addDeviceModel('device0', 'node0')
         self.createSnapshotSync('node0', 'overlay0')
         # This fails because node0 is now being used as a backing image
         self.delBlockDriverState('node0', expect_error = True)
-        # This succeeds because overlay0 only has the backend reference
-        self.delBlockBackend('drive0', 'overlay0')
-        self.checkBlockDriverState('node0', False)
+        self.delBlockDriverState('overlay0', expect_error = True)
+        # This succeeds because device0 only has the backend reference
+        self.delDeviceModel('device0')
+        # FIXME Would still be there if blockdev-snapshot-sync took a ref
+        self.checkBlockDriverState('overlay0', False)
+        self.delBlockDriverState('node0')
 
     def testSnapshot(self):
-        self.addBlockBackend('drive0', 'node0')
+        self.addBlockDriverState('node0')
+        self.addDeviceModel('device0', 'node0', 'scsi-cd')
         self.addBlockDriverStateOverlay('overlay0')
         self.createSnapshot('node0', 'overlay0')
-        self.delBlockBackend('drive0', 'overlay0', expect_error = True)
         self.delBlockDriverState('node0', expect_error = True)
         self.delBlockDriverState('overlay0', expect_error = True)
-        self.ejectDrive('drive0', 'overlay0', destroys_media = False)
-        self.delBlockBackend('drive0', None)
+        self.ejectDrive('device0', 'overlay0', destroys_media = False)
         self.delBlockDriverState('node0', expect_error = True)
         self.delBlockDriverState('overlay0')
-        self.checkBlockDriverState('node0', False)
+        self.delBlockDriverState('node0')
 
     def testMirror(self):
-        self.addBlockBackend('drive0', 'node0')
-        self.createMirror('drive0', 'node0', 'mirror0')
+        self.addBlockDriverState('node0')
+        self.addDeviceModel('device0', 'node0', 'scsi-cd')
+        self.createMirror('node0', 'mirror0')
         # The block job prevents removing the device
-        self.delBlockBackend('drive0', 'node0', expect_error = True)
         self.delBlockDriverState('node0', expect_error = True)
         self.delBlockDriverState('mirror0', expect_error = True)
-        self.wait_ready('drive0')
-        self.completeBlockJob('drive0', 'node0', 'mirror0')
+        self.wait_ready('node0')
+        self.completeBlockJob('node0', 'node0', 'mirror0')
         self.assert_no_active_block_jobs()
-        self.checkBlockDriverState('node0', False)
-        # This succeeds because the backend now points to mirror0
-        self.delBlockBackend('drive0', 'mirror0')
+        # This succeeds because the device now points to mirror0
+        self.delBlockDriverState('node0')
+        self.delBlockDriverState('mirror0', expect_error = True)
+        self.delDeviceModel('device0', False)
+        # FIXME mirror0 disappears, drive-mirror doesn't take a reference
+        #self.delBlockDriverState('mirror0')
 
     def testBlkDebug(self):
         self.addBlkDebug('debug0', 'node0')
diff --git a/tests/qemu-iotests/139.out b/tests/qemu-iotests/139.out
index 281b69efea..dae404e278 100644
--- a/tests/qemu-iotests/139.out
+++ b/tests/qemu-iotests/139.out
@@ -1,5 +1,5 @@
-............
+.........
 ----------------------------------------------------------------------
-Ran 12 tests
+Ran 9 tests
 
 OK
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
index b2617e5e2b..c092d872dc 100755
--- a/tests/qemu-iotests/141
+++ b/tests/qemu-iotests/141
@@ -51,7 +51,7 @@ test_blockjob()
         "{'execute': 'blockdev-add',
           'arguments': {
               'options': {
-                  'id': 'drv0',
+                  'node-name': 'drv0',
                   'driver': '$IMGFMT',
                   'file': {
                       'driver': 'file',
@@ -66,18 +66,18 @@ test_blockjob()
 
     # We want this to return an error because the block job is still running
     _send_qemu_cmd $QEMU_HANDLE \
-        "{'execute': 'x-blockdev-remove-medium',
-          'arguments': {'device': 'drv0'}}" \
+        "{'execute': 'x-blockdev-del',
+          'arguments': {'node-name': 'drv0'}}" \
         'error'
 
     _send_qemu_cmd $QEMU_HANDLE \
         "{'execute': 'block-job-cancel',
-          'arguments': {'device': 'drv0'}}" \
+          'arguments': {'device': 'job0'}}" \
         "$3"
 
     _send_qemu_cmd $QEMU_HANDLE \
         "{'execute': 'x-blockdev-del',
-          'arguments': {'id': 'drv0'}}" \
+          'arguments': {'node-name': 'drv0'}}" \
         'return'
 }
 
@@ -101,7 +101,8 @@ echo
 
 test_blockjob \
     "{'execute': 'drive-backup',
-      'arguments': {'device': 'drv0',
+      'arguments': {'job-id': 'job0',
+                    'device': 'drv0',
                     'target': '$TEST_DIR/o.$IMGFMT',
                     'format': '$IMGFMT',
                     'sync': 'none'}}" \
@@ -117,7 +118,8 @@ echo
 
 test_blockjob \
     "{'execute': 'drive-mirror',
-      'arguments': {'device': 'drv0',
+      'arguments': {'job-id': 'job0',
+                    'device': 'drv0',
                     'target': '$TEST_DIR/o.$IMGFMT',
                     'format': '$IMGFMT',
                     'sync': 'none'}}" \
@@ -134,7 +136,7 @@ echo
 
 test_blockjob \
     "{'execute': 'block-commit',
-      'arguments': {'device': 'drv0'}}" \
+      'arguments': {'job-id': 'job0', 'device': 'drv0'}}" \
     'BLOCK_JOB_READY' \
     'BLOCK_JOB_COMPLETED'
 
@@ -150,7 +152,8 @@ $QEMU_IO -c 'write 0 1M' "$TEST_DIR/m.$IMGFMT" | _filter_qemu_io
 
 test_blockjob \
     "{'execute': 'block-commit',
-      'arguments': {'device': 'drv0',
+      'arguments': {'job-id': 'job0',
+                    'device': 'drv0',
                     'top':    '$TEST_DIR/m.$IMGFMT',
                     'speed':  1}}" \
     'return' \
@@ -172,7 +175,8 @@ $QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io
 
 test_blockjob \
     "{'execute': 'block-stream',
-      'arguments': {'device': 'drv0',
+      'arguments': {'job-id': 'job0',
+                    'device': 'drv0',
                     'speed': 1}}" \
     'return' \
     'BLOCK_JOB_CANCELLED'
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
index eaf1e603ed..195ca1a604 100644
--- a/tests/qemu-iotests/141.out
+++ b/tests/qemu-iotests/141.out
@@ -9,30 +9,30 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
 {"return": {}}
 Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
 {"return": {}}
-{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: backup"}}
+{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
 {"return": {}}
 
 === Testing drive-mirror ===
 
 {"return": {}}
 Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
 {"return": {}}
-{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
+{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
 {"return": {}}
 
 === Testing active block-commit ===
 
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
 {"return": {}}
-{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
 {"return": {}}
 
 === Testing non-active block-commit ===
@@ -41,9 +41,9 @@ wrote 1048576/1048576 bytes at offset 0
 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": {}}
 {"return": {}}
-{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
 {"return": {}}
 
 === Testing block-stream ===
@@ -52,8 +52,8 @@ wrote 1048576/1048576 bytes at offset 0
 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": {}}
 {"return": {}}
-{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}}
+{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
 {"return": {}}
 *** done
diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158
new file mode 100755
index 0000000000..a6cdd6d8cf
--- /dev/null
+++ b/tests/qemu-iotests/158
@@ -0,0 +1,80 @@
+#!/bin/bash
+#
+# Test encrypted read/write using backing files
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=berrange@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+
+size=128M
+TEST_IMG_BASE=$TEST_IMG.base
+
+TEST_IMG_SAVE=$TEST_IMG
+TEST_IMG=$TEST_IMG_BASE
+echo "== create base =="
+IMGOPTS="encryption=on" _make_test_img $size
+TEST_IMG=$TEST_IMG_SAVE
+
+echo
+echo "== writing whole image =="
+echo "astrochicken" | $QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG_BASE" | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== verify pattern =="
+echo "astrochicken" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG_BASE" | _filter_qemu_io | _filter_testdir
+
+echo "== create overlay =="
+IMGOPTS="encryption=on" _make_test_img -b "$TEST_IMG_BASE" $size
+
+echo
+echo "== writing part of a cluster =="
+echo "astrochicken" | $QEMU_IO -c "write -P 0xe 0 1024" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== verify pattern =="
+echo "astrochicken" | $QEMU_IO -c "read -P 0xe 0 1024" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
+echo
+echo "== verify pattern =="
+echo "astrochicken" | $QEMU_IO -c "read -P 0xa 1024 64512" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
+
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/158.out b/tests/qemu-iotests/158.out
new file mode 100644
index 0000000000..b3f37e28ef
--- /dev/null
+++ b/tests/qemu-iotests/158.out
@@ -0,0 +1,36 @@
+QA output created by 158
+== create base ==
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on
+
+== writing whole image ==
+Disk image 'TEST_DIR/t.qcow2.base' is encrypted.
+password:
+wrote 134217728/134217728 bytes at offset 0
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verify pattern ==
+Disk image 'TEST_DIR/t.qcow2.base' is encrypted.
+password:
+read 134217728/134217728 bytes at offset 0
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+== create overlay ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base encryption=on
+
+== writing part of a cluster ==
+Disk image 'TEST_DIR/t.qcow2' is encrypted.
+password:
+wrote 1024/1024 bytes at offset 0
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verify pattern ==
+Disk image 'TEST_DIR/t.qcow2' is encrypted.
+password:
+read 1024/1024 bytes at offset 0
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verify pattern ==
+Disk image 'TEST_DIR/t.qcow2' is encrypted.
+password:
+read 64512/64512 bytes at offset 1024
+63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/159 b/tests/qemu-iotests/159
new file mode 100755
index 0000000000..825f05fab8
--- /dev/null
+++ b/tests/qemu-iotests/159
@@ -0,0 +1,70 @@
+#! /bin/bash
+#
+# qemu-img dd test with different block sizes
+#
+# Copyright (C) 2016 Reda Sallahi
+#
+# 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/>.
+#
+
+owner=fullmanet@gmail.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1
+
+_cleanup()
+{
+    _cleanup_test_img
+    rm -f "$TEST_IMG.out"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+. ./common.rc
+. ./common.filter
+. ./common.pattern
+
+_supported_fmt generic
+_supported_proto file
+_supported_os Linux
+
+TEST_SIZES="5 512 1024 1999 1K 64K 1M"
+
+for bs in $TEST_SIZES; do
+    echo
+    echo "== Creating image =="
+
+    size=1M
+    _make_test_img $size
+    _check_test_img
+    $QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
+
+    echo
+    echo "== Converting the image with dd with a block size of $bs =="
+
+    $QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" bs=$bs -O "$IMGFMT"
+    TEST_IMG="$TEST_IMG.out" _check_test_img
+
+    echo
+    echo "== Compare the images with qemu-img compare =="
+
+    $QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.out"
+done
+
+echo
+echo "*** done"
+rm -f "$seq.full"
+status=0
diff --git a/tests/qemu-iotests/159.out b/tests/qemu-iotests/159.out
new file mode 100644
index 0000000000..b86b63abe6
--- /dev/null
+++ b/tests/qemu-iotests/159.out
@@ -0,0 +1,87 @@
+QA output created by 159
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with a block size of 5 ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with a block size of 512 ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with a block size of 1024 ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with a block size of 1999 ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with a block size of 1K ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with a block size of 64K ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with a block size of 1M ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+*** done
diff --git a/tests/qemu-iotests/160 b/tests/qemu-iotests/160
new file mode 100755
index 0000000000..5c910e5bfc
--- /dev/null
+++ b/tests/qemu-iotests/160
@@ -0,0 +1,72 @@
+#! /bin/bash
+#
+# qemu-img dd test for the skip option
+#
+# Copyright (C) 2016 Reda Sallahi
+#
+# 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/>.
+#
+
+owner=fullmanet@gmail.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1
+
+_cleanup()
+{
+    _cleanup_test_img
+    rm -f "$TEST_IMG.out" "$TEST_IMG.out.dd"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+. ./common.rc
+. ./common.filter
+. ./common.pattern
+
+_supported_fmt raw
+_supported_proto file
+_supported_os Linux
+
+TEST_SKIP_BLOCKS="1 2 30 30K"
+
+for skip in $TEST_SKIP_BLOCKS; do
+    echo
+    echo "== Creating image =="
+
+    size=1M
+    _make_test_img $size
+    _check_test_img
+    $QEMU_IO -c "write -P 0xa 24 512k" "$TEST_IMG" | _filter_qemu_io
+
+    echo
+    echo "== Converting the image with dd with skip=$skip =="
+
+    $QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" skip="$skip" -O "$IMGFMT" \
+        2> /dev/null
+    TEST_IMG="$TEST_IMG.out" _check_test_img
+    dd if="$TEST_IMG" of="$TEST_IMG.out.dd" skip="$skip" status=none
+
+    echo
+    echo "== Compare the images with qemu-img compare =="
+
+    $QEMU_IMG compare "$TEST_IMG.out.dd" "$TEST_IMG.out"
+done
+
+echo
+echo "*** done"
+rm -f "$seq.full"
+status=0
diff --git a/tests/qemu-iotests/160.out b/tests/qemu-iotests/160.out
new file mode 100644
index 0000000000..9cedc80356
--- /dev/null
+++ b/tests/qemu-iotests/160.out
@@ -0,0 +1,51 @@
+QA output created by 160
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 524288/524288 bytes at offset 24
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=1 ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 524288/524288 bytes at offset 24
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=2 ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 524288/524288 bytes at offset 24
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=30 ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 524288/524288 bytes at offset 24
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd with skip=30K ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+*** done
diff --git a/tests/qemu-iotests/170 b/tests/qemu-iotests/170
new file mode 100755
index 0000000000..5b335dbc3e
--- /dev/null
+++ b/tests/qemu-iotests/170
@@ -0,0 +1,67 @@
+#! /bin/bash
+#
+# qemu-img dd test
+#
+# Copyright (C) 2016 Reda Sallahi
+#
+# 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/>.
+#
+
+owner=fullmanet@gmail.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1
+
+_cleanup()
+{
+    _cleanup_test_img
+    rm -f "$TEST_IMG.out"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+. ./common.rc
+. ./common.filter
+. ./common.pattern
+
+_supported_fmt generic
+_supported_proto file
+_supported_os Linux
+
+echo
+echo "== Creating image =="
+
+size=1M
+_make_test_img $size
+_check_test_img
+
+$QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== Converting the image with dd =="
+
+$QEMU_IMG dd if="$TEST_IMG" of="$TEST_IMG.out" -O "$IMGFMT"
+TEST_IMG="$TEST_IMG.out" _check_test_img
+
+echo
+echo "== Compare the images with qemu-img compare =="
+
+$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.out"
+
+echo
+echo "*** done"
+rm -f "$seq.full"
+status=0
diff --git a/tests/qemu-iotests/170.out b/tests/qemu-iotests/170.out
new file mode 100644
index 0000000000..a83fb82fa7
--- /dev/null
+++ b/tests/qemu-iotests/170.out
@@ -0,0 +1,15 @@
+QA output created by 170
+
+== Creating image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+No errors were found on the image.
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Converting the image with dd ==
+No errors were found on the image.
+
+== Compare the images with qemu-img compare ==
+Images are identical.
+
+*** done
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 3ab6e4d764..240ed0697a 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -44,6 +44,15 @@ _filter_imgfmt()
     sed -e "s#$IMGFMT#IMGFMT#g"
 }
 
+# Replace error message when the format is not supported and delete
+# the output lines after the first one
+_filter_qemu_img_check()
+{
+    sed -e '/allocated.*fragmented.*compressed clusters/d' \
+        -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \
+        -e '/Image end offset: [0-9]\+/d'
+}
+
 # Removes \r from messages
 _filter_win32()
 {
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 306b00c210..126bd67043 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -234,10 +234,7 @@ _check_test_img()
         else
             $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1
         fi
-    ) | _filter_testdir | \
-        sed -e '/allocated.*fragmented.*compressed clusters/d' \
-            -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \
-            -e '/Image end offset: [0-9]\+/d'
+    ) | _filter_testdir | _filter_qemu_img_check
 }
 
 _img_info()
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 50ddeed80a..7eb17707a2 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -157,4 +157,8 @@
 155 rw auto
 156 rw auto quick
 157 auto
+158 rw auto quick
+159 rw auto quick
+160 rw auto quick
 162 auto quick
+170 rw auto quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index dbe0ee548a..3329bc1721 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -50,6 +50,7 @@ cachemode = os.environ.get('CACHEMODE')
 qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE')
 
 socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
+debug = False
 
 def qemu_img(*args):
     '''Run qemu-img and return the exit code'''
@@ -86,10 +87,10 @@ def qemu_io(*args):
         sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args)))
     return subp.communicate()[0]
 
-def compare_images(img1, img2):
+def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
     '''Return True if two image files are identical'''
-    return qemu_img('compare', '-f', imgfmt,
-                    '-F', imgfmt, img1, img2) == 0
+    return qemu_img('compare', '-f', fmt1,
+                    '-F', fmt2, img1, img2) == 0
 
 def create_image(name, size):
     '''Create a fully-allocated raw image with sector markers'''
@@ -134,21 +135,28 @@ class VM(qtest.QEMUQtestMachine):
     def __init__(self):
         super(VM, self).__init__(qemu_prog, qemu_opts, test_dir=test_dir,
                                  socket_scm_helper=socket_scm_helper)
+        if debug:
+            self._debug = True
         self._num_drives = 0
 
+    def add_device(self, opts):
+        self._args.append('-device')
+        self._args.append(opts)
+        return self
+
     def add_drive_raw(self, opts):
         self._args.append('-drive')
         self._args.append(opts)
         return self
 
-    def add_drive(self, path, opts='', interface='virtio'):
+    def add_drive(self, path, opts='', interface='virtio', format=imgfmt):
         '''Add a virtio-blk drive to the VM'''
         options = ['if=%s' % interface,
                    'id=drive%d' % self._num_drives]
 
         if path is not None:
             options.append('file=%s' % path)
-            options.append('format=%s' % imgfmt)
+            options.append('format=%s' % format)
             options.append('cache=%s' % cachemode)
 
         if opts:
@@ -318,6 +326,8 @@ def verify_quorum():
 def main(supported_fmts=[], supported_oses=['linux']):
     '''Run tests'''
 
+    global debug
+
     # We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
     # indicate that we're not being run via "check". There may be
     # other things set up by "check" that individual test cases rely
diff --git a/tests/qom-test.c b/tests/qom-test.c
index 23493a2b0a..d48f890e84 100644
--- a/tests/qom-test.c
+++ b/tests/qom-test.c
@@ -115,7 +115,7 @@ static void add_machine_test_cases(void)
     const QListEntry *p;
     QObject *qobj;
     QString *qstr;
-    const char *mname, *path;
+    const char *mname;
 
     qtest_start("-machine none");
     response = qmp("{ 'execute': 'query-machines' }");
@@ -132,8 +132,9 @@ static void add_machine_test_cases(void)
         g_assert(qstr);
         mname = qstring_get_str(qstr);
         if (!is_blacklisted(arch, mname)) {
-            path = g_strdup_printf("qom/%s", mname);
+            char *path = g_strdup_printf("qom/%s", mname);
             qtest_add_data_func(path, g_strdup(mname), test_machine);
+            g_free(path);
         }
     }
 
diff --git a/tests/rtas-test.c b/tests/rtas-test.c
new file mode 100644
index 0000000000..ba0867afbd
--- /dev/null
+++ b/tests/rtas-test.c
@@ -0,0 +1,41 @@
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "libqtest.h"
+
+#include "libqos/libqos-spapr.h"
+#include "libqos/rtas.h"
+
+static void test_rtas_get_time_of_day(void)
+{
+    QOSState *qs;
+    struct tm tm;
+    uint32_t ns;
+    uint64_t ret;
+    time_t t1, t2;
+
+    qs = qtest_spapr_boot("-machine pseries");
+    g_assert(qs != NULL);
+
+    t1 = time(NULL);
+    ret = qrtas_get_time_of_day(qs->alloc, &tm, &ns);
+    g_assert_cmpint(ret, ==, 0);
+    t2 = mktimegm(&tm);
+    g_assert(t2 - t1 < 5); /* 5 sec max to run the test */
+
+    qtest_shutdown(qs);
+}
+
+int main(int argc, char *argv[])
+{
+    const char *arch = qtest_get_arch();
+
+    g_test_init(&argc, &argv, NULL);
+
+    if (strcmp(arch, "ppc64")) {
+        g_printerr("RTAS requires ppc64-softmmu/qemu-system-ppc64\n");
+        exit(EXIT_FAILURE);
+    }
+    qtest_add_func("rtas/get-time-of-day", test_rtas_get_time_of_day);
+
+    return g_test_run();
+}
diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c
index 13de7eeafd..c2f601a380 100644
--- a/tests/rtl8139-test.c
+++ b/tests/rtl8139-test.c
@@ -35,7 +35,7 @@ static QPCIDevice *get_device(void)
 {
     QPCIDevice *dev;
 
-    pcibus = qpci_init_pc();
+    pcibus = qpci_init_pc(NULL);
     qpci_device_foreach(pcibus, 0x10ec, 0x8139, save_fn, &dev);
     g_assert(dev != NULL);
 
diff --git a/tests/tcg/README b/tests/tcg/README
new file mode 100644
index 0000000000..5dcfb4852b
--- /dev/null
+++ b/tests/tcg/README
@@ -0,0 +1,76 @@
+This directory contains various interesting programs for
+regression testing.
+
+The target "make test" runs the programs and, if applicable,
+runs "diff" to detect mismatches between output on the host and
+output on QEMU.
+
+i386
+====
+
+test-i386
+---------
+
+This program executes most of the 16 bit and 32 bit x86 instructions and
+generates a text output, for comparison with the output obtained with
+a real CPU or another emulator.
+
+The Linux system call modify_ldt() is used to create x86 selectors
+to test some 16 bit addressing and 32 bit with segmentation cases.
+
+The Linux system call vm86() is used to test vm86 emulation.
+
+Various exceptions are raised to test most of the x86 user space
+exception reporting.
+
+linux-test
+----------
+
+This program tests various Linux system calls. It is used to verify
+that the system call parameters are correctly converted between target
+and host CPUs.
+
+test-i386-fprem
+---------------
+
+runcom
+------
+
+test-mmap
+---------
+
+sha1
+----
+
+hello-i386
+----------
+
+
+ARM
+===
+
+hello-arm
+---------
+
+test-arm-iwmmxt
+---------------
+
+MIPS
+====
+
+hello-mips
+----------
+
+hello-mipsel
+------------
+
+CRIS
+====
+The testsuite for CRIS is in tests/tcg/cris.  You can run it
+with "make test-cris".
+
+LM32
+====
+The testsuite for LM32 is in tests/tcg/cris.  You can run it
+with "make test-lm32".
+
diff --git a/tests/tcg/cris/Makefile b/tests/tcg/cris/Makefile
index d34bfd8f7a..6b3dba446c 100644
--- a/tests/tcg/cris/Makefile
+++ b/tests/tcg/cris/Makefile
@@ -23,6 +23,7 @@ SYS        = sys.o
 TESTCASES += check_abs.tst
 TESTCASES += check_addc.tst
 TESTCASES += check_addcm.tst
+TESTCASES += check_addcv17.tst
 TESTCASES += check_addo.tst
 TESTCASES += check_addoq.tst
 TESTCASES += check_addi.tst
@@ -108,14 +109,12 @@ TESTCASES += check_stat4.ctst
 TESTCASES += check_openpf1.ctst
 TESTCASES += check_openpf2.ctst
 TESTCASES += check_openpf3.ctst
-TESTCASES += check_openpf4.ctst
 TESTCASES += check_openpf5.ctst
 TESTCASES += check_mapbrk.ctst
 TESTCASES += check_mmap1.ctst
 TESTCASES += check_mmap2.ctst
 TESTCASES += check_mmap3.ctst
 TESTCASES += check_sigalrm.ctst
-TESTCASES += check_time1.ctst
 TESTCASES += check_time2.ctst
 TESTCASES += check_settls1.ctst
 
@@ -136,13 +135,27 @@ all: build
 %.ctst: %.o
 	$(CC) $(CFLAGS) $(LDLIBS) $< -o $@
 
+
+sysv10.o: sys.c
+	$(CC) $(CFLAGS) -mcpu=v10 -c $< -o $@
+
+crtv10.o: crt.s
+	$(AS) $(ASFLAGS) -mcpu=v10 -c $< -o $@
+
+check_addcv17.tst: ASFLAGS += -mcpu=v10
+check_addcv17.tst: CRT := crtv10.o
+check_addcv17.tst: SYS := sysv10.o
+check_addcv17.tst: crtv10.o sysv10.o
+
 build: $(CRT) $(SYS) $(TESTCASES)
 
 check: $(CRT) $(SYS) $(TESTCASES)
 	@echo -e "\nQEMU simulator."
 	for case in $(TESTCASES); do \
 		echo -n "$$case "; \
-		$(SIM) ./$$case; \
+		SIMARGS=; \
+		case $$case in *v17*) SIMARGS="-cpu crisv17";; esac; \
+		$(SIM) $$SIMARGS ./$$case; \
 	done
 check-g: $(CRT) $(SYS) $(TESTCASES)
 	@echo -e "\nGDB simulator."
@@ -152,4 +165,4 @@ check-g: $(CRT) $(SYS) $(TESTCASES)
 	done
 
 clean:
-	$(RM) -fr $(TESTCASES) $(CRT) $(SYS)
+	$(RM) -fr $(TESTCASES) *.o
diff --git a/tests/tcg/cris/check_abs.c b/tests/tcg/cris/check_abs.c
index 9770a8d9ef..08b67b6ef0 100644
--- a/tests/tcg/cris/check_abs.c
+++ b/tests/tcg/cris/check_abs.c
@@ -4,14 +4,14 @@
 #include "sys.h"
 #include "crisutils.h"
 
-static inline int cris_abs(int n)
+static always_inline int cris_abs(int n)
 {
 	int r;
 	asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));
 	return r;
 }
 
-static inline void
+static always_inline void
 verify_abs(int val, int res,
 	   const int n, const int z, const int v, const int c)
 {
diff --git a/tests/tcg/cris/check_addc.c b/tests/tcg/cris/check_addc.c
index facd1bea2d..fc3fb1faa8 100644
--- a/tests/tcg/cris/check_addc.c
+++ b/tests/tcg/cris/check_addc.c
@@ -4,7 +4,7 @@
 #include "sys.h"
 #include "crisutils.h"
 
-static inline int cris_addc(int a, const int b)
+static always_inline int cris_addc(int a, const int b)
 {
 	asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));
 	return a;
diff --git a/tests/tcg/cris/check_addcm.c b/tests/tcg/cris/check_addcm.c
index 7928bc9999..b355ba164f 100644
--- a/tests/tcg/cris/check_addcm.c
+++ b/tests/tcg/cris/check_addcm.c
@@ -5,14 +5,14 @@
 #include "crisutils.h"
 
 /* need to avoid acr as source here.  */
-static inline int cris_addc_m(int a, const int *b)
+static always_inline int cris_addc_m(int a, const int *b)
 {
 	asm volatile ("addc [%1], %0\n" : "+r" (a) : "r" (b));
 	return a;
 }
 
 /* 'b' is a crisv32 constrain to avoid postinc with $acr.  */
-static inline int cris_addc_pi_m(int a, int **b)
+static always_inline int cris_addc_pi_m(int a, int **b)
 {
 	asm volatile ("addc [%1+], %0\n" : "+r" (a), "+b" (*b));
 	return a;
diff --git a/tests/tcg/cris/check_addcv17.s b/tests/tcg/cris/check_addcv17.s
new file mode 100644
index 0000000000..52ef7a9716
--- /dev/null
+++ b/tests/tcg/cris/check_addcv17.s
@@ -0,0 +1,65 @@
+# mach:  crisv17
+
+ .include "testutils.inc"
+
+ .macro addc Rs Rd inc=0
+# Create the instruction manually since there is no assembler support yet
+ .word (\Rd << 12) | \Rs | (\inc << 10) | 0x09a0
+ .endm
+
+ start
+
+ .data
+mem1:
+ .dword 0x0
+mem2:
+ .dword 0x12345678
+
+ .text
+ move.d mem1,r4
+ clearf nzvc
+ addc 4 3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ move.d mem1,r4
+ clearf nzvc
+ ax
+ addc 4 3
+ test_cc 0 0 0 0
+ checkr3 0
+
+ move.d mem1,r4
+ clearf nzvc
+ setf c
+ addc 4 3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d mem2,r4
+ moveq 2, r3
+ clearf nzvc
+ setf c
+ addc 4 3
+ test_cc 0 0 0 0
+ checkr3 1234567b
+
+ move.d mem2,r5
+ clearf nzvc
+ cmp.d r4,r5
+ test_cc 0 1 0 0
+
+ move.d mem2,r4
+ moveq 2, r3
+ clearf nzvc
+ addc 4 3 inc=1
+ test_cc 0 0 0 0
+ checkr3 1234567a
+
+ move.d mem2,r5
+ clearf nzvc
+ addq 4,r5
+ cmp.d r4,r5
+ test_cc 0 1 0 0
+
+ quit
diff --git a/tests/tcg/cris/check_bound.c b/tests/tcg/cris/check_bound.c
index e8831754ec..d956ab9ade 100644
--- a/tests/tcg/cris/check_bound.c
+++ b/tests/tcg/cris/check_bound.c
@@ -4,21 +4,21 @@
 #include "sys.h"
 #include "crisutils.h"
 
-static inline int cris_bound_b(int v, int b)
+static always_inline int cris_bound_b(int v, int b)
 {
 	int r = v;
 	asm ("bound.b\t%1, %0\n" : "+r" (r) : "ri" (b));
 	return r;
 }
 
-static inline int cris_bound_w(int v, int b)
+static always_inline int cris_bound_w(int v, int b)
 {
 	int r = v;
 	asm ("bound.w\t%1, %0\n" : "+r" (r) : "ri" (b));
 	return r;
 }
 
-static inline int cris_bound_d(int v, int b)
+static always_inline int cris_bound_d(int v, int b)
 {
 	int r = v;
 	asm ("bound.d\t%1, %0\n" : "+r" (r) : "ri" (b));
diff --git a/tests/tcg/cris/check_ftag.c b/tests/tcg/cris/check_ftag.c
index 908773a38a..aaa5c97115 100644
--- a/tests/tcg/cris/check_ftag.c
+++ b/tests/tcg/cris/check_ftag.c
@@ -4,22 +4,22 @@
 #include "sys.h"
 #include "crisutils.h"
 
-static inline void cris_ftag_i(unsigned int x)
+static always_inline void cris_ftag_i(unsigned int x)
 {
 	register unsigned int v asm("$r10") = x;
 	asm ("ftagi\t[%0]\n" : : "r" (v) );
 }
-static inline void cris_ftag_d(unsigned int x)
+static always_inline void cris_ftag_d(unsigned int x)
 {
 	register unsigned int v asm("$r10") = x;
 	asm ("ftagd\t[%0]\n" : : "r" (v) );
 }
-static inline void cris_fidx_i(unsigned int x)
+static always_inline void cris_fidx_i(unsigned int x)
 {
 	register unsigned int v asm("$r10") = x;
 	asm ("fidxi\t[%0]\n" : : "r" (v) );
 }
-static inline void cris_fidx_d(unsigned int x)
+static always_inline void cris_fidx_d(unsigned int x)
 {
 	register unsigned int v asm("$r10") = x;
 	asm ("fidxd\t[%0]\n" : : "r" (v) );
diff --git a/tests/tcg/cris/check_int64.c b/tests/tcg/cris/check_int64.c
index fc600176e2..69caec1bb2 100644
--- a/tests/tcg/cris/check_int64.c
+++ b/tests/tcg/cris/check_int64.c
@@ -5,12 +5,12 @@
 #include "crisutils.h"
 
 
-static inline int64_t add64(const int64_t a, const int64_t b)
+static always_inline int64_t add64(const int64_t a, const int64_t b)
 {
 	return a + b;
 }
 
-static inline int64_t sub64(const int64_t a, const int64_t b)
+static always_inline int64_t sub64(const int64_t a, const int64_t b)
 {
 	return a - b;
 }
diff --git a/tests/tcg/cris/check_lz.c b/tests/tcg/cris/check_lz.c
index 69c2e6d4ec..bf051a6b55 100644
--- a/tests/tcg/cris/check_lz.c
+++ b/tests/tcg/cris/check_lz.c
@@ -3,7 +3,7 @@
 #include <stdint.h>
 #include "sys.h"
 
-static inline int cris_lz(int x)
+static always_inline int cris_lz(int x)
 {
 	int r;
 	asm ("lz\t%1, %0\n" : "=r" (r) : "r" (x));
diff --git a/tests/tcg/cris/check_openpf4.c b/tests/tcg/cris/check_openpf4.c
deleted file mode 100644
index 8bbee41a64..0000000000
--- a/tests/tcg/cris/check_openpf4.c
+++ /dev/null
@@ -1,5 +0,0 @@
-/* Basic file operations, now *with* sysroot.
-#sim: --sysroot=@exedir@
-*/
-#define PREFIX "/"
-#include "check_openpf3.c"
diff --git a/tests/tcg/cris/check_swap.c b/tests/tcg/cris/check_swap.c
index f851cbcef1..9a68c1e5d7 100644
--- a/tests/tcg/cris/check_swap.c
+++ b/tests/tcg/cris/check_swap.c
@@ -9,7 +9,7 @@
 #define B 2
 #define R 1
 
-static inline int cris_swap(const int mode, int x)
+static always_inline int cris_swap(const int mode, int x)
 {
 	switch (mode)
 	{
diff --git a/tests/tcg/cris/check_time1.c b/tests/tcg/cris/check_time1.c
deleted file mode 100644
index 3fcf0e1535..0000000000
--- a/tests/tcg/cris/check_time1.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Basic time functionality test: check that milliseconds are
-   incremented for each syscall (does not work on host).  */
-#include <stdio.h>
-#include <time.h>
-#include <sys/time.h>
-#include <string.h>
-#include <stdlib.h>
-
-void err (const char *s)
-{
-  perror (s);
-  abort ();
-}
-
-int
-main (void)
-{
-  struct timeval t_m = {0, 0};
-  struct timezone t_z = {0, 0};
-  struct timeval t_m1 = {0, 0};
-  int i;
-
-  if (gettimeofday (&t_m, &t_z) != 0)
-    err ("gettimeofday");
-
-  for (i = 1; i < 10000; i++)
-    if (gettimeofday (&t_m1, NULL) != 0)
-      err ("gettimeofday 1");
-    else
-      if (t_m1.tv_sec * 1000000 + t_m1.tv_usec
-	  != (t_m.tv_sec * 1000000 + t_m.tv_usec + i * 1000))
-	{
-	  fprintf (stderr, "t0 (%ld, %ld), i %d, t1 (%ld, %ld)\n",
-		   t_m.tv_sec, t_m.tv_usec, i, t_m1.tv_sec, t_m1.tv_usec);
-	  abort ();
-	}
-
-  if (time (NULL) != t_m1.tv_sec)
-    {
-      fprintf (stderr, "time != gettod\n");
-      abort ();
-    }
-
-  printf ("pass\n");
-  exit (0);
-}
diff --git a/tests/tcg/cris/crisutils.h b/tests/tcg/cris/crisutils.h
index 3456b9d50d..bbbe6c5540 100644
--- a/tests/tcg/cris/crisutils.h
+++ b/tests/tcg/cris/crisutils.h
@@ -13,57 +13,57 @@ void _err(void) {
 	_fail(tst_cc_loc);
 }
 
-static inline void cris_tst_cc_n1(void)
+static always_inline void cris_tst_cc_n1(void)
 {
 	asm volatile ("bpl _err\n"
 		      "nop\n");
 }
-static inline void cris_tst_cc_n0(void)
+static always_inline void cris_tst_cc_n0(void)
 {
 	asm volatile ("bmi _err\n"
 		      "nop\n");
 }
 
-static inline void cris_tst_cc_z1(void)
+static always_inline void cris_tst_cc_z1(void)
 {
 	asm volatile ("bne _err\n"
 		      "nop\n");
 }
-static inline void cris_tst_cc_z0(void)
+static always_inline void cris_tst_cc_z0(void)
 {
 	asm volatile ("beq _err\n"
 		      "nop\n");
 }
-static inline void cris_tst_cc_v1(void)
+static always_inline void cris_tst_cc_v1(void)
 {
 	asm volatile ("bvc _err\n"
 		      "nop\n");
 }
-static inline void cris_tst_cc_v0(void)
+static always_inline void cris_tst_cc_v0(void)
 {
 	asm volatile ("bvs _err\n"
 		      "nop\n");
 }
 
-static inline void cris_tst_cc_c1(void)
+static always_inline void cris_tst_cc_c1(void)
 {
 	asm volatile ("bcc _err\n"
 		      "nop\n");
 }
-static inline void cris_tst_cc_c0(void)
+static always_inline void cris_tst_cc_c0(void)
 {
 	asm volatile ("bcs _err\n"
 		      "nop\n");
 }
 
-static inline void cris_tst_mov_cc(int n, int z)
+static always_inline void cris_tst_mov_cc(int n, int z)
 {
 	if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
 	if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
 	asm volatile ("" : : "g" (_err));
 }
 
-static inline void cris_tst_cc(const int n, const int z,
+static always_inline void cris_tst_cc(const int n, const int z,
 			       const int v, const int c)
 {
 	if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
diff --git a/tests/tcg/cris/sys.c b/tests/tcg/cris/sys.c
index 551c5dd7cb..21f08c0747 100644
--- a/tests/tcg/cris/sys.c
+++ b/tests/tcg/cris/sys.c
@@ -33,19 +33,27 @@ void *memset (void *s, int c, size_t n) {
 }
 
 void exit (int status) {
-	asm volatile ("moveq 1, $r9\n" /* NR_exit.  */
-		      "break 13\n");
+	register unsigned int callno asm ("r9") = 1; /* NR_exit */
+
+	asm volatile ("break 13\n"
+		      :
+		      : "r" (callno)
+		      : "memory" );
 	while(1)
 		;
 }
 
 ssize_t write (int fd, const void *buf, size_t count) {
-	int r;
-	asm ("move.d %0, $r10\n"
-	     "move.d %1, $r11\n"
-	     "move.d %2, $r12\n"
-	     "moveq 4, $r9\n" /* NR_write.  */
-	     "break 13\n" : : "r" (fd), "r" (buf), "r" (count) : "memory");
-	asm ("move.d $r10, %0\n" : "=r" (r));
+	register unsigned int callno asm ("r9") = 4; /* NR_write */
+	register unsigned int r10 asm ("r10") = fd;
+	register const void *r11 asm ("r11") = buf;
+	register size_t r12 asm ("r12") = count;
+	register unsigned int r asm ("r10");
+
+	asm volatile ("break 13\n"
+	     : "=r" (r)
+	     : "r" (callno), "0" (r10), "r" (r11), "r" (r12)
+	     : "memory");
+
 	return r;
 }
diff --git a/tests/tcg/cris/sys.h b/tests/tcg/cris/sys.h
index c5f88e1a29..3dd47bb673 100644
--- a/tests/tcg/cris/sys.h
+++ b/tests/tcg/cris/sys.h
@@ -3,6 +3,8 @@
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
 
+#define always_inline inline __attribute__((always_inline))
+
 #define CURRENT_LOCATION __FILE__ ":" TOSTRING(__LINE__)
 
 #define err()                         \
diff --git a/tests/tco-test.c b/tests/tco-test.c
index 0d13aa8d63..0d201b1fcb 100644
--- a/tests/tco-test.c
+++ b/tests/tco-test.c
@@ -57,7 +57,7 @@ static void test_init(TestData *d)
     qtest_irq_intercept_in(qs, "ioapic");
     g_free(s);
 
-    bus = qpci_init_pc();
+    bus = qpci_init_pc(NULL);
     d->dev = qpci_device_find(bus, QPCI_DEVFN(0x1f, 0x00));
     g_assert(d->dev != NULL);
 
diff --git a/tests/test-bufferiszero.c b/tests/test-bufferiszero.c
new file mode 100644
index 0000000000..42d194cadf
--- /dev/null
+++ b/tests/test-bufferiszero.c
@@ -0,0 +1,78 @@
+/*
+ * QEMU buffer_is_zero test
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+
+static char buffer[8 * 1024 * 1024];
+
+static void test_1(void)
+{
+    size_t s, a, o;
+
+    /* Basic positive test.  */
+    g_assert(buffer_is_zero(buffer, sizeof(buffer)));
+
+    /* Basic negative test.  */
+    buffer[sizeof(buffer) - 1] = 1;
+    g_assert(!buffer_is_zero(buffer, sizeof(buffer)));
+    buffer[sizeof(buffer) - 1] = 0;
+
+    /* Positive tests for size and alignment.  */
+    for (a = 1; a <= 64; a++) {
+        for (s = 1; s < 1024; s++) {
+            buffer[a - 1] = 1;
+            buffer[a + s] = 1;
+            g_assert(buffer_is_zero(buffer + a, s));
+            buffer[a - 1] = 0;
+            buffer[a + s] = 0;
+        }
+    }
+
+    /* Negative tests for size, alignment, and the offset of the marker.  */
+    for (a = 1; a <= 64; a++) {
+        for (s = 1; s < 1024; s++) {
+            for (o = 0; o < s; ++o) {
+                buffer[a + o] = 1;
+                g_assert(!buffer_is_zero(buffer + a, s));
+                buffer[a + o] = 0;
+            }
+        }
+    }
+}
+
+static void test_2(void)
+{
+    if (g_test_perf()) {
+        test_1();
+    } else {
+        do {
+            test_1();
+        } while (test_buffer_is_zero_next_accel());
+    }
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/cutils/bufferiszero", test_2);
+
+    return g_test_run();
+}
diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c
index ee5e06d327..abd97c23c1 100644
--- a/tests/test-coroutine.c
+++ b/tests/test-coroutine.c
@@ -53,6 +53,47 @@ static void test_self(void)
 }
 
 /*
+ * Check that qemu_coroutine_entered() works
+ */
+
+static void coroutine_fn verify_entered_step_2(void *opaque)
+{
+    Coroutine *caller = (Coroutine *)opaque;
+
+    g_assert(qemu_coroutine_entered(caller));
+    g_assert(qemu_coroutine_entered(qemu_coroutine_self()));
+    qemu_coroutine_yield();
+
+    /* Once more to check it still works after yielding */
+    g_assert(qemu_coroutine_entered(caller));
+    g_assert(qemu_coroutine_entered(qemu_coroutine_self()));
+    qemu_coroutine_yield();
+}
+
+static void coroutine_fn verify_entered_step_1(void *opaque)
+{
+    Coroutine *self = qemu_coroutine_self();
+    Coroutine *coroutine;
+
+    g_assert(qemu_coroutine_entered(self));
+
+    coroutine = qemu_coroutine_create(verify_entered_step_2, self);
+    g_assert(!qemu_coroutine_entered(coroutine));
+    qemu_coroutine_enter(coroutine);
+    g_assert(!qemu_coroutine_entered(coroutine));
+    qemu_coroutine_enter(coroutine);
+}
+
+static void test_entered(void)
+{
+    Coroutine *coroutine;
+
+    coroutine = qemu_coroutine_create(verify_entered_step_1, NULL);
+    g_assert(!qemu_coroutine_entered(coroutine));
+    qemu_coroutine_enter(coroutine);
+}
+
+/*
  * Check that coroutines may nest multiple levels
  */
 
@@ -139,13 +180,20 @@ static void test_co_queue(void)
 {
     Coroutine *c1;
     Coroutine *c2;
+    Coroutine tmp;
 
     c2 = qemu_coroutine_create(c2_fn, NULL);
     c1 = qemu_coroutine_create(c1_fn, c2);
 
     qemu_coroutine_enter(c1);
+
+    /* c1 shouldn't be used any more now; make sure we segfault if it is */
+    tmp = *c1;
     memset(c1, 0xff, sizeof(Coroutine));
     qemu_coroutine_enter(c2);
+
+    /* Must restore the coroutine now to avoid corrupted pool */
+    *c1 = tmp;
 }
 
 /*
@@ -382,6 +430,7 @@ int main(int argc, char **argv)
     g_test_add_func("/basic/yield", test_yield);
     g_test_add_func("/basic/nesting", test_nesting);
     g_test_add_func("/basic/self", test_self);
+    g_test_add_func("/basic/entered", test_entered);
     g_test_add_func("/basic/in_coroutine", test_in_coroutine);
     g_test_add_func("/basic/order", test_order);
     if (g_test_perf()) {
diff --git a/tests/test-crypto-block.c b/tests/test-crypto-block.c
index a38110d3ff..1957a86743 100644
--- a/tests/test-crypto-block.c
+++ b/tests/test-crypto-block.c
@@ -28,7 +28,7 @@
 #include <sys/resource.h>
 #endif
 
-#if defined(CONFIG_UUID) && (defined(_WIN32) || defined RUSAGE_THREAD)
+#if (defined(_WIN32) || defined RUSAGE_THREAD)
 #define TEST_LUKS
 #else
 #undef TEST_LUKS
diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c
index 1b5130d5f6..b89dfa2b65 100644
--- a/tests/test-crypto-cipher.c
+++ b/tests/test-crypto-cipher.c
@@ -370,6 +370,17 @@ static QCryptoCipherTestData test_data[] = {
             "eb4a427d1923ce3ff262735779a418f2"
             "0a282df920147beabe421ee5319d0568",
     },
+    {
+        /* Bad config - cast5-128 has 8 byte block size
+         * which is incompatible with XTS
+         */
+        .path = "/crypto/cipher/cast5-xts-128",
+        .alg = QCRYPTO_CIPHER_ALG_CAST5_128,
+        .mode = QCRYPTO_CIPHER_MODE_XTS,
+        .key =
+            "27182818284590452353602874713526"
+            "31415926535897932384626433832795",
+    }
 };
 
 
@@ -432,15 +443,23 @@ static void test_cipher(const void *opaque)
     const QCryptoCipherTestData *data = opaque;
 
     QCryptoCipher *cipher;
-    uint8_t *key, *iv, *ciphertext, *plaintext, *outtext;
-    size_t nkey, niv, nciphertext, nplaintext;
-    char *outtexthex;
+    uint8_t *key, *iv = NULL, *ciphertext = NULL,
+        *plaintext = NULL, *outtext = NULL;
+    size_t nkey, niv = 0, nciphertext = 0, nplaintext = 0;
+    char *outtexthex = NULL;
     size_t ivsize, keysize, blocksize;
+    Error *err = NULL;
 
     nkey = unhex_string(data->key, &key);
-    niv = unhex_string(data->iv, &iv);
-    nciphertext = unhex_string(data->ciphertext, &ciphertext);
-    nplaintext = unhex_string(data->plaintext, &plaintext);
+    if (data->iv) {
+        niv = unhex_string(data->iv, &iv);
+    }
+    if (data->ciphertext) {
+        nciphertext = unhex_string(data->ciphertext, &ciphertext);
+    }
+    if (data->plaintext) {
+        nplaintext = unhex_string(data->plaintext, &plaintext);
+    }
 
     g_assert(nciphertext == nplaintext);
 
@@ -449,8 +468,15 @@ static void test_cipher(const void *opaque)
     cipher = qcrypto_cipher_new(
         data->alg, data->mode,
         key, nkey,
-        &error_abort);
-    g_assert(cipher != NULL);
+        &err);
+    if (data->plaintext) {
+        g_assert(err == NULL);
+        g_assert(cipher != NULL);
+    } else {
+        error_free_or_abort(&err);
+        g_assert(cipher == NULL);
+        goto cleanup;
+    }
 
     keysize = qcrypto_cipher_get_key_len(data->alg);
     blocksize = qcrypto_cipher_get_block_len(data->alg);
@@ -498,6 +524,7 @@ static void test_cipher(const void *opaque)
 
     g_assert_cmpstr(outtexthex, ==, data->plaintext);
 
+ cleanup:
     g_free(outtext);
     g_free(outtexthex);
     g_free(key);
diff --git a/tests/test-crypto-pbkdf.c b/tests/test-crypto-pbkdf.c
index 8ceceb1827..d937aff6b2 100644
--- a/tests/test-crypto-pbkdf.c
+++ b/tests/test-crypto-pbkdf.c
@@ -261,7 +261,6 @@ static QCryptoPbkdfTestData test_data[] = {
                "\xcc\x4a\x5e\x6d\xca\x04\xec\x58",
         .nout = 32
     },
-#if 0
     {
         .path = "/crypto/pbkdf/nonrfc/sha512/iter1200",
         .hash = QCRYPTO_HASH_ALG_SHA512,
@@ -280,6 +279,58 @@ static QCryptoPbkdfTestData test_data[] = {
         .nout = 32
     },
     {
+        .path = "/crypto/pbkdf/nonrfc/sha224/iter1200",
+        .hash = QCRYPTO_HASH_ALG_SHA224,
+        .iterations = 1200,
+        .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        .nkey = 129,
+        .salt = "pass phrase exceeds block size",
+        .nsalt = 30,
+        .out = "\x13\x3b\x88\x0c\x0e\x52\xa2\x41"
+               "\x49\x33\x35\xa6\xc3\x83\xae\x23"
+               "\xf6\x77\x43\x9e\x5b\x30\x92\x3e"
+               "\x4a\x3a\xaa\x24\x69\x3c\xed\x20",
+        .nout = 32
+    },
+    {
+        .path = "/crypto/pbkdf/nonrfc/sha384/iter1200",
+        .hash = QCRYPTO_HASH_ALG_SHA384,
+        .iterations = 1200,
+        .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        .nkey = 129,
+        .salt = "pass phrase exceeds block size",
+        .nsalt = 30,
+        .out = "\xfe\xe3\xe1\x84\xc9\x25\x3e\x10"
+               "\x47\xc8\x7d\x53\xc6\xa5\xe3\x77"
+               "\x29\x41\x76\xbd\x4b\xe3\x9b\xac"
+               "\x05\x6c\x11\xdd\x17\xc5\x93\x80",
+        .nout = 32
+    },
+    {
+        .path = "/crypto/pbkdf/nonrfc/ripemd160/iter1200",
+        .hash = QCRYPTO_HASH_ALG_RIPEMD160,
+        .iterations = 1200,
+        .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        .nkey = 129,
+        .salt = "pass phrase exceeds block size",
+        .nsalt = 30,
+        .out = "\xd6\xcb\xd8\xa7\xdb\x0c\xa2\x2a"
+               "\x23\x5e\x47\xaf\xdb\xda\xa8\xef"
+               "\xe4\x01\x0d\x6f\xb5\x33\xc8\xbd"
+               "\xce\xbf\x91\x14\x8b\x5c\x48\x41",
+        .nout = 32
+    },
+#if 0
+    {
         .path = "/crypto/pbkdf/nonrfc/whirlpool/iter1200",
         .hash = QCRYPTO_HASH_ALG_WHIRLPOOL,
         .iterations = 1200,
@@ -358,6 +409,7 @@ static void test_pbkdf_timing(void)
     iters = qcrypto_pbkdf2_count_iters(QCRYPTO_HASH_ALG_SHA256,
                                        key, sizeof(key),
                                        salt, sizeof(salt),
+                                       32,
                                        &error_abort);
 
     g_assert(iters >= (1 << 15));
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 64e3e95ce2..20b0f59ba2 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -378,7 +378,7 @@ static void test_qemu_strtol_hex(void)
 
 static void test_qemu_strtol_max(void)
 {
-    const char *str = g_strdup_printf("%ld", LONG_MAX);
+    char *str = g_strdup_printf("%ld", LONG_MAX);
     char f = 'X';
     const char *endptr = &f;
     long res = 999;
@@ -389,6 +389,7 @@ static void test_qemu_strtol_max(void)
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, LONG_MAX);
     g_assert(endptr == str + strlen(str));
+    g_free(str);
 }
 
 static void test_qemu_strtol_overflow(void)
@@ -497,7 +498,7 @@ static void test_qemu_strtol_full_trailing(void)
 
 static void test_qemu_strtol_full_max(void)
 {
-    const char *str = g_strdup_printf("%ld", LONG_MAX);
+    char *str = g_strdup_printf("%ld", LONG_MAX);
     long res;
     int err;
 
@@ -505,6 +506,7 @@ static void test_qemu_strtol_full_max(void)
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, LONG_MAX);
+    g_free(str);
 }
 
 static void test_qemu_strtoul_correct(void)
@@ -662,7 +664,7 @@ static void test_qemu_strtoul_hex(void)
 
 static void test_qemu_strtoul_max(void)
 {
-    const char *str = g_strdup_printf("%lu", ULONG_MAX);
+    char *str = g_strdup_printf("%lu", ULONG_MAX);
     char f = 'X';
     const char *endptr = &f;
     unsigned long res = 999;
@@ -673,6 +675,7 @@ static void test_qemu_strtoul_max(void)
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, ULONG_MAX);
     g_assert(endptr == str + strlen(str));
+    g_free(str);
 }
 
 static void test_qemu_strtoul_overflow(void)
@@ -776,7 +779,7 @@ static void test_qemu_strtoul_full_trailing(void)
 
 static void test_qemu_strtoul_full_max(void)
 {
-    const char *str = g_strdup_printf("%lu", ULONG_MAX);
+    char *str = g_strdup_printf("%lu", ULONG_MAX);
     unsigned long res = 999;
     int err;
 
@@ -784,6 +787,7 @@ static void test_qemu_strtoul_full_max(void)
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, ULONG_MAX);
+    g_free(str);
 }
 
 static void test_qemu_strtoll_correct(void)
@@ -941,7 +945,7 @@ static void test_qemu_strtoll_hex(void)
 
 static void test_qemu_strtoll_max(void)
 {
-    const char *str = g_strdup_printf("%lld", LLONG_MAX);
+    char *str = g_strdup_printf("%lld", LLONG_MAX);
     char f = 'X';
     const char *endptr = &f;
     int64_t res = 999;
@@ -952,6 +956,7 @@ static void test_qemu_strtoll_max(void)
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, LLONG_MAX);
     g_assert(endptr == str + strlen(str));
+    g_free(str);
 }
 
 static void test_qemu_strtoll_overflow(void)
@@ -1058,7 +1063,7 @@ static void test_qemu_strtoll_full_trailing(void)
 static void test_qemu_strtoll_full_max(void)
 {
 
-    const char *str = g_strdup_printf("%lld", LLONG_MAX);
+    char *str = g_strdup_printf("%lld", LLONG_MAX);
     int64_t res;
     int err;
 
@@ -1066,6 +1071,7 @@ static void test_qemu_strtoll_full_max(void)
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, LLONG_MAX);
+    g_free(str);
 }
 
 static void test_qemu_strtoull_correct(void)
@@ -1223,7 +1229,7 @@ static void test_qemu_strtoull_hex(void)
 
 static void test_qemu_strtoull_max(void)
 {
-    const char *str = g_strdup_printf("%llu", ULLONG_MAX);
+    char *str = g_strdup_printf("%llu", ULLONG_MAX);
     char f = 'X';
     const char *endptr = &f;
     uint64_t res = 999;
@@ -1234,6 +1240,7 @@ static void test_qemu_strtoull_max(void)
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, ULLONG_MAX);
     g_assert(endptr == str + strlen(str));
+    g_free(str);
 }
 
 static void test_qemu_strtoull_overflow(void)
@@ -1339,7 +1346,7 @@ static void test_qemu_strtoull_full_trailing(void)
 
 static void test_qemu_strtoull_full_max(void)
 {
-    const char *str = g_strdup_printf("%lld", ULLONG_MAX);
+    char *str = g_strdup_printf("%lld", ULLONG_MAX);
     uint64_t res = 999;
     int err;
 
@@ -1347,6 +1354,7 @@ static void test_qemu_strtoull_full_max(void)
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, ULLONG_MAX);
+    g_free(str);
 }
 
 static void test_qemu_strtosz_simple(void)
diff --git a/tests/test-iov.c b/tests/test-iov.c
index 46ae25efd6..a22d71fd2c 100644
--- a/tests/test-iov.c
+++ b/tests/test-iov.c
@@ -208,6 +208,9 @@ static void test_io(void)
                } while(k < j);
            }
        }
+       iov_free(iov, niov);
+       g_free(buf);
+       g_free(siov);
        exit(0);
 
     } else {
@@ -246,6 +249,10 @@ static void test_io(void)
                test_iov_bytes(iov, niov, i, j - i);
            }
         }
+
+       iov_free(iov, niov);
+       g_free(buf);
+       g_free(siov);
      }
 #endif
 }
diff --git a/tests/test-qga.c b/tests/test-qga.c
index dac8fb8c0a..40af64987a 100644
--- a/tests/test-qga.c
+++ b/tests/test-qga.c
@@ -198,6 +198,26 @@ static void test_qga_ping(gconstpointer fix)
     QDECREF(ret);
 }
 
+static void test_qga_invalid_args(gconstpointer fix)
+{
+    const TestFixture *fixture = fix;
+    QDict *ret, *error;
+    const gchar *class, *desc;
+
+    ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping', "
+                 "'arguments': {'foo': 42 }}");
+    g_assert_nonnull(ret);
+
+    error = qdict_get_qdict(ret, "error");
+    class = qdict_get_try_str(error, "class");
+    desc = qdict_get_try_str(error, "desc");
+
+    g_assert_cmpstr(class, ==, "GenericError");
+    g_assert_cmpstr(desc, ==, "QMP input object member 'foo' is unexpected");
+
+    QDECREF(ret);
+}
+
 static void test_qga_invalid_cmd(gconstpointer fix)
 {
     const TestFixture *fixture = fix;
@@ -398,6 +418,7 @@ static void test_qga_file_ops(gconstpointer fix)
     /* check content */
     path = g_build_filename(fixture->test_dir, "foo", NULL);
     f = fopen(path, "r");
+    g_free(path);
     g_assert_nonnull(f);
     count = fread(tmp, 1, sizeof(tmp), f);
     g_assert_cmpint(count, ==, sizeof(helloworld));
@@ -700,7 +721,9 @@ static void test_qga_config(gconstpointer data)
     cwd = g_get_current_dir();
     cmd = g_strdup_printf("%s%cqemu-ga -D",
                           cwd, G_DIR_SEPARATOR);
+    g_free(cwd);
     g_shell_parse_argv(cmd, NULL, &argv, &error);
+    g_free(cmd);
     g_assert_no_error(error);
 
     env[0] = g_strdup_printf("QGA_CONF=tests%cdata%ctest-qga-config",
@@ -708,6 +731,8 @@ static void test_qga_config(gconstpointer data)
     env[1] = NULL;
     g_spawn_sync(NULL, argv, env, 0,
                  NULL, NULL, &out, &err, &status, &error);
+    g_strfreev(argv);
+
     g_assert_no_error(error);
     g_assert_cmpstr(err, ==, "");
     g_assert_cmpint(status, ==, 0);
@@ -906,6 +931,7 @@ int main(int argc, char **argv)
     g_test_add_data_func("/qga/file-write-read", &fix, test_qga_file_write_read);
     g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time);
     g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd);
+    g_test_add_data_func("/qga/invalid-args", &fix, test_qga_invalid_args);
     g_test_add_data_func("/qga/fsfreeze-status", &fix,
                          test_qga_fsfreeze_status);
 
diff --git a/tests/test-qht.c b/tests/test-qht.c
index 46a64b6731..9b7423abb6 100644
--- a/tests/test-qht.c
+++ b/tests/test-qht.c
@@ -6,6 +6,7 @@
  */
 #include "qemu/osdep.h"
 #include "qemu/qht.h"
+#include "qemu/rcu.h"
 
 #define N 5000
 
@@ -51,6 +52,7 @@ static void check(int a, int b, bool expected)
     struct qht_stats stats;
     int i;
 
+    rcu_read_lock();
     for (i = a; i < b; i++) {
         void *p;
         uint32_t hash;
@@ -61,6 +63,8 @@ static void check(int a, int b, bool expected)
         p = qht_lookup(&ht, is_equal, &val, hash);
         g_assert_true(!!p == expected);
     }
+    rcu_read_unlock();
+
     qht_statistics_init(&ht, &stats);
     if (stats.used_head_buckets) {
         g_assert_cmpfloat(qdist_avg(&stats.chain), >=, 1.0);
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 261fd9e313..81cbe545c4 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -106,6 +106,7 @@ static void test_dispatch_cmd(void)
 static void test_dispatch_cmd_failure(void)
 {
     QDict *req = qdict_new();
+    QDict *args = qdict_new();
     QObject *resp;
 
     qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
@@ -116,6 +117,20 @@ static void test_dispatch_cmd_failure(void)
 
     qobject_decref(resp);
     QDECREF(req);
+
+    /* check that with extra arguments it throws an error */
+    req = qdict_new();
+    qdict_put(args, "a", qint_from_int(66));
+    qdict_put(req, "arguments", args);
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
+
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(qdict_haskey(qobject_to_qdict(resp), "error"));
+
+    qobject_decref(resp);
+    QDECREF(req);
 }
 
 static QObject *test_qmp_dispatch(QDict *req)
diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
index 814550ac71..d87f8b89a7 100644
--- a/tests/test-qmp-input-strict.c
+++ b/tests/test-qmp-input-strict.c
@@ -193,6 +193,50 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data,
     g_assert(!udp);
 }
 
+static void test_validate_fail_struct_missing(TestInputVisitorData *data,
+                                              const void *unused)
+{
+    Error *err = NULL;
+    Visitor *v;
+    QObject *any;
+    GenericAlternate *alt;
+    bool present;
+    int en;
+    int64_t i64;
+    uint32_t u32;
+    int8_t i8;
+    char *str;
+    double dbl;
+
+    v = validate_test_init(data, "{}");
+    visit_start_struct(v, NULL, NULL, 0, &error_abort);
+    visit_start_struct(v, "struct", NULL, 0, &err);
+    error_free_or_abort(&err);
+    visit_start_list(v, "list", NULL, 0, &err);
+    error_free_or_abort(&err);
+    visit_start_alternate(v, "alternate", &alt, sizeof(*alt), false, &err);
+    error_free_or_abort(&err);
+    visit_optional(v, "optional", &present);
+    g_assert(!present);
+    visit_type_enum(v, "enum", &en, EnumOne_lookup, &err);
+    error_free_or_abort(&err);
+    visit_type_int(v, "i64", &i64, &err);
+    error_free_or_abort(&err);
+    visit_type_uint32(v, "u32", &u32, &err);
+    error_free_or_abort(&err);
+    visit_type_int8(v, "i8", &i8, &err);
+    error_free_or_abort(&err);
+    visit_type_str(v, "i8", &str, &err);
+    error_free_or_abort(&err);
+    visit_type_number(v, "dbl", &dbl, &err);
+    error_free_or_abort(&err);
+    visit_type_any(v, "any", &any, &err);
+    error_free_or_abort(&err);
+    visit_type_null(v, "null", &err);
+    error_free_or_abort(&err);
+    visit_end_struct(v, NULL);
+}
+
 static void test_validate_fail_list(TestInputVisitorData *data,
                                      const void *unused)
 {
@@ -316,6 +360,8 @@ int main(int argc, char **argv)
                       &testdata, test_validate_fail_struct);
     validate_test_add("/visitor/input-strict/fail/struct-nested",
                       &testdata, test_validate_fail_struct_nested);
+    validate_test_add("/visitor/input-strict/fail/struct-missing",
+                      &testdata, test_validate_fail_struct_missing);
     validate_test_add("/visitor/input-strict/fail/list",
                       &testdata, test_validate_fail_list);
     validate_test_add("/visitor/input-strict/fail/union-flat",
diff --git a/tests/test-replication.c b/tests/test-replication.c
new file mode 100644
index 0000000000..0997bd8b74
--- /dev/null
+++ b/tests/test-replication.c
@@ -0,0 +1,575 @@
+/*
+ * Block replication tests
+ *
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Author: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/error.h"
+#include "replication.h"
+#include "block/block_int.h"
+#include "sysemu/block-backend.h"
+
+#define IMG_SIZE (64 * 1024 * 1024)
+
+/* primary */
+#define P_ID "primary-id"
+static char p_local_disk[] = "/tmp/p_local_disk.XXXXXX";
+
+/* secondary */
+#define S_ID "secondary-id"
+#define S_LOCAL_DISK_ID "secondary-local-disk-id"
+static char s_local_disk[] = "/tmp/s_local_disk.XXXXXX";
+static char s_active_disk[] = "/tmp/s_active_disk.XXXXXX";
+static char s_hidden_disk[] = "/tmp/s_hidden_disk.XXXXXX";
+
+/* FIXME: steal from blockdev.c */
+QemuOptsList qemu_drive_opts = {
+    .name = "drive",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
+    .desc = {
+        { /* end of list */ }
+    },
+};
+
+#define NOT_DONE 0x7fffffff
+
+static void blk_rw_done(void *opaque, int ret)
+{
+    *(int *)opaque = ret;
+}
+
+static void test_blk_read(BlockBackend *blk, long pattern,
+                          int64_t pattern_offset, int64_t pattern_count,
+                          int64_t offset, int64_t count,
+                          bool expect_failed)
+{
+    void *pattern_buf = NULL;
+    QEMUIOVector qiov;
+    void *cmp_buf = NULL;
+    int async_ret = NOT_DONE;
+
+    if (pattern) {
+        cmp_buf = g_malloc(pattern_count);
+        memset(cmp_buf, pattern, pattern_count);
+    }
+
+    pattern_buf = g_malloc(count);
+    if (pattern) {
+        memset(pattern_buf, pattern, count);
+    } else {
+        memset(pattern_buf, 0x00, count);
+    }
+
+    qemu_iovec_init(&qiov, 1);
+    qemu_iovec_add(&qiov, pattern_buf, count);
+
+    blk_aio_preadv(blk, offset, &qiov, 0, blk_rw_done, &async_ret);
+    while (async_ret == NOT_DONE) {
+        main_loop_wait(false);
+    }
+
+    if (expect_failed) {
+        g_assert(async_ret != 0);
+    } else {
+        g_assert(async_ret == 0);
+        if (pattern) {
+            g_assert(memcmp(pattern_buf + pattern_offset,
+                            cmp_buf, pattern_count) <= 0);
+        }
+    }
+
+    g_free(pattern_buf);
+}
+
+static void test_blk_write(BlockBackend *blk, long pattern, int64_t offset,
+                           int64_t count, bool expect_failed)
+{
+    void *pattern_buf = NULL;
+    QEMUIOVector qiov;
+    int async_ret = NOT_DONE;
+
+    pattern_buf = g_malloc(count);
+    if (pattern) {
+        memset(pattern_buf, pattern, count);
+    } else {
+        memset(pattern_buf, 0x00, count);
+    }
+
+    qemu_iovec_init(&qiov, 1);
+    qemu_iovec_add(&qiov, pattern_buf, count);
+
+    blk_aio_pwritev(blk, offset, &qiov, 0, blk_rw_done, &async_ret);
+    while (async_ret == NOT_DONE) {
+        main_loop_wait(false);
+    }
+
+    if (expect_failed) {
+        g_assert(async_ret != 0);
+    } else {
+        g_assert(async_ret == 0);
+    }
+
+    g_free(pattern_buf);
+}
+
+/*
+ * Create a uniquely-named empty temporary file.
+ */
+static void make_temp(char *template)
+{
+    int fd;
+
+    fd = mkstemp(template);
+    g_assert(fd >= 0);
+    close(fd);
+}
+
+static void prepare_imgs(void)
+{
+    Error *local_err = NULL;
+
+    make_temp(p_local_disk);
+    make_temp(s_local_disk);
+    make_temp(s_active_disk);
+    make_temp(s_hidden_disk);
+
+    /* Primary */
+    bdrv_img_create(p_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE,
+                    BDRV_O_RDWR, &local_err, true);
+    g_assert(!local_err);
+
+    /* Secondary */
+    bdrv_img_create(s_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE,
+                    BDRV_O_RDWR, &local_err, true);
+    g_assert(!local_err);
+    bdrv_img_create(s_active_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE,
+                    BDRV_O_RDWR, &local_err, true);
+    g_assert(!local_err);
+    bdrv_img_create(s_hidden_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE,
+                    BDRV_O_RDWR, &local_err, true);
+    g_assert(!local_err);
+}
+
+static void cleanup_imgs(void)
+{
+    /* Primary */
+    unlink(p_local_disk);
+
+    /* Secondary */
+    unlink(s_local_disk);
+    unlink(s_active_disk);
+    unlink(s_hidden_disk);
+}
+
+static BlockBackend *start_primary(void)
+{
+    BlockBackend *blk;
+    QemuOpts *opts;
+    QDict *qdict;
+    Error *local_err = NULL;
+    char *cmdline;
+
+    cmdline = g_strdup_printf("driver=replication,mode=primary,node-name=xxx,"
+                              "file.driver=qcow2,file.file.filename=%s"
+                              , p_local_disk);
+    opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false);
+    g_free(cmdline);
+
+    qdict = qemu_opts_to_qdict(opts, NULL);
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
+
+    blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err);
+    g_assert(blk);
+    g_assert(!local_err);
+
+    monitor_add_blk(blk, P_ID, &local_err);
+    g_assert(!local_err);
+
+    qemu_opts_del(opts);
+
+    return blk;
+}
+
+static void teardown_primary(void)
+{
+    BlockBackend *blk;
+
+    /* remove P_ID */
+    blk = blk_by_name(P_ID);
+    assert(blk);
+
+    monitor_remove_blk(blk);
+    blk_unref(blk);
+}
+
+static void test_primary_read(void)
+{
+    BlockBackend *blk;
+
+    blk = start_primary();
+
+    /* read from 0 to IMG_SIZE */
+    test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true);
+
+    teardown_primary();
+}
+
+static void test_primary_write(void)
+{
+    BlockBackend *blk;
+
+    blk = start_primary();
+
+    /* write from 0 to IMG_SIZE */
+    test_blk_write(blk, 0, 0, IMG_SIZE, true);
+
+    teardown_primary();
+}
+
+static void test_primary_start(void)
+{
+    BlockBackend *blk = NULL;
+    Error *local_err = NULL;
+
+    blk = start_primary();
+
+    replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
+    g_assert(!local_err);
+
+    /* read from 0 to IMG_SIZE */
+    test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true);
+
+    /* write 0x22 from 0 to IMG_SIZE */
+    test_blk_write(blk, 0x22, 0, IMG_SIZE, false);
+
+    teardown_primary();
+}
+
+static void test_primary_stop(void)
+{
+    Error *local_err = NULL;
+    bool failover = true;
+
+    start_primary();
+
+    replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
+    g_assert(!local_err);
+
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    teardown_primary();
+}
+
+static void test_primary_do_checkpoint(void)
+{
+    Error *local_err = NULL;
+
+    start_primary();
+
+    replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
+    g_assert(!local_err);
+
+    replication_do_checkpoint_all(&local_err);
+    g_assert(!local_err);
+
+    teardown_primary();
+}
+
+static void test_primary_get_error_all(void)
+{
+    Error *local_err = NULL;
+
+    start_primary();
+
+    replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
+    g_assert(!local_err);
+
+    replication_get_error_all(&local_err);
+    g_assert(!local_err);
+
+    teardown_primary();
+}
+
+static BlockBackend *start_secondary(void)
+{
+    QemuOpts *opts;
+    QDict *qdict;
+    BlockBackend *blk;
+    char *cmdline;
+    Error *local_err = NULL;
+
+    /* add s_local_disk and forge S_LOCAL_DISK_ID */
+    cmdline = g_strdup_printf("file.filename=%s,driver=qcow2", s_local_disk);
+    opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false);
+    g_free(cmdline);
+
+    qdict = qemu_opts_to_qdict(opts, NULL);
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
+
+    blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err);
+    assert(blk);
+    monitor_add_blk(blk, S_LOCAL_DISK_ID, &local_err);
+    g_assert(!local_err);
+
+    /* format s_local_disk with pattern "0x11" */
+    test_blk_write(blk, 0x11, 0, IMG_SIZE, false);
+
+    qemu_opts_del(opts);
+
+    /* add S_(ACTIVE/HIDDEN)_DISK and forge S_ID */
+    cmdline = g_strdup_printf("driver=replication,mode=secondary,top-id=%s,"
+                              "file.driver=qcow2,file.file.filename=%s,"
+                              "file.backing.driver=qcow2,"
+                              "file.backing.file.filename=%s,"
+                              "file.backing.backing=%s"
+                              , S_ID, s_active_disk, s_hidden_disk
+                              , S_LOCAL_DISK_ID);
+    opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false);
+    g_free(cmdline);
+
+    qdict = qemu_opts_to_qdict(opts, NULL);
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
+
+    blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err);
+    assert(blk);
+    monitor_add_blk(blk, S_ID, &local_err);
+    g_assert(!local_err);
+
+    qemu_opts_del(opts);
+
+    return blk;
+}
+
+static void teardown_secondary(void)
+{
+    /* only need to destroy two BBs */
+    BlockBackend *blk;
+
+    /* remove S_LOCAL_DISK_ID */
+    blk = blk_by_name(S_LOCAL_DISK_ID);
+    assert(blk);
+
+    monitor_remove_blk(blk);
+    blk_unref(blk);
+
+    /* remove S_ID */
+    blk = blk_by_name(S_ID);
+    assert(blk);
+
+    monitor_remove_blk(blk);
+    blk_unref(blk);
+}
+
+static void test_secondary_read(void)
+{
+    BlockBackend *blk;
+
+    blk = start_secondary();
+
+    /* read from 0 to IMG_SIZE */
+    test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true);
+
+    teardown_secondary();
+}
+
+static void test_secondary_write(void)
+{
+    BlockBackend *blk;
+
+    blk = start_secondary();
+
+    /* write from 0 to IMG_SIZE */
+    test_blk_write(blk, 0, 0, IMG_SIZE, true);
+
+    teardown_secondary();
+}
+
+static void test_secondary_start(void)
+{
+    BlockBackend *top_blk, *local_blk;
+    Error *local_err = NULL;
+    bool failover = true;
+
+    top_blk = start_secondary();
+    replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
+    g_assert(!local_err);
+
+    /* read from s_local_disk (0, IMG_SIZE) */
+    test_blk_read(top_blk, 0x11, 0, IMG_SIZE, 0, IMG_SIZE, false);
+
+    /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
+    local_blk = blk_by_name(S_LOCAL_DISK_ID);
+    test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false);
+
+    /* replication will backup s_local_disk to s_hidden_disk */
+    test_blk_read(top_blk, 0x11, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */
+    test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false);
+
+    /* read from s_active_disk (0, IMG_SIZE/2) */
+    test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2,
+                  0, IMG_SIZE / 2, false);
+
+    /* unblock top_bs */
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    teardown_secondary();
+}
+
+
+static void test_secondary_stop(void)
+{
+    BlockBackend *top_blk, *local_blk;
+    Error *local_err = NULL;
+    bool failover = true;
+
+    top_blk = start_secondary();
+    replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
+    g_assert(!local_err);
+
+    /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
+    local_blk = blk_by_name(S_LOCAL_DISK_ID);
+    test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false);
+
+    /* replication will backup s_local_disk to s_hidden_disk */
+    test_blk_read(top_blk, 0x11, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */
+    test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false);
+
+    /* do active commit */
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    /* read from s_local_disk (0, IMG_SIZE / 2) */
+    test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2,
+                  0, IMG_SIZE / 2, false);
+
+
+    /* read from s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
+    test_blk_read(top_blk, 0x22, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    teardown_secondary();
+}
+
+static void test_secondary_do_checkpoint(void)
+{
+    BlockBackend *top_blk, *local_blk;
+    Error *local_err = NULL;
+    bool failover = true;
+
+    top_blk = start_secondary();
+    replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
+    g_assert(!local_err);
+
+    /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
+    local_blk = blk_by_name(S_LOCAL_DISK_ID);
+    test_blk_write(local_blk, 0x22, IMG_SIZE / 2,
+                   IMG_SIZE / 2, false);
+
+    /* replication will backup s_local_disk to s_hidden_disk */
+    test_blk_read(top_blk, 0x11, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    replication_do_checkpoint_all(&local_err);
+    g_assert(!local_err);
+
+    /* after checkpoint, read pattern 0x22 from s_local_disk */
+    test_blk_read(top_blk, 0x22, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    /* unblock top_bs */
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    teardown_secondary();
+}
+
+static void test_secondary_get_error_all(void)
+{
+    Error *local_err = NULL;
+    bool failover = true;
+
+    start_secondary();
+    replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
+    g_assert(!local_err);
+
+    replication_get_error_all(&local_err);
+    g_assert(!local_err);
+
+    /* unblock top_bs */
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    teardown_secondary();
+}
+
+static void sigabrt_handler(int signo)
+{
+    cleanup_imgs();
+}
+
+static void setup_sigabrt_handler(void)
+{
+    struct sigaction sigact;
+
+    sigact = (struct sigaction) {
+        .sa_handler = sigabrt_handler,
+        .sa_flags = SA_RESETHAND,
+    };
+    sigemptyset(&sigact.sa_mask);
+    sigaction(SIGABRT, &sigact, NULL);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+    qemu_init_main_loop(&error_fatal);
+    bdrv_init();
+
+    g_test_init(&argc, &argv, NULL);
+    setup_sigabrt_handler();
+
+    prepare_imgs();
+
+    /* Primary */
+    g_test_add_func("/replication/primary/read",    test_primary_read);
+    g_test_add_func("/replication/primary/write",   test_primary_write);
+    g_test_add_func("/replication/primary/start",   test_primary_start);
+    g_test_add_func("/replication/primary/stop",    test_primary_stop);
+    g_test_add_func("/replication/primary/do_checkpoint",
+                    test_primary_do_checkpoint);
+    g_test_add_func("/replication/primary/get_error_all",
+                    test_primary_get_error_all);
+
+    /* Secondary */
+    g_test_add_func("/replication/secondary/read",  test_secondary_read);
+    g_test_add_func("/replication/secondary/write", test_secondary_write);
+    g_test_add_func("/replication/secondary/start", test_secondary_start);
+    g_test_add_func("/replication/secondary/stop",  test_secondary_stop);
+    g_test_add_func("/replication/secondary/do_checkpoint",
+                    test_secondary_do_checkpoint);
+    g_test_add_func("/replication/secondary/get_error_all",
+                    test_secondary_get_error_all);
+
+    ret = g_test_run();
+
+    cleanup_imgs();
+
+    return ret;
+}
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
index d837ebedad..a679fbc678 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -228,6 +228,7 @@ static void test_visitor_in_fuzz(TestInputVisitorData *data,
 
         v = visitor_input_test_init(data, buf);
         visit_type_intList(v, NULL, &ilres, NULL);
+        qapi_free_intList(ilres);
         visitor_input_teardown(data, NULL);
 
         v = visitor_input_test_init(data, buf);
diff --git a/tests/test-uuid.c b/tests/test-uuid.c
new file mode 100644
index 0000000000..77dcdc4b55
--- /dev/null
+++ b/tests/test-uuid.c
@@ -0,0 +1,177 @@
+/*
+ * QEMU UUID Library
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/uuid.h"
+
+struct {
+    const char *uuidstr;
+    QemuUUID uuid;
+    bool uuidstr_is_valid;
+    bool check_unparse;
+} uuid_test_data[] = {
+    {    /* Normal */
+        "586ece27-7f09-41e0-9e74-e901317e9d42",
+        { { {
+             0x58, 0x6e, 0xce, 0x27, 0x7f, 0x09, 0x41, 0xe0,
+             0x9e, 0x74, 0xe9, 0x01, 0x31, 0x7e, 0x9d, 0x42,
+        } } },
+        true, true,
+    }, { /* NULL */
+        "00000000-0000-0000-0000-000000000000",
+        { },
+        true, true,
+    }, { /* Upper case */
+        "0CC6C752-3961-4028-A286-C05CC616D396",
+        { { {
+             0x0c, 0xc6, 0xc7, 0x52, 0x39, 0x61, 0x40, 0x28,
+             0xa2, 0x86, 0xc0, 0x5c, 0xc6, 0x16, 0xd3, 0x96,
+        } } },
+        true, false,
+    }, { /* Mixed case */
+        "0CC6C752-3961-4028-a286-c05cc616D396",
+        { { {
+             0x0c, 0xc6, 0xc7, 0x52, 0x39, 0x61, 0x40, 0x28,
+             0xa2, 0x86, 0xc0, 0x5c, 0xc6, 0x16, 0xd3, 0x96,
+        } } },
+        true, false,
+    }, { /* Empty */
+        ""
+    }, { /* Too short */
+        "abc",
+    }, { /* Non-hex */
+        "abcdefgh-0000-0000-0000-000000000000",
+    }, { /* No '-' */
+        "0cc6c75239614028a286c05cc616d396",
+    }, { /* '-' in wrong position */
+        "0cc6c-7523961-4028-a286-c05cc616d396",
+    }, { /* Double '-' */
+        "0cc6c752--3961-4028-a286-c05cc616d396",
+    }, { /* Too long */
+        "0000000000000000000000000000000000000000000000",
+    }, { /* Invalid char in the beginning */
+        ")cc6c752-3961-4028-a286-c05cc616d396",
+    }, { /* Invalid char in the beginning, in extra */
+        ")0cc6c752-3961-4028-a286-c05cc616d396",
+    }, { /* Invalid char in the middle */
+        "0cc6c752-39*1-4028-a286-c05cc616d396",
+    }, { /* Invalid char in the middle, in extra */
+        "0cc6c752-39*61-4028-a286-c05cc616d396",
+    }, { /* Invalid char in the end */
+        "0cc6c752-3961-4028-a286-c05cc616d39&",
+    }, { /* Invalid char in the end, in extra */
+        "0cc6c752-3961-4028-a286-c05cc616d396&",
+    }, { /* Short end and trailing space */
+        "0cc6c752-3961-4028-a286-c05cc616d39 ",
+    }, { /* Leading space and short end */
+        " 0cc6c752-3961-4028-a286-c05cc616d39",
+    },
+};
+
+static inline bool uuid_is_valid(QemuUUID *uuid)
+{
+    return qemu_uuid_is_null(uuid) ||
+            ((uuid->data[6] & 0xf0) == 0x40 && (uuid->data[8] & 0xc0) == 0x80);
+}
+
+static void test_uuid_generate(void)
+{
+    QemuUUID uuid;
+    int i;
+
+    for (i = 0; i < 100; ++i) {
+        qemu_uuid_generate(&uuid);
+        g_assert(uuid_is_valid(&uuid));
+    }
+}
+
+static void test_uuid_is_null(void)
+{
+    QemuUUID uuid_null = { };
+    QemuUUID uuid_not_null = { { {
+        0x58, 0x6e, 0xce, 0x27, 0x7f, 0x09, 0x41, 0xe0,
+        0x9e, 0x74, 0xe9, 0x01, 0x31, 0x7e, 0x9d, 0x42
+    } } };
+    QemuUUID uuid_not_null_2 = { { { 1 } } };
+
+    g_assert(qemu_uuid_is_null(&uuid_null));
+    g_assert_false(qemu_uuid_is_null(&uuid_not_null));
+    g_assert_false(qemu_uuid_is_null(&uuid_not_null_2));
+}
+
+static void test_uuid_parse(void)
+{
+    int i, r;
+
+    for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
+        QemuUUID uuid;
+        bool is_valid = uuid_test_data[i].uuidstr_is_valid;
+
+        r = qemu_uuid_parse(uuid_test_data[i].uuidstr, &uuid);
+        g_assert_cmpint(!r, ==, is_valid);
+        if (is_valid) {
+            g_assert_cmpint(is_valid, ==, uuid_is_valid(&uuid));
+            g_assert_cmpmem(&uuid_test_data[i].uuid, sizeof(uuid),
+                            &uuid, sizeof(uuid));
+        }
+    }
+}
+
+static void test_uuid_unparse(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
+        char out[37];
+
+        if (!uuid_test_data[i].check_unparse) {
+            continue;
+        }
+        qemu_uuid_unparse(&uuid_test_data[i].uuid, out);
+        g_assert_cmpstr(uuid_test_data[i].uuidstr, ==, out);
+    }
+}
+
+static void test_uuid_unparse_strdup(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
+        char *out;
+
+        if (!uuid_test_data[i].check_unparse) {
+            continue;
+        }
+        out = qemu_uuid_unparse_strdup(&uuid_test_data[i].uuid);
+        g_assert_cmpstr(uuid_test_data[i].uuidstr, ==, out);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/uuid/generate", test_uuid_generate);
+    g_test_add_func("/uuid/is_null", test_uuid_is_null);
+    g_test_add_func("/uuid/parse", test_uuid_parse);
+    g_test_add_func("/uuid/unparse", test_uuid_unparse);
+    g_test_add_func("/uuid/unparse_strdup", test_uuid_unparse_strdup);
+
+    return g_test_run();
+}
diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c
index 41fd841aed..d8da26f974 100644
--- a/tests/test-vmstate.c
+++ b/tests/test-vmstate.c
@@ -50,16 +50,20 @@ static QEMUFile *open_test_file(bool write)
 {
     int fd = dup(temp_fd);
     QIOChannel *ioc;
+    QEMUFile *f;
+
     lseek(fd, 0, SEEK_SET);
     if (write) {
         g_assert_cmpint(ftruncate(fd, 0), ==, 0);
     }
     ioc = QIO_CHANNEL(qio_channel_file_new_fd(fd));
     if (write) {
-        return qemu_fopen_channel_output(ioc);
+        f = qemu_fopen_channel_output(ioc);
     } else {
-        return qemu_fopen_channel_input(ioc);
+        f = qemu_fopen_channel_input(ioc);
     }
+    object_unref(OBJECT(ioc));
+    return f;
 }
 
 #define SUCCESS(val) \
diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c
new file mode 100644
index 0000000000..83162a44c0
--- /dev/null
+++ b/tests/test-x86-cpuid-compat.c
@@ -0,0 +1,171 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qint.h"
+#include "libqtest.h"
+
+static char *get_cpu0_qom_path(void)
+{
+    QDict *resp;
+    QList *ret;
+    QDict *cpu0;
+    char *path;
+
+    resp = qmp("{'execute': 'query-cpus', 'arguments': {}}");
+    g_assert(qdict_haskey(resp, "return"));
+    ret = qdict_get_qlist(resp, "return");
+
+    cpu0 = qobject_to_qdict(qlist_peek(ret));
+    path = g_strdup(qdict_get_str(cpu0, "qom_path"));
+    QDECREF(resp);
+    return path;
+}
+
+static QObject *qom_get(const char *path, const char *prop)
+{
+    QDict *resp = qmp("{ 'execute': 'qom-get',"
+                      "  'arguments': { 'path': %s,"
+                      "                 'property': %s } }",
+                      path, prop);
+    QObject *ret = qdict_get(resp, "return");
+    qobject_incref(ret);
+    QDECREF(resp);
+    return ret;
+}
+
+typedef struct CpuidTestArgs {
+    const char *cmdline;
+    const char *property;
+    int64_t expected_value;
+} CpuidTestArgs;
+
+static void test_cpuid_prop(const void *data)
+{
+    const CpuidTestArgs *args = data;
+    char *path;
+    QInt *value;
+
+    qtest_start(args->cmdline);
+    path = get_cpu0_qom_path();
+    value = qobject_to_qint(qom_get(path, args->property));
+    g_assert_cmpint(qint_get_int(value), ==, args->expected_value);
+    qtest_end();
+
+    QDECREF(value);
+    g_free(path);
+}
+
+static void add_cpuid_test(const char *name, const char *cmdline,
+                           const char *property, int64_t expected_value)
+{
+    CpuidTestArgs *args = g_new0(CpuidTestArgs, 1);
+    args->cmdline = cmdline;
+    args->property = property;
+    args->expected_value = expected_value;
+    qtest_add_data_func(name, args, test_cpuid_prop);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    /* Original level values for CPU models: */
+    add_cpuid_test("x86/cpuid/phenom/level",
+                   "-cpu phenom", "level", 5);
+    add_cpuid_test("x86/cpuid/Conroe/level",
+                   "-cpu Conroe", "level", 10);
+    add_cpuid_test("x86/cpuid/SandyBridge/level",
+                   "-cpu SandyBridge", "level", 0xd);
+    add_cpuid_test("x86/cpuid/486/xlevel",
+                   "-cpu 486", "xlevel", 0);
+    add_cpuid_test("x86/cpuid/core2duo/xlevel",
+                   "-cpu core2duo", "xlevel", 0x80000008);
+    add_cpuid_test("x86/cpuid/phenom/xlevel",
+                   "-cpu phenom", "xlevel", 0x8000001A);
+    add_cpuid_test("x86/cpuid/athlon/xlevel",
+                   "-cpu athlon", "xlevel", 0x80000008);
+
+    /* If level is not large enough, it should increase automatically: */
+    /* CPUID[6].EAX: */
+    add_cpuid_test("x86/cpuid/auto-level/phenom/arat",
+                   "-cpu 486,+arat", "level", 6);
+    /* CPUID[EAX=7,ECX=0].EBX: */
+    add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase",
+                   "-cpu phenom,+fsgsbase", "level", 7);
+    /* CPUID[EAX=7,ECX=0].ECX: */
+    add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi",
+                   "-cpu phenom,+avx512vbmi", "level", 7);
+    /* CPUID[EAX=0xd,ECX=1].EAX: */
+    add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt",
+                   "-cpu phenom,+xsaveopt", "level", 0xd);
+    /* CPUID[8000_0001].EDX: */
+    add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow",
+                   "-cpu 486,+3dnow", "xlevel", 0x80000001);
+    /* CPUID[8000_0001].ECX: */
+    add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a",
+                   "-cpu 486,+sse4a", "xlevel", 0x80000001);
+    /* CPUID[8000_0007].EDX: */
+    add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc",
+                   "-cpu 486,+invtsc", "xlevel", 0x80000007);
+    /* CPUID[8000_000A].EDX: */
+    add_cpuid_test("x86/cpuid/auto-xlevel/486/npt",
+                   "-cpu 486,+npt", "xlevel", 0x8000000A);
+    /* CPUID[C000_0001].EDX: */
+    add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore",
+                   "-cpu phenom,+xstore", "xlevel2", 0xC0000001);
+    /* SVM needs CPUID[0x8000000A] */
+    add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm",
+                   "-cpu athlon,+svm", "xlevel", 0x8000000A);
+
+
+    /* If level is already large enough, it shouldn't change: */
+    add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple",
+                   "-cpu SandyBridge,+arat,+fsgsbase,+avx512vbmi",
+                   "level", 0xd);
+    /* If level is explicitly set, it shouldn't change: */
+    add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF",
+                   "-cpu 486,level=0xF,+arat,+fsgsbase,+avx512vbmi,+xsaveopt",
+                   "level", 0xF);
+    add_cpuid_test("x86/cpuid/auto-level/486/fixed/2",
+                   "-cpu 486,level=2,+arat,+fsgsbase,+avx512vbmi,+xsaveopt",
+                   "level", 2);
+    add_cpuid_test("x86/cpuid/auto-level/486/fixed/0",
+                   "-cpu 486,level=0,+arat,+fsgsbase,+avx512vbmi,+xsaveopt",
+                   "level", 0);
+
+    /* if xlevel is already large enough, it shouldn't change: */
+    add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow",
+                   "-cpu phenom,+3dnow,+sse4a,+invtsc,+npt,+svm",
+                   "xlevel", 0x8000001A);
+    /* If xlevel is explicitly set, it shouldn't change: */
+    add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002",
+                   "-cpu 486,xlevel=0x80000002,+3dnow,+sse4a,+invtsc,+npt,+svm",
+                   "xlevel", 0x80000002);
+    add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A",
+                   "-cpu 486,xlevel=0x8000001A,+3dnow,+sse4a,+invtsc,+npt,+svm",
+                   "xlevel", 0x8000001A);
+    add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0",
+                   "-cpu 486,xlevel=0,+3dnow,+sse4a,+invtsc,+npt,+svm",
+                   "xlevel", 0);
+
+    /* if xlevel2 is already large enough, it shouldn't change: */
+    add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed",
+                   "-cpu 486,xlevel2=0xC0000002,+xstore",
+                   "xlevel2", 0xC0000002);
+
+    /* Check compatibility of old machine-types that didn't
+     * auto-increase level/xlevel/xlevel2: */
+
+    add_cpuid_test("x86/cpuid/auto-level/pc-2.7",
+                   "-machine pc-i440fx-2.7 -cpu 486,+arat,+avx512vbmi,+xsaveopt",
+                   "level", 1);
+    add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7",
+                   "-machine pc-i440fx-2.7 -cpu 486,+3dnow,+sse4a,+invtsc,+npt,+svm",
+                   "xlevel", 0);
+    add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7",
+                   "-machine pc-i440fx-2.7 -cpu 486,+xstore",
+                   "xlevel2", 0);
+
+    return g_test_run();
+}
diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c
index eb247ad453..a4ceeaaa43 100644
--- a/tests/usb-hcd-ehci-test.c
+++ b/tests/usb-hcd-ehci-test.c
@@ -56,7 +56,7 @@ static void pci_init(void)
     if (pcibus) {
         return;
     }
-    pcibus = qpci_init_pc();
+    pcibus = qpci_init_pc(NULL);
     g_assert(pcibus != NULL);
 
     qusb_pci_init_one(pcibus, &uhci1, QPCI_DEVFN(0x1d, 0), 4);
diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c
index 5cd59ad91f..4b951ce492 100644
--- a/tests/usb-hcd-uhci-test.c
+++ b/tests/usb-hcd-uhci-test.c
@@ -9,9 +9,13 @@
 
 #include "qemu/osdep.h"
 #include "libqtest.h"
+#include "libqos/libqos.h"
 #include "libqos/usb.h"
+#include "libqos/libqos-pc.h"
+#include "libqos/libqos-spapr.h"
 #include "hw/usb/uhci-regs.h"
 
+static QOSState *qs;
 
 static void test_uhci_init(void)
 {
@@ -19,13 +23,10 @@ static void test_uhci_init(void)
 
 static void test_port(int port)
 {
-    QPCIBus *pcibus;
     struct qhc uhci;
 
     g_assert(port > 0);
-    pcibus = qpci_init_pc();
-    g_assert(pcibus != NULL);
-    qusb_pci_init_one(pcibus, &uhci, QPCI_DEVFN(0x1d, 0), 4);
+    qusb_pci_init_one(qs->pcibus, &uhci, QPCI_DEVFN(0x1d, 0), 4);
     uhci_port_test(&uhci, port - 1, UHCI_PORT_CCS);
 }
 
@@ -75,6 +76,7 @@ static void test_usb_storage_hotplug(void)
 
 int main(int argc, char **argv)
 {
+    const char *arch = qtest_get_arch();
     int ret;
 
     g_test_init(&argc, &argv, NULL);
@@ -84,11 +86,17 @@ int main(int argc, char **argv)
     qtest_add_func("/uhci/pci/hotplug", test_uhci_hotplug);
     qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug);
 
-    qtest_start("-device piix3-usb-uhci,id=uhci,addr=1d.0"
-                " -drive id=drive0,if=none,file=/dev/null,format=raw"
-                " -device usb-tablet,bus=uhci.0,port=1");
+    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+        qs = qtest_pc_boot("-device piix3-usb-uhci,id=uhci,addr=1d.0"
+                           " -drive id=drive0,if=none,file=/dev/null,format=raw"
+                           " -device usb-tablet,bus=uhci.0,port=1");
+    } else if (strcmp(arch, "ppc64") == 0) {
+        qs = qtest_spapr_boot("-device piix3-usb-uhci,id=uhci,addr=1d.0"
+                           " -drive id=drive0,if=none,file=/dev/null,format=raw"
+                           " -device usb-tablet,bus=uhci.0,port=1");
+    }
     ret = g_test_run();
-    qtest_end();
+    qtest_shutdown(qs);
 
     return ret;
 }
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 27b10c19b8..d7c48c589a 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -16,8 +16,18 @@
 #include "qemu/sockets.h"
 #include "sysemu/char.h"
 #include "sysemu/sysemu.h"
+#include "libqos/libqos.h"
+#include "libqos/pci-pc.h"
+#include "libqos/virtio-pci.h"
+
+#include "libqos/pci-pc.h"
+#include "libqos/virtio-pci.h"
+#include "libqos/malloc-pc.h"
+#include "hw/virtio/virtio-net.h"
 
 #include <linux/vhost.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_net.h>
 #include <sys/vfs.h>
 
 /* GLIB version compatibility flags */
@@ -29,14 +39,13 @@
 #define HAVE_MONOTONIC_TIME
 #endif
 
-#define QEMU_CMD_ACCEL  " -machine accel=tcg"
 #define QEMU_CMD_MEM    " -m %d -object memory-backend-file,id=mem,size=%dM,"\
                         "mem-path=%s,share=on -numa node,memdev=mem"
 #define QEMU_CMD_CHR    " -chardev socket,id=%s,path=%s%s"
 #define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce"
-#define QEMU_CMD_NET    " -device virtio-net-pci,netdev=net0,romfile=./pc-bios/pxe-virtio.rom"
+#define QEMU_CMD_NET    " -device virtio-net-pci,netdev=net0"
 
-#define QEMU_CMD        QEMU_CMD_ACCEL QEMU_CMD_MEM QEMU_CMD_CHR \
+#define QEMU_CMD        QEMU_CMD_MEM QEMU_CMD_CHR \
                         QEMU_CMD_NETDEV QEMU_CMD_NET
 
 #define HUGETLBFS_MAGIC       0x958458f6
@@ -46,6 +55,7 @@
 #define VHOST_MEMORY_MAX_NREGIONS    8
 
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
+#define VHOST_USER_PROTOCOL_F_MQ 0
 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1
 
 #define VHOST_LOG_PAGE 0x1000
@@ -68,6 +78,7 @@ typedef enum VhostUserRequest {
     VHOST_USER_SET_VRING_ERR = 14,
     VHOST_USER_GET_PROTOCOL_FEATURES = 15,
     VHOST_USER_SET_PROTOCOL_FEATURES = 16,
+    VHOST_USER_GET_QUEUE_NUM = 17,
     VHOST_USER_SET_VRING_ENABLE = 18,
     VHOST_USER_MAX
 } VhostUserRequest;
@@ -119,6 +130,13 @@ static VhostUserMsg m __attribute__ ((unused));
 #define VHOST_USER_VERSION    (0x1)
 /*****************************************************************************/
 
+enum {
+    TEST_FLAGS_OK,
+    TEST_FLAGS_DISCONNECT,
+    TEST_FLAGS_BAD,
+    TEST_FLAGS_END,
+};
+
 typedef struct TestServer {
     gchar *socket_path;
     gchar *mig_path;
@@ -131,11 +149,38 @@ typedef struct TestServer {
     CompatGCond data_cond;
     int log_fd;
     uint64_t rings;
+    bool test_fail;
+    int test_flags;
+    int queues;
 } TestServer;
 
 static const char *tmpfs;
 static const char *root;
 
+static void init_virtio_dev(TestServer *s)
+{
+    QPCIBus *bus;
+    QVirtioPCIDevice *dev;
+    uint32_t features;
+
+    bus = qpci_init_pc(NULL);
+    g_assert_nonnull(bus);
+
+    dev = qvirtio_pci_device_find(bus, VIRTIO_ID_NET);
+    g_assert_nonnull(dev);
+
+    qvirtio_pci_device_enable(dev);
+    qvirtio_reset(&qvirtio_pci, &dev->vdev);
+    qvirtio_set_acknowledge(&qvirtio_pci, &dev->vdev);
+    qvirtio_set_driver(&qvirtio_pci, &dev->vdev);
+
+    features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
+    features = features & VIRTIO_NET_F_MAC;
+    qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
+
+    qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
+}
+
 static void wait_for_fds(TestServer *s)
 {
     gint64 end_time;
@@ -221,6 +266,12 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
     uint8_t *p = (uint8_t *) &msg;
     int fd;
 
+    if (s->test_fail) {
+        qemu_chr_disconnect(chr);
+        /* now switch to non-failure */
+        s->test_fail = false;
+    }
+
     if (size != VHOST_USER_HDR_SIZE) {
         g_test_message("Wrong message size received %d\n", size);
         return;
@@ -246,6 +297,13 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         msg.size = sizeof(m.payload.u64);
         msg.payload.u64 = 0x1ULL << VHOST_F_LOG_ALL |
             0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
+        if (s->queues > 1) {
+            msg.payload.u64 |= 0x1ULL << VIRTIO_NET_F_MQ;
+        }
+        if (s->test_flags >= TEST_FLAGS_BAD) {
+            msg.payload.u64 = 0;
+            s->test_flags = TEST_FLAGS_END;
+        }
         p = (uint8_t *) &msg;
         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
         break;
@@ -253,6 +311,10 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
     case VHOST_USER_SET_FEATURES:
 	g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
 			!=, 0ULL);
+        if (s->test_flags == TEST_FLAGS_DISCONNECT) {
+            qemu_chr_disconnect(chr);
+            s->test_flags = TEST_FLAGS_BAD;
+        }
         break;
 
     case VHOST_USER_GET_PROTOCOL_FEATURES:
@@ -260,6 +322,9 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         msg.flags |= VHOST_USER_REPLY_MASK;
         msg.size = sizeof(m.payload.u64);
         msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
+        if (s->queues > 1) {
+            msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ;
+        }
         p = (uint8_t *) &msg;
         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
         break;
@@ -272,7 +337,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         p = (uint8_t *) &msg;
         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
 
-        assert(msg.payload.state.index < 2);
+        assert(msg.payload.state.index < s->queues * 2);
         s->rings &= ~(0x1ULL << msg.payload.state.index);
         break;
 
@@ -312,10 +377,18 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         break;
 
     case VHOST_USER_SET_VRING_BASE:
-        assert(msg.payload.state.index < 2);
+        assert(msg.payload.state.index < s->queues * 2);
         s->rings |= 0x1ULL << msg.payload.state.index;
         break;
 
+    case VHOST_USER_GET_QUEUE_NUM:
+        msg.flags |= VHOST_USER_REPLY_MASK;
+        msg.size = sizeof(m.payload.u64);
+        msg.payload.u64 = s->queues;
+        p = (uint8_t *) &msg;
+        qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
+        break;
+
     default:
         break;
     }
@@ -362,10 +435,21 @@ static TestServer *test_server_new(const gchar *name)
     g_cond_init(&server->data_cond);
 
     server->log_fd = -1;
+    server->queues = 1;
 
     return server;
 }
 
+static void chr_event(void *opaque, int event)
+{
+    TestServer *s = opaque;
+
+    if (s->test_flags == TEST_FLAGS_END &&
+        event == CHR_EVENT_CLOSED) {
+        s->test_flags = TEST_FLAGS_OK;
+    }
+}
+
 static void test_server_create_chr(TestServer *server, const gchar *opt)
 {
     gchar *chr_path;
@@ -374,7 +458,8 @@ static void test_server_create_chr(TestServer *server, const gchar *opt)
     server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
     g_free(chr_path);
 
-    qemu_chr_add_handlers(server->chr, chr_can_read, chr_read, NULL, server);
+    qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
+                          chr_event, server);
 }
 
 static void test_server_listen(TestServer *server)
@@ -548,6 +633,7 @@ static void test_migrate(void)
     from = qtest_start(cmd);
     g_free(cmd);
 
+    init_virtio_dev(s);
     wait_for_fds(s);
     size = get_log_size(s);
     g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
@@ -612,7 +698,6 @@ static void test_migrate(void)
     global_qtest = global;
 }
 
-#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
 static void wait_for_rings_started(TestServer *s, size_t count)
 {
     gint64 end_time;
@@ -630,6 +715,7 @@ static void wait_for_rings_started(TestServer *s, size_t count)
     g_mutex_unlock(&s->data_mutex);
 }
 
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
 static gboolean
 reconnect_cb(gpointer user_data)
 {
@@ -662,6 +748,7 @@ static void test_reconnect_subprocess(void)
     qtest_start(cmd);
     g_free(cmd);
 
+    init_virtio_dev(s);
     wait_for_fds(s);
     wait_for_rings_started(s, 2);
 
@@ -685,8 +772,144 @@ static void test_reconnect(void)
     g_test_trap_assert_passed();
     g_free(path);
 }
+
+static void test_connect_fail_subprocess(void)
+{
+    TestServer *s = test_server_new("connect-fail");
+    char *cmd;
+
+    s->test_fail = true;
+    g_thread_new("connect", connect_thread, s);
+    cmd = GET_QEMU_CMDE(s, 2, ",server", "");
+    qtest_start(cmd);
+    g_free(cmd);
+
+    init_virtio_dev(s);
+    wait_for_fds(s);
+    wait_for_rings_started(s, 2);
+
+    qtest_end();
+    test_server_free(s);
+}
+
+static void test_connect_fail(void)
+{
+    gchar *path = g_strdup_printf("/%s/vhost-user/connect-fail/subprocess",
+                                  qtest_get_arch());
+    g_test_trap_subprocess(path, 0, 0);
+    g_test_trap_assert_passed();
+    g_free(path);
+}
+
+static void test_flags_mismatch_subprocess(void)
+{
+    TestServer *s = test_server_new("flags-mismatch");
+    char *cmd;
+
+    s->test_flags = TEST_FLAGS_DISCONNECT;
+    g_thread_new("connect", connect_thread, s);
+    cmd = GET_QEMU_CMDE(s, 2, ",server", "");
+    qtest_start(cmd);
+    g_free(cmd);
+
+    init_virtio_dev(s);
+    wait_for_fds(s);
+    wait_for_rings_started(s, 2);
+
+    qtest_end();
+    test_server_free(s);
+}
+
+static void test_flags_mismatch(void)
+{
+    gchar *path = g_strdup_printf("/%s/vhost-user/flags-mismatch/subprocess",
+                                  qtest_get_arch());
+    g_test_trap_subprocess(path, 0, 0);
+    g_test_trap_assert_passed();
+    g_free(path);
+}
+
 #endif
 
+static QVirtioPCIDevice *virtio_net_pci_init(QPCIBus *bus, int slot)
+{
+    QVirtioPCIDevice *dev;
+
+    dev = qvirtio_pci_device_find(bus, VIRTIO_ID_NET);
+    g_assert(dev != NULL);
+    g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_NET);
+
+    qvirtio_pci_device_enable(dev);
+    qvirtio_reset(&qvirtio_pci, &dev->vdev);
+    qvirtio_set_acknowledge(&qvirtio_pci, &dev->vdev);
+    qvirtio_set_driver(&qvirtio_pci, &dev->vdev);
+
+    return dev;
+}
+
+static void driver_init(const QVirtioBus *bus, QVirtioDevice *dev)
+{
+    uint32_t features;
+
+    features = qvirtio_get_features(bus, dev);
+    features = features & ~(QVIRTIO_F_BAD_FEATURE |
+                            (1u << VIRTIO_RING_F_INDIRECT_DESC) |
+                            (1u << VIRTIO_RING_F_EVENT_IDX));
+    qvirtio_set_features(bus, dev, features);
+
+    qvirtio_set_driver_ok(bus, dev);
+}
+
+#define PCI_SLOT                0x04
+
+static void test_multiqueue(void)
+{
+    const int queues = 2;
+    TestServer *s = test_server_new("mq");
+    QVirtioPCIDevice *dev;
+    QPCIBus *bus;
+    QVirtQueuePCI *vq[queues * 2];
+    QGuestAllocator *alloc;
+    char *cmd;
+    int i;
+
+    s->queues = queues;
+    test_server_listen(s);
+
+    cmd = g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
+                          "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
+                          512, 512, root, s->chr_name,
+                          s->socket_path, "", s->chr_name,
+                          queues, queues * 2 + 2);
+    qtest_start(cmd);
+    g_free(cmd);
+
+    bus = qpci_init_pc(NULL);
+    dev = virtio_net_pci_init(bus, PCI_SLOT);
+
+    alloc = pc_alloc_init();
+    for (i = 0; i < queues * 2; i++) {
+        vq[i] = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
+                                              alloc, i);
+    }
+
+    driver_init(&qvirtio_pci, &dev->vdev);
+    wait_for_rings_started(s, queues * 2);
+
+    /* End test */
+    for (i = 0; i < queues * 2; i++) {
+        qvirtqueue_cleanup(&qvirtio_pci, &vq[i]->vq, alloc);
+    }
+    pc_alloc_uninit(alloc);
+    qvirtio_pci_device_disable(dev);
+    g_free(dev->pdev);
+    g_free(dev);
+    qpci_free_pc(bus);
+    qtest_end();
+
+    test_server_free(s);
+}
+
 int main(int argc, char **argv)
 {
     QTestState *s = NULL;
@@ -728,13 +951,21 @@ int main(int argc, char **argv)
 
     s = qtest_start(qemu_cmd);
     g_free(qemu_cmd);
+    init_virtio_dev(server);
 
     qtest_add_data_func("/vhost-user/read-guest-mem", server, read_guest_mem);
     qtest_add_func("/vhost-user/migrate", test_migrate);
+    qtest_add_func("/vhost-user/multiqueue", test_multiqueue);
 #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
     qtest_add_func("/vhost-user/reconnect/subprocess",
                    test_reconnect_subprocess);
     qtest_add_func("/vhost-user/reconnect", test_reconnect);
+    qtest_add_func("/vhost-user/connect-fail/subprocess",
+                   test_connect_fail_subprocess);
+    qtest_add_func("/vhost-user/connect-fail", test_connect_fail);
+    qtest_add_func("/vhost-user/flags-mismatch/subprocess",
+                   test_flags_mismatch_subprocess);
+    qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch);
 #endif
 
     ret = g_test_run();
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 1e39335a79..e8b21967d8 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -10,34 +10,119 @@
 #include "qemu/osdep.h"
 #include "libqtest.h"
 #include "qemu-common.h"
+#include "libqos/pci-pc.h"
+#include "libqos/virtio.h"
+#include "libqos/virtio-pci.h"
+#include "libqos/malloc.h"
+#include "libqos/malloc-pc.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_pci.h"
 
-/* Tests only initialization so far. TODO: Replace with functional tests */
-static void pci_nop(void)
-{
-}
+static const char mount_tag[] = "qtest";
+static char *test_share;
 
-static char test_share[] = "/tmp/qtest.XXXXXX";
-
-int main(int argc, char **argv)
+static void qvirtio_9p_start(void)
 {
     char *args;
-    int ret;
 
-    g_test_init(&argc, &argv, NULL);
-    qtest_add_func("/virtio/9p/pci/nop", pci_nop);
-
-    g_assert(mkdtemp(test_share));
+    test_share = g_strdup("/tmp/qtest.XXXXXX");
+    g_assert_nonnull(mkdtemp(test_share));
 
     args = g_strdup_printf("-fsdev local,id=fsdev0,security_model=none,path=%s "
-                           "-device virtio-9p-pci,fsdev=fsdev0,mount_tag=qtest",
-                           test_share);
+                           "-device virtio-9p-pci,fsdev=fsdev0,mount_tag=%s",
+                           test_share, mount_tag);
+
     qtest_start(args);
     g_free(args);
+}
 
-    ret = g_test_run();
-
+static void qvirtio_9p_stop(void)
+{
     qtest_end();
     rmdir(test_share);
+    g_free(test_share);
+}
+
+static void pci_nop(void)
+{
+    qvirtio_9p_start();
+    qvirtio_9p_stop();
+}
+
+typedef struct {
+    QVirtioDevice *dev;
+    QGuestAllocator *alloc;
+    QPCIBus *bus;
+    QVirtQueue *vq;
+} QVirtIO9P;
+
+static QVirtIO9P *qvirtio_9p_pci_init(void)
+{
+    QVirtIO9P *v9p;
+    QVirtioPCIDevice *dev;
+
+    v9p = g_new0(QVirtIO9P, 1);
+    v9p->alloc = pc_alloc_init();
+    v9p->bus = qpci_init_pc(NULL);
+
+    dev = qvirtio_pci_device_find(v9p->bus, VIRTIO_ID_9P);
+    g_assert_nonnull(dev);
+    g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_9P);
+    v9p->dev = (QVirtioDevice *) dev;
+
+    qvirtio_pci_device_enable(dev);
+    qvirtio_reset(&qvirtio_pci, v9p->dev);
+    qvirtio_set_acknowledge(&qvirtio_pci, v9p->dev);
+    qvirtio_set_driver(&qvirtio_pci, v9p->dev);
+
+    v9p->vq = qvirtqueue_setup(&qvirtio_pci, v9p->dev, v9p->alloc, 0);
+    return v9p;
+}
+
+static void qvirtio_9p_pci_free(QVirtIO9P *v9p)
+{
+    qvirtqueue_cleanup(&qvirtio_pci, v9p->vq, v9p->alloc);
+    pc_alloc_uninit(v9p->alloc);
+    qvirtio_pci_device_disable(container_of(v9p->dev, QVirtioPCIDevice, vdev));
+    g_free(v9p->dev);
+    qpci_free_pc(v9p->bus);
+    g_free(v9p);
+}
+
+static void pci_basic_config(void)
+{
+    QVirtIO9P *v9p;
+    void *addr;
+    size_t tag_len;
+    char *tag;
+    int i;
+
+    qvirtio_9p_start();
+    v9p = qvirtio_9p_pci_init();
+
+    addr = ((QVirtioPCIDevice *) v9p->dev)->addr + VIRTIO_PCI_CONFIG_OFF(false);
+    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev,
+                                   (uint64_t)(uintptr_t)addr);
+    g_assert_cmpint(tag_len, ==, strlen(mount_tag));
+    addr += sizeof(uint16_t);
+
+    tag = g_malloc(tag_len);
+    for (i = 0; i < tag_len; i++) {
+        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev,
+                                      (uint64_t)(uintptr_t)addr + i);
+    }
+    g_assert_cmpmem(tag, tag_len, mount_tag, tag_len);
+    g_free(tag);
+
+    qvirtio_9p_pci_free(v9p);
+    qvirtio_9p_stop();
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    qtest_add_func("/virtio/9p/pci/nop", pci_nop);
+    qtest_add_func("/virtio/9p/pci/basic/configuration", pci_basic_config);
 
-    return ret;
+    return g_test_run();
 }
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
index 811cf756c8..3c4fecc1f0 100644
--- a/tests/virtio-blk-test.c
+++ b/tests/virtio-blk-test.c
@@ -75,7 +75,7 @@ static QPCIBus *pci_test_start(void)
     g_free(tmp_path);
     g_free(cmdline);
 
-    return qpci_init_pc();
+    return qpci_init_pc(NULL);
 }
 
 static void arm_test_start(void)
diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
index 361506faf5..a343a6b048 100644
--- a/tests/virtio-net-test.c
+++ b/tests/virtio-net-test.c
@@ -62,7 +62,7 @@ static QPCIBus *pci_test_start(int socket)
     qtest_start(cmdline);
     g_free(cmdline);
 
-    return qpci_init_pc();
+    return qpci_init_pc(NULL);
 }
 
 static void driver_init(const QVirtioBus *bus, QVirtioDevice *dev)
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
index f1489e68a0..79088bb249 100644
--- a/tests/virtio-scsi-test.c
+++ b/tests/virtio-scsi-test.c
@@ -146,7 +146,7 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
 
     vs = g_new0(QVirtIOSCSI, 1);
     vs->alloc = pc_alloc_init();
-    vs->bus = qpci_init_pc();
+    vs->bus = qpci_init_pc(NULL);
 
     dev = qvirtio_pci_device_find(vs->bus, VIRTIO_ID_SCSI);
     vs->dev = (QVirtioDevice *)dev;