Merge remote-tracking branch 'qemu-kvm/uq/master' into staging

# By Jan Kiszka (1) and others
# Via Gleb Natapov
* qemu-kvm/uq/master:
  kvm: Fix uninitialized cpuid_data
  pci-assign: Remove dead code for direct I/O region access from userspace
  KVM: x86: fix typo in KVM_GET_XCRS

Message-id: cover.1385040432.git.gleb@redhat.com
Signed-off-by: Anthony Liguori <aliguori@amazon.com>
diff --git a/.gitignore b/.gitignore
index 8e1b73f..5584b5f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,7 +44,7 @@
 qemu-bridge-helper
 qemu-monitor.texi
 vscclient
-QMP/qmp-commands.txt
+qmp-commands.txt
 test-bitops
 test-coroutine
 test-int128
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..90f1676
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,71 @@
+language: c
+python:
+  - "2.4"
+compiler:
+  - gcc
+  - clang
+env:
+  global:
+    - TEST_CMD="make check"
+    - EXTRA_CONFIG=""
+    # Development packages, EXTRA_PKGS saved for additional builds
+    - CORE_PKGS="libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev"
+    - NET_PKGS="libseccomp-dev libgnutls-dev libssh2-1-dev  libspice-server-dev libspice-protocol-dev libnss3-dev"
+    - GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev"
+    - EXTRA_PKGS=""
+  matrix:
+  - TARGETS=alpha-softmmu,alpha-linux-user
+  - TARGETS=arm-softmmu,arm-linux-user
+  - TARGETS=cris-softmmu
+  - TARGETS=i386-softmmu,x86_64-softmmu
+  - TARGETS=lm32-softmmu
+  - TARGETS=m68k-softmmu
+  - TARGETS=microblaze-softmmu,microblazeel-softmmu
+  - TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
+  - TARGETS=moxie-softmmu
+  - TARGETS=or32-softmmu,
+  - TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
+  - TARGETS=s390x-softmmu
+  - TARGETS=sh4-softmmu,sh4eb-softmmu
+  - TARGETS=sparc-softmmu,sparc64-softmmu
+  - TARGETS=unicore32-softmmu
+  - TARGETS=xtensa-softmmu,xtensaeb-softmmu
+before_install:
+  - git submodule update --init --recursive
+  - sudo apt-get update -qq
+  - sudo apt-get install -qq ${CORE_PKGS} ${NET_PKGS} ${GUI_PKGS} ${EXTRA_PKGS}
+script: "./configure --target-list=${TARGETS} ${EXTRA_CONFIG} && make && ${TEST_CMD}"
+matrix:
+  # We manually include a number of additional build for non-standard bits
+  include:
+    # Debug related options
+    - env: TARGETS=i386-softmmu,x86_64-softmmu
+           EXTRA_CONFIG="--enable-debug"
+      compiler: gcc
+    - env: TARGETS=i386-softmmu,x86_64-softmmu
+           EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter"
+      compiler: gcc
+    # Currently configure doesn't force --disable-pie
+    - env: TARGETS=i386-softmmu,x86_64-softmmu
+           EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie"
+      compiler: gcc
+    - env: TARGETS=i386-softmmu,x86_64-softmmu
+           EXTRA_PKGS="sparse"
+           EXTRA_CONFIG="--enable-sparse"
+      compiler: gcc
+    # All the trace backends (apart from dtrace)
+    - env: TARGETS=i386-softmmu,x86_64-softmmu
+           EXTRA_CONFIG="--enable-trace-backend=stderr"
+      compiler: gcc
+    - env: TARGETS=i386-softmmu,x86_64-softmmu
+           EXTRA_CONFIG="--enable-trace-backend=simple"
+      compiler: gcc
+    - env: TARGETS=i386-softmmu,x86_64-softmmu
+           EXTRA_CONFIG="--enable-trace-backend=ftrace"
+           TEST_CMD=""
+      compiler: gcc
+    # This disabled make check for the ftrace backend which needs more setting up
+    # Currently broken on 12.04 due to mis-packaged liburcu and changed API, will be pulled.
+    #- env: TARGETS=i386-softmmu,x86_64-softmmu
+    #       EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
+    #       EXTRA_CONFIG="--enable-trace-backend=ust"
diff --git a/MAINTAINERS b/MAINTAINERS
index 77edacf..c19133f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -639,6 +639,8 @@
 F: block*
 F: block/
 F: hw/block/
+T: git git://repo.or.cz/qemu/kevin.git block
+T: git git://github.com/stefanha/qemu.git block
 
 Character Devices
 M: Anthony Liguori <aliguori@amazon.com>
@@ -699,6 +701,7 @@
 F: monitor.c
 F: hmp.c
 F: hmp-commands.hx
+T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
 
 Network device layer
 M: Anthony Liguori <aliguori@amazon.com>
@@ -720,6 +723,7 @@
 M: Michael Roth <mdroth@linux.vnet.ibm.com>
 S: Supported
 F: qapi/
+T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
 
 QAPI Schema
 M: Eric Blake <eblake@redhat.com>
@@ -727,6 +731,7 @@
 M: Markus Armbruster <armbru@redhat.com>
 S: Supported
 F: qapi-schema.json
+T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
 
 QMP
 M: Luiz Capitulino <lcapitulino@redhat.com>
@@ -735,6 +740,7 @@
 F: monitor.c
 F: qmp-commands.hx
 F: QMP/
+T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
 
 SLIRP
 M: Jan Kiszka <jan.kiszka@siemens.com>
@@ -857,3 +863,43 @@
 L: qemu-stable@nongnu.org
 T: git git://git.qemu-project.org/qemu-stable-0.10.git
 S: Orphan
+
+Block drivers
+-------------
+VMDK
+M: Fam Zheng <famz@redhat.com>
+S: Supported
+F: block/vmdk.c
+
+RBD
+M: Josh Durgin <josh.durgin@inktank.com>
+S: Supported
+F: block/rbd.c
+
+Sheepdog
+M: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
+M: Liu Yuan <namei.unix@gmail.com>
+S: Supported
+F: block/sheepdog.c
+
+VHDX
+M: Jeff Cody <jcody@redhat.com>
+S: Supported
+F: block/vhdx*
+
+VDI
+M: Stefan Weil <sw@weilnetz.de>
+S: Maintained
+F: block/vdi.c
+
+iSCSI
+M: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+M: Paolo Bonzini <pbonzini@redhat.com>
+M: Peter Lieven <pl@kamp.de>
+S: Supported
+F: block/iscsi.c
+
+SSH
+M: Richard W.M. Jones <rjones@redhat.com>
+S: Supported
+F: block/ssh.c
diff --git a/Makefile b/Makefile
index b15003f..3321b98 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,14 @@
 include $(SRC_PATH)/rules.mak
 config-host.mak: $(SRC_PATH)/configure
 	@echo $@ is out-of-date, running configure
-	@sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh
+	@# TODO: The next lines include code which supports a smooth
+	@# transition from old configurations without config.status.
+	@# This code can be removed after QEMU 1.7.
+	@if test -x config.status; then \
+	    ./config.status; \
+        else \
+	    sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh; \
+	fi
 else
 config-host.mak:
 ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
@@ -280,7 +287,7 @@
 KEYMAPS=da     en-gb  et  fr     fr-ch  is  lt  modifiers  no  pt-br  sv \
 ar      de     en-us  fi  fr-be  hr     it  lv  nl         pl  ru     th \
 common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr \
-bepo
+bepo    cz
 
 ifdef INSTALL_BLOBS
 BLOBS=bios.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
diff --git a/VERSION b/VERSION
index 0a8112b..86e63cc 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.6.50
+1.6.90
diff --git a/arch_init.c b/arch_init.c
index 7545d96..e0acbc5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -850,14 +850,6 @@
 {
     if (ch != 0 || !is_zero_range(host, size)) {
         memset(host, ch, size);
-#ifndef _WIN32
-        if (ch == 0 && (!kvm_enabled() || kvm_has_sync_mmu())) {
-            size = size & ~(getpagesize() - 1);
-            if (size > 0) {
-                qemu_madvise(host, size, QEMU_MADV_DONTNEED);
-            }
-        }
-#endif
     }
 }
 
diff --git a/audio/audio.c b/audio/audio.c
index af4cdf6..b3db679 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1124,7 +1124,8 @@
 static void audio_reset_timer (AudioState *s)
 {
     if (audio_is_timer_needed ()) {
-        timer_mod (s->ts, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1);
+        timer_mod (s->ts,
+            qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + conf.period.ticks);
     }
     else {
         timer_del (s->ts);
diff --git a/audio/mixeng_template.h b/audio/mixeng_template.h
index 30849a6..77cc89b 100644
--- a/audio/mixeng_template.h
+++ b/audio/mixeng_template.h
@@ -35,7 +35,7 @@
 #define IN_T glue (glue (ITYPE, BSIZE), _t)
 
 #ifdef FLOAT_MIXENG
-static mixeng_real inline glue (conv_, ET) (IN_T v)
+static inline mixeng_real glue (conv_, ET) (IN_T v)
 {
     IN_T nv = ENDIAN_CONVERT (v);
 
@@ -54,7 +54,7 @@
 #endif
 }
 
-static IN_T inline glue (clip_, ET) (mixeng_real v)
+static inline IN_T glue (clip_, ET) (mixeng_real v)
 {
     if (v >= 0.5) {
         return IN_MAX;
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 007c641..5a73716 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -849,6 +849,10 @@
 
 static void *oss_audio_init (void)
 {
+    if (access(conf.devpath_in, R_OK | W_OK) < 0 ||
+        access(conf.devpath_out, R_OK | W_OK) < 0) {
+        return NULL;
+    }
     return &conf;
 }
 
diff --git a/block.c b/block.c
index fd05a80..382ea71 100644
--- a/block.c
+++ b/block.c
@@ -640,7 +640,7 @@
         if (length < 0) {
             return length;
         }
-        hint = length >> BDRV_SECTOR_BITS;
+        hint = DIV_ROUND_UP(length, BDRV_SECTOR_SIZE);
     }
 
     bs->total_sectors = hint;
@@ -999,20 +999,23 @@
     }
 
     /* backing files always opened read-only */
-    back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT);
+    back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT |
+                                    BDRV_O_COPY_ON_READ);
 
     ret = bdrv_open(bs->backing_hd,
                     *backing_filename ? backing_filename : NULL, options,
                     back_flags, back_drv, &local_err);
-    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
-            bs->backing_hd->file->filename);
     if (ret < 0) {
         bdrv_unref(bs->backing_hd);
         bs->backing_hd = NULL;
         bs->open_flags |= BDRV_O_NO_BACKING;
-        error_propagate(errp, local_err);
+        error_setg(errp, "Could not open backing file: %s",
+                   error_get_pretty(local_err));
+        error_free(local_err);
         return ret;
     }
+    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+            bs->backing_hd->file->filename);
     return 0;
 }
 
@@ -1083,8 +1086,8 @@
             snprintf(backing_filename, sizeof(backing_filename),
                      "%s", filename);
         } else if (!realpath(filename, backing_filename)) {
-            error_setg_errno(errp, errno, "Could not resolve path '%s'", filename);
             ret = -errno;
+            error_setg_errno(errp, errno, "Could not resolve path '%s'", filename);
             goto fail;
         }
 
@@ -1134,6 +1137,11 @@
     if (drvname) {
         drv = bdrv_find_format(drvname);
         qdict_del(options, "driver");
+        if (!drv) {
+            error_setg(errp, "Invalid driver: '%s'", drvname);
+            ret = -EINVAL;
+            goto unlink_and_fail;
+        }
     }
 
     if (!drv) {
@@ -2868,9 +2876,10 @@
     if (!drv)
         return -ENOMEDIUM;
 
-    if (bdrv_dev_has_removable_media(bs)) {
-        if (drv->bdrv_getlength) {
-            return drv->bdrv_getlength(bs);
+    if (drv->has_variable_length) {
+        int ret = refresh_total_sectors(bs, bs->total_sectors);
+        if (ret < 0) {
+            return ret;
         }
     }
     return bs->total_sectors * BDRV_SECTOR_SIZE;
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 3bb85b5..f43ecbc 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -2,7 +2,7 @@
 block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
 block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
 block-obj-y += qed-check.o
-block-obj-y += vhdx.o
+block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
 block-obj-y += parallels.o blkdebug.o blkverify.o
 block-obj-y += snapshot.o qapi.o
 block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
diff --git a/block/iscsi.c b/block/iscsi.c
index a2a961e..a2d578c 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -866,7 +866,7 @@
         /* in case the get_lba_status_callout fails (i.e.
          * because the device is busy or the cmd is not
          * supported) we pretend all blocks are allocated
-         * for backwards compatiblity */
+         * for backwards compatibility */
         goto out;
     }
 
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 0348b97..791083a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -101,7 +101,7 @@
     /* set new table */
     BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE);
     cpu_to_be32w((uint32_t*)data, new_l1_size);
-    cpu_to_be64wu((uint64_t*)(data + 4), new_l1_table_offset);
+    stq_be_p(data + 4, new_l1_table_offset);
     ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size), data,sizeof(data));
     if (ret < 0) {
         goto fail;
@@ -290,7 +290,7 @@
         uint64_t *l2_table, uint64_t stop_flags)
 {
     int i;
-    uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW2_CLUSTER_COMPRESSED;
+    uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
     uint64_t first_entry = be64_to_cpu(l2_table[0]);
     uint64_t offset = first_entry & mask;
 
diff --git a/block/qcow2.c b/block/qcow2.c
index c1abaff..6e5d98d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1584,6 +1584,16 @@
         }
     }
 
+    bdrv_close(bs);
+
+    /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */
+    ret = bdrv_open(bs, filename, NULL,
+                    BDRV_O_RDWR | BDRV_O_CACHE_WB, drv, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        goto out;
+    }
+
     ret = 0;
 out:
     bdrv_unref(bs);
@@ -1939,13 +1949,22 @@
                               int64_t pos)
 {
     BDRVQcowState *s = bs->opaque;
+    int64_t total_sectors = bs->total_sectors;
     int growable = bs->growable;
+    bool zero_beyond_eof = bs->zero_beyond_eof;
     int ret;
 
     BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE);
     bs->growable = 1;
+    bs->zero_beyond_eof = false;
     ret = bdrv_pwritev(bs, qcow2_vm_state_offset(s) + pos, qiov);
     bs->growable = growable;
+    bs->zero_beyond_eof = zero_beyond_eof;
+
+    /* bdrv_co_do_writev will have increased the total_sectors value to include
+     * the VM state - the VM state is however not an actual part of the block
+     * device, therefore, we need to restore the old value. */
+    bs->total_sectors = total_sectors;
 
     return ret;
 }
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 6f03fbf..f836c8e 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -310,7 +310,6 @@
         if (ret == -EROFS) {
             ret = -EACCES;
         }
-        error_setg_errno(errp, -ret, "Could not open file");
         goto fail;
     }
     s->fd = fd;
@@ -1715,7 +1714,8 @@
     .bdrv_aio_flush	= raw_aio_flush,
 
     .bdrv_truncate      = raw_truncate,
-    .bdrv_getlength	= raw_getlength,
+    .bdrv_getlength      = raw_getlength,
+    .has_variable_length = true,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
@@ -1824,7 +1824,8 @@
     .bdrv_aio_flush	= raw_aio_flush,
 
     .bdrv_truncate      = raw_truncate,
-    .bdrv_getlength     = raw_getlength,
+    .bdrv_getlength      = raw_getlength,
+    .has_variable_length = true,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
@@ -1840,7 +1841,8 @@
 #endif /* __linux__ */
 
 #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
-static int cdrom_open(BlockDriverState *bs, QDict *options, int flags)
+static int cdrom_open(BlockDriverState *bs, QDict *options, int flags,
+                      Error **errp)
 {
     BDRVRawState *s = bs->opaque;
     Error *local_err = NULL;
@@ -1951,7 +1953,8 @@
     .bdrv_aio_flush	= raw_aio_flush,
 
     .bdrv_truncate      = raw_truncate,
-    .bdrv_getlength     = raw_getlength,
+    .bdrv_getlength      = raw_getlength,
+    .has_variable_length = true,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 676b570..2bad5a3 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -280,7 +280,6 @@
         } else {
             ret = -EINVAL;
         }
-        error_setg_errno(errp, -ret, "Could not open file");
         goto fail;
     }
 
@@ -616,7 +615,9 @@
     .bdrv_aio_writev    = raw_aio_writev,
     .bdrv_aio_flush     = raw_aio_flush,
 
-    .bdrv_getlength	= raw_getlength,
+    .bdrv_getlength      = raw_getlength,
+    .has_variable_length = true,
+
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 };
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index 0078c1b..2265dcc 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -178,6 +178,7 @@
     .bdrv_co_get_block_status = &raw_co_get_block_status,
     .bdrv_truncate        = &raw_truncate,
     .bdrv_getlength       = &raw_getlength,
+    .has_variable_length  = true,
     .bdrv_get_info        = &raw_get_info,
     .bdrv_is_inserted     = &raw_is_inserted,
     .bdrv_media_changed   = &raw_media_changed,
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 5f81c93..ef387de 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -125,8 +125,9 @@
     uint32_t data_length;
     uint64_t oid;
     uint64_t cow_oid;
-    uint32_t copies;
-    uint32_t rsvd;
+    uint8_t copies;
+    uint8_t copy_policy;
+    uint8_t reserved[6];
     uint64_t offset;
 } SheepdogObjReq;
 
@@ -138,7 +139,9 @@
     uint32_t id;
     uint32_t data_length;
     uint32_t result;
-    uint32_t copies;
+    uint8_t copies;
+    uint8_t copy_policy;
+    uint8_t reserved[2];
     uint32_t pad[6];
 } SheepdogObjRsp;
 
@@ -151,7 +154,9 @@
     uint32_t data_length;
     uint64_t vdi_size;
     uint32_t vdi_id;
-    uint32_t copies;
+    uint8_t copies;
+    uint8_t copy_policy;
+    uint8_t reserved[2];
     uint32_t snapid;
     uint32_t pad[3];
 } SheepdogVdiReq;
@@ -222,6 +227,11 @@
     return oid & (MAX_DATA_OBJS - 1);
 }
 
+static inline uint32_t oid_to_vid(uint64_t oid)
+{
+    return (oid & ~VDI_BIT) >> VDI_SPACE_SHIFT;
+}
+
 static inline uint64_t vid_to_vdi_oid(uint32_t vid)
 {
     return VDI_BIT | ((uint64_t)vid << VDI_SPACE_SHIFT);
@@ -289,11 +299,14 @@
     Coroutine *coroutine;
     void (*aio_done_func)(SheepdogAIOCB *);
 
-    bool canceled;
+    bool cancelable;
+    bool *finished;
     int nr_pending;
 };
 
 typedef struct BDRVSheepdogState {
+    BlockDriverState *bs;
+
     SheepdogInode inode;
 
     uint32_t min_dirty_data_idx;
@@ -313,8 +326,11 @@
     Coroutine *co_recv;
 
     uint32_t aioreq_seq_num;
+
+    /* Every aio request must be linked to either of these queues. */
     QLIST_HEAD(inflight_aio_head, AIOReq) inflight_aio_head;
     QLIST_HEAD(pending_aio_head, AIOReq) pending_aio_head;
+    QLIST_HEAD(failed_aio_head, AIOReq) failed_aio_head;
 } BDRVSheepdogState;
 
 static const char * sd_strerror(int err)
@@ -403,6 +419,7 @@
 {
     SheepdogAIOCB *acb = aio_req->aiocb;
 
+    acb->cancelable = false;
     QLIST_REMOVE(aio_req, aio_siblings);
     g_free(aio_req);
 
@@ -411,23 +428,68 @@
 
 static void coroutine_fn sd_finish_aiocb(SheepdogAIOCB *acb)
 {
-    if (!acb->canceled) {
-        qemu_coroutine_enter(acb->coroutine, NULL);
+    qemu_coroutine_enter(acb->coroutine, NULL);
+    if (acb->finished) {
+        *acb->finished = true;
     }
     qemu_aio_release(acb);
 }
 
+/*
+ * Check whether the specified acb can be canceled
+ *
+ * We can cancel aio when any request belonging to the acb is:
+ *  - Not processed by the sheepdog server.
+ *  - Not linked to the inflight queue.
+ */
+static bool sd_acb_cancelable(const SheepdogAIOCB *acb)
+{
+    BDRVSheepdogState *s = acb->common.bs->opaque;
+    AIOReq *aioreq;
+
+    if (!acb->cancelable) {
+        return false;
+    }
+
+    QLIST_FOREACH(aioreq, &s->inflight_aio_head, aio_siblings) {
+        if (aioreq->aiocb == acb) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
 {
     SheepdogAIOCB *acb = (SheepdogAIOCB *)blockacb;
+    BDRVSheepdogState *s = acb->common.bs->opaque;
+    AIOReq *aioreq, *next;
+    bool finished = false;
 
-    /*
-     * Sheepdog cannot cancel the requests which are already sent to
-     * the servers, so we just complete the request with -EIO here.
-     */
-    acb->ret = -EIO;
-    qemu_coroutine_enter(acb->coroutine, NULL);
-    acb->canceled = true;
+    acb->finished = &finished;
+    while (!finished) {
+        if (sd_acb_cancelable(acb)) {
+            /* Remove outstanding requests from pending and failed queues.  */
+            QLIST_FOREACH_SAFE(aioreq, &s->pending_aio_head, aio_siblings,
+                               next) {
+                if (aioreq->aiocb == acb) {
+                    free_aio_req(s, aioreq);
+                }
+            }
+            QLIST_FOREACH_SAFE(aioreq, &s->failed_aio_head, aio_siblings,
+                               next) {
+                if (aioreq->aiocb == acb) {
+                    free_aio_req(s, aioreq);
+                }
+            }
+
+            assert(acb->nr_pending == 0);
+            sd_finish_aiocb(acb);
+            return;
+        }
+        qemu_aio_wait();
+    }
 }
 
 static const AIOCBInfo sd_aiocb_info = {
@@ -448,7 +510,8 @@
     acb->nb_sectors = nb_sectors;
 
     acb->aio_done_func = NULL;
-    acb->canceled = false;
+    acb->cancelable = true;
+    acb->finished = NULL;
     acb->coroutine = qemu_coroutine_self();
     acb->ret = 0;
     acb->nr_pending = 0;
@@ -489,13 +552,13 @@
     int ret;
 
     ret = qemu_co_send(sockfd, hdr, sizeof(*hdr));
-    if (ret < sizeof(*hdr)) {
+    if (ret != sizeof(*hdr)) {
         error_report("failed to send a req, %s", strerror(errno));
         return ret;
     }
 
     ret = qemu_co_send(sockfd, data, *wlen);
-    if (ret < *wlen) {
+    if (ret != *wlen) {
         error_report("failed to send a req, %s", strerror(errno));
     }
 
@@ -541,7 +604,7 @@
     qemu_aio_set_fd_handler(sockfd, restart_co_req, NULL, co);
 
     ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
-    if (ret < sizeof(*hdr)) {
+    if (ret != sizeof(*hdr)) {
         error_report("failed to get a rsp, %s", strerror(errno));
         ret = -errno;
         goto out;
@@ -553,7 +616,7 @@
 
     if (*rlen) {
         ret = qemu_co_recv(sockfd, data, *rlen);
-        if (ret < *rlen) {
+        if (ret != *rlen) {
             error_report("failed to get the data, %s", strerror(errno));
             ret = -errno;
             goto out;
@@ -596,11 +659,13 @@
     return srco.ret;
 }
 
-static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
+static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
                            struct iovec *iov, int niov, bool create,
                            enum AIOCBState aiocb_type);
-static int coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req);
-
+static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req);
+static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag);
+static int get_sheep_fd(BDRVSheepdogState *s);
+static void co_write_request(void *opaque);
 
 static AIOReq *find_pending_req(BDRVSheepdogState *s, uint64_t oid)
 {
@@ -623,22 +688,59 @@
 {
     AIOReq *aio_req;
     SheepdogAIOCB *acb;
-    int ret;
 
     while ((aio_req = find_pending_req(s, oid)) != NULL) {
         acb = aio_req->aiocb;
         /* move aio_req from pending list to inflight one */
         QLIST_REMOVE(aio_req, aio_siblings);
         QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
-        ret = add_aio_request(s, aio_req, acb->qiov->iov,
-                              acb->qiov->niov, false, acb->aiocb_type);
-        if (ret < 0) {
-            error_report("add_aio_request is failed");
-            free_aio_req(s, aio_req);
-            if (!acb->nr_pending) {
-                sd_finish_aiocb(acb);
-            }
+        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, false,
+                        acb->aiocb_type);
+    }
+}
+
+static coroutine_fn void reconnect_to_sdog(void *opaque)
+{
+    BDRVSheepdogState *s = opaque;
+    AIOReq *aio_req, *next;
+
+    qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
+    close(s->fd);
+    s->fd = -1;
+
+    /* Wait for outstanding write requests to be completed. */
+    while (s->co_send != NULL) {
+        co_write_request(opaque);
+    }
+
+    /* Try to reconnect the sheepdog server every one second. */
+    while (s->fd < 0) {
+        s->fd = get_sheep_fd(s);
+        if (s->fd < 0) {
+            DPRINTF("Wait for connection to be established\n");
+            co_aio_sleep_ns(bdrv_get_aio_context(s->bs), QEMU_CLOCK_REALTIME,
+                            1000000000ULL);
         }
+    };
+
+    /*
+     * Now we have to resend all the request in the inflight queue.  However,
+     * resend_aioreq() can yield and newly created requests can be added to the
+     * inflight queue before the coroutine is resumed.  To avoid mixing them, we
+     * have to move all the inflight requests to the failed queue before
+     * resend_aioreq() is called.
+     */
+    QLIST_FOREACH_SAFE(aio_req, &s->inflight_aio_head, aio_siblings, next) {
+        QLIST_REMOVE(aio_req, aio_siblings);
+        QLIST_INSERT_HEAD(&s->failed_aio_head, aio_req, aio_siblings);
+    }
+
+    /* Resend all the failed aio requests. */
+    while (!QLIST_EMPTY(&s->failed_aio_head)) {
+        aio_req = QLIST_FIRST(&s->failed_aio_head);
+        QLIST_REMOVE(aio_req, aio_siblings);
+        QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
+        resend_aioreq(s, aio_req);
     }
 }
 
@@ -658,15 +760,11 @@
     SheepdogAIOCB *acb;
     uint64_t idx;
 
-    if (QLIST_EMPTY(&s->inflight_aio_head)) {
-        goto out;
-    }
-
     /* read a header */
     ret = qemu_co_recv(fd, &rsp, sizeof(rsp));
-    if (ret < 0) {
+    if (ret != sizeof(rsp)) {
         error_report("failed to get the header, %s", strerror(errno));
-        goto out;
+        goto err;
     }
 
     /* find the right aio_req from the inflight aio list */
@@ -677,7 +775,7 @@
     }
     if (!aio_req) {
         error_report("cannot find aio_req %x", rsp.id);
-        goto out;
+        goto err;
     }
 
     acb = aio_req->aiocb;
@@ -715,9 +813,9 @@
     case AIOCB_READ_UDATA:
         ret = qemu_co_recvv(fd, acb->qiov->iov, acb->qiov->niov,
                             aio_req->iov_offset, rsp.data_length);
-        if (ret < 0) {
+        if (ret != rsp.data_length) {
             error_report("failed to get the data, %s", strerror(errno));
-            goto out;
+            goto err;
         }
         break;
     case AIOCB_FLUSH_CACHE:
@@ -748,11 +846,20 @@
     case SD_RES_SUCCESS:
         break;
     case SD_RES_READONLY:
-        ret = resend_aioreq(s, aio_req);
-        if (ret == SD_RES_SUCCESS) {
-            goto out;
+        if (s->inode.vdi_id == oid_to_vid(aio_req->oid)) {
+            ret = reload_inode(s, 0, "");
+            if (ret < 0) {
+                goto err;
+            }
         }
-        /* fall through */
+        if (is_data_obj(aio_req->oid)) {
+            aio_req->oid = vid_to_data_oid(s->inode.vdi_id,
+                                           data_oid_to_idx(aio_req->oid));
+        } else {
+            aio_req->oid = vid_to_vdi_oid(s->inode.vdi_id);
+        }
+        resend_aioreq(s, aio_req);
+        goto out;
     default:
         acb->ret = -EIO;
         error_report("%s", sd_strerror(rsp.result));
@@ -769,6 +876,10 @@
     }
 out:
     s->co_recv = NULL;
+    return;
+err:
+    s->co_recv = NULL;
+    reconnect_to_sdog(opaque);
 }
 
 static void co_read_response(void *opaque)
@@ -997,7 +1108,7 @@
     return ret;
 }
 
-static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
+static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
                            struct iovec *iov, int niov, bool create,
                            enum AIOCBState aiocb_type)
 {
@@ -1059,29 +1170,25 @@
 
     /* send a header */
     ret = qemu_co_send(s->fd, &hdr, sizeof(hdr));
-    if (ret < 0) {
-        qemu_co_mutex_unlock(&s->lock);
+    if (ret != sizeof(hdr)) {
         error_report("failed to send a req, %s", strerror(errno));
-        return -errno;
+        goto out;
     }
 
     if (wlen) {
         ret = qemu_co_sendv(s->fd, iov, niov, aio_req->iov_offset, wlen);
-        if (ret < 0) {
-            qemu_co_mutex_unlock(&s->lock);
+        if (ret != wlen) {
             error_report("failed to send a data, %s", strerror(errno));
-            return -errno;
         }
     }
-
+out:
     socket_set_cork(s->fd, 0);
     qemu_aio_set_fd_handler(s->fd, co_read_response, NULL, s);
+    s->co_send = NULL;
     qemu_co_mutex_unlock(&s->lock);
-
-    return 0;
 }
 
-static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
+static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
                              unsigned int datalen, uint64_t offset,
                              bool write, bool create, uint32_t cache_flags)
 {
@@ -1129,7 +1236,7 @@
     }
 }
 
-static int read_object(int fd, char *buf, uint64_t oid, int copies,
+static int read_object(int fd, char *buf, uint64_t oid, uint8_t copies,
                        unsigned int datalen, uint64_t offset,
                        uint32_t cache_flags)
 {
@@ -1137,7 +1244,7 @@
                              false, cache_flags);
 }
 
-static int write_object(int fd, char *buf, uint64_t oid, int copies,
+static int write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
                         unsigned int datalen, uint64_t offset, bool create,
                         uint32_t cache_flags)
 {
@@ -1181,51 +1288,62 @@
     return ret;
 }
 
-static int coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
+/* Return true if the specified request is linked to the pending list. */
+static bool check_simultaneous_create(BDRVSheepdogState *s, AIOReq *aio_req)
+{
+    AIOReq *areq;
+    QLIST_FOREACH(areq, &s->inflight_aio_head, aio_siblings) {
+        if (areq != aio_req && areq->oid == aio_req->oid) {
+            /*
+             * Sheepdog cannot handle simultaneous create requests to the same
+             * object, so we cannot send the request until the previous request
+             * finishes.
+             */
+            DPRINTF("simultaneous create to %" PRIx64 "\n", aio_req->oid);
+            aio_req->flags = 0;
+            aio_req->base_oid = 0;
+            QLIST_REMOVE(aio_req, aio_siblings);
+            QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req, aio_siblings);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
 {
     SheepdogAIOCB *acb = aio_req->aiocb;
     bool create = false;
-    int ret;
-
-    ret = reload_inode(s, 0, "");
-    if (ret < 0) {
-        return ret;
-    }
-
-    aio_req->oid = vid_to_data_oid(s->inode.vdi_id,
-                                   data_oid_to_idx(aio_req->oid));
 
     /* check whether this request becomes a CoW one */
-    if (acb->aiocb_type == AIOCB_WRITE_UDATA) {
+    if (acb->aiocb_type == AIOCB_WRITE_UDATA && is_data_obj(aio_req->oid)) {
         int idx = data_oid_to_idx(aio_req->oid);
-        AIOReq *areq;
 
-        if (s->inode.data_vdi_id[idx] == 0) {
-            create = true;
-            goto out;
-        }
         if (is_data_obj_writable(&s->inode, idx)) {
             goto out;
         }
 
-        /* link to the pending list if there is another CoW request to
-         * the same object */
-        QLIST_FOREACH(areq, &s->inflight_aio_head, aio_siblings) {
-            if (areq != aio_req && areq->oid == aio_req->oid) {
-                DPRINTF("simultaneous CoW to %" PRIx64 "\n", aio_req->oid);
-                QLIST_REMOVE(aio_req, aio_siblings);
-                QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req, aio_siblings);
-                return SD_RES_SUCCESS;
-            }
+        if (check_simultaneous_create(s, aio_req)) {
+            return;
         }
 
-        aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);
-        aio_req->flags |= SD_FLAG_CMD_COW;
+        if (s->inode.data_vdi_id[idx]) {
+            aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);
+            aio_req->flags |= SD_FLAG_CMD_COW;
+        }
         create = true;
     }
 out:
-    return add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
-                           create, acb->aiocb_type);
+    if (is_data_obj(aio_req->oid)) {
+        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,
+                        acb->aiocb_type);
+    } else {
+        struct iovec iov;
+        iov.iov_base = &s->inode;
+        iov.iov_len = sizeof(s->inode);
+        add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
+    }
 }
 
 /* TODO Convert to fine grained options */
@@ -1255,6 +1373,8 @@
     Error *local_err = NULL;
     const char *filename;
 
+    s->bs = bs;
+
     opts = qemu_opts_create_nofail(&runtime_opts);
     qemu_opts_absorb_qdict(opts, options, &local_err);
     if (error_is_set(&local_err)) {
@@ -1268,6 +1388,7 @@
 
     QLIST_INIT(&s->inflight_aio_head);
     QLIST_INIT(&s->pending_aio_head);
+    QLIST_INIT(&s->failed_aio_head);
     s->fd = -1;
 
     memset(vdi, 0, sizeof(vdi));
@@ -1344,7 +1465,8 @@
 }
 
 static int do_sd_create(BDRVSheepdogState *s, char *filename, int64_t vdi_size,
-                        uint32_t base_vid, uint32_t *vdi_id, int snapshot)
+                        uint32_t base_vid, uint32_t *vdi_id, int snapshot,
+                        uint8_t copy_policy)
 {
     SheepdogVdiReq hdr;
     SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
@@ -1374,6 +1496,7 @@
 
     hdr.data_length = wlen;
     hdr.vdi_size = vdi_size;
+    hdr.copy_policy = copy_policy;
 
     ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
 
@@ -1526,7 +1649,8 @@
         bdrv_unref(bs);
     }
 
-    ret = do_sd_create(s, vdi, vdi_size, base_vid, &vid, 0);
+    /* TODO: allow users to specify copy number */
+    ret = do_sd_create(s, vdi, vdi_size, base_vid, &vid, 0, 0);
     if (!prealloc || ret) {
         goto out;
     }
@@ -1621,7 +1745,6 @@
  */
 static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
 {
-    int ret;
     BDRVSheepdogState *s = acb->common.bs->opaque;
     struct iovec iov;
     AIOReq *aio_req;
@@ -1643,18 +1766,13 @@
         aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
                                 data_len, offset, 0, 0, offset);
         QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
-        ret = add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
-        if (ret) {
-            free_aio_req(s, aio_req);
-            acb->ret = -EIO;
-            goto out;
-        }
+        add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
 
         acb->aio_done_func = sd_finish_aiocb;
         acb->aiocb_type = AIOCB_WRITE_UDATA;
         return;
     }
-out:
+
     sd_finish_aiocb(acb);
 }
 
@@ -1716,7 +1834,7 @@
      */
     deleted = sd_delete(s);
     ret = do_sd_create(s, s->name, s->inode.vdi_size, s->inode.vdi_id, &vid,
-                       !deleted);
+                       !deleted, s->inode.copy_policy);
     if (ret) {
         goto out;
     }
@@ -1840,35 +1958,16 @@
         }
 
         aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, old_oid, done);
+        QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
 
         if (create) {
-            AIOReq *areq;
-            QLIST_FOREACH(areq, &s->inflight_aio_head, aio_siblings) {
-                if (areq->oid == oid) {
-                    /*
-                     * Sheepdog cannot handle simultaneous create
-                     * requests to the same object.  So we cannot send
-                     * the request until the previous request
-                     * finishes.
-                     */
-                    aio_req->flags = 0;
-                    aio_req->base_oid = 0;
-                    QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req,
-                                      aio_siblings);
-                    goto done;
-                }
+            if (check_simultaneous_create(s, aio_req)) {
+                goto done;
             }
         }
 
-        QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
-        ret = add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
-                              create, acb->aiocb_type);
-        if (ret < 0) {
-            error_report("add_aio_request is failed");
-            free_aio_req(s, aio_req);
-            acb->ret = -EIO;
-            goto out;
-        }
+        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,
+                        acb->aiocb_type);
     done:
         offset = 0;
         idx++;
@@ -1936,7 +2035,6 @@
     BDRVSheepdogState *s = bs->opaque;
     SheepdogAIOCB *acb;
     AIOReq *aio_req;
-    int ret;
 
     if (s->cache_flags != SD_FLAG_CMD_CACHE) {
         return 0;
@@ -1949,13 +2047,7 @@
     aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
                             0, 0, 0, 0, 0);
     QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
-    ret = add_aio_request(s, aio_req, NULL, 0, false, acb->aiocb_type);
-    if (ret < 0) {
-        error_report("add_aio_request is failed");
-        free_aio_req(s, aio_req);
-        qemu_aio_release(acb);
-        return ret;
-    }
+    add_aio_request(s, aio_req, NULL, 0, false, acb->aiocb_type);
 
     qemu_coroutine_yield();
     return acb->ret;
@@ -2006,7 +2098,7 @@
     }
 
     ret = do_sd_create(s, s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid,
-                       1);
+                       1, s->inode.copy_policy);
     if (ret < 0) {
         error_report("failed to create inode for snapshot. %s",
                      strerror(errno));
diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c
new file mode 100644
index 0000000..fe879ed
--- /dev/null
+++ b/block/vhdx-endian.c
@@ -0,0 +1,216 @@
+/*
+ * Block driver for Hyper-V VHDX Images
+ *
+ * Copyright (c) 2013 Red Hat, Inc.,
+ *
+ * Authors:
+ *  Jeff Cody <jcody@redhat.com>
+ *
+ *  This is based on the "VHDX Format Specification v1.00", published 8/25/2012
+ *  by Microsoft:
+ *      https://www.microsoft.com/en-us/download/details.aspx?id=34750
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "block/block_int.h"
+#include "block/vhdx.h"
+
+#include <uuid/uuid.h>
+
+
+/*
+ * All the VHDX formats on disk are little endian - the following
+ * are helper import/export functions to correctly convert
+ * endianness from disk read to native cpu format, and back again.
+ */
+
+
+/* VHDX File Header */
+
+
+void vhdx_header_le_import(VHDXHeader *h)
+{
+    assert(h != NULL);
+
+    le32_to_cpus(&h->signature);
+    le32_to_cpus(&h->checksum);
+    le64_to_cpus(&h->sequence_number);
+
+    leguid_to_cpus(&h->file_write_guid);
+    leguid_to_cpus(&h->data_write_guid);
+    leguid_to_cpus(&h->log_guid);
+
+    le16_to_cpus(&h->log_version);
+    le16_to_cpus(&h->version);
+    le32_to_cpus(&h->log_length);
+    le64_to_cpus(&h->log_offset);
+}
+
+void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
+{
+    assert(orig_h != NULL);
+    assert(new_h != NULL);
+
+    new_h->signature       = cpu_to_le32(orig_h->signature);
+    new_h->checksum        = cpu_to_le32(orig_h->checksum);
+    new_h->sequence_number = cpu_to_le64(orig_h->sequence_number);
+
+    new_h->file_write_guid = orig_h->file_write_guid;
+    new_h->data_write_guid = orig_h->data_write_guid;
+    new_h->log_guid        = orig_h->log_guid;
+
+    cpu_to_leguids(&new_h->file_write_guid);
+    cpu_to_leguids(&new_h->data_write_guid);
+    cpu_to_leguids(&new_h->log_guid);
+
+    new_h->log_version     = cpu_to_le16(orig_h->log_version);
+    new_h->version         = cpu_to_le16(orig_h->version);
+    new_h->log_length      = cpu_to_le32(orig_h->log_length);
+    new_h->log_offset      = cpu_to_le64(orig_h->log_offset);
+}
+
+
+/* VHDX Log Headers */
+
+
+void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
+{
+    assert(d != NULL);
+
+    le32_to_cpus(&d->signature);
+    le32_to_cpus(&d->trailing_bytes);
+    le64_to_cpus(&d->leading_bytes);
+    le64_to_cpus(&d->file_offset);
+    le64_to_cpus(&d->sequence_number);
+}
+
+void vhdx_log_desc_le_export(VHDXLogDescriptor *d)
+{
+    assert(d != NULL);
+
+    cpu_to_le32s(&d->signature);
+    cpu_to_le32s(&d->trailing_bytes);
+    cpu_to_le64s(&d->leading_bytes);
+    cpu_to_le64s(&d->file_offset);
+    cpu_to_le64s(&d->sequence_number);
+}
+
+void vhdx_log_data_le_export(VHDXLogDataSector *d)
+{
+    assert(d != NULL);
+
+    cpu_to_le32s(&d->data_signature);
+    cpu_to_le32s(&d->sequence_high);
+    cpu_to_le32s(&d->sequence_low);
+}
+
+void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr)
+{
+    assert(hdr != NULL);
+
+    le32_to_cpus(&hdr->signature);
+    le32_to_cpus(&hdr->checksum);
+    le32_to_cpus(&hdr->entry_length);
+    le32_to_cpus(&hdr->tail);
+    le64_to_cpus(&hdr->sequence_number);
+    le32_to_cpus(&hdr->descriptor_count);
+    leguid_to_cpus(&hdr->log_guid);
+    le64_to_cpus(&hdr->flushed_file_offset);
+    le64_to_cpus(&hdr->last_file_offset);
+}
+
+void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr)
+{
+    assert(hdr != NULL);
+
+    cpu_to_le32s(&hdr->signature);
+    cpu_to_le32s(&hdr->checksum);
+    cpu_to_le32s(&hdr->entry_length);
+    cpu_to_le32s(&hdr->tail);
+    cpu_to_le64s(&hdr->sequence_number);
+    cpu_to_le32s(&hdr->descriptor_count);
+    cpu_to_leguids(&hdr->log_guid);
+    cpu_to_le64s(&hdr->flushed_file_offset);
+    cpu_to_le64s(&hdr->last_file_offset);
+}
+
+
+/* Region table entries */
+void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr)
+{
+    assert(hdr != NULL);
+
+    le32_to_cpus(&hdr->signature);
+    le32_to_cpus(&hdr->checksum);
+    le32_to_cpus(&hdr->entry_count);
+}
+
+void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr)
+{
+    assert(hdr != NULL);
+
+    cpu_to_le32s(&hdr->signature);
+    cpu_to_le32s(&hdr->checksum);
+    cpu_to_le32s(&hdr->entry_count);
+}
+
+void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
+{
+    assert(e != NULL);
+
+    leguid_to_cpus(&e->guid);
+    le64_to_cpus(&e->file_offset);
+    le32_to_cpus(&e->length);
+    le32_to_cpus(&e->data_bits);
+}
+
+void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
+{
+    assert(e != NULL);
+
+    cpu_to_leguids(&e->guid);
+    cpu_to_le64s(&e->file_offset);
+    cpu_to_le32s(&e->length);
+    cpu_to_le32s(&e->data_bits);
+}
+
+
+/* Metadata headers & table */
+void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr)
+{
+    assert(hdr != NULL);
+
+    le64_to_cpus(&hdr->signature);
+    le16_to_cpus(&hdr->entry_count);
+}
+
+void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr)
+{
+    assert(hdr != NULL);
+
+    cpu_to_le64s(&hdr->signature);
+    cpu_to_le16s(&hdr->entry_count);
+}
+
+void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
+{
+    assert(e != NULL);
+
+    leguid_to_cpus(&e->item_id);
+    le32_to_cpus(&e->offset);
+    le32_to_cpus(&e->length);
+    le32_to_cpus(&e->data_bits);
+}
+void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e)
+{
+    assert(e != NULL);
+
+    cpu_to_leguids(&e->item_id);
+    cpu_to_le32s(&e->offset);
+    cpu_to_le32s(&e->length);
+    cpu_to_le32s(&e->data_bits);
+}
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
new file mode 100644
index 0000000..ee5583c
--- /dev/null
+++ b/block/vhdx-log.c
@@ -0,0 +1,1010 @@
+/*
+ * Block driver for Hyper-V VHDX Images
+ *
+ * Copyright (c) 2013 Red Hat, Inc.,
+ *
+ * Authors:
+ *  Jeff Cody <jcody@redhat.com>
+ *
+ *  This is based on the "VHDX Format Specification v1.00", published 8/25/2012
+ *  by Microsoft:
+ *      https://www.microsoft.com/en-us/download/details.aspx?id=34750
+ *
+ * This file covers the functionality of the metadata log writing, parsing, and
+ * replay.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#include "qemu-common.h"
+#include "block/block_int.h"
+#include "qemu/module.h"
+#include "block/vhdx.h"
+
+
+typedef struct VHDXLogSequence {
+    bool valid;
+    uint32_t count;
+    VHDXLogEntries log;
+    VHDXLogEntryHeader hdr;
+} VHDXLogSequence;
+
+typedef struct VHDXLogDescEntries {
+    VHDXLogEntryHeader hdr;
+    VHDXLogDescriptor desc[];
+} VHDXLogDescEntries;
+
+static const MSGUID zero_guid = { 0 };
+
+/* The log located on the disk is circular buffer containing
+ * sectors of 4096 bytes each.
+ *
+ * It is assumed for the read/write functions below that the
+ * circular buffer scheme uses a 'one sector open' to indicate
+ * the buffer is full.  Given the validation methods used for each
+ * sector, this method should be compatible with other methods that
+ * do not waste a sector.
+ */
+
+
+/* Allow peeking at the hdr entry at the beginning of the current
+ * read index, without advancing the read index */
+static int vhdx_log_peek_hdr(BlockDriverState *bs, VHDXLogEntries *log,
+                             VHDXLogEntryHeader *hdr)
+{
+    int ret = 0;
+    uint64_t offset;
+    uint32_t read;
+
+    assert(hdr != NULL);
+
+    /* peek is only supported on sector boundaries */
+    if (log->read % VHDX_LOG_SECTOR_SIZE) {
+        ret = -EFAULT;
+        goto exit;
+    }
+
+    read = log->read;
+    /* we are guaranteed that a) log sectors are 4096 bytes,
+     * and b) the log length is a multiple of 1MB. So, there
+     * is always a round number of sectors in the buffer */
+    if ((read + sizeof(VHDXLogEntryHeader)) > log->length) {
+        read = 0;
+    }
+
+    if (read == log->write) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    offset = log->offset + read;
+
+    ret = bdrv_pread(bs->file, offset, hdr, sizeof(VHDXLogEntryHeader));
+    if (ret < 0) {
+        goto exit;
+    }
+
+exit:
+    return ret;
+}
+
+/* Index increment for log, based on sector boundaries */
+static int vhdx_log_inc_idx(uint32_t idx, uint64_t length)
+{
+    idx += VHDX_LOG_SECTOR_SIZE;
+    /* we are guaranteed that a) log sectors are 4096 bytes,
+     * and b) the log length is a multiple of 1MB. So, there
+     * is always a round number of sectors in the buffer */
+    return idx >= length ? 0 : idx;
+}
+
+
+/* Reset the log to empty */
+static void vhdx_log_reset(BlockDriverState *bs, BDRVVHDXState *s)
+{
+    MSGUID guid = { 0 };
+    s->log.read = s->log.write = 0;
+    /* a log guid of 0 indicates an empty log to any parser of v0
+     * VHDX logs */
+    vhdx_update_headers(bs, s, false, &guid);
+}
+
+/* Reads num_sectors from the log (all log sectors are 4096 bytes),
+ * into buffer 'buffer'.  Upon return, *sectors_read will contain
+ * the number of sectors successfully read.
+ *
+ * It is assumed that 'buffer' is already allocated, and of sufficient
+ * size (i.e. >= 4096*num_sectors).
+ *
+ * If 'peek' is true, then the tail (read) pointer for the circular buffer is
+ * not modified.
+ *
+ * 0 is returned on success, -errno otherwise.  */
+static int vhdx_log_read_sectors(BlockDriverState *bs, VHDXLogEntries *log,
+                                 uint32_t *sectors_read, void *buffer,
+                                 uint32_t num_sectors, bool peek)
+{
+    int ret = 0;
+    uint64_t offset;
+    uint32_t read;
+
+    read = log->read;
+
+    *sectors_read = 0;
+    while (num_sectors) {
+        if (read == log->write) {
+            /* empty */
+            break;
+        }
+        offset = log->offset + read;
+
+        ret = bdrv_pread(bs->file, offset, buffer, VHDX_LOG_SECTOR_SIZE);
+        if (ret < 0) {
+            goto exit;
+        }
+        read = vhdx_log_inc_idx(read, log->length);
+
+        *sectors_read = *sectors_read + 1;
+        num_sectors--;
+    }
+
+exit:
+    if (!peek) {
+        log->read = read;
+    }
+    return ret;
+}
+
+/* Writes num_sectors to the log (all log sectors are 4096 bytes),
+ * from buffer 'buffer'.  Upon return, *sectors_written will contain
+ * the number of sectors successfully written.
+ *
+ * It is assumed that 'buffer' is at least 4096*num_sectors large.
+ *
+ * 0 is returned on success, -errno otherwise */
+static int vhdx_log_write_sectors(BlockDriverState *bs, VHDXLogEntries *log,
+                                  uint32_t *sectors_written, void *buffer,
+                                  uint32_t num_sectors)
+{
+    int ret = 0;
+    uint64_t offset;
+    uint32_t write;
+    void *buffer_tmp;
+    BDRVVHDXState *s = bs->opaque;
+
+    ret = vhdx_user_visible_write(bs, s);
+    if (ret < 0) {
+        goto exit;
+    }
+
+    write = log->write;
+
+    buffer_tmp = buffer;
+    while (num_sectors) {
+
+        offset = log->offset + write;
+        write = vhdx_log_inc_idx(write, log->length);
+        if (write == log->read) {
+            /* full */
+            break;
+        }
+        ret = bdrv_pwrite(bs->file, offset, buffer_tmp, VHDX_LOG_SECTOR_SIZE);
+        if (ret < 0) {
+            goto exit;
+        }
+        buffer_tmp += VHDX_LOG_SECTOR_SIZE;
+
+        log->write = write;
+        *sectors_written = *sectors_written + 1;
+        num_sectors--;
+    }
+
+exit:
+    return ret;
+}
+
+
+/* Validates a log entry header */
+static bool vhdx_log_hdr_is_valid(VHDXLogEntries *log, VHDXLogEntryHeader *hdr,
+                                  BDRVVHDXState *s)
+{
+    int valid = false;
+
+    if (memcmp(&hdr->signature, "loge", 4)) {
+        goto exit;
+    }
+
+    /* if the individual entry length is larger than the whole log
+     * buffer, that is obviously invalid */
+    if (log->length < hdr->entry_length) {
+        goto exit;
+    }
+
+    /* length of entire entry must be in units of 4KB (log sector size) */
+    if (hdr->entry_length % (VHDX_LOG_SECTOR_SIZE)) {
+        goto exit;
+    }
+
+    /* per spec, sequence # must be > 0 */
+    if (hdr->sequence_number == 0) {
+        goto exit;
+    }
+
+    /* log entries are only valid if they match the file-wide log guid
+     * found in the active header */
+    if (!guid_eq(hdr->log_guid, s->headers[s->curr_header]->log_guid)) {
+        goto exit;
+    }
+
+    if (hdr->descriptor_count * sizeof(VHDXLogDescriptor) > hdr->entry_length) {
+        goto exit;
+    }
+
+    valid = true;
+
+exit:
+    return valid;
+}
+
+/*
+ * Given a log header, this will validate that the descriptors and the
+ * corresponding data sectors (if applicable)
+ *
+ * Validation consists of:
+ *      1. Making sure the sequence numbers matches the entry header
+ *      2. Verifying a valid signature ('zero' or 'desc' for descriptors)
+ *      3. File offset field is a multiple of 4KB
+ *      4. If a data descriptor, the corresponding data sector
+ *         has its signature ('data') and matching sequence number
+ *
+ * @desc: the data buffer containing the descriptor
+ * @hdr:  the log entry header
+ *
+ * Returns true if valid
+ */
+static bool vhdx_log_desc_is_valid(VHDXLogDescriptor *desc,
+                                   VHDXLogEntryHeader *hdr)
+{
+    bool ret = false;
+
+    if (desc->sequence_number != hdr->sequence_number) {
+        goto exit;
+    }
+    if (desc->file_offset % VHDX_LOG_SECTOR_SIZE) {
+        goto exit;
+    }
+
+    if (!memcmp(&desc->signature, "zero", 4)) {
+        if (desc->zero_length % VHDX_LOG_SECTOR_SIZE == 0) {
+            /* valid */
+            ret = true;
+        }
+    } else if (!memcmp(&desc->signature, "desc", 4)) {
+            /* valid */
+            ret = true;
+    }
+
+exit:
+    return ret;
+}
+
+
+/* Prior to sector data for a log entry, there is the header
+ * and the descriptors referenced in the header:
+ *
+ * [] = 4KB sector
+ *
+ * [ hdr, desc ][   desc   ][ ... ][ data ][ ... ]
+ *
+ * The first sector in a log entry has a 64 byte header, and
+ * up to 126 32-byte descriptors.  If more descriptors than
+ * 126 are required, then subsequent sectors can have up to 128
+ * descriptors.  Each sector is 4KB.  Data follows the descriptor
+ * sectors.
+ *
+ * This will return the number of sectors needed to encompass
+ * the passed number of descriptors in desc_cnt.
+ *
+ * This will never return 0, even if desc_cnt is 0.
+ */
+static int vhdx_compute_desc_sectors(uint32_t desc_cnt)
+{
+    uint32_t desc_sectors;
+
+    desc_cnt += 2; /* account for header in first sector */
+    desc_sectors = desc_cnt / 128;
+    if (desc_cnt % 128) {
+        desc_sectors++;
+    }
+
+    return desc_sectors;
+}
+
+
+/* Reads the log header, and subsequent descriptors (if any).  This
+ * will allocate all the space for buffer, which must be NULL when
+ * passed into this function. Each descriptor will also be validated,
+ * and error returned if any are invalid. */
+static int vhdx_log_read_desc(BlockDriverState *bs, BDRVVHDXState *s,
+                              VHDXLogEntries *log, VHDXLogDescEntries **buffer)
+{
+    int ret = 0;
+    uint32_t desc_sectors;
+    uint32_t sectors_read;
+    VHDXLogEntryHeader hdr;
+    VHDXLogDescEntries *desc_entries = NULL;
+    int i;
+
+    assert(*buffer == NULL);
+
+    ret = vhdx_log_peek_hdr(bs, log, &hdr);
+    if (ret < 0) {
+        goto exit;
+    }
+    vhdx_log_entry_hdr_le_import(&hdr);
+    if (vhdx_log_hdr_is_valid(log, &hdr, s) == false) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    desc_sectors = vhdx_compute_desc_sectors(hdr.descriptor_count);
+    desc_entries = qemu_blockalign(bs, desc_sectors * VHDX_LOG_SECTOR_SIZE);
+
+    ret = vhdx_log_read_sectors(bs, log, &sectors_read, desc_entries,
+                                desc_sectors, false);
+    if (ret < 0) {
+        goto free_and_exit;
+    }
+    if (sectors_read != desc_sectors) {
+        ret = -EINVAL;
+        goto free_and_exit;
+    }
+
+    /* put in proper endianness, and validate each desc */
+    for (i = 0; i < hdr.descriptor_count; i++) {
+        vhdx_log_desc_le_import(&desc_entries->desc[i]);
+        if (vhdx_log_desc_is_valid(&desc_entries->desc[i], &hdr) == false) {
+            ret = -EINVAL;
+            goto free_and_exit;
+        }
+    }
+
+    *buffer = desc_entries;
+    goto exit;
+
+free_and_exit:
+    qemu_vfree(desc_entries);
+exit:
+    return ret;
+}
+
+
+/* Flushes the descriptor described by desc to the VHDX image file.
+ * If the descriptor is a data descriptor, than 'data' must be non-NULL,
+ * and >= 4096 bytes (VHDX_LOG_SECTOR_SIZE), containing the data to be
+ * written.
+ *
+ * Verification is performed to make sure the sequence numbers of a data
+ * descriptor match the sequence number in the desc.
+ *
+ * For a zero descriptor, it may describe multiple sectors to fill with zeroes.
+ * In this case, it should be noted that zeroes are written to disk, and the
+ * image file is not extended as a sparse file.  */
+static int vhdx_log_flush_desc(BlockDriverState *bs, VHDXLogDescriptor *desc,
+                               VHDXLogDataSector *data)
+{
+    int ret = 0;
+    uint64_t seq, file_offset;
+    uint32_t offset = 0;
+    void *buffer = NULL;
+    uint64_t count = 1;
+    int i;
+
+    buffer = qemu_blockalign(bs, VHDX_LOG_SECTOR_SIZE);
+
+    if (!memcmp(&desc->signature, "desc", 4)) {
+        /* data sector */
+        if (data == NULL) {
+            ret = -EFAULT;
+            goto exit;
+        }
+
+        /* The sequence number of the data sector must match that
+         * in the descriptor */
+        seq = data->sequence_high;
+        seq <<= 32;
+        seq |= data->sequence_low & 0xffffffff;
+
+        if (seq != desc->sequence_number) {
+            ret = -EINVAL;
+            goto exit;
+        }
+
+        /* Each data sector is in total 4096 bytes, however the first
+         * 8 bytes, and last 4 bytes, are located in the descriptor */
+        memcpy(buffer, &desc->leading_bytes, 8);
+        offset += 8;
+
+        memcpy(buffer+offset, data->data, 4084);
+        offset += 4084;
+
+        memcpy(buffer+offset, &desc->trailing_bytes, 4);
+
+    } else if (!memcmp(&desc->signature, "zero", 4)) {
+        /* write 'count' sectors of sector */
+        memset(buffer, 0, VHDX_LOG_SECTOR_SIZE);
+        count = desc->zero_length / VHDX_LOG_SECTOR_SIZE;
+    }
+
+    file_offset = desc->file_offset;
+
+    /* count is only > 1 if we are writing zeroes */
+    for (i = 0; i < count; i++) {
+        ret = bdrv_pwrite_sync(bs->file, file_offset, buffer,
+                               VHDX_LOG_SECTOR_SIZE);
+        if (ret < 0) {
+            goto exit;
+        }
+        file_offset += VHDX_LOG_SECTOR_SIZE;
+    }
+
+exit:
+    qemu_vfree(buffer);
+    return ret;
+}
+
+/* Flush the entire log (as described by 'logs') to the VHDX image
+ * file, and then set the log to 'empty' status once complete.
+ *
+ * The log entries should be validate prior to flushing */
+static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
+                          VHDXLogSequence *logs)
+{
+    int ret = 0;
+    int i;
+    uint32_t cnt, sectors_read;
+    uint64_t new_file_size;
+    void *data = NULL;
+    VHDXLogDescEntries *desc_entries = NULL;
+    VHDXLogEntryHeader hdr_tmp = { 0 };
+
+    cnt = logs->count;
+
+    data = qemu_blockalign(bs, VHDX_LOG_SECTOR_SIZE);
+
+    ret = vhdx_user_visible_write(bs, s);
+    if (ret < 0) {
+        goto exit;
+    }
+
+    /* each iteration represents one log sequence, which may span multiple
+     * sectors */
+    while (cnt--) {
+        ret = vhdx_log_peek_hdr(bs, &logs->log, &hdr_tmp);
+        if (ret < 0) {
+            goto exit;
+        }
+        /* if the log shows a FlushedFileOffset larger than our current file
+         * size, then that means the file has been truncated / corrupted, and
+         * we must refused to open it / use it */
+        if (hdr_tmp.flushed_file_offset > bdrv_getlength(bs->file)) {
+            ret = -EINVAL;
+            goto exit;
+        }
+
+        ret = vhdx_log_read_desc(bs, s, &logs->log, &desc_entries);
+        if (ret < 0) {
+            goto exit;
+        }
+
+        for (i = 0; i < desc_entries->hdr.descriptor_count; i++) {
+            if (!memcmp(&desc_entries->desc[i].signature, "desc", 4)) {
+                /* data sector, so read a sector to flush */
+                ret = vhdx_log_read_sectors(bs, &logs->log, &sectors_read,
+                                            data, 1, false);
+                if (ret < 0) {
+                    goto exit;
+                }
+                if (sectors_read != 1) {
+                    ret = -EINVAL;
+                    goto exit;
+                }
+            }
+
+            ret = vhdx_log_flush_desc(bs, &desc_entries->desc[i], data);
+            if (ret < 0) {
+                goto exit;
+            }
+        }
+        if (bdrv_getlength(bs->file) < desc_entries->hdr.last_file_offset) {
+            new_file_size = desc_entries->hdr.last_file_offset;
+            if (new_file_size % (1024*1024)) {
+                /* round up to nearest 1MB boundary */
+                new_file_size = ((new_file_size >> 20) + 1) << 20;
+                bdrv_truncate(bs->file, new_file_size);
+            }
+        }
+        qemu_vfree(desc_entries);
+        desc_entries = NULL;
+    }
+
+    bdrv_flush(bs);
+    /* once the log is fully flushed, indicate that we have an empty log
+     * now.  This also sets the log guid to 0, to indicate an empty log */
+    vhdx_log_reset(bs, s);
+
+exit:
+    qemu_vfree(data);
+    qemu_vfree(desc_entries);
+    return ret;
+}
+
+static int vhdx_validate_log_entry(BlockDriverState *bs, BDRVVHDXState *s,
+                                   VHDXLogEntries *log, uint64_t seq,
+                                   bool *valid, VHDXLogEntryHeader *entry)
+{
+    int ret = 0;
+    VHDXLogEntryHeader hdr;
+    void *buffer = NULL;
+    uint32_t i, desc_sectors, total_sectors, crc;
+    uint32_t sectors_read = 0;
+    VHDXLogDescEntries *desc_buffer = NULL;
+
+    *valid = false;
+
+    ret = vhdx_log_peek_hdr(bs, log, &hdr);
+    if (ret < 0) {
+        goto inc_and_exit;
+    }
+
+    vhdx_log_entry_hdr_le_import(&hdr);
+
+
+    if (vhdx_log_hdr_is_valid(log, &hdr, s) == false) {
+        goto inc_and_exit;
+    }
+
+    if (seq > 0) {
+        if (hdr.sequence_number != seq + 1) {
+            goto inc_and_exit;
+        }
+    }
+
+    desc_sectors = vhdx_compute_desc_sectors(hdr.descriptor_count);
+
+    /* Read desc sectors, and calculate log checksum */
+
+    total_sectors = hdr.entry_length / VHDX_LOG_SECTOR_SIZE;
+
+
+    /* read_desc() will incrememnt the read idx */
+    ret = vhdx_log_read_desc(bs, s, log, &desc_buffer);
+    if (ret < 0) {
+        goto free_and_exit;
+    }
+
+    crc = vhdx_checksum_calc(0xffffffff, (void *)desc_buffer,
+                            desc_sectors * VHDX_LOG_SECTOR_SIZE, 4);
+    crc ^= 0xffffffff;
+
+    buffer = qemu_blockalign(bs, VHDX_LOG_SECTOR_SIZE);
+    if (total_sectors > desc_sectors) {
+        for (i = 0; i < total_sectors - desc_sectors; i++) {
+            sectors_read = 0;
+            ret = vhdx_log_read_sectors(bs, log, &sectors_read, buffer,
+                                        1, false);
+            if (ret < 0 || sectors_read != 1) {
+                goto free_and_exit;
+            }
+            crc = vhdx_checksum_calc(crc, buffer, VHDX_LOG_SECTOR_SIZE, -1);
+            crc ^= 0xffffffff;
+        }
+    }
+    crc ^= 0xffffffff;
+    if (crc != desc_buffer->hdr.checksum) {
+        goto free_and_exit;
+    }
+
+    *valid = true;
+    *entry = hdr;
+    goto free_and_exit;
+
+inc_and_exit:
+    log->read = vhdx_log_inc_idx(log->read, log->length);
+
+free_and_exit:
+    qemu_vfree(buffer);
+    qemu_vfree(desc_buffer);
+    return ret;
+}
+
+/* Search through the log circular buffer, and find the valid, active
+ * log sequence, if any exists
+ * */
+static int vhdx_log_search(BlockDriverState *bs, BDRVVHDXState *s,
+                           VHDXLogSequence *logs)
+{
+    int ret = 0;
+    uint32_t tail;
+    bool seq_valid = false;
+    VHDXLogSequence candidate = { 0 };
+    VHDXLogEntryHeader hdr = { 0 };
+    VHDXLogEntries curr_log;
+
+    memcpy(&curr_log, &s->log, sizeof(VHDXLogEntries));
+    curr_log.write = curr_log.length;   /* assume log is full */
+    curr_log.read = 0;
+
+
+    /* now we will go through the whole log sector by sector, until
+     * we find a valid, active log sequence, or reach the end of the
+     * log buffer */
+    for (;;) {
+        uint64_t curr_seq = 0;
+        VHDXLogSequence current = { 0 };
+
+        tail = curr_log.read;
+
+        ret = vhdx_validate_log_entry(bs, s, &curr_log, curr_seq,
+                                      &seq_valid, &hdr);
+        if (ret < 0) {
+            goto exit;
+        }
+
+        if (seq_valid) {
+            current.valid     = true;
+            current.log       = curr_log;
+            current.log.read  = tail;
+            current.log.write = curr_log.read;
+            current.count     = 1;
+            current.hdr       = hdr;
+
+
+            for (;;) {
+                ret = vhdx_validate_log_entry(bs, s, &curr_log, curr_seq,
+                                              &seq_valid, &hdr);
+                if (ret < 0) {
+                    goto exit;
+                }
+                if (seq_valid == false) {
+                    break;
+                }
+                current.log.write = curr_log.read;
+                current.count++;
+
+                curr_seq = hdr.sequence_number;
+            }
+        }
+
+        if (current.valid) {
+            if (candidate.valid == false ||
+                current.hdr.sequence_number > candidate.hdr.sequence_number) {
+                candidate = current;
+            }
+        }
+
+        if (curr_log.read < tail) {
+            break;
+        }
+    }
+
+    *logs = candidate;
+
+    if (candidate.valid) {
+        /* this is the next sequence number, for writes */
+        s->log.sequence = candidate.hdr.sequence_number + 1;
+    }
+
+
+exit:
+    return ret;
+}
+
+/* Parse the replay log.  Per the VHDX spec, if the log is present
+ * it must be replayed prior to opening the file, even read-only.
+ *
+ * If read-only, we must replay the log in RAM (or refuse to open
+ * a dirty VHDX file read-only) */
+int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed)
+{
+    int ret = 0;
+    VHDXHeader *hdr;
+    VHDXLogSequence logs = { 0 };
+
+    hdr = s->headers[s->curr_header];
+
+    *flushed = false;
+
+    /* s->log.hdr is freed in vhdx_close() */
+    if (s->log.hdr == NULL) {
+        s->log.hdr = qemu_blockalign(bs, sizeof(VHDXLogEntryHeader));
+    }
+
+    s->log.offset = hdr->log_offset;
+    s->log.length = hdr->log_length;
+
+    if (s->log.offset < VHDX_LOG_MIN_SIZE ||
+        s->log.offset % VHDX_LOG_MIN_SIZE) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    /* per spec, only log version of 0 is supported */
+    if (hdr->log_version != 0) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    /* If either the log guid, or log length is zero,
+     * then a replay log is not present */
+    if (guid_eq(hdr->log_guid, zero_guid)) {
+        goto exit;
+    }
+
+    if (hdr->log_length == 0) {
+        goto exit;
+    }
+
+    if (hdr->log_length % VHDX_LOG_MIN_SIZE) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+
+    /* The log is present, we need to find if and where there is an active
+     * sequence of valid entries present in the log.  */
+
+    ret = vhdx_log_search(bs, s, &logs);
+    if (ret < 0) {
+        goto exit;
+    }
+
+    if (logs.valid) {
+        /* now flush the log */
+        ret = vhdx_log_flush(bs, s, &logs);
+        if (ret < 0) {
+            goto exit;
+        }
+        *flushed = true;
+    }
+
+
+exit:
+    return ret;
+}
+
+
+
+static void vhdx_log_raw_to_le_sector(VHDXLogDescriptor *desc,
+                                      VHDXLogDataSector *sector, void *data,
+                                      uint64_t seq)
+{
+    /* 8 + 4084 + 4 = 4096, 1 log sector */
+    memcpy(&desc->leading_bytes, data, 8);
+    data += 8;
+    cpu_to_le64s(&desc->leading_bytes);
+    memcpy(sector->data, data, 4084);
+    data += 4084;
+    memcpy(&desc->trailing_bytes, data, 4);
+    cpu_to_le32s(&desc->trailing_bytes);
+    data += 4;
+
+    sector->sequence_high  = (uint32_t) (seq >> 32);
+    sector->sequence_low   = (uint32_t) (seq & 0xffffffff);
+    sector->data_signature = VHDX_LOG_DATA_SIGNATURE;
+
+    vhdx_log_desc_le_export(desc);
+    vhdx_log_data_le_export(sector);
+}
+
+
+static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
+                          void *data, uint32_t length, uint64_t offset)
+{
+    int ret = 0;
+    void *buffer = NULL;
+    void *merged_sector = NULL;
+    void *data_tmp, *sector_write;
+    unsigned int i;
+    int sector_offset;
+    uint32_t desc_sectors, sectors, total_length;
+    uint32_t sectors_written = 0;
+    uint32_t aligned_length;
+    uint32_t leading_length = 0;
+    uint32_t trailing_length = 0;
+    uint32_t partial_sectors = 0;
+    uint32_t bytes_written = 0;
+    uint64_t file_offset;
+    VHDXHeader *header;
+    VHDXLogEntryHeader new_hdr;
+    VHDXLogDescriptor *new_desc = NULL;
+    VHDXLogDataSector *data_sector = NULL;
+    MSGUID new_guid = { 0 };
+
+    header = s->headers[s->curr_header];
+
+    /* need to have offset read data, and be on 4096 byte boundary */
+
+    if (length > header->log_length) {
+        /* no log present.  we could create a log here instead of failing */
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    if (guid_eq(header->log_guid, zero_guid)) {
+        vhdx_guid_generate(&new_guid);
+        vhdx_update_headers(bs, s, false, &new_guid);
+    } else {
+        /* currently, we require that the log be flushed after
+         * every write. */
+        ret = -ENOTSUP;
+        goto exit;
+    }
+
+    /* 0 is an invalid sequence number, but may also represent the first
+     * log write (or a wrapped seq) */
+    if (s->log.sequence == 0) {
+        s->log.sequence = 1;
+    }
+
+    sector_offset = offset % VHDX_LOG_SECTOR_SIZE;
+    file_offset = (offset / VHDX_LOG_SECTOR_SIZE) * VHDX_LOG_SECTOR_SIZE;
+
+    aligned_length = length;
+
+    /* add in the unaligned head and tail bytes */
+    if (sector_offset) {
+        leading_length = (VHDX_LOG_SECTOR_SIZE - sector_offset);
+        leading_length = leading_length > length ? length : leading_length;
+        aligned_length -= leading_length;
+        partial_sectors++;
+    }
+
+    sectors = aligned_length / VHDX_LOG_SECTOR_SIZE;
+    trailing_length = aligned_length - (sectors * VHDX_LOG_SECTOR_SIZE);
+    if (trailing_length) {
+        partial_sectors++;
+    }
+
+    sectors += partial_sectors;
+
+    /* sectors is now how many sectors the data itself takes, not
+     * including the header and descriptor metadata */
+
+    new_hdr = (VHDXLogEntryHeader) {
+                .signature           = VHDX_LOG_SIGNATURE,
+                .tail                = s->log.tail,
+                .sequence_number     = s->log.sequence,
+                .descriptor_count    = sectors,
+                .reserved            = 0,
+                .flushed_file_offset = bdrv_getlength(bs->file),
+                .last_file_offset    = bdrv_getlength(bs->file),
+              };
+
+    new_hdr.log_guid = header->log_guid;
+
+    desc_sectors = vhdx_compute_desc_sectors(new_hdr.descriptor_count);
+
+    total_length = (desc_sectors + sectors) * VHDX_LOG_SECTOR_SIZE;
+    new_hdr.entry_length = total_length;
+
+    vhdx_log_entry_hdr_le_export(&new_hdr);
+
+    buffer = qemu_blockalign(bs, total_length);
+    memcpy(buffer, &new_hdr, sizeof(new_hdr));
+
+    new_desc = (VHDXLogDescriptor *) (buffer + sizeof(new_hdr));
+    data_sector = buffer + (desc_sectors * VHDX_LOG_SECTOR_SIZE);
+    data_tmp = data;
+
+    /* All log sectors are 4KB, so for any partial sectors we must
+     * merge the data with preexisting data from the final file
+     * destination */
+    merged_sector = qemu_blockalign(bs, VHDX_LOG_SECTOR_SIZE);
+
+    for (i = 0; i < sectors; i++) {
+        new_desc->signature       = VHDX_LOG_DESC_SIGNATURE;
+        new_desc->sequence_number = s->log.sequence;
+        new_desc->file_offset     = file_offset;
+
+        if (i == 0 && leading_length) {
+            /* partial sector at the front of the buffer */
+            ret = bdrv_pread(bs->file, file_offset, merged_sector,
+                             VHDX_LOG_SECTOR_SIZE);
+            if (ret < 0) {
+                goto exit;
+            }
+            memcpy(merged_sector + sector_offset, data_tmp, leading_length);
+            bytes_written = leading_length;
+            sector_write = merged_sector;
+        } else if (i == sectors - 1 && trailing_length) {
+            /* partial sector at the end of the buffer */
+            ret = bdrv_pread(bs->file,
+                            file_offset,
+                            merged_sector + trailing_length,
+                            VHDX_LOG_SECTOR_SIZE - trailing_length);
+            if (ret < 0) {
+                goto exit;
+            }
+            memcpy(merged_sector, data_tmp, trailing_length);
+            bytes_written = trailing_length;
+            sector_write = merged_sector;
+        } else {
+            bytes_written = VHDX_LOG_SECTOR_SIZE;
+            sector_write = data_tmp;
+        }
+
+        /* populate the raw sector data into the proper structures,
+         * as well as update the descriptor, and convert to proper
+         * endianness */
+        vhdx_log_raw_to_le_sector(new_desc, data_sector, sector_write,
+                                  s->log.sequence);
+
+        data_tmp += bytes_written;
+        data_sector++;
+        new_desc++;
+        file_offset += VHDX_LOG_SECTOR_SIZE;
+    }
+
+    /* checksum covers entire entry, from the log header through the
+     * last data sector */
+    vhdx_update_checksum(buffer, total_length,
+                         offsetof(VHDXLogEntryHeader, checksum));
+    cpu_to_le32s((uint32_t *)(buffer + 4));
+
+    /* now write to the log */
+    vhdx_log_write_sectors(bs, &s->log, &sectors_written, buffer,
+                           desc_sectors + sectors);
+    if (ret < 0) {
+        goto exit;
+    }
+
+    if (sectors_written != desc_sectors + sectors) {
+        /* instead of failing, we could flush the log here */
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    s->log.sequence++;
+    /* write new tail */
+    s->log.tail = s->log.write;
+
+exit:
+    qemu_vfree(buffer);
+    qemu_vfree(merged_sector);
+    return ret;
+}
+
+/* Perform a log write, and then immediately flush the entire log */
+int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
+                             void *data, uint32_t length, uint64_t offset)
+{
+    int ret = 0;
+    VHDXLogSequence logs = { .valid = true,
+                             .count = 1,
+                             .hdr = { 0 } };
+
+
+    /* Make sure data written (new and/or changed blocks) is stable
+     * on disk, before creating log entry */
+    bdrv_flush(bs);
+    ret = vhdx_log_write(bs, s, data, length, offset);
+    if (ret < 0) {
+        goto exit;
+    }
+    logs.log = s->log;
+
+    /* Make sure log is stable on disk */
+    bdrv_flush(bs);
+    ret = vhdx_log_flush(bs, s, &logs);
+    if (ret < 0) {
+        goto exit;
+    }
+
+    s->log = logs.log;
+
+exit:
+    return ret;
+}
+
diff --git a/block/vhdx.c b/block/vhdx.c
index 6cb0412..7d1af96 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -6,9 +6,9 @@
  * Authors:
  *  Jeff Cody <jcody@redhat.com>
  *
- *  This is based on the "VHDX Format Specification v0.95", published 4/12/2012
+ *  This is based on the "VHDX Format Specification v1.00", published 8/25/2012
  *  by Microsoft:
- *      https://www.microsoft.com/en-us/download/details.aspx?id=29681
+ *      https://www.microsoft.com/en-us/download/details.aspx?id=34750
  *
  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
  * See the COPYING.LIB file in the top-level directory.
@@ -22,6 +22,20 @@
 #include "block/vhdx.h"
 #include "migration/migration.h"
 
+#include <uuid/uuid.h>
+#include <glib.h>
+
+/* Options for VHDX creation */
+
+#define VHDX_BLOCK_OPT_LOG_SIZE   "log_size"
+#define VHDX_BLOCK_OPT_BLOCK_SIZE "block_size"
+#define VHDX_BLOCK_OPT_ZERO "block_state_zero"
+
+typedef enum VHDXImageType {
+    VHDX_TYPE_DYNAMIC = 0,
+    VHDX_TYPE_FIXED,
+    VHDX_TYPE_DIFFERENCING,   /* Currently unsupported */
+} VHDXImageType;
 
 /* Several metadata and region table data entries are identified by
  * guids in  a MS-specific GUID format. */
@@ -104,16 +118,6 @@
      META_PAGE_83_PRESENT | META_LOGICAL_SECTOR_SIZE_PRESENT | \
      META_PHYS_SECTOR_SIZE_PRESENT)
 
-typedef struct VHDXMetadataEntries {
-    VHDXMetadataTableEntry file_parameters_entry;
-    VHDXMetadataTableEntry virtual_disk_size_entry;
-    VHDXMetadataTableEntry page83_data_entry;
-    VHDXMetadataTableEntry logical_sector_size_entry;
-    VHDXMetadataTableEntry phys_sector_size_entry;
-    VHDXMetadataTableEntry parent_locator_entry;
-    uint16_t present;
-} VHDXMetadataEntries;
-
 
 typedef struct VHDXSectorInfo {
     uint32_t bat_idx;       /* BAT entry index */
@@ -124,44 +128,31 @@
     uint64_t block_offset;  /* block offset, in bytes */
 } VHDXSectorInfo;
 
+/* Calculates new checksum.
+ *
+ * Zero is substituted during crc calculation for the original crc field
+ * crc_offset: byte offset in buf of the buffer crc
+ * buf: buffer pointer
+ * size: size of buffer (must be > crc_offset+4)
+ *
+ * Note: The resulting checksum is in the CPU endianness, not necessarily
+ *       in the file format endianness (LE).  Any header export to disk should
+ *       make sure that vhdx_header_le_export() is used to convert to the
+ *       correct endianness
+ */
+uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset)
+{
+    uint32_t crc;
 
+    assert(buf != NULL);
+    assert(size > (crc_offset + sizeof(crc)));
 
-typedef struct BDRVVHDXState {
-    CoMutex lock;
+    memset(buf + crc_offset, 0, sizeof(crc));
+    crc =  crc32c(0xffffffff, buf, size);
+    memcpy(buf + crc_offset, &crc, sizeof(crc));
 
-    int curr_header;
-    VHDXHeader *headers[2];
-
-    VHDXRegionTableHeader rt;
-    VHDXRegionTableEntry bat_rt;         /* region table for the BAT */
-    VHDXRegionTableEntry metadata_rt;    /* region table for the metadata */
-
-    VHDXMetadataTableHeader metadata_hdr;
-    VHDXMetadataEntries metadata_entries;
-
-    VHDXFileParameters params;
-    uint32_t block_size;
-    uint32_t block_size_bits;
-    uint32_t sectors_per_block;
-    uint32_t sectors_per_block_bits;
-
-    uint64_t virtual_disk_size;
-    uint32_t logical_sector_size;
-    uint32_t physical_sector_size;
-
-    uint64_t chunk_ratio;
-    uint32_t chunk_ratio_bits;
-    uint32_t logical_sector_size_bits;
-
-    uint32_t bat_entries;
-    VHDXBatEntry *bat;
-    uint64_t bat_offset;
-
-    VHDXParentLocatorHeader parent_header;
-    VHDXParentLocatorEntry *parent_entries;
-
-    Error *migration_blocker;
-} BDRVVHDXState;
+    return crc;
+}
 
 uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
                             int crc_offset)
@@ -214,6 +205,71 @@
 
 
 /*
+ * This generates a UUID that is compliant with the MS GUIDs used
+ * in the VHDX spec (and elsewhere).
+ */
+void vhdx_guid_generate(MSGUID *guid)
+{
+    uuid_t uuid;
+    assert(guid != NULL);
+
+    uuid_generate(uuid);
+    memcpy(guid, uuid, sizeof(MSGUID));
+}
+
+/* Check for region overlaps inside the VHDX image */
+static int vhdx_region_check(BDRVVHDXState *s, uint64_t start, uint64_t length)
+{
+    int ret = 0;
+    uint64_t end;
+    VHDXRegionEntry *r;
+
+    end = start + length;
+    QLIST_FOREACH(r, &s->regions, entries) {
+        if (!((start >= r->end) || (end <= r->start))) {
+            ret = -EINVAL;
+            goto exit;
+        }
+    }
+
+exit:
+    return ret;
+}
+
+/* Register a region for future checks */
+static void vhdx_region_register(BDRVVHDXState *s,
+                                 uint64_t start, uint64_t length)
+{
+    VHDXRegionEntry *r;
+
+    r = g_malloc0(sizeof(*r));
+
+    r->start = start;
+    r->end = start + length;
+
+    QLIST_INSERT_HEAD(&s->regions, r, entries);
+}
+
+/* Free all registered regions */
+static void vhdx_region_unregister_all(BDRVVHDXState *s)
+{
+    VHDXRegionEntry *r, *r_next;
+
+    QLIST_FOREACH_SAFE(r, &s->regions, entries, r_next) {
+        QLIST_REMOVE(r, entries);
+        g_free(r);
+    }
+}
+
+static void vhdx_set_shift_bits(BDRVVHDXState *s)
+{
+    s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size);
+    s->sectors_per_block_bits =   31 - clz32(s->sectors_per_block);
+    s->chunk_ratio_bits =         63 - clz64(s->chunk_ratio);
+    s->block_size_bits =          31 - clz32(s->block_size);
+}
+
+/*
  * Per the MS VHDX Specification, for every VHDX file:
  *      - The header section is fixed size - 1 MB
  *      - The header section is always the first "object"
@@ -232,25 +288,118 @@
     return 0;
 }
 
-/* All VHDX structures on disk are little endian */
-static void vhdx_header_le_import(VHDXHeader *h)
+/*
+ * Writes the header to the specified offset.
+ *
+ * This will optionally read in buffer data from disk (otherwise zero-fill),
+ * and then update the header checksum.  Header is converted to proper
+ * endianness before being written to the specified file offset
+ */
+static int vhdx_write_header(BlockDriverState *bs_file, VHDXHeader *hdr,
+                             uint64_t offset, bool read)
 {
-    assert(h != NULL);
+    uint8_t *buffer = NULL;
+    int ret;
+    VHDXHeader header_le;
 
-    le32_to_cpus(&h->signature);
-    le32_to_cpus(&h->checksum);
-    le64_to_cpus(&h->sequence_number);
+    assert(bs_file != NULL);
+    assert(hdr != NULL);
 
-    leguid_to_cpus(&h->file_write_guid);
-    leguid_to_cpus(&h->data_write_guid);
-    leguid_to_cpus(&h->log_guid);
+    /* the header checksum is not over just the packed size of VHDXHeader,
+     * but rather over the entire 'reserved' range for the header, which is
+     * 4KB (VHDX_HEADER_SIZE). */
 
-    le16_to_cpus(&h->log_version);
-    le16_to_cpus(&h->version);
-    le32_to_cpus(&h->log_length);
-    le64_to_cpus(&h->log_offset);
+    buffer = qemu_blockalign(bs_file, VHDX_HEADER_SIZE);
+    if (read) {
+        /* if true, we can't assume the extra reserved bytes are 0 */
+        ret = bdrv_pread(bs_file, offset, buffer, VHDX_HEADER_SIZE);
+        if (ret < 0) {
+            goto exit;
+        }
+    } else {
+        memset(buffer, 0, VHDX_HEADER_SIZE);
+    }
+
+    /* overwrite the actual VHDXHeader portion */
+    memcpy(buffer, hdr, sizeof(VHDXHeader));
+    hdr->checksum = vhdx_update_checksum(buffer, VHDX_HEADER_SIZE,
+                                         offsetof(VHDXHeader, checksum));
+    vhdx_header_le_export(hdr, &header_le);
+    ret = bdrv_pwrite_sync(bs_file, offset, &header_le, sizeof(VHDXHeader));
+
+exit:
+    qemu_vfree(buffer);
+    return ret;
 }
 
+/* Update the VHDX headers
+ *
+ * This follows the VHDX spec procedures for header updates.
+ *
+ *  - non-current header is updated with largest sequence number
+ */
+static int vhdx_update_header(BlockDriverState *bs, BDRVVHDXState *s,
+                              bool generate_data_write_guid, MSGUID *log_guid)
+{
+    int ret = 0;
+    int hdr_idx = 0;
+    uint64_t header_offset = VHDX_HEADER1_OFFSET;
+
+    VHDXHeader *active_header;
+    VHDXHeader *inactive_header;
+
+    /* operate on the non-current header */
+    if (s->curr_header == 0) {
+        hdr_idx = 1;
+        header_offset = VHDX_HEADER2_OFFSET;
+    }
+
+    active_header   = s->headers[s->curr_header];
+    inactive_header = s->headers[hdr_idx];
+
+    inactive_header->sequence_number = active_header->sequence_number + 1;
+
+    /* a new file guid must be generated before any file write, including
+     * headers */
+    inactive_header->file_write_guid = s->session_guid;
+
+    /* a new data guid only needs to be generated before any guest-visible
+     * writes (i.e. something observable via virtual disk read) */
+    if (generate_data_write_guid) {
+        vhdx_guid_generate(&inactive_header->data_write_guid);
+    }
+
+    /* update the log guid if present */
+    if (log_guid) {
+        inactive_header->log_guid = *log_guid;
+    }
+
+    vhdx_write_header(bs->file, inactive_header, header_offset, true);
+    if (ret < 0) {
+        goto exit;
+    }
+    s->curr_header = hdr_idx;
+
+exit:
+    return ret;
+}
+
+/*
+ * The VHDX spec calls for header updates to be performed twice, so that both
+ * the current and non-current header have valid info
+ */
+int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s,
+                        bool generate_data_write_guid, MSGUID *log_guid)
+{
+    int ret;
+
+    ret = vhdx_update_header(bs, s, generate_data_write_guid, log_guid);
+    if (ret < 0) {
+        return ret;
+    }
+    ret = vhdx_update_header(bs, s, generate_data_write_guid, log_guid);
+    return ret;
+}
 
 /* opens the specified header block from the VHDX file header section */
 static int vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s)
@@ -264,6 +413,7 @@
     uint64_t h2_seq = 0;
     uint8_t *buffer;
 
+    /* header1 & header2 are freed in vhdx_close() */
     header1 = qemu_blockalign(bs, sizeof(VHDXHeader));
     header2 = qemu_blockalign(bs, sizeof(VHDXHeader));
 
@@ -328,6 +478,9 @@
         }
     }
 
+    vhdx_region_register(s, s->headers[s->curr_header]->log_offset,
+                            s->headers[s->curr_header]->log_length);
+
     ret = 0;
 
     goto exit;
@@ -364,10 +517,7 @@
         goto fail;
     }
     memcpy(&s->rt, buffer, sizeof(s->rt));
-    le32_to_cpus(&s->rt.signature);
-    le32_to_cpus(&s->rt.checksum);
-    le32_to_cpus(&s->rt.entry_count);
-    le32_to_cpus(&s->rt.reserved);
+    vhdx_region_header_le_import(&s->rt);
     offset += sizeof(s->rt);
 
     if (!vhdx_checksum_is_valid(buffer, VHDX_HEADER_BLOCK_SIZE, 4) ||
@@ -386,10 +536,16 @@
         memcpy(&rt_entry, buffer + offset, sizeof(rt_entry));
         offset += sizeof(rt_entry);
 
-        leguid_to_cpus(&rt_entry.guid);
-        le64_to_cpus(&rt_entry.file_offset);
-        le32_to_cpus(&rt_entry.length);
-        le32_to_cpus(&rt_entry.data_bits);
+        vhdx_region_entry_le_import(&rt_entry);
+
+        /* check for region overlap between these entries, and any
+         * other memory regions in the file */
+        ret = vhdx_region_check(s, rt_entry.file_offset, rt_entry.length);
+        if (ret < 0) {
+            goto fail;
+        }
+
+        vhdx_region_register(s, rt_entry.file_offset, rt_entry.length);
 
         /* see if we recognize the entry */
         if (guid_eq(rt_entry.guid, bat_guid)) {
@@ -421,6 +577,12 @@
             goto fail;
         }
     }
+
+    if (!bat_rt_found || !metadata_rt_found) {
+        ret = -EINVAL;
+        goto fail;
+    }
+
     ret = 0;
 
 fail:
@@ -464,9 +626,7 @@
     memcpy(&s->metadata_hdr, buffer, sizeof(s->metadata_hdr));
     offset += sizeof(s->metadata_hdr);
 
-    le64_to_cpus(&s->metadata_hdr.signature);
-    le16_to_cpus(&s->metadata_hdr.reserved);
-    le16_to_cpus(&s->metadata_hdr.entry_count);
+    vhdx_metadata_header_le_import(&s->metadata_hdr);
 
     if (memcmp(&s->metadata_hdr.signature, "metadata", 8)) {
         ret = -EINVAL;
@@ -485,11 +645,7 @@
         memcpy(&md_entry, buffer + offset, sizeof(md_entry));
         offset += sizeof(md_entry);
 
-        leguid_to_cpus(&md_entry.item_id);
-        le32_to_cpus(&md_entry.offset);
-        le32_to_cpus(&md_entry.length);
-        le32_to_cpus(&md_entry.data_bits);
-        le32_to_cpus(&md_entry.reserved2);
+        vhdx_metadata_entry_le_import(&md_entry);
 
         if (guid_eq(md_entry.item_id, file_param_guid)) {
             if (s->metadata_entries.present & META_FILE_PARAMETER_PRESENT) {
@@ -662,10 +818,7 @@
         goto exit;
     }
 
-    s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size);
-    s->sectors_per_block_bits =   31 - clz32(s->sectors_per_block);
-    s->chunk_ratio_bits =         63 - clz64(s->chunk_ratio);
-    s->block_size_bits =          31 - clz32(s->block_size);
+    vhdx_set_shift_bits(s);
 
     ret = 0;
 
@@ -674,98 +827,14 @@
     return ret;
 }
 
-/* Parse the replay log.  Per the VHDX spec, if the log is present
- * it must be replayed prior to opening the file, even read-only.
- *
- * If read-only, we must replay the log in RAM (or refuse to open
- * a dirty VHDX file read-only */
-static int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s)
+/*
+ * Calculate the number of BAT entries, including sector
+ * bitmap entries.
+ */
+static void vhdx_calc_bat_entries(BDRVVHDXState *s)
 {
-    int ret = 0;
-    int i;
-    VHDXHeader *hdr;
-
-    hdr = s->headers[s->curr_header];
-
-    /* either the log guid, or log length is zero,
-     * then a replay log is present */
-    for (i = 0; i < sizeof(hdr->log_guid.data4); i++) {
-        ret |= hdr->log_guid.data4[i];
-    }
-    if (hdr->log_guid.data1 == 0 &&
-        hdr->log_guid.data2 == 0 &&
-        hdr->log_guid.data3 == 0 &&
-        ret == 0) {
-        goto exit;
-    }
-
-    /* per spec, only log version of 0 is supported */
-    if (hdr->log_version != 0) {
-        ret = -EINVAL;
-        goto exit;
-    }
-
-    if (hdr->log_length == 0) {
-        goto exit;
-    }
-
-    /* We currently do not support images with logs to replay */
-    ret = -ENOTSUP;
-
-exit:
-    return ret;
-}
-
-
-static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
-                     Error **errp)
-{
-    BDRVVHDXState *s = bs->opaque;
-    int ret = 0;
-    uint32_t i;
-    uint64_t signature;
     uint32_t data_blocks_cnt, bitmap_blocks_cnt;
 
-
-    s->bat = NULL;
-
-    qemu_co_mutex_init(&s->lock);
-
-    /* validate the file signature */
-    ret = bdrv_pread(bs->file, 0, &signature, sizeof(uint64_t));
-    if (ret < 0) {
-        goto fail;
-    }
-    if (memcmp(&signature, "vhdxfile", 8)) {
-        ret = -EINVAL;
-        goto fail;
-    }
-
-    ret = vhdx_parse_header(bs, s);
-    if (ret) {
-        goto fail;
-    }
-
-    ret = vhdx_parse_log(bs, s);
-    if (ret) {
-        goto fail;
-    }
-
-    ret = vhdx_open_region_tables(bs, s);
-    if (ret) {
-        goto fail;
-    }
-
-    ret = vhdx_parse_metadata(bs, s);
-    if (ret) {
-        goto fail;
-    }
-    s->block_size = s->params.block_size;
-
-    /* the VHDX spec dictates that virtual_disk_size is always a multiple of
-     * logical_sector_size */
-    bs->total_sectors = s->virtual_disk_size >> s->logical_sector_size_bits;
-
     data_blocks_cnt = s->virtual_disk_size >> s->block_size_bits;
     if (s->virtual_disk_size - (data_blocks_cnt << s->block_size_bits)) {
         data_blocks_cnt++;
@@ -782,6 +851,85 @@
                          ((data_blocks_cnt - 1) >> s->chunk_ratio_bits);
     }
 
+}
+
+static void vhdx_close(BlockDriverState *bs)
+{
+    BDRVVHDXState *s = bs->opaque;
+    qemu_vfree(s->headers[0]);
+    s->headers[0] = NULL;
+    qemu_vfree(s->headers[1]);
+    s->headers[1] = NULL;
+    qemu_vfree(s->bat);
+    s->bat = NULL;
+    qemu_vfree(s->parent_entries);
+    s->parent_entries = NULL;
+    migrate_del_blocker(s->migration_blocker);
+    error_free(s->migration_blocker);
+    qemu_vfree(s->log.hdr);
+    s->log.hdr = NULL;
+    vhdx_region_unregister_all(s);
+}
+
+static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
+                     Error **errp)
+{
+    BDRVVHDXState *s = bs->opaque;
+    int ret = 0;
+    uint32_t i;
+    uint64_t signature;
+    bool log_flushed = false;
+
+
+    s->bat = NULL;
+    s->first_visible_write = true;
+
+    qemu_co_mutex_init(&s->lock);
+    QLIST_INIT(&s->regions);
+
+    /* validate the file signature */
+    ret = bdrv_pread(bs->file, 0, &signature, sizeof(uint64_t));
+    if (ret < 0) {
+        goto fail;
+    }
+    if (memcmp(&signature, "vhdxfile", 8)) {
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    /* This is used for any header updates, for the file_write_guid.
+     * The spec dictates that a new value should be used for the first
+     * header update */
+    vhdx_guid_generate(&s->session_guid);
+
+    ret = vhdx_parse_header(bs, s);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    ret = vhdx_parse_log(bs, s, &log_flushed);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    ret = vhdx_open_region_tables(bs, s);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    ret = vhdx_parse_metadata(bs, s);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    s->block_size = s->params.block_size;
+
+    /* the VHDX spec dictates that virtual_disk_size is always a multiple of
+     * logical_sector_size */
+    bs->total_sectors = s->virtual_disk_size >> s->logical_sector_size_bits;
+
+    vhdx_calc_bat_entries(s);
+
     s->bat_offset = s->bat_rt.file_offset;
 
     if (s->bat_entries > s->bat_rt.length / sizeof(VHDXBatEntry)) {
@@ -790,6 +938,7 @@
         goto fail;
     }
 
+    /* s->bat is freed in vhdx_close() */
     s->bat = qemu_blockalign(bs, s->bat_rt.length);
 
     ret = bdrv_pread(bs->file, s->bat_offset, s->bat, s->bat_rt.length);
@@ -797,16 +946,36 @@
         goto fail;
     }
 
+    uint64_t payblocks = s->chunk_ratio;
+    /* endian convert, and verify populated BAT field file offsets against
+     * region table and log entries */
     for (i = 0; i < s->bat_entries; i++) {
         le64_to_cpus(&s->bat[i]);
+        if (payblocks--) {
+            /* payload bat entries */
+            if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
+                    PAYLOAD_BLOCK_FULLY_PRESENT) {
+                ret = vhdx_region_check(s, s->bat[i] & VHDX_BAT_FILE_OFF_MASK,
+                                        s->block_size);
+                if (ret < 0) {
+                    goto fail;
+                }
+            }
+        } else {
+            payblocks = s->chunk_ratio;
+            /* Once differencing files are supported, verify sector bitmap
+             * blocks here */
+        }
     }
 
     if (flags & BDRV_O_RDWR) {
-        ret = -ENOTSUP;
-        goto fail;
+        ret = vhdx_update_headers(bs, s, false, NULL);
+        if (ret < 0) {
+            goto fail;
+        }
     }
 
-    /* TODO: differencing files, write */
+    /* TODO: differencing files */
 
     /* Disable migration when VHDX images are used */
     error_set(&s->migration_blocker,
@@ -816,10 +985,7 @@
 
     return 0;
 fail:
-    qemu_vfree(s->headers[0]);
-    qemu_vfree(s->headers[1]);
-    qemu_vfree(s->bat);
-    qemu_vfree(s->parent_entries);
+    vhdx_close(bs);
     return ret;
 }
 
@@ -859,7 +1025,7 @@
 
     sinfo->bytes_avail = sinfo->sectors_avail << s->logical_sector_size_bits;
 
-    sinfo->file_offset = s->bat[sinfo->bat_idx] >> VHDX_BAT_FILE_OFF_BITS;
+    sinfo->file_offset = s->bat[sinfo->bat_idx] & VHDX_BAT_FILE_OFF_MASK;
 
     sinfo->block_offset = block_offset << s->logical_sector_size_bits;
 
@@ -873,7 +1039,6 @@
      * in the block, and add in the payload data block offset
      * in the file, in bytes, to get the final read address */
 
-    sinfo->file_offset <<= 20;  /* now in bytes, rather than 1MB units */
     sinfo->file_offset += sinfo->block_offset;
 }
 
@@ -914,7 +1079,7 @@
                 /* return zero */
                 qemu_iovec_memset(&hd_qiov, 0, 0, sinfo.bytes_avail);
                 break;
-            case PAYLOAD_BLOCK_FULL_PRESENT:
+            case PAYLOAD_BLOCK_FULLY_PRESENT:
                 qemu_co_mutex_unlock(&s->lock);
                 ret = bdrv_co_readv(bs->file,
                                     sinfo.file_offset >> BDRV_SECTOR_BITS,
@@ -944,26 +1109,772 @@
     return ret;
 }
 
+/*
+ * Allocate a new payload block at the end of the file.
+ *
+ * Allocation will happen at 1MB alignment inside the file
+ *
+ * Returns the file offset start of the new payload block
+ */
+static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
+                                    uint64_t *new_offset)
+{
+    *new_offset = bdrv_getlength(bs->file);
 
+    /* per the spec, the address for a block is in units of 1MB */
+    *new_offset = ROUND_UP(*new_offset, 1024 * 1024);
+
+    return bdrv_truncate(bs->file, *new_offset + s->block_size);
+}
+
+/*
+ * Update the BAT table entry with the new file offset, and the new entry
+ * state */
+static void vhdx_update_bat_table_entry(BlockDriverState *bs, BDRVVHDXState *s,
+                                       VHDXSectorInfo *sinfo,
+                                       uint64_t *bat_entry_le,
+                                       uint64_t *bat_offset, int state)
+{
+    /* The BAT entry is a uint64, with 44 bits for the file offset in units of
+     * 1MB, and 3 bits for the block state. */
+    s->bat[sinfo->bat_idx]  = sinfo->file_offset;
+
+    s->bat[sinfo->bat_idx] |= state & VHDX_BAT_STATE_BIT_MASK;
+
+    *bat_entry_le = cpu_to_le64(s->bat[sinfo->bat_idx]);
+    *bat_offset = s->bat_offset + sinfo->bat_idx * sizeof(VHDXBatEntry);
+
+}
+
+/* Per the spec, on the first write of guest-visible data to the file the
+ * data write guid must be updated in the header */
+int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s)
+{
+    int ret = 0;
+    if (s->first_visible_write) {
+        s->first_visible_write = false;
+        ret = vhdx_update_headers(bs, s, true, NULL);
+    }
+    return ret;
+}
 
 static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
                                       int nb_sectors, QEMUIOVector *qiov)
 {
-    return -ENOTSUP;
-}
-
-
-static void vhdx_close(BlockDriverState *bs)
-{
+    int ret = -ENOTSUP;
     BDRVVHDXState *s = bs->opaque;
-    qemu_vfree(s->headers[0]);
-    qemu_vfree(s->headers[1]);
-    qemu_vfree(s->bat);
-    qemu_vfree(s->parent_entries);
-    migrate_del_blocker(s->migration_blocker);
-    error_free(s->migration_blocker);
+    VHDXSectorInfo sinfo;
+    uint64_t bytes_done = 0;
+    uint64_t bat_entry = 0;
+    uint64_t bat_entry_offset = 0;
+    QEMUIOVector hd_qiov;
+    struct iovec iov1 = { 0 };
+    struct iovec iov2 = { 0 };
+    int sectors_to_write;
+    int bat_state;
+    uint64_t bat_prior_offset = 0;
+    bool bat_update = false;
+
+    qemu_iovec_init(&hd_qiov, qiov->niov);
+
+    qemu_co_mutex_lock(&s->lock);
+
+    ret = vhdx_user_visible_write(bs, s);
+    if (ret < 0) {
+        goto exit;
+    }
+
+    while (nb_sectors > 0) {
+        bool use_zero_buffers = false;
+        bat_update = false;
+        if (s->params.data_bits & VHDX_PARAMS_HAS_PARENT) {
+            /* not supported yet */
+            ret = -ENOTSUP;
+            goto exit;
+        } else {
+            vhdx_block_translate(s, sector_num, nb_sectors, &sinfo);
+            sectors_to_write = sinfo.sectors_avail;
+
+            qemu_iovec_reset(&hd_qiov);
+            /* check the payload block state */
+            bat_state = s->bat[sinfo.bat_idx] & VHDX_BAT_STATE_BIT_MASK;
+            switch (bat_state) {
+            case PAYLOAD_BLOCK_ZERO:
+                /* in this case, we need to preserve zero writes for
+                 * data that is not part of this write, so we must pad
+                 * the rest of the buffer to zeroes */
+
+                /* if we are on a posix system with ftruncate() that extends
+                 * a file, then it is zero-filled for us.  On Win32, the raw
+                 * layer uses SetFilePointer and SetFileEnd, which does not
+                 * zero fill AFAIK */
+
+                /* Queue another write of zero buffers if the underlying file
+                 * does not zero-fill on file extension */
+
+                if (bdrv_has_zero_init(bs->file) == 0) {
+                    use_zero_buffers = true;
+
+                    /* zero fill the front, if any */
+                    if (sinfo.block_offset) {
+                        iov1.iov_len = sinfo.block_offset;
+                        iov1.iov_base = qemu_blockalign(bs, iov1.iov_len);
+                        memset(iov1.iov_base, 0, iov1.iov_len);
+                        qemu_iovec_concat_iov(&hd_qiov, &iov1, 1, 0,
+                                              sinfo.block_offset);
+                        sectors_to_write += iov1.iov_len >> BDRV_SECTOR_BITS;
+                    }
+
+                    /* our actual data */
+                    qemu_iovec_concat(&hd_qiov, qiov,  bytes_done,
+                                      sinfo.bytes_avail);
+
+                    /* zero fill the back, if any */
+                    if ((sinfo.bytes_avail - sinfo.block_offset) <
+                         s->block_size) {
+                        iov2.iov_len = s->block_size -
+                                      (sinfo.bytes_avail + sinfo.block_offset);
+                        iov2.iov_base = qemu_blockalign(bs, iov2.iov_len);
+                        memset(iov2.iov_base, 0, iov2.iov_len);
+                        qemu_iovec_concat_iov(&hd_qiov, &iov2, 1, 0,
+                                              sinfo.block_offset);
+                        sectors_to_write += iov2.iov_len >> BDRV_SECTOR_BITS;
+                    }
+                }
+
+                /* fall through */
+            case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */
+            case PAYLOAD_BLOCK_UNMAPPED:    /* fall through */
+            case PAYLOAD_BLOCK_UNDEFINED:   /* fall through */
+                bat_prior_offset = sinfo.file_offset;
+                ret = vhdx_allocate_block(bs, s, &sinfo.file_offset);
+                if (ret < 0) {
+                    goto exit;
+                }
+                /* once we support differencing files, this may also be
+                 * partially present */
+                /* update block state to the newly specified state */
+                vhdx_update_bat_table_entry(bs, s, &sinfo, &bat_entry,
+                                            &bat_entry_offset,
+                                            PAYLOAD_BLOCK_FULLY_PRESENT);
+                bat_update = true;
+                /* since we just allocated a block, file_offset is the
+                 * beginning of the payload block. It needs to be the
+                 * write address, which includes the offset into the block */
+                if (!use_zero_buffers) {
+                    sinfo.file_offset += sinfo.block_offset;
+                }
+                /* fall through */
+            case PAYLOAD_BLOCK_FULLY_PRESENT:
+                /* if the file offset address is in the header zone,
+                 * there is a problem */
+                if (sinfo.file_offset < (1024 * 1024)) {
+                    ret = -EFAULT;
+                    goto error_bat_restore;
+                }
+
+                if (!use_zero_buffers) {
+                    qemu_iovec_concat(&hd_qiov, qiov,  bytes_done,
+                                      sinfo.bytes_avail);
+                }
+                /* block exists, so we can just overwrite it */
+                qemu_co_mutex_unlock(&s->lock);
+                ret = bdrv_co_writev(bs->file,
+                                    sinfo.file_offset >> BDRV_SECTOR_BITS,
+                                    sectors_to_write, &hd_qiov);
+                qemu_co_mutex_lock(&s->lock);
+                if (ret < 0) {
+                    goto error_bat_restore;
+                }
+                break;
+            case PAYLOAD_BLOCK_PARTIALLY_PRESENT:
+                /* we don't yet support difference files, fall through
+                 * to error */
+            default:
+                ret = -EIO;
+                goto exit;
+                break;
+            }
+
+            if (bat_update) {
+                /* this will update the BAT entry into the log journal, and
+                 * then flush the log journal out to disk */
+                ret =  vhdx_log_write_and_flush(bs, s, &bat_entry,
+                                                sizeof(VHDXBatEntry),
+                                                bat_entry_offset);
+                if (ret < 0) {
+                    goto exit;
+                }
+            }
+
+            nb_sectors -= sinfo.sectors_avail;
+            sector_num += sinfo.sectors_avail;
+            bytes_done += sinfo.bytes_avail;
+
+        }
+    }
+
+    goto exit;
+
+error_bat_restore:
+    if (bat_update) {
+        /* keep metadata in sync, and restore the bat entry state
+         * if error. */
+        sinfo.file_offset = bat_prior_offset;
+        vhdx_update_bat_table_entry(bs, s, &sinfo, &bat_entry,
+                                    &bat_entry_offset, bat_state);
+    }
+exit:
+    qemu_vfree(iov1.iov_base);
+    qemu_vfree(iov2.iov_base);
+    qemu_co_mutex_unlock(&s->lock);
+    qemu_iovec_destroy(&hd_qiov);
+    return ret;
 }
 
+
+
+/*
+ * Create VHDX Headers
+ *
+ * There are 2 headers, and the highest sequence number will represent
+ * the active header
+ */
+static int vhdx_create_new_headers(BlockDriverState *bs, uint64_t image_size,
+                                   uint32_t log_size)
+{
+    int ret = 0;
+    VHDXHeader *hdr = NULL;
+
+    hdr = g_malloc0(sizeof(VHDXHeader));
+
+    hdr->signature       = VHDX_HEADER_SIGNATURE;
+    hdr->sequence_number = g_random_int();
+    hdr->log_version     = 0;
+    hdr->version         = 1;
+    hdr->log_length      = log_size;
+    hdr->log_offset      = VHDX_HEADER_SECTION_END;
+    vhdx_guid_generate(&hdr->file_write_guid);
+    vhdx_guid_generate(&hdr->data_write_guid);
+
+    ret = vhdx_write_header(bs, hdr, VHDX_HEADER1_OFFSET, false);
+    if (ret < 0) {
+        goto exit;
+    }
+    hdr->sequence_number++;
+    ret = vhdx_write_header(bs, hdr, VHDX_HEADER2_OFFSET, false);
+    if (ret < 0) {
+        goto exit;
+    }
+
+exit:
+    g_free(hdr);
+    return ret;
+}
+
+
+/*
+ * Create the Metadata entries.
+ *
+ * For more details on the entries, see section 3.5 (pg 29) in the
+ * VHDX 1.00 specification.
+ *
+ * We support 5 metadata entries (all required by spec):
+ *          File Parameters,
+ *          Virtual Disk Size,
+ *          Page 83 Data,
+ *          Logical Sector Size,
+ *          Physical Sector Size
+ *
+ * The first 64KB of the Metadata section is reserved for the metadata
+ * header and entries; beyond that, the metadata items themselves reside.
+ */
+static int vhdx_create_new_metadata(BlockDriverState *bs,
+                                    uint64_t image_size,
+                                    uint32_t block_size,
+                                    uint32_t sector_size,
+                                    uint64_t metadata_offset,
+                                    VHDXImageType type)
+{
+    int ret = 0;
+    uint32_t offset = 0;
+    void *buffer = NULL;
+    void *entry_buffer;
+    VHDXMetadataTableHeader *md_table;;
+    VHDXMetadataTableEntry  *md_table_entry;
+
+    /* Metadata entries */
+    VHDXFileParameters     *mt_file_params;
+    VHDXVirtualDiskSize    *mt_virtual_size;
+    VHDXPage83Data         *mt_page83;
+    VHDXVirtualDiskLogicalSectorSize  *mt_log_sector_size;
+    VHDXVirtualDiskPhysicalSectorSize *mt_phys_sector_size;
+
+    entry_buffer = g_malloc0(sizeof(VHDXFileParameters)               +
+                             sizeof(VHDXVirtualDiskSize)              +
+                             sizeof(VHDXPage83Data)                   +
+                             sizeof(VHDXVirtualDiskLogicalSectorSize) +
+                             sizeof(VHDXVirtualDiskPhysicalSectorSize));
+
+    mt_file_params = entry_buffer;
+    offset += sizeof(VHDXFileParameters);
+    mt_virtual_size = entry_buffer + offset;
+    offset += sizeof(VHDXVirtualDiskSize);
+    mt_page83 = entry_buffer + offset;
+    offset += sizeof(VHDXPage83Data);
+    mt_log_sector_size = entry_buffer + offset;
+    offset += sizeof(VHDXVirtualDiskLogicalSectorSize);
+    mt_phys_sector_size = entry_buffer + offset;
+
+    mt_file_params->block_size = cpu_to_le32(block_size);
+    if (type == VHDX_TYPE_FIXED) {
+        mt_file_params->data_bits |= VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED;
+        cpu_to_le32s(&mt_file_params->data_bits);
+    }
+
+    vhdx_guid_generate(&mt_page83->page_83_data);
+    cpu_to_leguids(&mt_page83->page_83_data);
+    mt_virtual_size->virtual_disk_size        = cpu_to_le64(image_size);
+    mt_log_sector_size->logical_sector_size   = cpu_to_le32(sector_size);
+    mt_phys_sector_size->physical_sector_size = cpu_to_le32(sector_size);
+
+    buffer = g_malloc0(VHDX_HEADER_BLOCK_SIZE);
+    md_table = buffer;
+
+    md_table->signature   = VHDX_METADATA_SIGNATURE;
+    md_table->entry_count = 5;
+    vhdx_metadata_header_le_export(md_table);
+
+
+    /* This will reference beyond the reserved table portion */
+    offset = 64 * KiB;
+
+    md_table_entry = buffer + sizeof(VHDXMetadataTableHeader);
+
+    md_table_entry[0].item_id = file_param_guid;
+    md_table_entry[0].offset  = offset;
+    md_table_entry[0].length  = sizeof(VHDXFileParameters);
+    md_table_entry[0].data_bits |= VHDX_META_FLAGS_IS_REQUIRED;
+    offset += md_table_entry[0].length;
+    vhdx_metadata_entry_le_export(&md_table_entry[0]);
+
+    md_table_entry[1].item_id = virtual_size_guid;
+    md_table_entry[1].offset  = offset;
+    md_table_entry[1].length  = sizeof(VHDXVirtualDiskSize);
+    md_table_entry[1].data_bits |= VHDX_META_FLAGS_IS_REQUIRED |
+                                   VHDX_META_FLAGS_IS_VIRTUAL_DISK;
+    offset += md_table_entry[1].length;
+    vhdx_metadata_entry_le_export(&md_table_entry[1]);
+
+    md_table_entry[2].item_id = page83_guid;
+    md_table_entry[2].offset  = offset;
+    md_table_entry[2].length  = sizeof(VHDXPage83Data);
+    md_table_entry[2].data_bits |= VHDX_META_FLAGS_IS_REQUIRED |
+                                   VHDX_META_FLAGS_IS_VIRTUAL_DISK;
+    offset += md_table_entry[2].length;
+    vhdx_metadata_entry_le_export(&md_table_entry[2]);
+
+    md_table_entry[3].item_id = logical_sector_guid;
+    md_table_entry[3].offset  = offset;
+    md_table_entry[3].length  = sizeof(VHDXVirtualDiskLogicalSectorSize);
+    md_table_entry[3].data_bits |= VHDX_META_FLAGS_IS_REQUIRED |
+                                   VHDX_META_FLAGS_IS_VIRTUAL_DISK;
+    offset += md_table_entry[3].length;
+    vhdx_metadata_entry_le_export(&md_table_entry[3]);
+
+    md_table_entry[4].item_id = phys_sector_guid;
+    md_table_entry[4].offset  = offset;
+    md_table_entry[4].length  = sizeof(VHDXVirtualDiskPhysicalSectorSize);
+    md_table_entry[4].data_bits |= VHDX_META_FLAGS_IS_REQUIRED |
+                                   VHDX_META_FLAGS_IS_VIRTUAL_DISK;
+    vhdx_metadata_entry_le_export(&md_table_entry[4]);
+
+    ret = bdrv_pwrite(bs, metadata_offset, buffer, VHDX_HEADER_BLOCK_SIZE);
+    if (ret < 0) {
+        goto exit;
+    }
+
+    ret = bdrv_pwrite(bs, metadata_offset + (64 * KiB), entry_buffer,
+                      VHDX_HEADER_BLOCK_SIZE);
+    if (ret < 0) {
+        goto exit;
+    }
+
+
+exit:
+    g_free(buffer);
+    g_free(entry_buffer);
+    return ret;
+}
+
+/* This create the actual BAT itself.  We currently only support
+ * 'Dynamic' and 'Fixed' image types.
+ *
+ *  Dynamic images: default state of the BAT is all zeroes.
+ *
+ *  Fixed images: default state of the BAT is fully populated, with
+ *                file offsets and state PAYLOAD_BLOCK_FULLY_PRESENT.
+ */
+static int vhdx_create_bat(BlockDriverState *bs, BDRVVHDXState *s,
+                           uint64_t image_size, VHDXImageType type,
+                           bool use_zero_blocks, VHDXRegionTableEntry *rt_bat)
+{
+    int ret = 0;
+    uint64_t data_file_offset;
+    uint64_t total_sectors = 0;
+    uint64_t sector_num = 0;
+    uint64_t unused;
+    int block_state;
+    VHDXSectorInfo sinfo;
+
+    assert(s->bat == NULL);
+
+    /* this gives a data start after BAT/bitmap entries, and well
+     * past any metadata entries (with a 4 MB buffer for future
+     * expansion */
+    data_file_offset = rt_bat->file_offset + rt_bat->length + 5 * MiB;
+    total_sectors = image_size >> s->logical_sector_size_bits;
+
+    if (type == VHDX_TYPE_DYNAMIC) {
+        /* All zeroes, so we can just extend the file - the end of the BAT
+         * is the furthest thing we have written yet */
+        ret = bdrv_truncate(bs, data_file_offset);
+        if (ret < 0) {
+            goto exit;
+        }
+    } else if (type == VHDX_TYPE_FIXED) {
+        ret = bdrv_truncate(bs, data_file_offset + image_size);
+        if (ret < 0) {
+            goto exit;
+        }
+    } else {
+        ret = -ENOTSUP;
+        goto exit;
+    }
+
+    if (type == VHDX_TYPE_FIXED ||
+                use_zero_blocks ||
+                bdrv_has_zero_init(bs) == 0) {
+        /* for a fixed file, the default BAT entry is not zero */
+        s->bat = g_malloc0(rt_bat->length);
+        block_state = type == VHDX_TYPE_FIXED ? PAYLOAD_BLOCK_FULLY_PRESENT :
+                                                PAYLOAD_BLOCK_NOT_PRESENT;
+        block_state = use_zero_blocks ? PAYLOAD_BLOCK_ZERO : block_state;
+        /* fill the BAT by emulating sector writes of sectors_per_block size */
+        while (sector_num < total_sectors) {
+            vhdx_block_translate(s, sector_num, s->sectors_per_block, &sinfo);
+            sinfo.file_offset = data_file_offset +
+                                (sector_num << s->logical_sector_size_bits);
+            sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
+            vhdx_update_bat_table_entry(bs, s, &sinfo, &unused, &unused,
+                                        block_state);
+            cpu_to_le64s(&s->bat[sinfo.bat_idx]);
+            sector_num += s->sectors_per_block;
+        }
+        ret = bdrv_pwrite(bs, rt_bat->file_offset, s->bat, rt_bat->length);
+        if (ret < 0) {
+            goto exit;
+        }
+    }
+
+
+
+exit:
+    g_free(s->bat);
+    return ret;
+}
+
+/* Creates the region table header, and region table entries.
+ * There are 2 supported region table entries: BAT, and Metadata/
+ *
+ * As the calculations for the BAT region table are also needed
+ * to create the BAT itself, we will also cause the BAT to be
+ * created.
+ */
+static int vhdx_create_new_region_table(BlockDriverState *bs,
+                                        uint64_t image_size,
+                                        uint32_t block_size,
+                                        uint32_t sector_size,
+                                        uint32_t log_size,
+                                        bool use_zero_blocks,
+                                        VHDXImageType type,
+                                        uint64_t *metadata_offset)
+{
+    int ret = 0;
+    uint32_t offset = 0;
+    void *buffer = NULL;
+    BDRVVHDXState *s = NULL;
+    VHDXRegionTableHeader *region_table;
+    VHDXRegionTableEntry *rt_bat;
+    VHDXRegionTableEntry *rt_metadata;
+
+    assert(metadata_offset != NULL);
+
+    /* Populate enough of the BDRVVHDXState to be able to use the
+     * pre-existing BAT calculation, translation, and update functions */
+    s = g_malloc0(sizeof(BDRVVHDXState));
+
+    s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *
+                     (uint64_t) sector_size / (uint64_t) block_size;
+
+    s->sectors_per_block = block_size / sector_size;
+    s->virtual_disk_size = image_size;
+    s->block_size = block_size;
+    s->logical_sector_size = sector_size;
+
+    vhdx_set_shift_bits(s);
+
+    vhdx_calc_bat_entries(s);
+
+    /* At this point the VHDX state is populated enough for creation */
+
+    /* a single buffer is used so we can calculate the checksum over the
+     * entire 64KB block */
+    buffer = g_malloc0(VHDX_HEADER_BLOCK_SIZE);
+    region_table = buffer;
+    offset += sizeof(VHDXRegionTableHeader);
+    rt_bat = buffer + offset;
+    offset += sizeof(VHDXRegionTableEntry);
+    rt_metadata  = buffer + offset;
+
+    region_table->signature = VHDX_REGION_SIGNATURE;
+    region_table->entry_count = 2;   /* BAT and Metadata */
+
+    rt_bat->guid        = bat_guid;
+    rt_bat->length      = ROUND_UP(s->bat_entries * sizeof(VHDXBatEntry), MiB);
+    rt_bat->file_offset = ROUND_UP(VHDX_HEADER_SECTION_END + log_size, MiB);
+    s->bat_offset = rt_bat->file_offset;
+
+    rt_metadata->guid        = metadata_guid;
+    rt_metadata->file_offset = ROUND_UP(rt_bat->file_offset + rt_bat->length,
+                                        MiB);
+    rt_metadata->length      = 1 * MiB; /* min size, and more than enough */
+    *metadata_offset = rt_metadata->file_offset;
+
+    vhdx_update_checksum(buffer, VHDX_HEADER_BLOCK_SIZE,
+                         offsetof(VHDXRegionTableHeader, checksum));
+
+
+    /* The region table gives us the data we need to create the BAT,
+     * so do that now */
+    ret = vhdx_create_bat(bs, s, image_size, type, use_zero_blocks, rt_bat);
+
+    /* Now write out the region headers to disk */
+    vhdx_region_header_le_export(region_table);
+    vhdx_region_entry_le_export(rt_bat);
+    vhdx_region_entry_le_export(rt_metadata);
+
+    ret = bdrv_pwrite(bs, VHDX_REGION_TABLE_OFFSET, buffer,
+                      VHDX_HEADER_BLOCK_SIZE);
+    if (ret < 0) {
+        goto exit;
+    }
+
+    ret = bdrv_pwrite(bs, VHDX_REGION_TABLE2_OFFSET, buffer,
+                      VHDX_HEADER_BLOCK_SIZE);
+    if (ret < 0) {
+        goto exit;
+    }
+
+
+exit:
+    g_free(s);
+    g_free(buffer);
+    return ret;
+}
+
+/* We need to create the following elements:
+ *
+ *    .-----------------------------------------------------------------.
+ *    |   (A)    |   (B)    |    (C)    |     (D)       |     (E)       |
+ *    |  File ID |  Header1 |  Header 2 |  Region Tbl 1 |  Region Tbl 2 |
+ *    |          |          |           |               |               |
+ *    .-----------------------------------------------------------------.
+ *    0         64KB      128KB       192KB           256KB           320KB
+ *
+ *
+ *    .---- ~ ----------- ~ ------------ ~ ---------------- ~ -----------.
+ *    |     (F)     |     (G)       |    (H)    |                        |
+ *    | Journal Log |  BAT / Bitmap |  Metadata |  .... data ......      |
+ *    |             |               |           |                        |
+ *    .---- ~ ----------- ~ ------------ ~ ---------------- ~ -----------.
+ *   1MB
+ */
+static int vhdx_create(const char *filename, QEMUOptionParameter *options,
+                       Error **errp)
+{
+    int ret = 0;
+    uint64_t image_size = (uint64_t) 2 * GiB;
+    uint32_t log_size   = 1 * MiB;
+    uint32_t block_size = 0;
+    uint64_t signature;
+    uint64_t metadata_offset;
+    bool use_zero_blocks = false;
+
+    gunichar2 *creator = NULL;
+    glong creator_items;
+    BlockDriverState *bs;
+    const char *type = NULL;
+    VHDXImageType image_type;
+    Error *local_err = NULL;
+
+    while (options && options->name) {
+        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+            image_size = options->value.n;
+        } else if (!strcmp(options->name, VHDX_BLOCK_OPT_LOG_SIZE)) {
+            log_size = options->value.n;
+        } else if (!strcmp(options->name, VHDX_BLOCK_OPT_BLOCK_SIZE)) {
+            block_size = options->value.n;
+        } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
+            type = options->value.s;
+        } else if (!strcmp(options->name, VHDX_BLOCK_OPT_ZERO)) {
+            use_zero_blocks = options->value.n != 0;
+        }
+        options++;
+    }
+
+    if (image_size > VHDX_MAX_IMAGE_SIZE) {
+        error_setg_errno(errp, EINVAL, "Image size too large; max of 64TB");
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    if (type == NULL) {
+        type = "dynamic";
+    }
+
+    if (!strcmp(type, "dynamic")) {
+        image_type = VHDX_TYPE_DYNAMIC;
+    } else if (!strcmp(type, "fixed")) {
+        image_type = VHDX_TYPE_FIXED;
+    } else if (!strcmp(type, "differencing")) {
+        error_setg_errno(errp, ENOTSUP,
+                         "Differencing files not yet supported");
+        ret = -ENOTSUP;
+        goto exit;
+    } else {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    /* These are pretty arbitrary, and mainly designed to keep the BAT
+     * size reasonable to load into RAM */
+    if (block_size == 0) {
+        if (image_size > 32 * TiB) {
+            block_size = 64 * MiB;
+        } else if (image_size > (uint64_t) 100 * GiB) {
+            block_size = 32 * MiB;
+        } else if (image_size > 1 * GiB) {
+            block_size = 16 * MiB;
+        } else {
+            block_size = 8 * MiB;
+        }
+    }
+
+
+    /* make the log size close to what was specified, but must be
+     * min 1MB, and multiple of 1MB */
+    log_size = ROUND_UP(log_size, MiB);
+
+    block_size = ROUND_UP(block_size, MiB);
+    block_size = block_size > VHDX_BLOCK_SIZE_MAX ? VHDX_BLOCK_SIZE_MAX :
+                                                    block_size;
+
+    ret = bdrv_create_file(filename, options, &local_err);
+    if (ret < 0) {
+        error_propagate(errp, local_err);
+        goto exit;
+    }
+
+    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err);
+    if (ret < 0) {
+        error_propagate(errp, local_err);
+        goto exit;
+    }
+
+    /* Create (A) */
+
+    /* The creator field is optional, but may be useful for
+     * debugging / diagnostics */
+    creator = g_utf8_to_utf16("QEMU v" QEMU_VERSION, -1, NULL,
+                              &creator_items, NULL);
+    signature = cpu_to_le64(VHDX_FILE_SIGNATURE);
+    bdrv_pwrite(bs, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature));
+    if (ret < 0) {
+        goto delete_and_exit;
+    }
+    if (creator) {
+        bdrv_pwrite(bs, VHDX_FILE_ID_OFFSET + sizeof(signature), creator,
+                    creator_items * sizeof(gunichar2));
+        if (ret < 0) {
+            goto delete_and_exit;
+        }
+    }
+
+
+    /* Creates (B),(C) */
+    ret = vhdx_create_new_headers(bs, image_size, log_size);
+    if (ret < 0) {
+        goto delete_and_exit;
+    }
+
+    /* Creates (D),(E),(G) explicitly. (F) created as by-product */
+    ret = vhdx_create_new_region_table(bs, image_size, block_size, 512,
+                                       log_size, use_zero_blocks, image_type,
+                                       &metadata_offset);
+    if (ret < 0) {
+        goto delete_and_exit;
+    }
+
+    /* Creates (H) */
+    ret = vhdx_create_new_metadata(bs, image_size, block_size, 512,
+                                   metadata_offset, image_type);
+    if (ret < 0) {
+        goto delete_and_exit;
+    }
+
+
+
+delete_and_exit:
+    bdrv_unref(bs);
+exit:
+    g_free(creator);
+    return ret;
+}
+
+static QEMUOptionParameter vhdx_create_options[] = {
+    {
+        .name = BLOCK_OPT_SIZE,
+        .type = OPT_SIZE,
+        .help = "Virtual disk size; max of 64TB."
+    },
+    {
+        .name = VHDX_BLOCK_OPT_LOG_SIZE,
+        .type = OPT_SIZE,
+        .value.n = 1 * MiB,
+        .help = "Log size; min 1MB."
+    },
+    {
+        .name = VHDX_BLOCK_OPT_BLOCK_SIZE,
+        .type = OPT_SIZE,
+        .value.n = 0,
+        .help = "Block Size; min 1MB, max 256MB. " \
+                "0 means auto-calculate based on image size."
+    },
+    {
+        .name = BLOCK_OPT_SUBFMT,
+        .type = OPT_STRING,
+        .help = "VHDX format type, can be either 'dynamic' or 'fixed'. "\
+                "Default is 'dynamic'."
+    },
+    {
+        .name = VHDX_BLOCK_OPT_ZERO,
+        .type = OPT_FLAG,
+        .help = "Force use of payload blocks of type 'ZERO'.  Non-standard."
+    },
+    { NULL }
+};
+
 static BlockDriver bdrv_vhdx = {
     .format_name            = "vhdx",
     .instance_size          = sizeof(BDRVVHDXState),
@@ -973,6 +1884,9 @@
     .bdrv_reopen_prepare    = vhdx_reopen_prepare,
     .bdrv_co_readv          = vhdx_co_readv,
     .bdrv_co_writev         = vhdx_co_writev,
+    .bdrv_create            = vhdx_create,
+
+    .create_options         = vhdx_create_options,
 };
 
 static void bdrv_vhdx_init(void)
diff --git a/block/vhdx.h b/block/vhdx.h
index fb687ed..51183b2 100644
--- a/block/vhdx.h
+++ b/block/vhdx.h
@@ -6,9 +6,9 @@
  * Authors:
  *  Jeff Cody <jcody@redhat.com>
  *
- *  This is based on the "VHDX Format Specification v0.95", published 4/12/2012
+ *  This is based on the "VHDX Format Specification v1.00", published 8/25/2012
  *  by Microsoft:
- *      https://www.microsoft.com/en-us/download/details.aspx?id=29681
+ *      https://www.microsoft.com/en-us/download/details.aspx?id=34750
  *
  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
  * See the COPYING.LIB file in the top-level directory.
@@ -18,6 +18,11 @@
 #ifndef BLOCK_VHDX_H
 #define BLOCK_VHDX_H
 
+#define KiB              (1 * 1024)
+#define MiB            (KiB * 1024)
+#define GiB            (MiB * 1024)
+#define TiB ((uint64_t) GiB * 1024)
+
 /* Structures and fields present in the VHDX file */
 
 /* The header section has the following blocks,
@@ -30,14 +35,15 @@
  * 0.........64KB...........128KB........192KB..........256KB................1MB
  */
 
-#define VHDX_HEADER_BLOCK_SIZE      (64*1024)
+#define VHDX_HEADER_BLOCK_SIZE      (64 * 1024)
 
 #define VHDX_FILE_ID_OFFSET         0
-#define VHDX_HEADER1_OFFSET         (VHDX_HEADER_BLOCK_SIZE*1)
-#define VHDX_HEADER2_OFFSET         (VHDX_HEADER_BLOCK_SIZE*2)
-#define VHDX_REGION_TABLE_OFFSET    (VHDX_HEADER_BLOCK_SIZE*3)
+#define VHDX_HEADER1_OFFSET         (VHDX_HEADER_BLOCK_SIZE * 1)
+#define VHDX_HEADER2_OFFSET         (VHDX_HEADER_BLOCK_SIZE * 2)
+#define VHDX_REGION_TABLE_OFFSET    (VHDX_HEADER_BLOCK_SIZE * 3)
+#define VHDX_REGION_TABLE2_OFFSET   (VHDX_HEADER_BLOCK_SIZE * 4)
 
-
+#define VHDX_HEADER_SECTION_END     (1 * MiB)
 /*
  * A note on the use of MS-GUID fields.  For more details on the GUID,
  * please see: https://en.wikipedia.org/wiki/Globally_unique_identifier.
@@ -55,10 +61,11 @@
 /* These structures are ones that are defined in the VHDX specification
  * document */
 
+#define VHDX_FILE_SIGNATURE 0x656C696678646876  /* "vhdxfile" in ASCII */
 typedef struct VHDXFileIdentifier {
     uint64_t    signature;              /* "vhdxfile" in ASCII */
     uint16_t    creator[256];           /* optional; utf-16 string to identify
-                                           the vhdx file creator.  Diagnotistic
+                                           the vhdx file creator.  Diagnostic
                                            only */
 } VHDXFileIdentifier;
 
@@ -67,7 +74,7 @@
  * Microsoft is not just 16 bytes though - it is a structure that is defined,
  * so we need to follow it here so that endianness does not trip us up */
 
-typedef struct MSGUID {
+typedef struct QEMU_PACKED MSGUID {
     uint32_t  data1;
     uint16_t  data2;
     uint16_t  data3;
@@ -77,14 +84,15 @@
 #define guid_eq(a, b) \
     (memcmp(&(a), &(b), sizeof(MSGUID)) == 0)
 
-#define VHDX_HEADER_SIZE (4*1024)   /* although the vhdx_header struct in disk
-                                       is only 582 bytes, for purposes of crc
-                                       the header is the first 4KB of the 64KB
-                                       block */
+#define VHDX_HEADER_SIZE (4 * 1024)   /* although the vhdx_header struct in disk
+                                         is only 582 bytes, for purposes of crc
+                                         the header is the first 4KB of the 64KB
+                                         block */
 
 /* The full header is 4KB, although the actual header data is much smaller.
  * But for the checksum calculation, it is over the entire 4KB structure,
  * not just the defined portion of it */
+#define VHDX_HEADER_SIGNATURE 0x64616568
 typedef struct QEMU_PACKED VHDXHeader {
     uint32_t    signature;              /* "head" in ASCII */
     uint32_t    checksum;               /* CRC-32C hash of the whole header */
@@ -92,7 +100,7 @@
                                            VHDX file has 2 of these headers,
                                            and only the header with the highest
                                            sequence number is valid */
-    MSGUID      file_write_guid;       /* 128 bit unique identifier. Must be
+    MSGUID      file_write_guid;        /* 128 bit unique identifier. Must be
                                            updated to new, unique value before
                                            the first modification is made to
                                            file */
@@ -114,9 +122,9 @@
                                            there is no valid log. If non-zero,
                                            log entries with this guid are
                                            valid. */
-    uint16_t    log_version;            /* version of the log format. Mustn't be
-                                           zero, unless log_guid is also zero */
-    uint16_t    version;                /* version of th evhdx file.  Currently,
+    uint16_t    log_version;            /* version of the log format. Must be
+                                           set to zero */
+    uint16_t    version;                /* version of the vhdx file.  Currently,
                                            only supported version is "1" */
     uint32_t    log_length;             /* length of the log.  Must be multiple
                                            of 1MB */
@@ -125,6 +133,7 @@
 } VHDXHeader;
 
 /* Header for the region table block */
+#define VHDX_REGION_SIGNATURE  0x69676572  /* "regi" in ASCII */
 typedef struct QEMU_PACKED VHDXRegionTableHeader {
     uint32_t    signature;              /* "regi" in ASCII */
     uint32_t    checksum;               /* CRC-32C hash of the 64KB table */
@@ -151,7 +160,10 @@
 
 
 /* ---- LOG ENTRY STRUCTURES ---- */
+#define VHDX_LOG_MIN_SIZE (1024 * 1024)
+#define VHDX_LOG_SECTOR_SIZE 4096
 #define VHDX_LOG_HDR_SIZE 64
+#define VHDX_LOG_SIGNATURE 0x65676f6c
 typedef struct QEMU_PACKED VHDXLogEntryHeader {
     uint32_t    signature;              /* "loge" in ASCII */
     uint32_t    checksum;               /* CRC-32C hash of the 64KB table */
@@ -174,7 +186,8 @@
 } VHDXLogEntryHeader;
 
 #define VHDX_LOG_DESC_SIZE 32
-
+#define VHDX_LOG_DESC_SIGNATURE 0x63736564
+#define VHDX_LOG_ZERO_SIGNATURE 0x6f72657a
 typedef struct QEMU_PACKED VHDXLogDescriptor {
     uint32_t    signature;              /* "zero" or "desc" in ASCII */
     union  {
@@ -194,6 +207,7 @@
                                            vhdx_log_entry_header */
 } VHDXLogDescriptor;
 
+#define VHDX_LOG_DATA_SIGNATURE 0x61746164
 typedef struct QEMU_PACKED VHDXLogDataSector {
     uint32_t    data_signature;         /* "data" in ASCII */
     uint32_t    sequence_high;          /* 4 MSB of 8 byte sequence_number */
@@ -212,19 +226,19 @@
 #define PAYLOAD_BLOCK_UNDEFINED         1
 #define PAYLOAD_BLOCK_ZERO              2
 #define PAYLOAD_BLOCK_UNMAPPED          5
-#define PAYLOAD_BLOCK_FULL_PRESENT      6
+#define PAYLOAD_BLOCK_FULLY_PRESENT     6
 #define PAYLOAD_BLOCK_PARTIALLY_PRESENT 7
 
 #define SB_BLOCK_NOT_PRESENT    0
 #define SB_BLOCK_PRESENT        6
 
 /* per the spec */
-#define VHDX_MAX_SECTORS_PER_BLOCK  (1<<23)
+#define VHDX_MAX_SECTORS_PER_BLOCK  (1 << 23)
 
 /* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
    other bits are reserved */
 #define VHDX_BAT_STATE_BIT_MASK 0x07
-#define VHDX_BAT_FILE_OFF_BITS (64-44)
+#define VHDX_BAT_FILE_OFF_MASK  0xFFFFFFFFFFF00000 /* upper 44 bits */
 typedef uint64_t VHDXBatEntry;
 
 /* ---- METADATA REGION STRUCTURES ---- */
@@ -233,6 +247,7 @@
 #define VHDX_METADATA_MAX_ENTRIES 2047  /* not including the header */
 #define VHDX_METADATA_TABLE_MAX_SIZE \
     (VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
+#define VHDX_METADATA_SIGNATURE 0x617461646174656D  /* "metadata" in ASCII */
 typedef struct QEMU_PACKED VHDXMetadataTableHeader {
     uint64_t    signature;              /* "metadata" in ASCII */
     uint16_t    reserved;
@@ -252,8 +267,8 @@
                                            metadata region */
                                         /* note: if length = 0, so is offset */
     uint32_t    length;                 /* length of metadata. <= 1MB. */
-    uint32_t    data_bits;      /* least-significant 3 bits are flags, the
-                                   rest are reserved (see above) */
+    uint32_t    data_bits;              /* least-significant 3 bits are flags,
+                                           the rest are reserved (see above) */
     uint32_t    reserved2;
 } VHDXMetadataTableEntry;
 
@@ -262,13 +277,16 @@
                                                    If set indicates a fixed
                                                    size VHDX file */
 #define VHDX_PARAMS_HAS_PARENT           0x02    /* has parent / backing file */
+#define VHDX_BLOCK_SIZE_MIN             (1   * MiB)
+#define VHDX_BLOCK_SIZE_MAX             (256 * MiB)
 typedef struct QEMU_PACKED VHDXFileParameters {
     uint32_t    block_size;             /* size of each payload block, always
                                            power of 2, <= 256MB and >= 1MB. */
-    uint32_t data_bits;     /* least-significant 2 bits are flags, the rest
-                               are reserved (see above) */
+    uint32_t data_bits;                 /* least-significant 2 bits are flags,
+                                           the rest are reserved (see above) */
 } VHDXFileParameters;
 
+#define VHDX_MAX_IMAGE_SIZE  ((uint64_t) 64 * TiB)
 typedef struct QEMU_PACKED VHDXVirtualDiskSize {
     uint64_t    virtual_disk_size;      /* Size of the virtual disk, in bytes.
                                            Must be multiple of the sector size,
@@ -276,7 +294,7 @@
 } VHDXVirtualDiskSize;
 
 typedef struct QEMU_PACKED VHDXPage83Data {
-    MSGUID      page_83_data[16];       /* unique id for scsi devices that
+    MSGUID      page_83_data;           /* unique id for scsi devices that
                                            support page 0x83 */
 } VHDXPage83Data;
 
@@ -291,7 +309,7 @@
 } VHDXVirtualDiskPhysicalSectorSize;
 
 typedef struct QEMU_PACKED VHDXParentLocatorHeader {
-    MSGUID      locator_type[16];       /* type of the parent virtual disk. */
+    MSGUID      locator_type;           /* type of the parent virtual disk. */
     uint16_t    reserved;
     uint16_t    key_value_count;        /* number of key/value pairs for this
                                            locator */
@@ -308,18 +326,122 @@
 
 /* ----- END VHDX SPECIFICATION STRUCTURES ---- */
 
+typedef struct VHDXMetadataEntries {
+    VHDXMetadataTableEntry file_parameters_entry;
+    VHDXMetadataTableEntry virtual_disk_size_entry;
+    VHDXMetadataTableEntry page83_data_entry;
+    VHDXMetadataTableEntry logical_sector_size_entry;
+    VHDXMetadataTableEntry phys_sector_size_entry;
+    VHDXMetadataTableEntry parent_locator_entry;
+    uint16_t present;
+} VHDXMetadataEntries;
 
+typedef struct VHDXLogEntries {
+    uint64_t offset;
+    uint64_t length;
+    uint32_t write;
+    uint32_t read;
+    VHDXLogEntryHeader *hdr;
+    void *desc_buffer;
+    uint64_t sequence;
+    uint32_t tail;
+} VHDXLogEntries;
+
+typedef struct VHDXRegionEntry {
+    uint64_t start;
+    uint64_t end;
+    QLIST_ENTRY(VHDXRegionEntry) entries;
+} VHDXRegionEntry;
+
+typedef struct BDRVVHDXState {
+    CoMutex lock;
+
+    int curr_header;
+    VHDXHeader *headers[2];
+
+    VHDXRegionTableHeader rt;
+    VHDXRegionTableEntry bat_rt;         /* region table for the BAT */
+    VHDXRegionTableEntry metadata_rt;    /* region table for the metadata */
+
+    VHDXMetadataTableHeader metadata_hdr;
+    VHDXMetadataEntries metadata_entries;
+
+    VHDXFileParameters params;
+    uint32_t block_size;
+    uint32_t block_size_bits;
+    uint32_t sectors_per_block;
+    uint32_t sectors_per_block_bits;
+
+    uint64_t virtual_disk_size;
+    uint32_t logical_sector_size;
+    uint32_t physical_sector_size;
+
+    uint64_t chunk_ratio;
+    uint32_t chunk_ratio_bits;
+    uint32_t logical_sector_size_bits;
+
+    uint32_t bat_entries;
+    VHDXBatEntry *bat;
+    uint64_t bat_offset;
+
+    bool first_visible_write;
+    MSGUID session_guid;
+
+    VHDXLogEntries log;
+
+    VHDXParentLocatorHeader parent_header;
+    VHDXParentLocatorEntry *parent_entries;
+
+    Error *migration_blocker;
+
+    QLIST_HEAD(VHDXRegionHead, VHDXRegionEntry) regions;
+} BDRVVHDXState;
+
+void vhdx_guid_generate(MSGUID *guid);
+
+int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s, bool rw,
+                        MSGUID *log_guid);
+
+uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset);
 uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
                             int crc_offset);
 
 bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
 
+int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed);
 
-static void leguid_to_cpus(MSGUID *guid)
+int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
+                             void *data, uint32_t length, uint64_t offset);
+
+static inline void leguid_to_cpus(MSGUID *guid)
 {
     le32_to_cpus(&guid->data1);
     le16_to_cpus(&guid->data2);
     le16_to_cpus(&guid->data3);
 }
 
+static inline void cpu_to_leguids(MSGUID *guid)
+{
+    cpu_to_le32s(&guid->data1);
+    cpu_to_le16s(&guid->data2);
+    cpu_to_le16s(&guid->data3);
+}
+
+void vhdx_header_le_import(VHDXHeader *h);
+void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h);
+void vhdx_log_desc_le_import(VHDXLogDescriptor *d);
+void vhdx_log_desc_le_export(VHDXLogDescriptor *d);
+void vhdx_log_data_le_export(VHDXLogDataSector *d);
+void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr);
+void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr);
+void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr);
+void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr);
+void vhdx_region_entry_le_import(VHDXRegionTableEntry *e);
+void vhdx_region_entry_le_export(VHDXRegionTableEntry *e);
+void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr);
+void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr);
+void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e);
+void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e);
+int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s);
+
 #endif
diff --git a/block/vmdk.c b/block/vmdk.c
index 32ec8b7..a7ebd0f 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -106,6 +106,7 @@
     uint32_t l2_cache_counts[L2_CACHE_SIZE];
 
     int64_t cluster_sectors;
+    char *type;
 } VmdkExtent;
 
 typedef struct BDRVVmdkState {
@@ -113,11 +114,13 @@
     uint64_t desc_offset;
     bool cid_updated;
     bool cid_checked;
+    uint32_t cid;
     uint32_t parent_cid;
     int num_extents;
     /* Extent array with num_extents entries, ascend ordered by address */
     VmdkExtent *extents;
     Error *migration_blocker;
+    char *create_type;
 } BDRVVmdkState;
 
 typedef struct VmdkMetaData {
@@ -214,6 +217,7 @@
         g_free(e->l1_table);
         g_free(e->l2_cache);
         g_free(e->l1_backup_table);
+        g_free(e->type);
         if (e->file != bs->file) {
             bdrv_unref(e->file);
         }
@@ -534,6 +538,7 @@
     uint32_t l1_size, l1_entry_sectors;
     VMDK4Header header;
     VmdkExtent *extent;
+    BDRVVmdkState *s = bs->opaque;
     int64_t l1_backup_offset = 0;
 
     ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
@@ -549,6 +554,10 @@
         }
     }
 
+    if (!s->create_type) {
+        s->create_type = g_strdup("monolithicSparse");
+    }
+
     if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) {
         /*
          * The footer takes precedence over the header, so read it in. The
@@ -709,6 +718,8 @@
     int64_t flat_offset;
     char extent_path[PATH_MAX];
     BlockDriverState *extent_file;
+    BDRVVmdkState *s = bs->opaque;
+    VmdkExtent *extent;
 
     while (*p) {
         /* parse extent line:
@@ -751,7 +762,6 @@
         /* save to extents array */
         if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) {
             /* FLAT extent */
-            VmdkExtent *extent;
 
             ret = vmdk_add_extent(bs, extent_file, true, sectors,
                             0, 0, 0, 0, 0, &extent, errp);
@@ -766,10 +776,12 @@
                 bdrv_unref(extent_file);
                 return ret;
             }
+            extent = &s->extents[s->num_extents - 1];
         } else {
             error_setg(errp, "Unsupported extent type '%s'", type);
             return -ENOTSUP;
         }
+        extent->type = g_strdup(type);
 next_line:
         /* move to next line */
         while (*p) {
@@ -817,6 +829,7 @@
         ret = -ENOTSUP;
         goto exit;
     }
+    s->create_type = g_strdup(ct);
     s->desc_offset = 0;
     ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp);
 exit:
@@ -843,6 +856,7 @@
     if (ret) {
         goto fail;
     }
+    s->cid = vmdk_read_cid(bs, 0);
     s->parent_cid = vmdk_read_cid(bs, 1);
     qemu_co_mutex_init(&s->lock);
 
@@ -855,6 +869,8 @@
     return 0;
 
 fail:
+    g_free(s->create_type);
+    s->create_type = NULL;
     vmdk_free_extents(bs);
     return ret;
 }
@@ -1766,6 +1782,7 @@
     BDRVVmdkState *s = bs->opaque;
 
     vmdk_free_extents(bs);
+    g_free(s->create_type);
 
     migrate_del_blocker(s->migration_blocker);
     error_free(s->migration_blocker);
@@ -1827,6 +1844,54 @@
     return 1;
 }
 
+static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
+{
+    ImageInfo *info = g_new0(ImageInfo, 1);
+
+    *info = (ImageInfo){
+        .filename         = g_strdup(extent->file->filename),
+        .format           = g_strdup(extent->type),
+        .virtual_size     = extent->sectors * BDRV_SECTOR_SIZE,
+        .compressed       = extent->compressed,
+        .has_compressed   = extent->compressed,
+        .cluster_size     = extent->cluster_sectors * BDRV_SECTOR_SIZE,
+        .has_cluster_size = !extent->flat,
+    };
+
+    return info;
+}
+
+static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
+{
+    int i;
+    BDRVVmdkState *s = bs->opaque;
+    ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
+    ImageInfoList **next;
+
+    *spec_info = (ImageInfoSpecific){
+        .kind = IMAGE_INFO_SPECIFIC_KIND_VMDK,
+        {
+            .vmdk = g_new0(ImageInfoSpecificVmdk, 1),
+        },
+    };
+
+    *spec_info->vmdk = (ImageInfoSpecificVmdk) {
+        .create_type = g_strdup(s->create_type),
+        .cid = s->cid,
+        .parent_cid = s->parent_cid,
+    };
+
+    next = &spec_info->vmdk->extents;
+    for (i = 0; i < s->num_extents; i++) {
+        *next = g_new0(ImageInfoList, 1);
+        (*next)->value = vmdk_get_extent_info(&s->extents[i]);
+        (*next)->next = NULL;
+        next = &(*next)->next;
+    }
+
+    return spec_info;
+}
+
 static QEMUOptionParameter vmdk_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -1879,6 +1944,7 @@
     .bdrv_co_get_block_status     = vmdk_co_get_block_status,
     .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
     .bdrv_has_zero_init           = vmdk_has_zero_init,
+    .bdrv_get_specific_info       = vmdk_get_specific_info,
 
     .create_options               = vmdk_create_options,
 };
diff --git a/block/vpc.c b/block/vpc.c
index b5dca39..577cc45 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -211,6 +211,15 @@
     bs->total_sectors = (int64_t)
         be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
 
+    /* images created with disk2vhd report a far higher virtual size
+     * than expected with the cyls * heads * sectors_per_cyl formula.
+     * use the footer->size instead if the image was created with
+     * disk2vhd.
+     */
+    if (!strncmp(footer->creator_app, "d2v", 4)) {
+        bs->total_sectors = be64_to_cpu(footer->size) / BDRV_SECTOR_SIZE;
+    }
+
     /* Allow a maximum disk size of approximately 2 TB */
     if (bs->total_sectors >= 65535LL * 255 * 255) {
         ret = -EFBIG;
@@ -260,6 +269,13 @@
             }
         }
 
+        if (s->free_data_block_offset > bdrv_getlength(bs->file)) {
+            error_setg(errp, "block-vpc: free_data_block_offset points after "
+                             "the end of file. The image has been truncated.");
+            ret = -EINVAL;
+            goto fail;
+        }
+
         s->last_bitmap_offset = (int64_t) -1;
 
 #ifdef CACHE
diff --git a/blockdev.c b/blockdev.c
index b260477..330aa4a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -47,7 +47,6 @@
 #include "sysemu/arch_init.h"
 
 static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
-extern QemuOptsList qemu_common_drive_opts;
 
 static const char *const if_name[IF_COUNT] = {
     [IF_NONE] = "none",
@@ -341,7 +340,7 @@
     qemu_opts_absorb_qdict(opts, bs_opts, &error);
     if (error_is_set(&error)) {
         error_propagate(errp, error);
-        return NULL;
+        goto early_err;
     }
 
     if (id) {
@@ -361,7 +360,7 @@
     if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
         if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) {
             error_setg(errp, "invalid discard option");
-            return NULL;
+            goto early_err;
         }
     }
 
@@ -383,7 +382,7 @@
             /* this is the default */
         } else {
            error_setg(errp, "invalid aio option");
-           return NULL;
+           goto early_err;
         }
     }
 #endif
@@ -393,13 +392,13 @@
             error_printf("Supported formats:");
             bdrv_iterate_format(bdrv_format_print, NULL);
             error_printf("\n");
-            return NULL;
+            goto early_err;
         }
 
         drv = bdrv_find_format(buf);
         if (!drv) {
             error_setg(errp, "'%s' invalid format", buf);
-            return NULL;
+            goto early_err;
         }
     }
 
@@ -435,20 +434,20 @@
 
     if (!check_throttle_config(&cfg, &error)) {
         error_propagate(errp, error);
-        return NULL;
+        goto early_err;
     }
 
     on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
     if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
         if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
             error_setg(errp, "werror is not supported by this bus type");
-            return NULL;
+            goto early_err;
         }
 
         on_write_error = parse_block_error_action(buf, 0, &error);
         if (error_is_set(&error)) {
             error_propagate(errp, error);
-            return NULL;
+            goto early_err;
         }
     }
 
@@ -456,13 +455,13 @@
     if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
         if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
             error_report("rerror is not supported by this bus type");
-            return NULL;
+            goto early_err;
         }
 
         on_read_error = parse_block_error_action(buf, 1, &error);
         if (error_is_set(&error)) {
             error_propagate(errp, error);
-            return NULL;
+            goto early_err;
         }
     }
 
@@ -491,6 +490,8 @@
         if (has_driver_specific_opts) {
             file = NULL;
         } else {
+            QDECREF(bs_opts);
+            qemu_opts_del(opts);
             return dinfo;
         }
     }
@@ -529,12 +530,13 @@
     return dinfo;
 
 err:
-    qemu_opts_del(opts);
-    QDECREF(bs_opts);
     bdrv_unref(dinfo->bdrv);
     g_free(dinfo->id);
     QTAILQ_REMOVE(&drives, dinfo, next);
     g_free(dinfo);
+early_err:
+    QDECREF(bs_opts);
+    qemu_opts_del(opts);
     return NULL;
 }
 
@@ -2026,7 +2028,9 @@
         return;
     }
 
-    if (sync == MIRROR_SYNC_MODE_FULL && mode != NEW_IMAGE_MODE_EXISTING) {
+    if ((sync == MIRROR_SYNC_MODE_FULL || !source)
+        && mode != NEW_IMAGE_MODE_EXISTING)
+    {
         /* create new image w/o backing file */
         assert(format && drv);
         bdrv_img_create(target, format,
diff --git a/configure b/configure
index 57ee62a..508f6a5 100755
--- a/configure
+++ b/configure
@@ -27,6 +27,19 @@
 echo >> config.log
 echo "#" >> config.log
 
+# Save the configure command line for later reuse.
+cat <<EOD >config.status
+#!/bin/sh
+# Generated by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+EOD
+printf "exec" >>config.status
+printf " '%s'" "$0" "$@" >>config.status
+echo >>config.status
+chmod +x config.status
+
 error_exit() {
     echo
     echo "ERROR: $1"
@@ -119,6 +132,7 @@
 # default parameters
 source_path=`dirname "$0"`
 cpu=""
+iasl="iasl"
 interp_prefix="/usr/gnemul/qemu-%M"
 static="no"
 cross_prefix=""
@@ -246,6 +260,7 @@
 gtkabi="2.0"
 tpm="no"
 libssh2=""
+vhdx=""
 
 # parse CC options first
 for opt do
@@ -257,6 +272,8 @@
   ;;
   --cxx=*) CXX="$optarg"
   ;;
+  --iasl=*) iasl="$optarg"
+  ;;
   --source-path=*) source_path="$optarg"
   ;;
   --cpu=*) cpu="$optarg"
@@ -576,7 +593,7 @@
 
 : ${make=${MAKE-make}}
 : ${install=${INSTALL-install}}
-: ${python=${PYTHON-python -B}}
+: ${python=${PYTHON-python}}
 : ${smbd=${SMBD-/usr/sbin/smbd}}
 
 # Default objcc to clang if available, otherwise use CC
@@ -969,6 +986,10 @@
   ;;
   --enable-libssh2) libssh2="yes"
   ;;
+  --enable-vhdx) vhdx="yes"
+  ;;
+  --disable-vhdx) vhdx="no"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -1058,6 +1079,7 @@
 echo "  --source-path=PATH       path of source code [$source_path]"
 echo "  --cross-prefix=PREFIX    use PREFIX for compile tools [$cross_prefix]"
 echo "  --cc=CC                  use C compiler CC [$cc]"
+echo "  --iasl=IASL              use ACPI compiler IASL [$iasl]"
 echo "  --host-cc=CC             use C compiler CC [$host_cc] for code run at"
 echo "                           build time"
 echo "  --cxx=CXX                use C++ compiler CXX [$cxx]"
@@ -1200,6 +1222,8 @@
 echo "  --enable-tpm             enable TPM support"
 echo "  --disable-libssh2        disable ssh block device support"
 echo "  --enable-libssh2         enable ssh block device support"
+echo "  --disable-vhdx           disables support for the Microsoft VHDX image format"
+echo "  --enable-vhdx            enable support for the Microsoft VHDX image format"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -1396,6 +1420,13 @@
       "Use --python=/path/to/python to specify a supported Python."
 fi
 
+# The -B switch was added in Python 2.6.
+# If it is supplied, compiled files are not written.
+# Use it for Python versions which support it.
+if $python -B -c 'import sys; sys.exit(0)' 2>/dev/null; then
+  python="$python -B"
+fi
+
 if test -z "${target_list+xxx}" ; then
     target_list="$default_target_list"
 else
@@ -1429,39 +1460,27 @@
       "configure was not able to find it"
 }
 
-if test -z "$cross_prefix" ; then
-
 # ---
 # big/little endian test
 cat > $TMPC << EOF
-#include <inttypes.h>
-int main(void) {
-        volatile uint32_t i=0x01234567;
-        return (*((uint8_t*)(&i))) == 0x67;
+short big_endian[] = { 0x4269, 0x4765, 0x4e64, 0x4961, 0x4e00, 0, };
+short little_endian[] = { 0x694c, 0x7454, 0x654c, 0x6e45, 0x6944, 0x6e41, 0, };
+extern int foo(short *, short *);
+int main(int argc, char *argv[]) {
+    return foo(big_endian, little_endian);
 }
 EOF
 
-if compile_prog "" "" ; then
-$TMPE && bigendian="yes"
-else
-echo big/little test failed
-fi
-
-else
-
-# if cross compiling, cannot launch a program, so make a static guess
-case "$cpu" in
-  arm)
-    # ARM can be either way; ask the compiler which one we are
-    if check_define __ARMEB__; then
-      bigendian=yes
+if compile_object ; then
+    if grep -q BiGeNdIaN $TMPO ; then
+        bigendian="yes"
+    elif grep -q LiTtLeEnDiAn $TMPO ; then
+        bigendian="no"
+    else
+        echo big/little test failed
     fi
-  ;;
-  hppa|m68k|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
-    bigendian=yes
-  ;;
-esac
-
+else
+    echo big/little test failed
 fi
 
 ##########################################
@@ -2012,6 +2031,18 @@
   fi
 fi
 
+if test "$vhdx" = "yes" ; then
+    if test "$uuid" = "no" ; then
+        error_exit "uuid required for VHDX support"
+    fi
+elif test "$vhdx" != "no" ; then
+    if test "$uuid" = "yes" ; then
+        vhdx=yes
+    else
+        vhdx=no
+    fi
+fi
+
 ##########################################
 # xfsctl() probe, used for raw-posix
 if test "$xfs" != "no" ; then
@@ -3755,6 +3786,7 @@
 echo "libssh2 support   $libssh2"
 echo "TPM passthrough   $tpm_passthrough"
 echo "QOM debugging     $qom_cast_debug"
+echo "vhdx              $vhdx"
 
 if test "$sdl_too_old" = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -3765,8 +3797,6 @@
 echo "# Automatically generated by configure - do not modify" >config-all-disas.mak
 
 echo "# Automatically generated by configure - do not modify" > $config_host_mak
-printf "# Configured with:" >> $config_host_mak
-printf " '%s'" "$0" "$@" >> $config_host_mak
 echo >> $config_host_mak
 
 echo all: >> $config_host_mak
@@ -4149,6 +4179,10 @@
   echo 'CONFIG_VIRTIO_BLK_DATA_PLANE=$(CONFIG_VIRTIO)' >> $config_host_mak
 fi
 
+if test "$vhdx" = "yes" ; then
+  echo "CONFIG_VHDX=y" >> $config_host_mak
+fi
+
 # USB host support
 if test "$libusb" = "yes"; then
   echo "HOST_USB=libusb legacy" >> $config_host_mak
@@ -4234,6 +4268,9 @@
 fi
 echo "PYTHON=$python" >> $config_host_mak
 echo "CC=$cc" >> $config_host_mak
+if $iasl -h > /dev/null 2>&1; then
+  echo "IASL=$iasl" >> $config_host_mak
+fi
 echo "CC_I386=$cc_i386" >> $config_host_mak
 echo "HOST_CC=$host_cc" >> $config_host_mak
 echo "CXX=$cxx" >> $config_host_mak
@@ -4647,6 +4684,7 @@
 
 # build tree in object directory in case the source is not in the current directory
 DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests"
+DIRS="$DIRS fsdev"
 DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
 DIRS="$DIRS roms/seabios roms/vgabios"
 DIRS="$DIRS qapi-generated"
@@ -4686,7 +4724,7 @@
     echo "BCC=bcc" >> $config_mak
     echo "CPP=$cpp" >> $config_mak
     echo "OBJCOPY=objcopy" >> $config_mak
-    echo "IASL=iasl" >> $config_mak
+    echo "IASL=$iasl" >> $config_mak
     echo "LD=$ld" >> $config_mak
 done
 
diff --git a/cpus.c b/cpus.c
index 398229e..01d128d 100644
--- a/cpus.c
+++ b/cpus.c
@@ -165,36 +165,38 @@
 /* Caller must hold the BQL */
 int64_t cpu_get_ticks(void)
 {
+    int64_t ticks;
+
     if (use_icount) {
         return cpu_get_icount();
     }
-    if (!timers_state.cpu_ticks_enabled) {
-        return timers_state.cpu_ticks_offset;
-    } else {
-        int64_t ticks;
-        ticks = cpu_get_real_ticks();
-        if (timers_state.cpu_ticks_prev > ticks) {
-            /* Note: non increasing ticks may happen if the host uses
-               software suspend */
-            timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
-        }
-        timers_state.cpu_ticks_prev = ticks;
-        return ticks + timers_state.cpu_ticks_offset;
+
+    ticks = timers_state.cpu_ticks_offset;
+    if (timers_state.cpu_ticks_enabled) {
+        ticks += cpu_get_real_ticks();
     }
+
+    if (timers_state.cpu_ticks_prev > ticks) {
+        /* Note: non increasing ticks may happen if the host uses
+           software suspend */
+        timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
+        ticks = timers_state.cpu_ticks_prev;
+    }
+
+    timers_state.cpu_ticks_prev = ticks;
+    return ticks;
 }
 
 static int64_t cpu_get_clock_locked(void)
 {
-    int64_t ti;
+    int64_t ticks;
 
-    if (!timers_state.cpu_ticks_enabled) {
-        ti = timers_state.cpu_clock_offset;
-    } else {
-        ti = get_clock();
-        ti += timers_state.cpu_clock_offset;
+    ticks = timers_state.cpu_clock_offset;
+    if (timers_state.cpu_ticks_enabled) {
+        ticks += get_clock();
     }
 
-    return ti;
+    return ticks;
 }
 
 /* return the host CPU monotonic timer and handle stop/restart */
@@ -235,7 +237,7 @@
     /* Here, the really thing protected by seqlock is cpu_clock_offset. */
     seqlock_write_lock(&timers_state.vm_clock_seqlock);
     if (timers_state.cpu_ticks_enabled) {
-        timers_state.cpu_ticks_offset = cpu_get_ticks();
+        timers_state.cpu_ticks_offset += cpu_get_real_ticks();
         timers_state.cpu_clock_offset = cpu_get_clock_locked();
         timers_state.cpu_ticks_enabled = 0;
     }
@@ -1403,7 +1405,10 @@
         l = sizeof(buf);
         if (l > size)
             l = size;
-        cpu_memory_rw_debug(cpu, addr, buf, l, 0);
+        if (cpu_memory_rw_debug(cpu, addr, buf, l, 0) != 0) {
+            error_setg(errp, "Invalid addr 0x%016" PRIx64 "specified", addr);
+            goto exit;
+        }
         if (fwrite(buf, 1, l, f) != l) {
             error_set(errp, QERR_IO_ERROR);
             goto exit;
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index d13bc2b..a555eef 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -61,6 +61,7 @@
 CONFIG_FRAMEBUFFER=y
 CONFIG_XILINX_SPIPS=y
 
+CONFIG_ARM11SCU=y
 CONFIG_A9SCU=y
 CONFIG_MARVELL_88W8618=y
 CONFIG_OMAP=y
@@ -79,3 +80,4 @@
 CONFIG_VERSATILE_I2C=y
 
 CONFIG_SDHCI=y
+CONFIG_INTEGRATOR_DEBUG=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 975112a..fb34a9b 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -46,6 +46,7 @@
 CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
 # For pSeries
 CONFIG_XICS=$(CONFIG_PSERIES)
+CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
 # For PReP
 CONFIG_I82378=y
 CONFIG_I8259=y
diff --git a/docs/ccid.txt b/docs/ccid.txt
index 8bbaa94..83c174d 100644
--- a/docs/ccid.txt
+++ b/docs/ccid.txt
@@ -52,7 +52,7 @@
 Assuming you have a working smartcard on the host with the current
 user, using NSS, qemu acts as another NSS client using ccid-card-emulated:
 
-    qemu -usb -device usb-ccid -device ccid-card-emualated
+    qemu -usb -device usb-ccid -device ccid-card-emulated
 
 4. Using ccid-card-emulated with certificates
 
diff --git a/docs/memory.txt b/docs/memory.txt
index feb9fe9..22eaec7 100644
--- a/docs/memory.txt
+++ b/docs/memory.txt
@@ -52,6 +52,15 @@
   hole".  Aliases may point to any type of region, including other aliases,
   but an alias may not point back to itself, directly or indirectly.
 
+It is valid to add subregions to a region which is not a pure container
+(that is, to an MMIO, RAM or ROM region). This means that the region
+will act like a container, except that any addresses within the container's
+region which are not claimed by any subregion are handled by the
+container itself (ie by its MMIO callbacks or RAM backing). However
+it is generally possible to achieve the same effect with a pure container
+one of whose subregions is a low priority "background" region covering
+the whole address range; this is often clearer and is preferred.
+Subregions cannot be added to an alias region.
 
 Region names
 ------------
@@ -80,6 +89,53 @@
 allows the region to overlap any other region in the same container, and
 specifies a priority that allows the core to decide which of two regions at
 the same address are visible (highest wins).
+Priority values are signed, and the default value is zero. This means that
+you can use memory_region_add_subregion_overlap() both to specify a region
+that must sit 'above' any others (with a positive priority) and also a
+background region that sits 'below' others (with a negative priority).
+
+If the higher priority region in an overlap is a container or alias, then
+the lower priority region will appear in any "holes" that the higher priority
+region has left by not mapping subregions to that area of its address range.
+(This applies recursively -- if the subregions are themselves containers or
+aliases that leave holes then the lower priority region will appear in these
+holes too.)
+
+For example, suppose we have a container A of size 0x8000 with two subregions
+B and C. B is a container mapped at 0x2000, size 0x4000, priority 1; C is
+an MMIO region mapped at 0x0, size 0x6000, priority 2. B currently has two
+of its own subregions: D of size 0x1000 at offset 0 and E of size 0x1000 at
+offset 0x2000. As a diagram:
+
+        0      1000   2000   3000   4000   5000   6000   7000    8000
+        |------|------|------|------|------|------|------|-------|
+  A:    [                                                       ]
+  C:    [CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC]
+  B:                  [                          ]
+  D:                  [DDDDD]
+  E:                                [EEEEE]
+
+The regions that will be seen within this address range then are:
+        [CCCCCCCCCCCC][DDDDD][CCCCC][EEEEE][CCCCC]
+
+Since B has higher priority than C, its subregions appear in the flat map
+even where they overlap with C. In ranges where B has not mapped anything
+C's region appears.
+
+If B had provided its own MMIO operations (ie it was not a pure container)
+then these would be used for any addresses in its range not handled by
+D or E, and the result would be:
+        [CCCCCCCCCCCC][DDDDD][BBBBB][EEEEE][BBBBB]
+
+Priority values are local to a container, because the priorities of two
+regions are only compared when they are both children of the same container.
+This means that the device in charge of the container (typically modelling
+a bus or a memory controller) can use them to manage the interaction of
+its child regions without any side effects on other parts of the system.
+In the example above, the priorities of D and E are unimportant because
+they do not overlap each other. It is the relative priority of B and C
+that causes D and E to appear on top of C: D and E's priorities are never
+compared against the priority of C.
 
 Visibility
 ----------
@@ -90,11 +146,19 @@
   descending priority order
   - if the address lies outside the region offset/size, the subregion is
     discarded
-  - if the subregion is a leaf (RAM or MMIO), the search terminates
+  - if the subregion is a leaf (RAM or MMIO), the search terminates, returning
+    this leaf region
   - if the subregion is a container, the same algorithm is used within the
     subregion (after the address is adjusted by the subregion offset)
-  - if the subregion is an alias, the search is continues at the alias target
+  - if the subregion is an alias, the search is continued at the alias target
     (after the address is adjusted by the subregion offset and alias offset)
+  - if a recursive search within a container or alias subregion does not
+    find a match (because of a "hole" in the container's coverage of its
+    address range), then if this is a container with its own MMIO or RAM
+    backing the search terminates, returning the container itself. Otherwise
+    we continue with the next subregion in priority order
+- if none of the subregions match the address then the search terminates
+  with no match found
 
 Example memory map
 ------------------
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 91f44d0..0728f36 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -164,7 +164,7 @@
  { "file": "my_existing_block_device_id" }
  { "file": { "driver": "file",
              "readonly": false,
-             'filename': "/tmp/mydisk.qcow2" } }
+             "filename": "/tmp/mydisk.qcow2" } }
 
 
 === Commands ===
diff --git a/dump.c b/dump.c
index 846155c..80a9116 100644
--- a/dump.c
+++ b/dump.c
@@ -66,7 +66,7 @@
     uint32_t sh_info;
     bool have_section;
     bool resume;
-    size_t note_size;
+    ssize_t note_size;
     hwaddr memory_offset;
     int fd;
 
@@ -765,7 +765,7 @@
 
     s->note_size = cpu_get_note_size(s->dump_info.d_class,
                                      s->dump_info.d_machine, nr_cpus);
-    if (ret < 0) {
+    if (s->note_size < 0) {
         error_set(errp, QERR_UNSUPPORTED);
         goto cleanup;
     }
diff --git a/exec.c b/exec.c
index 2e31ffc..95c4356 100644
--- a/exec.c
+++ b/exec.c
@@ -409,8 +409,10 @@
 #else
 static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
 {
-    tb_invalidate_phys_addr(cpu_get_phys_page_debug(cpu, pc) |
-            (pc & ~TARGET_PAGE_MASK));
+    hwaddr phys = cpu_get_phys_page_debug(cpu, pc);
+    if (phys != -1) {
+        tb_invalidate_phys_addr(phys | (pc & ~TARGET_PAGE_MASK));
+    }
 }
 #endif
 #endif /* TARGET_HAS_ICE */
@@ -2099,7 +2101,9 @@
         if (bounce.buffer) {
             return NULL;
         }
-        bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
+        /* Avoid unbounded allocations */
+        l = MIN(l, TARGET_PAGE_SIZE);
+        bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l);
         bounce.addr = addr;
         bounce.len = l;
 
diff --git a/gdbstub.c b/gdbstub.c
index 0e5a3f5..e8ab0b2 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -368,9 +368,6 @@
 #ifdef CONFIG_USER_ONLY
     s->running_state = 1;
 #else
-    if (runstate_check(RUN_STATE_GUEST_PANICKED)) {
-        runstate_set(RUN_STATE_DEBUG);
-    }
     if (!runstate_needs_reset()) {
         vm_start();
     }
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 0243d6a..d91b9cc 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -18,6 +18,7 @@
 devices-dirs-$(CONFIG_SOFTMMU) += nvram/
 devices-dirs-$(CONFIG_SOFTMMU) += pci/
 devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/
+devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/
 devices-dirs-$(CONFIG_SOFTMMU) += scsi/
 devices-dirs-$(CONFIG_SOFTMMU) += sd/
 devices-dirs-$(CONFIG_SOFTMMU) += ssi/
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 7138139..58308a3 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -170,8 +170,7 @@
     }
 
     /* increase number of tables */
-    cpu_to_le16wu((uint16_t *)acpi_tables,
-                  le16_to_cpupu((uint16_t *)acpi_tables) + 1u);
+    stw_le_p(acpi_tables, lduw_le_p(acpi_tables) + 1u);
 
     /* Update the header fields. The strings need not be NUL-terminated. */
     changed_fields = 0;
@@ -309,6 +308,46 @@
     error_propagate(errp, err);
 }
 
+static bool acpi_table_builtin = false;
+
+void acpi_table_add_builtin(const QemuOpts *opts, Error **errp)
+{
+    acpi_table_builtin = true;
+    acpi_table_add(opts, errp);
+}
+
+unsigned acpi_table_len(void *current)
+{
+    struct acpi_table_header *hdr = current - sizeof(hdr->_length);
+    return hdr->_length;
+}
+
+static
+void *acpi_table_hdr(void *h)
+{
+    struct acpi_table_header *hdr = h;
+    return &hdr->sig;
+}
+
+uint8_t *acpi_table_first(void)
+{
+    if (acpi_table_builtin || !acpi_tables) {
+        return NULL;
+    }
+    return acpi_table_hdr(acpi_tables + ACPI_TABLE_PFX_SIZE);
+}
+
+uint8_t *acpi_table_next(uint8_t *current)
+{
+    uint8_t *next = current + acpi_table_len(current);
+
+    if (next - acpi_tables >= acpi_tables_len) {
+        return NULL;
+    } else {
+        return acpi_table_hdr(next);
+    }
+}
+
 static void acpi_notify_wakeup(Notifier *notifier, void *data)
 {
     ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup);
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 3fb443d..7e0429e 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -24,6 +24,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 #include "hw/hw.h"
+#include "qapi/visitor.h"
 #include "hw/i386/pc.h"
 #include "hw/pci/pci.h"
 #include "qemu/timer.h"
@@ -228,3 +229,26 @@
     pm->powerdown_notifier.notify = pm_powerdown_req;
     qemu_register_powerdown_notifier(&pm->powerdown_notifier);
 }
+
+static void ich9_pm_get_gpe0_blk(Object *obj, Visitor *v,
+                                 void *opaque, const char *name,
+                                 Error **errp)
+{
+    ICH9LPCPMRegs *pm = opaque;
+    uint32_t value = pm->pm_io_base + ICH9_PMIO_GPE0_STS;
+
+    visit_type_uint32(v, &value, name, errp);
+}
+
+void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
+{
+    static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
+
+    object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
+                                   &pm->pm_io_base, errp);
+    object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32",
+                        ich9_pm_get_gpe0_blk,
+                        NULL, NULL, pm, NULL);
+    object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
+                                   &gpe0_len, errp);
+}
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index b46bd5e..93849c8 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -29,6 +29,7 @@
 #include "exec/ioport.h"
 #include "hw/nvram/fw_cfg.h"
 #include "exec/address-spaces.h"
+#include "hw/acpi/piix4.h"
 
 //#define DEBUG
 
@@ -69,6 +70,8 @@
     /*< public >*/
 
     MemoryRegion io;
+    uint32_t io_base;
+
     MemoryRegion io_gpe;
     MemoryRegion io_pci;
     MemoryRegion io_cpu;
@@ -152,14 +155,13 @@
 static void pm_io_space_update(PIIX4PMState *s)
 {
     PCIDevice *d = PCI_DEVICE(s);
-    uint32_t pm_io_base;
 
-    pm_io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
-    pm_io_base &= 0xffc0;
+    s->io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
+    s->io_base &= 0xffc0;
 
     memory_region_transaction_begin();
     memory_region_set_enabled(&s->io, d->config[0x80] & 1);
-    memory_region_set_address(&s->io, pm_io_base);
+    memory_region_set_address(&s->io, s->io_base);
     memory_region_transaction_commit();
 }
 
@@ -326,7 +328,7 @@
             if (pc->no_hotplug) {
                 slot_free = false;
             } else {
-                qdev_free(qdev);
+                object_unparent(OBJECT(qdev));
             }
         }
     }
@@ -407,6 +409,28 @@
         (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
 }
 
+static void piix4_pm_add_propeties(PIIX4PMState *s)
+{
+    static const uint8_t acpi_enable_cmd = ACPI_ENABLE;
+    static const uint8_t acpi_disable_cmd = ACPI_DISABLE;
+    static const uint32_t gpe0_blk = GPE_BASE;
+    static const uint32_t gpe0_blk_len = GPE_LEN;
+    static const uint16_t sci_int = 9;
+
+    object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_ENABLE_CMD,
+                                  &acpi_enable_cmd, NULL);
+    object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_DISABLE_CMD,
+                                  &acpi_disable_cmd, NULL);
+    object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK,
+                                  &gpe0_blk, NULL);
+    object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK_LEN,
+                                  &gpe0_blk_len, NULL);
+    object_property_add_uint16_ptr(OBJECT(s), ACPI_PM_PROP_SCI_INT,
+                                  &sci_int, NULL);
+    object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_PM_IO_BASE,
+                                  &s->io_base, NULL);
+}
+
 static int piix4_pm_initfn(PCIDevice *dev)
 {
     PIIX4PMState *s = PIIX4_PM(dev);
@@ -456,9 +480,21 @@
 
     piix4_acpi_system_hot_add_init(pci_address_space_io(dev), dev->bus, s);
 
+    piix4_pm_add_propeties(s);
     return 0;
 }
 
+Object *piix4_pm_find(void)
+{
+    bool ambig;
+    Object *o = object_resolve_path_type("", TYPE_PIIX4_PM, &ambig);
+
+    if (ambig || !o) {
+        return NULL;
+    }
+    return o;
+}
+
 i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
                        qemu_irq sci_irq, qemu_irq smi_irq,
                        int kvm_enabled, FWCfgState *fw_cfg)
@@ -489,9 +525,9 @@
 
 static Property piix4_pm_properties[] = {
     DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
-    DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0),
-    DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0),
-    DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2),
+    DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
+    DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
+    DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 89a9015..397e8df 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -11,6 +11,8 @@
 #include "hw/arm/arm.h"
 #include "hw/loader.h"
 #include "elf.h"
+#include "sysemu/qtest.h"
+#include "qemu/error-report.h"
 
 /* Bitbanded IO.  Each word corresponds to a single bit.  */
 
@@ -232,21 +234,22 @@
     big_endian = 0;
 #endif
 
-    if (!kernel_filename) {
+    if (!kernel_filename && !qtest_enabled()) {
         fprintf(stderr, "Guest image must be specified (using -kernel)\n");
         exit(1);
     }
 
-    image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
-                          NULL, big_endian, ELF_MACHINE, 1);
-    if (image_size < 0) {
-        image_size = load_image_targphys(kernel_filename, 0, flash_size);
-	lowaddr = 0;
-    }
-    if (image_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                kernel_filename);
-        exit(1);
+    if (kernel_filename) {
+        image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
+                              NULL, big_endian, ELF_MACHINE, 1);
+        if (image_size < 0) {
+            image_size = load_image_targphys(kernel_filename, 0, flash_size);
+            lowaddr = 0;
+        }
+        if (image_size < 0) {
+            error_report("Could not load kernel '%s'", kernel_filename);
+            exit(1);
+        }
     }
 
     /* Hack to map an additional page of ram at the top of the address
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 1e313af..583ec79 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -354,8 +354,10 @@
 
     /* Load the kernel.  */
     if (!info->kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
+        /* If no kernel specified, do nothing; we will start from address 0
+         * (typically a boot ROM image) in the same way as hardware.
+         */
+        return;
     }
 
     info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
index 2929f9f..26cedec 100644
--- a/hw/arm/exynos4_boards.c
+++ b/hw/arm/exynos4_boards.c
@@ -22,6 +22,7 @@
  */
 
 #include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
 #include "hw/sysbus.h"
 #include "net/net.h"
 #include "hw/arm/arm.h"
@@ -96,7 +97,7 @@
 static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
                                                    Exynos4BoardType board_type)
 {
-    if (smp_cpus != EXYNOS4210_NCPUS) {
+    if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
         fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
                 " value.\n",
                 exynos4_machines[board_type].name,
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
index e97fbbd..aeea172 100644
--- a/hw/arm/gumstix.c
+++ b/hw/arm/gumstix.c
@@ -42,6 +42,7 @@
 #include "hw/boards.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
 
 static const int sector_len = 128 * 1024;
 
@@ -58,7 +59,7 @@
     cpu = pxa255_init(address_space_mem, connex_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
+    if (!dinfo && !qtest_enabled()) {
         fprintf(stderr, "A flash image must be given with the "
                 "'pflash' parameter\n");
         exit(1);
@@ -70,7 +71,8 @@
     be = 0;
 #endif
     if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
-                               dinfo->bdrv, sector_len, connex_rom / sector_len,
+                               dinfo ? dinfo->bdrv : NULL,
+                               sector_len, connex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
         exit(1);
@@ -95,7 +97,7 @@
     cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0");
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
+    if (!dinfo && !qtest_enabled()) {
         fprintf(stderr, "A flash image must be given with the "
                 "'pflash' parameter\n");
         exit(1);
@@ -107,7 +109,8 @@
     be = 0;
 #endif
     if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
-                               dinfo->bdrv, sector_len, verdex_rom / sector_len,
+                               dinfo ? dinfo->bdrv : NULL,
+                               sector_len, verdex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
         exit(1);
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 2ef93ed..c44b2a4 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -11,6 +11,7 @@
 #include "hw/devices.h"
 #include "hw/boards.h"
 #include "hw/arm/arm.h"
+#include "hw/misc/arm_integrator_debug.h"
 #include "net/net.h"
 #include "exec/address-spaces.h"
 #include "sysemu/sysemu.h"
@@ -508,6 +509,7 @@
     icp_control_init(0xcb000000);
     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
     sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
+    sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0);
     sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
     if (nd_table[0].used)
         smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
index b244f7e..9402c84 100644
--- a/hw/arm/mainstone.c
+++ b/hw/arm/mainstone.c
@@ -21,6 +21,7 @@
 #include "sysemu/blockdev.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
 
 /* Device addresses */
 #define MST_FPGA_PHYS	0x08000000
@@ -127,6 +128,9 @@
     for (i = 0; i < 2; i ++) {
         dinfo = drive_get(IF_PFLASH, 0, i);
         if (!dinfo) {
+            if (qtest_enabled()) {
+                break;
+            }
             fprintf(stderr, "Two flash images must be given with the "
                     "'pflash' parameter\n");
             exit(1);
@@ -147,7 +151,6 @@
                     qdev_get_gpio_in(mpu->gpio, 0));
 
     /* setup keypad */
-    printf("map addr %p\n", &map);
     pxa27x_register_keypad(mpu->kp, map, 0xe0);
 
     /* MMC/SD host */
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
index b0f8664..3ba263a 100644
--- a/hw/arm/omap_sx1.c
+++ b/hw/arm/omap_sx1.c
@@ -32,6 +32,7 @@
 #include "hw/arm/arm.h"
 #include "hw/block/flash.h"
 #include "sysemu/blockdev.h"
+#include "sysemu/qtest.h"
 #include "exec/address-spaces.h"
 
 /*****************************************************************************/
@@ -188,18 +189,16 @@
                                 OMAP_CS1_BASE, &cs[1]);
     }
 
-    if (!args->kernel_filename && !fl_idx) {
+    if (!args->kernel_filename && !fl_idx && !qtest_enabled()) {
         fprintf(stderr, "Kernel or Flash image must be specified\n");
         exit(1);
     }
 
     /* Load the kernel.  */
-    if (args->kernel_filename) {
-        sx1_binfo.kernel_filename = args->kernel_filename;
-        sx1_binfo.kernel_cmdline = args->kernel_cmdline;
-        sx1_binfo.initrd_filename = args->initrd_filename;
-        arm_load_kernel(mpu->cpu, &sx1_binfo);
-    }
+    sx1_binfo.kernel_filename = args->kernel_filename;
+    sx1_binfo.kernel_cmdline = args->kernel_cmdline;
+    sx1_binfo.initrd_filename = args->initrd_filename;
+    arm_load_kernel(mpu->cpu, &sx1_binfo);
 
     /* TODO: fix next line */
     //~ qemu_console_resize(ds, 640, 480);
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
index 3e39044..fac4f69 100644
--- a/hw/arm/palm.c
+++ b/hw/arm/palm.c
@@ -19,6 +19,7 @@
 #include "hw/hw.h"
 #include "audio/audio.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
 #include "ui/console.h"
 #include "hw/arm/omap.h"
 #include "hw/boards.h"
@@ -255,18 +256,16 @@
         }
     }
 
-    if (!rom_loaded && !kernel_filename) {
+    if (!rom_loaded && !kernel_filename && !qtest_enabled()) {
         fprintf(stderr, "Kernel or ROM image must be specified\n");
         exit(1);
     }
 
     /* Load the kernel.  */
-    if (kernel_filename) {
-        palmte_binfo.kernel_filename = kernel_filename;
-        palmte_binfo.kernel_cmdline = kernel_cmdline;
-        palmte_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(mpu->cpu, &palmte_binfo);
-    }
+    palmte_binfo.kernel_filename = kernel_filename;
+    palmte_binfo.kernel_cmdline = kernel_cmdline;
+    palmte_binfo.initrd_filename = initrd_filename;
+    arm_load_kernel(mpu->cpu, &palmte_binfo);
 }
 
 static QEMUMachine palmte_machine = {
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 2e0d5d4..d52c501 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -24,6 +24,7 @@
 #include "ui/console.h"
 #include "audio/audio.h"
 #include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
 
 #ifdef DEBUG_Z2
 #define DPRINTF(fmt, ...) \
@@ -323,7 +324,7 @@
     be = 0;
 #endif
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
+    if (!dinfo && !qtest_enabled()) {
         fprintf(stderr, "Flash image must be given with the "
                 "'pflash' parameter\n");
         exit(1);
@@ -331,7 +332,7 @@
 
     if (!pflash_cfi01_register(Z2_FLASH_BASE,
                                NULL, "z2.flash0", Z2_FLASH_SIZE,
-                               dinfo->bdrv, sector_len,
+                               dinfo ? dinfo->bdrv : NULL, sector_len,
                                Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
                                be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -360,13 +361,11 @@
     qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
         qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
 
-    if (kernel_filename) {
-        z2_binfo.kernel_filename = kernel_filename;
-        z2_binfo.kernel_cmdline = kernel_cmdline;
-        z2_binfo.initrd_filename = initrd_filename;
-        z2_binfo.board_id = 0x6dd;
-        arm_load_kernel(mpu->cpu, &z2_binfo);
-    }
+    z2_binfo.kernel_filename = kernel_filename;
+    z2_binfo.kernel_cmdline = kernel_cmdline;
+    z2_binfo.initrd_filename = initrd_filename;
+    z2_binfo.board_id = 0x6dd;
+    arm_load_kernel(mpu->cpu, &z2_binfo);
 }
 
 static QEMUMachine z2_machine = {
diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
index 01b4dfb..03f4846 100644
--- a/hw/audio/ac97.c
+++ b/hw/audio/ac97.c
@@ -280,12 +280,12 @@
     if (level) {
         s->glob_sta |= masks[r - s->bm_regs];
         dolog ("set irq level=1\n");
-        qemu_set_irq (s->dev.irq[0], 1);
+        pci_irq_assert(&s->dev);
     }
     else {
         s->glob_sta &= ~masks[r - s->bm_regs];
         dolog ("set irq level=0\n");
-        qemu_set_irq (s->dev.irq[0], 0);
+        pci_irq_deassert(&s->dev);
     }
 }
 
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index adb66ce..1ec7ace 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -323,7 +323,7 @@
     else {
         s->status = new_status & ~STAT_INTR;
     }
-    qemu_set_irq (s->dev.irq[0], !!level);
+    pci_set_irq(&s->dev, !!level);
 }
 
 static void es1370_reset (ES1370State *s)
@@ -349,7 +349,7 @@
             s->dac_voice[i] = NULL;
         }
     }
-    qemu_irq_lower (s->dev.irq[0]);
+    pci_irq_deassert(&s->dev);
 }
 
 static void es1370_maybe_lower_irq (ES1370State *s, uint32_t sctl)
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index a6666c6..4327264 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -269,7 +269,7 @@
             msi_notify(&d->pci, 0);
         }
     } else {
-        qemu_set_irq(d->pci.irq[0], level);
+        pci_set_irq(&d->pci, level);
     }
 }
 
diff --git a/hw/block/cdrom.c b/hw/block/cdrom.c
index 38469fa..4e1019c 100644
--- a/hw/block/cdrom.c
+++ b/hw/block/cdrom.c
@@ -59,7 +59,7 @@
             q += 3;
         } else {
             /* sector 0 */
-            cpu_to_be32wu((uint32_t *)q, 0);
+            stl_be_p(q, 0);
             q += 4;
         }
     }
@@ -73,11 +73,11 @@
         lba_to_msf(q, nb_sectors);
         q += 3;
     } else {
-        cpu_to_be32wu((uint32_t *)q, nb_sectors);
+        stl_be_p(q, nb_sectors);
         q += 4;
     }
     len = q - buf;
-    cpu_to_be16wu((uint16_t *)buf, len - 2);
+    stw_be_p(buf, len - 2);
     return len;
 }
 
@@ -127,7 +127,7 @@
         lba_to_msf(q, nb_sectors);
         q += 3;
     } else {
-        cpu_to_be32wu((uint32_t *)q, nb_sectors);
+        stl_be_p(q, nb_sectors);
         q += 4;
     }
 
@@ -150,6 +150,6 @@
     }
 
     len = q - buf;
-    cpu_to_be16wu((uint16_t *)buf, len - 2);
+    stw_be_p(buf, len - 2);
     return len;
 }
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 5dee229..2882ffe 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -69,7 +69,7 @@
         if (msix_enabled(&(n->parent_obj))) {
             msix_notify(&(n->parent_obj), cq->vector);
         } else {
-            qemu_irq_pulse(n->parent_obj.irq[0]);
+            pci_irq_pulse(&n->parent_obj);
         }
     }
 }
diff --git a/hw/block/tc58128.c b/hw/block/tc58128.c
index a3929d4..728f1c3 100644
--- a/hw/block/tc58128.c
+++ b/hw/block/tc58128.c
@@ -1,6 +1,8 @@
 #include "hw/hw.h"
 #include "hw/sh4/sh.h"
 #include "hw/loader.h"
+#include "sysemu/qtest.h"
+#include "qemu/error-report.h"
 
 #define CE1  0x0100
 #define CE2  0x0200
@@ -36,10 +38,10 @@
 	/* Load flash image skipping the first block */
 	ret = load_image(filename, dev->flash_contents + 528 * 32);
 	if (ret < 0) {
-	    fprintf(stderr, "ret=%d\n", ret);
-	    fprintf(stderr, "qemu: could not load flash image %s\n",
-		    filename);
-	    exit(1);
+            if (!qtest_enabled()) {
+                error_report("Could not load flash image %s", filename);
+                exit(1);
+            }
 	} else {
 	    /* Build first block with number of blocks */
 	    blocks = (ret + 528 * 32 - 1) / (528 * 32);
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index 2e4b5c5..2c52a0f 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -195,22 +195,26 @@
     s->regs[R_STAT] = STAT_THRE;
 }
 
-static int milkymist_uart_init(SysBusDevice *dev)
+static void milkymist_uart_realize(DeviceState *dev, Error **errp)
 {
     MilkymistUartState *s = MILKYMIST_UART(dev);
 
-    sysbus_init_irq(dev, &s->irq);
-
-    memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
-                          "milkymist-uart", R_MAX * 4);
-    sysbus_init_mmio(dev, &s->regs_region);
-
     s->chr = qemu_char_get_next_serial();
     if (s->chr) {
         qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
     }
+}
 
-    return 0;
+static void milkymist_uart_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    MilkymistUartState *s = MILKYMIST_UART(obj);
+
+    sysbus_init_irq(sbd, &s->irq);
+
+    memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
+                          "milkymist-uart", R_MAX * 4);
+    sysbus_init_mmio(sbd, &s->regs_region);
 }
 
 static const VMStateDescription vmstate_milkymist_uart = {
@@ -227,9 +231,8 @@
 static void milkymist_uart_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = milkymist_uart_init;
+    dc->realize = milkymist_uart_realize;
     dc->reset = milkymist_uart_reset;
     dc->vmsd = &vmstate_milkymist_uart;
 }
@@ -238,6 +241,7 @@
     .name          = TYPE_MILKYMIST_UART,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistUartState),
+    .instance_init = milkymist_uart_init,
     .class_init    = milkymist_uart_class_init,
 };
 
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index aec6705..991c99f 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -61,7 +61,7 @@
     }
 
     pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
-    s->irq = pci->dev.irq[0];
+    s->irq = pci_allocate_irq(&pci->dev);
 
     memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
@@ -79,7 +79,7 @@
             pending = 1;
         }
     }
-    qemu_set_irq(pci->dev.irq[0], pending);
+    pci_set_irq(&pci->dev, pending);
 }
 
 static int multi_serial_pci_init(PCIDevice *dev)
@@ -132,6 +132,7 @@
 
     serial_exit_core(s);
     memory_region_destroy(&s->io);
+    qemu_free_irq(s->irq);
 }
 
 static void multi_serial_pci_exit(PCIDevice *dev)
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 9c2aef8..f8a4981 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -168,6 +168,7 @@
     k->dt_name = "vty";
     k->dt_type = "serial";
     k->dt_compatible = "hvterm1";
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     dc->props = spapr_vty_properties;
     dc->vmsd = &vmstate_spapr_vty;
 }
diff --git a/hw/char/tpci200.c b/hw/char/tpci200.c
index e04ff26..a49d2ed 100644
--- a/hw/char/tpci200.c
+++ b/hw/char/tpci200.c
@@ -134,8 +134,8 @@
     /* Check if the interrupt is edge sensitive */
     if (dev->ctrl[ip_n] & CTRL_INT_EDGE(intno)) {
         if (level) {
-            qemu_set_irq(dev->dev.irq[0], !dev->int_set);
-            qemu_set_irq(dev->dev.irq[0],  dev->int_set);
+            pci_set_irq(&dev->dev, !dev->int_set);
+            pci_set_irq(&dev->dev,  dev->int_set);
         }
     } else {
         unsigned i, j;
@@ -153,10 +153,10 @@
         }
 
         if (level_status && !dev->int_set) {
-            qemu_irq_raise(dev->dev.irq[0]);
+            pci_irq_assert(&dev->dev);
             dev->int_set = 1;
         } else if (!level_status && dev->int_set) {
-            qemu_irq_lower(dev->dev.irq[0]);
+            pci_irq_deassert(&dev->dev);
             dev->int_set = 0;
         }
     }
diff --git a/hw/core/irq.c b/hw/core/irq.c
index 2078542..03c8cb3 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -68,6 +68,17 @@
     return qemu_extend_irqs(NULL, 0, handler, opaque, n);
 }
 
+qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
+{
+    struct IRQState *irq;
+
+    irq = g_new(struct IRQState, 1);
+    irq->handler = handler;
+    irq->opaque = opaque;
+    irq->n = n;
+
+    return irq;
+}
 
 void qemu_free_irqs(qemu_irq *s)
 {
@@ -75,6 +86,11 @@
     g_free(s);
 }
 
+void qemu_free_irq(qemu_irq irq)
+{
+    g_free(irq);
+}
+
 static void qemu_notirq(void *opaque, int line, int level)
 {
     struct IRQState *irq = opaque;
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 7b3d3ee..60d2ebd 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -663,7 +663,7 @@
     rom_insert(rom);
     if (rom->fw_file && fw_cfg) {
         const char *basename;
-        char fw_file_name[56];
+        char fw_file_name[FW_CFG_MAX_FILE_PATH];
         void *data;
 
         basename = strrchr(rom->fw_file, '/');
@@ -700,10 +700,12 @@
     return -1;
 }
 
-int rom_add_blob(const char *name, const void *blob, size_t len,
-                 hwaddr addr)
+void *rom_add_blob(const char *name, const void *blob, size_t len,
+                   hwaddr addr, const char *fw_file_name,
+                   FWCfgReadCallback fw_callback, void *callback_opaque)
 {
     Rom *rom;
+    void *data = NULL;
 
     rom           = g_malloc0(sizeof(*rom));
     rom->name     = g_strdup(name);
@@ -713,7 +715,22 @@
     rom->data     = g_malloc0(rom->datasize);
     memcpy(rom->data, blob, len);
     rom_insert(rom);
-    return 0;
+    if (fw_file_name && fw_cfg) {
+        char devpath[100];
+
+        snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
+
+        if (rom_file_in_ram) {
+            data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
+        } else {
+            data = rom->data;
+        }
+
+        fw_cfg_add_file_callback(fw_cfg, fw_file_name,
+                                 fw_callback, callback_opaque,
+                                 data, rom->romsize);
+    }
+    return data;
 }
 
 /* This function is specific for elf program because we don't need to allocate
@@ -795,10 +812,14 @@
         memory_region_unref(section.mr);
     }
     qemu_register_reset(rom_reset, NULL);
-    roms_loaded = 1;
     return 0;
 }
 
+void rom_load_done(void)
+{
+    roms_loaded = 1;
+}
+
 void rom_set_fw(FWCfgState *f)
 {
     fw_cfg = f;
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 533f6dd..e374a93 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -164,7 +164,7 @@
     if (local_err != NULL) {
         qerror_report_err(local_err);
         error_free(local_err);
-        qdev_free(dev);
+        object_unparent(OBJECT(dev));
         return -1;
     }
     return 0;
@@ -258,7 +258,7 @@
 int qdev_simple_unplug_cb(DeviceState *dev)
 {
     /* just zap it */
-    qdev_free(dev);
+    object_unparent(OBJECT(dev));
     return 0;
 }
 
@@ -280,12 +280,6 @@
     }
 }
 
-/* Unlink device from bus and free the structure.  */
-void qdev_free(DeviceState *dev)
-{
-    object_unparent(OBJECT(dev));
-}
-
 void qdev_machine_creation_done(void)
 {
     /*
@@ -458,7 +452,7 @@
 
     while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
         DeviceState *dev = kid->child;
-        qdev_free(dev);
+        object_unparent(OBJECT(dev));
     }
     if (bus->parent) {
         QLIST_REMOVE(bus, sibling);
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index b84cd4a..146f50a 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -49,7 +49,7 @@
 }
 
 static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr,
-                                   bool may_overlap, unsigned priority)
+                                   bool may_overlap, int priority)
 {
     assert(n >= 0 && n < dev->num_mmio);
 
@@ -81,7 +81,7 @@
 }
 
 void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
-                             unsigned priority)
+                             int priority)
 {
     sysbus_mmio_map_common(dev, n, addr, true, priority);
 }
diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
index df287c1..6381238 100644
--- a/hw/cpu/Makefile.objs
+++ b/hw/cpu/Makefile.objs
@@ -1,4 +1,5 @@
 obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
+obj-$(CONFIG_REALVIEW) += realview_mpcore.o
 obj-$(CONFIG_A9MPCORE) += a9mpcore.o
 obj-$(CONFIG_A15MPCORE) += a15mpcore.o
 obj-$(CONFIG_ICC_BUS) += icc_bus.o
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 9abba67..acc419e 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -18,55 +18,60 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw/sysbus.h"
+#include "hw/cpu/a15mpcore.h"
 #include "sysemu/kvm.h"
 
-/* A15MP private memory region.  */
-
-#define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
-#define A15MPCORE_PRIV(obj) \
-    OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV)
-
-typedef struct A15MPPrivState {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    uint32_t num_cpu;
-    uint32_t num_irq;
-    MemoryRegion container;
-    DeviceState *gic;
-} A15MPPrivState;
-
 static void a15mp_priv_set_irq(void *opaque, int irq, int level)
 {
     A15MPPrivState *s = (A15MPPrivState *)opaque;
-    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+
+    qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
 }
 
-static int a15mp_priv_init(SysBusDevice *dev)
+static void a15mp_priv_initfn(Object *obj)
 {
-    A15MPPrivState *s = A15MPCORE_PRIV(dev);
-    SysBusDevice *busdev;
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    A15MPPrivState *s = A15MPCORE_PRIV(obj);
+    DeviceState *gicdev;
     const char *gictype = "arm_gic";
-    int i;
 
     if (kvm_irqchip_in_kernel()) {
         gictype = "kvm-arm-gic";
     }
 
-    s->gic = qdev_create(NULL, gictype);
-    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
-    qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
-    qdev_prop_set_uint32(s->gic, "revision", 2);
-    qdev_init_nofail(s->gic);
-    busdev = SYS_BUS_DEVICE(s->gic);
+    memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000);
+    sysbus_init_mmio(sbd, &s->container);
+
+    object_initialize(&s->gic, sizeof(s->gic), gictype);
+    gicdev = DEVICE(&s->gic);
+    qdev_set_parent_bus(gicdev, sysbus_get_default());
+    qdev_prop_set_uint32(gicdev, "revision", 2);
+}
+
+static void a15mp_priv_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    A15MPPrivState *s = A15MPCORE_PRIV(dev);
+    DeviceState *gicdev;
+    SysBusDevice *busdev;
+    int i;
+    Error *err = NULL;
+
+    gicdev = DEVICE(&s->gic);
+    qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
+    qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
+    object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(&s->gic);
 
     /* Pass through outbound IRQ lines from the GIC */
-    sysbus_pass_irq(dev, busdev);
+    sysbus_pass_irq(sbd, busdev);
 
     /* Pass through inbound GPIO lines to the GIC */
-    qdev_init_gpio_in(DEVICE(dev), a15mp_priv_set_irq, s->num_irq - 32);
+    qdev_init_gpio_in(dev, a15mp_priv_set_irq, s->num_irq - 32);
 
     /* Wire the outputs from each CPU's generic timer to the
      * appropriate GIC PPI inputs
@@ -78,10 +83,10 @@
          * since a real A15 always has TrustZone but QEMU doesn't.
          */
         qdev_connect_gpio_out(cpudev, 0,
-                              qdev_get_gpio_in(s->gic, ppibase + 30));
+                              qdev_get_gpio_in(gicdev, ppibase + 30));
         /* virtual timer */
         qdev_connect_gpio_out(cpudev, 1,
-                              qdev_get_gpio_in(s->gic, ppibase + 27));
+                              qdev_get_gpio_in(gicdev, ppibase + 27));
     }
 
     /* Memory map (addresses are offsets from PERIPHBASE):
@@ -92,15 +97,10 @@
      *  0x5000-0x5fff -- GIC virtual interface control (not modelled)
      *  0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
      */
-    memory_region_init(&s->container, OBJECT(s),
-                       "a15mp-priv-container", 0x8000);
     memory_region_add_subregion(&s->container, 0x1000,
                                 sysbus_mmio_get_region(busdev, 0));
     memory_region_add_subregion(&s->container, 0x2000,
                                 sysbus_mmio_get_region(busdev, 1));
-
-    sysbus_init_mmio(dev, &s->container);
-    return 0;
 }
 
 static Property a15mp_priv_properties[] = {
@@ -118,8 +118,8 @@
 static void a15mp_priv_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-    k->init = a15mp_priv_init;
+
+    dc->realize = a15mp_priv_realize;
     dc->props = a15mp_priv_properties;
     /* We currently have no savable state */
 }
@@ -128,6 +128,7 @@
     .name  = TYPE_A15MPCORE_PRIV,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(A15MPPrivState),
+    .instance_init = a15mp_priv_initfn,
     .class_init = a15mp_priv_class_init,
 };
 
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index 3e675e3..918a7d1 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -8,64 +8,86 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw/sysbus.h"
-
-#define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
-#define A9MPCORE_PRIV(obj) \
-    OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV)
-
-typedef struct A9MPPrivState {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    uint32_t num_cpu;
-    MemoryRegion container;
-    DeviceState *mptimer;
-    DeviceState *wdt;
-    DeviceState *gic;
-    DeviceState *scu;
-    uint32_t num_irq;
-} A9MPPrivState;
+#include "hw/cpu/a9mpcore.h"
 
 static void a9mp_priv_set_irq(void *opaque, int irq, int level)
 {
     A9MPPrivState *s = (A9MPPrivState *)opaque;
-    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+
+    qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
 }
 
-static int a9mp_priv_init(SysBusDevice *dev)
+static void a9mp_priv_initfn(Object *obj)
 {
+    A9MPPrivState *s = A9MPCORE_PRIV(obj);
+
+    memory_region_init(&s->container, obj, "a9mp-priv-container", 0x2000);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container);
+
+    object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
+    qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
+
+    object_initialize(&s->scu, sizeof(s->scu), TYPE_A9_SCU);
+    qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
+
+    object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER);
+    qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default());
+
+    object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ARM_MPTIMER);
+    qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
+}
+
+static void a9mp_priv_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     A9MPPrivState *s = A9MPCORE_PRIV(dev);
+    DeviceState *gicdev, *scudev, *mptimerdev, *wdtdev;
     SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev;
+    Error *err = NULL;
     int i;
 
-    s->gic = qdev_create(NULL, "arm_gic");
-    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
-    qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
-    qdev_init_nofail(s->gic);
-    gicbusdev = SYS_BUS_DEVICE(s->gic);
+    gicdev = DEVICE(&s->gic);
+    qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
+    qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
+    object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    gicbusdev = SYS_BUS_DEVICE(&s->gic);
 
     /* Pass through outbound IRQ lines from the GIC */
-    sysbus_pass_irq(dev, gicbusdev);
+    sysbus_pass_irq(sbd, gicbusdev);
 
     /* Pass through inbound GPIO lines to the GIC */
-    qdev_init_gpio_in(DEVICE(dev), a9mp_priv_set_irq, s->num_irq - 32);
+    qdev_init_gpio_in(dev, a9mp_priv_set_irq, s->num_irq - 32);
 
-    s->scu = qdev_create(NULL, "a9-scu");
-    qdev_prop_set_uint32(s->scu, "num-cpu", s->num_cpu);
-    qdev_init_nofail(s->scu);
-    scubusdev = SYS_BUS_DEVICE(s->scu);
+    scudev = DEVICE(&s->scu);
+    qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    scubusdev = SYS_BUS_DEVICE(&s->scu);
 
-    s->mptimer = qdev_create(NULL, "arm_mptimer");
-    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
-    qdev_init_nofail(s->mptimer);
-    timerbusdev = SYS_BUS_DEVICE(s->mptimer);
+    mptimerdev = DEVICE(&s->mptimer);
+    qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
 
-    s->wdt = qdev_create(NULL, "arm_mptimer");
-    qdev_prop_set_uint32(s->wdt, "num-cpu", s->num_cpu);
-    qdev_init_nofail(s->wdt);
-    wdtbusdev = SYS_BUS_DEVICE(s->wdt);
+    wdtdev = DEVICE(&s->wdt);
+    qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    wdtbusdev = SYS_BUS_DEVICE(&s->wdt);
 
     /* Memory map (addresses are offsets from PERIPHBASE):
      *  0x0000-0x00ff -- Snoop Control Unit
@@ -78,7 +100,6 @@
      *
      * We should implement the global timer but don't currently do so.
      */
-    memory_region_init(&s->container, OBJECT(s), "a9mp-priv-container", 0x2000);
     memory_region_add_subregion(&s->container, 0,
                                 sysbus_mmio_get_region(scubusdev, 0));
     /* GIC CPU interface */
@@ -94,19 +115,16 @@
     memory_region_add_subregion(&s->container, 0x1000,
                                 sysbus_mmio_get_region(gicbusdev, 0));
 
-    sysbus_init_mmio(dev, &s->container);
-
     /* Wire up the interrupt from each watchdog and timer.
      * For each core the timer is PPI 29 and the watchdog PPI 30.
      */
     for (i = 0; i < s->num_cpu; i++) {
         int ppibase = (s->num_irq - 32) + i * 32;
         sysbus_connect_irq(timerbusdev, i,
-                           qdev_get_gpio_in(s->gic, ppibase + 29));
+                           qdev_get_gpio_in(gicdev, ppibase + 29));
         sysbus_connect_irq(wdtbusdev, i,
-                           qdev_get_gpio_in(s->gic, ppibase + 30));
+                           qdev_get_gpio_in(gicdev, ppibase + 30));
     }
-    return 0;
 }
 
 static Property a9mp_priv_properties[] = {
@@ -124,9 +142,8 @@
 static void a9mp_priv_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = a9mp_priv_init;
+    dc->realize = a9mp_priv_realize;
     dc->props = a9mp_priv_properties;
 }
 
@@ -134,6 +151,7 @@
     .name          = TYPE_A9MPCORE_PRIV,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(A9MPPrivState),
+    .instance_init = a9mp_priv_initfn,
     .class_init    = a9mp_priv_class_init,
 };
 
diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
index a786c62..717d3e4 100644
--- a/hw/cpu/arm11mpcore.c
+++ b/hw/cpu/arm11mpcore.c
@@ -7,96 +7,28 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
+#include "hw/cpu/arm11mpcore.h"
+#include "hw/intc/realview_gic.h"
 
-/* MPCore private memory region.  */
-
-#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
-#define ARM11MPCORE_PRIV(obj) \
-    OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV)
-
-typedef struct ARM11MPCorePriveState {
-    SysBusDevice parent_obj;
-
-    uint32_t scu_control;
-    int iomemtype;
-    uint32_t old_timer_status[8];
-    uint32_t num_cpu;
-    MemoryRegion iomem;
-    MemoryRegion container;
-    DeviceState *mptimer;
-    DeviceState *wdtimer;
-    DeviceState *gic;
-    uint32_t num_irq;
-} ARM11MPCorePriveState;
-
-/* Per-CPU private memory mapped IO.  */
-
-static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
-                                unsigned size)
-{
-    ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
-    int id;
-    /* SCU */
-    switch (offset) {
-    case 0x00: /* Control.  */
-        return s->scu_control;
-    case 0x04: /* Configuration.  */
-        id = ((1 << s->num_cpu) - 1) << 4;
-        return id | (s->num_cpu - 1);
-    case 0x08: /* CPU status.  */
-        return 0;
-    case 0x0c: /* Invalidate all.  */
-        return 0;
-    default:
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "mpcore_priv_read: Bad offset %x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void mpcore_scu_write(void *opaque, hwaddr offset,
-                             uint64_t value, unsigned size)
-{
-    ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
-    /* SCU */
-    switch (offset) {
-    case 0: /* Control register.  */
-        s->scu_control = value & 1;
-        break;
-    case 0x0c: /* Invalidate all.  */
-        /* This is a no-op as cache is not emulated.  */
-        break;
-    default:
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "mpcore_priv_read: Bad offset %x\n", (int)offset);
-    }
-}
-
-static const MemoryRegionOps mpcore_scu_ops = {
-    .read = mpcore_scu_read,
-    .write = mpcore_scu_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
 
 static void mpcore_priv_set_irq(void *opaque, int irq, int level)
 {
     ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
-    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+
+    qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
 }
 
 static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
 {
     int i;
-    SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
-    SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer);
-    SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer);
-    memory_region_init(&s->container, OBJECT(s),
-                       "mpcode-priv-container", 0x2000);
-    memory_region_init_io(&s->iomem, OBJECT(s),
-                          &mpcore_scu_ops, s, "mpcore-scu", 0x100);
-    memory_region_add_subregion(&s->container, 0, &s->iomem);
+    SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu);
+    DeviceState *gicdev = DEVICE(&s->gic);
+    SysBusDevice *gicbusdev = SYS_BUS_DEVICE(&s->gic);
+    SysBusDevice *timerbusdev = SYS_BUS_DEVICE(&s->mptimer);
+    SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(&s->wdtimer);
+
+    memory_region_add_subregion(&s->container, 0,
+                                sysbus_mmio_get_region(scubusdev, 0));
     /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
      * at 0x200, 0x300...
      */
@@ -124,134 +56,84 @@
     for (i = 0; i < s->num_cpu; i++) {
         int ppibase = (s->num_irq - 32) + i * 32;
         sysbus_connect_irq(timerbusdev, i,
-                           qdev_get_gpio_in(s->gic, ppibase + 29));
+                           qdev_get_gpio_in(gicdev, ppibase + 29));
         sysbus_connect_irq(wdtbusdev, i,
-                           qdev_get_gpio_in(s->gic, ppibase + 30));
+                           qdev_get_gpio_in(gicdev, ppibase + 30));
     }
 }
 
-static int mpcore_priv_init(SysBusDevice *sbd)
+static void mpcore_priv_realize(DeviceState *dev, Error **errp)
 {
-    DeviceState *dev = DEVICE(sbd);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev);
+    DeviceState *scudev = DEVICE(&s->scu);
+    DeviceState *gicdev = DEVICE(&s->gic);
+    DeviceState *mptimerdev = DEVICE(&s->mptimer);
+    DeviceState *wdtimerdev = DEVICE(&s->wdtimer);
+    Error *err = NULL;
 
-    s->gic = qdev_create(NULL, "arm_gic");
-    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
-    qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
-    /* Request the legacy 11MPCore GIC behaviour: */
-    qdev_prop_set_uint32(s->gic, "revision", 0);
-    qdev_init_nofail(s->gic);
+    qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
+    qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
+    object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
 
     /* Pass through outbound IRQ lines from the GIC */
-    sysbus_pass_irq(sbd, SYS_BUS_DEVICE(s->gic));
+    sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->gic));
 
     /* Pass through inbound GPIO lines to the GIC */
     qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32);
 
-    s->mptimer = qdev_create(NULL, "arm_mptimer");
-    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
-    qdev_init_nofail(s->mptimer);
+    qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
 
-    s->wdtimer = qdev_create(NULL, "arm_mptimer");
-    qdev_prop_set_uint32(s->wdtimer, "num-cpu", s->num_cpu);
-    qdev_init_nofail(s->wdtimer);
+    qdev_prop_set_uint32(wdtimerdev, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->wdtimer), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
 
     mpcore_priv_map_setup(s);
+}
+
+static void mpcore_priv_initfn(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(obj);
+
+    memory_region_init(&s->container, OBJECT(s),
+                       "mpcore-priv-container", 0x2000);
     sysbus_init_mmio(sbd, &s->container);
-    return 0;
+
+    object_initialize(&s->scu, sizeof(s->scu), TYPE_ARM11_SCU);
+    qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
+
+    object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
+    qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
+    /* Request the legacy 11MPCore GIC behaviour: */
+    qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 0);
+
+    object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER);
+    qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default());
+
+    object_initialize(&s->wdtimer, sizeof(s->wdtimer), TYPE_ARM_MPTIMER);
+    qdev_set_parent_bus(DEVICE(&s->wdtimer), sysbus_get_default());
 }
 
-#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
-#define REALVIEW_MPCORE_RIRQ(obj) \
-    OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ)
-
-/* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
-   controllers.  The output of these, plus some of the raw input lines
-   are fed into a single SMP-aware interrupt controller on the CPU.  */
-typedef struct {
-    SysBusDevice parent_obj;
-
-    SysBusDevice *priv;
-    qemu_irq cpuic[32];
-    qemu_irq rvic[4][64];
-    uint32_t num_cpu;
-} mpcore_rirq_state;
-
-/* Map baseboard IRQs onto CPU IRQ lines.  */
-static const int mpcore_irq_map[32] = {
-    -1, -1, -1, -1,  1,  2, -1, -1,
-    -1, -1,  6, -1,  4,  5, -1, -1,
-    -1, 14, 15,  0,  7,  8, -1, -1,
-    -1, -1, -1, -1,  9,  3, -1, -1,
-};
-
-static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
-{
-    mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        qemu_set_irq(s->rvic[i][irq], level);
-    }
-    if (irq < 32) {
-        irq = mpcore_irq_map[irq];
-        if (irq >= 0) {
-            qemu_set_irq(s->cpuic[irq], level);
-        }
-    }
-}
-
-static int realview_mpcore_init(SysBusDevice *sbd)
-{
-    DeviceState *dev = DEVICE(sbd);
-    mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev);
-    DeviceState *gic;
-    DeviceState *priv;
-    int n;
-    int i;
-
-    priv = qdev_create(NULL, TYPE_ARM11MPCORE_PRIV);
-    qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
-    qdev_init_nofail(priv);
-    s->priv = SYS_BUS_DEVICE(priv);
-    sysbus_pass_irq(sbd, s->priv);
-    for (i = 0; i < 32; i++) {
-        s->cpuic[i] = qdev_get_gpio_in(priv, i);
-    }
-    /* ??? IRQ routing is hardcoded to "normal" mode.  */
-    for (n = 0; n < 4; n++) {
-        gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000,
-                                   s->cpuic[10 + n]);
-        for (i = 0; i < 64; i++) {
-            s->rvic[n][i] = qdev_get_gpio_in(gic, i);
-        }
-    }
-    qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
-    sysbus_init_mmio(sbd, sysbus_mmio_get_region(s->priv, 0));
-    return 0;
-}
-
-static Property mpcore_rirq_properties[] = {
-    DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = realview_mpcore_init;
-    dc->props = mpcore_rirq_properties;
-}
-
-static const TypeInfo mpcore_rirq_info = {
-    .name          = TYPE_REALVIEW_MPCORE_RIRQ,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mpcore_rirq_state),
-    .class_init    = mpcore_rirq_class_init,
-};
-
 static Property mpcore_priv_properties[] = {
     DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1),
     /* The ARM11 MPCORE TRM says the on-chip controller may have
@@ -269,9 +151,8 @@
 static void mpcore_priv_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = mpcore_priv_init;
+    dc->realize = mpcore_priv_realize;
     dc->props = mpcore_priv_properties;
 }
 
@@ -279,12 +160,12 @@
     .name          = TYPE_ARM11MPCORE_PRIV,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ARM11MPCorePriveState),
+    .instance_init = mpcore_priv_initfn,
     .class_init    = mpcore_priv_class_init,
 };
 
 static void arm11mpcore_register_types(void)
 {
-    type_register_static(&mpcore_rirq_info);
     type_register_static(&mpcore_priv_info);
 }
 
diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c
new file mode 100644
index 0000000..c39a2da
--- /dev/null
+++ b/hw/cpu/realview_mpcore.c
@@ -0,0 +1,139 @@
+/*
+ * RealView ARM11MPCore internal peripheral emulation
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2013 SUSE LINUX Products GmbH
+ * Written by Paul Brook and Andreas Färber
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/cpu/arm11mpcore.h"
+#include "hw/intc/realview_gic.h"
+
+#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
+#define REALVIEW_MPCORE_RIRQ(obj) \
+    OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ)
+
+/* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
+   controllers.  The output of these, plus some of the raw input lines
+   are fed into a single SMP-aware interrupt controller on the CPU.  */
+typedef struct {
+    SysBusDevice parent_obj;
+
+    qemu_irq cpuic[32];
+    qemu_irq rvic[4][64];
+    uint32_t num_cpu;
+
+    ARM11MPCorePriveState priv;
+    RealViewGICState gic[4];
+} mpcore_rirq_state;
+
+/* Map baseboard IRQs onto CPU IRQ lines.  */
+static const int mpcore_irq_map[32] = {
+    -1, -1, -1, -1,  1,  2, -1, -1,
+    -1, -1,  6, -1,  4,  5, -1, -1,
+    -1, 14, 15,  0,  7,  8, -1, -1,
+    -1, -1, -1, -1,  9,  3, -1, -1,
+};
+
+static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
+{
+    mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        qemu_set_irq(s->rvic[i][irq], level);
+    }
+    if (irq < 32) {
+        irq = mpcore_irq_map[irq];
+        if (irq >= 0) {
+            qemu_set_irq(s->cpuic[irq], level);
+        }
+    }
+}
+
+static void realview_mpcore_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev);
+    DeviceState *priv = DEVICE(&s->priv);
+    DeviceState *gic;
+    SysBusDevice *gicbusdev;
+    Error *err = NULL;
+    int n;
+    int i;
+
+    qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
+    object_property_set_bool(OBJECT(&s->priv), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv));
+    for (i = 0; i < 32; i++) {
+        s->cpuic[i] = qdev_get_gpio_in(priv, i);
+    }
+    /* ??? IRQ routing is hardcoded to "normal" mode.  */
+    for (n = 0; n < 4; n++) {
+        object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+        gic = DEVICE(&s->gic[n]);
+        gicbusdev = SYS_BUS_DEVICE(&s->gic[n]);
+        sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000);
+        sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]);
+        for (i = 0; i < 64; i++) {
+            s->rvic[n][i] = qdev_get_gpio_in(gic, i);
+        }
+    }
+    qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
+}
+
+static void mpcore_rirq_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj);
+    SysBusDevice *privbusdev;
+    int i;
+
+    object_initialize(&s->priv, sizeof(s->priv), TYPE_ARM11MPCORE_PRIV);
+    qdev_set_parent_bus(DEVICE(&s->priv), sysbus_get_default());
+    privbusdev = SYS_BUS_DEVICE(&s->priv);
+    sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0));
+
+    for (i = 0; i < 4; i++) {
+        object_initialize(&s->gic[i], sizeof(s->gic[i]), TYPE_REALVIEW_GIC);
+        qdev_set_parent_bus(DEVICE(&s->gic[i]), sysbus_get_default());
+    }
+}
+
+static Property mpcore_rirq_properties[] = {
+    DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = realview_mpcore_realize;
+    dc->props = mpcore_rirq_properties;
+}
+
+static const TypeInfo mpcore_rirq_info = {
+    .name          = TYPE_REALVIEW_MPCORE_RIRQ,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mpcore_rirq_state),
+    .instance_init = mpcore_rirq_init,
+    .class_init    = mpcore_rirq_class_init,
+};
+
+static void realview_mpcore_register_types(void)
+{
+    type_register_static(&mpcore_rirq_info);
+}
+
+type_init(realview_mpcore_register_types)
diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
index 03058d3..5524088 100644
--- a/hw/cris/axis_dev88.c
+++ b/hw/cris/axis_dev88.c
@@ -32,6 +32,7 @@
 #include "boot.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
 
 #define D(x)
 #define DNAND(x)
@@ -340,14 +341,14 @@
                              irq[0x14 + i]);
     }
 
-    if (!kernel_filename) {
+    if (kernel_filename) {
+        li.image_filename = kernel_filename;
+        li.cmdline = kernel_cmdline;
+        cris_load_image(cpu, &li);
+    } else if (!qtest_enabled()) {
         fprintf(stderr, "Kernel image must be specified\n");
         exit(1);
     }
-
-    li.image_filename = kernel_filename;
-    li.cmdline = kernel_cmdline;
-    cris_load_image(cpu, &li);
 }
 
 static QEMUMachine axisdev88_machine = {
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index de835d6..efdefd6 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1101,7 +1101,7 @@
     uint32_t pending = le32_to_cpu(d->ram->int_pending);
     uint32_t mask    = le32_to_cpu(d->ram->int_mask);
     int level = !!(pending & mask);
-    qemu_set_irq(d->pci.irq[0], level);
+    pci_set_irq(&d->pci, level);
     qxl_ring_set_dirty(d);
 }
 
@@ -1701,15 +1701,9 @@
     },
 };
 
-static void pipe_read(void *opaque)
+static void qxl_update_irq_bh(void *opaque)
 {
     PCIQXLDevice *d = opaque;
-    char dummy;
-    int len;
-
-    do {
-        len = read(d->pipe[0], &dummy, sizeof(dummy));
-    } while (len == sizeof(dummy));
     qxl_update_irq(d);
 }
 
@@ -1730,28 +1724,7 @@
     if ((old_pending & le_events) == le_events) {
         return;
     }
-    if (qemu_thread_is_self(&d->main)) {
-        qxl_update_irq(d);
-    } else {
-        if (write(d->pipe[1], d, 1) != 1) {
-            dprint(d, 1, "%s: write to pipe failed\n", __func__);
-        }
-    }
-}
-
-static void init_pipe_signaling(PCIQXLDevice *d)
-{
-    if (pipe(d->pipe) < 0) {
-        fprintf(stderr, "%s:%s: qxl pipe creation failed\n",
-                __FILE__, __func__);
-        exit(1);
-    }
-    fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
-    fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
-    fcntl(d->pipe[0], F_SETOWN, getpid());
-
-    qemu_thread_get_self(&d->main);
-    qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
+    qemu_bh_schedule(d->update_irq);
 }
 
 /* graphics console */
@@ -2044,7 +2017,7 @@
     }
     qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
 
-    init_pipe_signaling(qxl);
+    qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
     qxl_reset_state(qxl);
 
     qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
diff --git a/hw/display/qxl.h b/hw/display/qxl.h
index 84f0182..c5de3d7 100644
--- a/hw/display/qxl.h
+++ b/hw/display/qxl.h
@@ -81,8 +81,7 @@
     QemuMutex          track_lock;
 
     /* thread signaling */
-    QemuThread         main;
-    int                pipe[2];
+    QEMUBH             *update_irq;
 
     /* ram pci bar */
     QXLRam             *ram;
diff --git a/hw/display/vga.c b/hw/display/vga.c
index b5e2284..063319d 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1707,7 +1707,6 @@
     } else if (is_buffer_shared(surface) &&
                (full_update || surface_data(surface) != s->vram_ptr
                 + (s->start_addr * 4))) {
-        DisplaySurface *surface;
         surface = qemu_create_displaysurface_from(disp_width,
                 height, depth, s->line_offset,
                 s->vram_ptr + (s->start_addr * 4), byteswap);
diff --git a/hw/display/vga_template.h b/hw/display/vga_template.h
index f6f6a01..6cfae56 100644
--- a/hw/display/vga_template.h
+++ b/hw/display/vga_template.h
@@ -113,20 +113,22 @@
     do {
         font_data = font_ptr[0];
 #if BPP == 1
-        cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
+        stl_p((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
         v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
-        cpu_to_32wu(((uint32_t *)d)+1, v);
+        stl_p(((uint32_t *)d)+1, v);
         if (dup9)
             ((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
         else
             ((uint8_t *)d)[8] = bgcol;
 
 #elif BPP == 2
-        cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
-        cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
-        cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
+        stl_p(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
+        stl_p(((uint32_t *)d)+1,
+              (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
+        stl_p(((uint32_t *)d)+2,
+              (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
         v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
-        cpu_to_32wu(((uint32_t *)d)+3, v);
+        stl_p(((uint32_t *)d)+3, v);
         if (dup9)
             ((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
         else
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 45e6165..09ac433 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -5,3 +5,30 @@
 obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
 
 obj-y += kvmvapic.o
+obj-y += acpi-build.o
+obj-y += bios-linker-loader.o
+hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \
+	hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \
+	hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex
+
+iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
+    ; then echo "$(2)"; else echo "$(3)"; fi ;)
+
+ifdef IASL
+#IASL Present. Generate hex files from .dsl
+hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.dsl $(SRC_PATH)/scripts/acpi_extract_preprocess.py $(SRC_PATH)/scripts/acpi_extract.py
+	$(call quiet-command, cpp -P $< -o $*.dsl.i.orig, "  CPP $(TARGET_DIR)$*.dsl.i.orig")
+	$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract_preprocess.py $*.dsl.i.orig > $*.dsl.i, "  ACPI_PREPROCESS $(TARGET_DIR)$*.dsl.i")
+	$(call quiet-command, $(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $* $*.dsl.i $(if $(V), , > /dev/null) 2>&1 ,"  IASL $(TARGET_DIR)$*.dsl.i")
+	$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract.py $*.lst > $*.off, "  ACPI_EXTRACT $(TARGET_DIR)$*.off")
+	$(call quiet-command, cat $*.off > $@, "  CAT $(TARGET_DIR)$@")
+else
+#IASL Not present. Restore pre-generated hex files.
+hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.hex.generated
+	$(call quiet-command, cp -f $< $@, "  CP $(TARGET_DIR)$@")
+endif
+
+.PHONY: cleanhex
+cleanhex:
+	rm -f hw/i386/*hex
+clean: cleanhex
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
new file mode 100644
index 0000000..486e705
--- /dev/null
+++ b/hw/i386/acpi-build.c
@@ -0,0 +1,1219 @@
+/* Support for generating ACPI tables and passing them to Guests
+ *
+ * Copyright (C) 2008-2010  Kevin O'Connor <kevin@koconnor.net>
+ * Copyright (C) 2006 Fabrice Bellard
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "acpi-build.h"
+#include <stddef.h>
+#include <glib.h>
+#include "qemu-common.h"
+#include "qemu/bitmap.h"
+#include "qemu/range.h"
+#include "hw/pci/pci.h"
+#include "qom/cpu.h"
+#include "hw/i386/pc.h"
+#include "target-i386/cpu.h"
+#include "hw/timer/hpet.h"
+#include "hw/i386/acpi-defs.h"
+#include "hw/acpi/acpi.h"
+#include "hw/nvram/fw_cfg.h"
+#include "bios-linker-loader.h"
+#include "hw/loader.h"
+
+/* Supported chipsets: */
+#include "hw/acpi/piix4.h"
+#include "hw/i386/ich9.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci-host/q35.h"
+
+#include "hw/i386/q35-acpi-dsdt.hex"
+#include "hw/i386/acpi-dsdt.hex"
+
+#include "qapi/qmp/qint.h"
+#include "qom/qom-qobject.h"
+
+typedef struct AcpiCpuInfo {
+    DECLARE_BITMAP(found_cpus, MAX_CPUMASK_BITS + 1);
+} AcpiCpuInfo;
+
+typedef struct AcpiMcfgInfo {
+    uint64_t mcfg_base;
+    uint32_t mcfg_size;
+} AcpiMcfgInfo;
+
+typedef struct AcpiPmInfo {
+    bool s3_disabled;
+    bool s4_disabled;
+    uint8_t s4_val;
+    uint16_t sci_int;
+    uint8_t acpi_enable_cmd;
+    uint8_t acpi_disable_cmd;
+    uint32_t gpe0_blk;
+    uint32_t gpe0_blk_len;
+    uint32_t io_base;
+} AcpiPmInfo;
+
+typedef struct AcpiMiscInfo {
+    bool has_hpet;
+    DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
+    const unsigned char *dsdt_code;
+    unsigned dsdt_size;
+    uint16_t pvpanic_port;
+} AcpiMiscInfo;
+
+static void acpi_get_dsdt(AcpiMiscInfo *info)
+{
+    Object *piix = piix4_pm_find();
+    Object *lpc = ich9_lpc_find();
+    assert(!!piix != !!lpc);
+
+    if (piix) {
+        info->dsdt_code = AcpiDsdtAmlCode;
+        info->dsdt_size = sizeof AcpiDsdtAmlCode;
+    }
+    if (lpc) {
+        info->dsdt_code = Q35AcpiDsdtAmlCode;
+        info->dsdt_size = sizeof Q35AcpiDsdtAmlCode;
+    }
+}
+
+static
+int acpi_add_cpu_info(Object *o, void *opaque)
+{
+    AcpiCpuInfo *cpu = opaque;
+    uint64_t apic_id;
+
+    if (object_dynamic_cast(o, TYPE_CPU)) {
+        apic_id = object_property_get_int(o, "apic-id", NULL);
+        assert(apic_id <= MAX_CPUMASK_BITS);
+
+        set_bit(apic_id, cpu->found_cpus);
+    }
+
+    object_child_foreach(o, acpi_add_cpu_info, opaque);
+    return 0;
+}
+
+static void acpi_get_cpu_info(AcpiCpuInfo *cpu)
+{
+    Object *root = object_get_root();
+
+    memset(cpu->found_cpus, 0, sizeof cpu->found_cpus);
+    object_child_foreach(root, acpi_add_cpu_info, cpu);
+}
+
+static void acpi_get_pm_info(AcpiPmInfo *pm)
+{
+    Object *piix = piix4_pm_find();
+    Object *lpc = ich9_lpc_find();
+    Object *obj = NULL;
+    QObject *o;
+
+    if (piix) {
+        obj = piix;
+    }
+    if (lpc) {
+        obj = lpc;
+    }
+    assert(obj);
+
+    /* Fill in optional s3/s4 related properties */
+    o = object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL);
+    if (o) {
+        pm->s3_disabled = qint_get_int(qobject_to_qint(o));
+    } else {
+        pm->s3_disabled = false;
+    }
+    o = object_property_get_qobject(obj, ACPI_PM_PROP_S4_DISABLED, NULL);
+    if (o) {
+        pm->s4_disabled = qint_get_int(qobject_to_qint(o));
+    } else {
+        pm->s4_disabled = false;
+    }
+    o = object_property_get_qobject(obj, ACPI_PM_PROP_S4_VAL, NULL);
+    if (o) {
+        pm->s4_val = qint_get_int(qobject_to_qint(o));
+    } else {
+        pm->s4_val = false;
+    }
+
+    /* Fill in mandatory properties */
+    pm->sci_int = object_property_get_int(obj, ACPI_PM_PROP_SCI_INT, NULL);
+
+    pm->acpi_enable_cmd = object_property_get_int(obj,
+                                                  ACPI_PM_PROP_ACPI_ENABLE_CMD,
+                                                  NULL);
+    pm->acpi_disable_cmd = object_property_get_int(obj,
+                                                  ACPI_PM_PROP_ACPI_DISABLE_CMD,
+                                                  NULL);
+    pm->io_base = object_property_get_int(obj, ACPI_PM_PROP_PM_IO_BASE,
+                                          NULL);
+    pm->gpe0_blk = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK,
+                                           NULL);
+    pm->gpe0_blk_len = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
+                                               NULL);
+}
+
+static void acpi_get_hotplug_info(AcpiMiscInfo *misc)
+{
+    int i;
+    PCIBus *bus = find_i440fx();
+
+    if (!bus) {
+        /* Only PIIX supports ACPI hotplug */
+        memset(misc->slot_hotplug_enable, 0, sizeof misc->slot_hotplug_enable);
+        return;
+    }
+
+    memset(misc->slot_hotplug_enable, 0xff,
+           DIV_ROUND_UP(PCI_SLOT_MAX, BITS_PER_BYTE));
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        PCIDeviceClass *pc;
+        PCIDevice *pdev = bus->devices[i];
+
+        if (!pdev) {
+            continue;
+        }
+
+        pc = PCI_DEVICE_GET_CLASS(pdev);
+
+        if (pc->no_hotplug) {
+            int slot = PCI_SLOT(i);
+
+            clear_bit(slot, misc->slot_hotplug_enable);
+        }
+    }
+}
+
+static void acpi_get_misc_info(AcpiMiscInfo *info)
+{
+    info->has_hpet = hpet_find();
+    info->pvpanic_port = pvpanic_port();
+}
+
+static void acpi_get_pci_info(PcPciInfo *info)
+{
+    Object *pci_host;
+    bool ambiguous;
+
+    pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
+    g_assert(!ambiguous);
+    g_assert(pci_host);
+
+    info->w32.begin = object_property_get_int(pci_host,
+                                              PCI_HOST_PROP_PCI_HOLE_START,
+                                              NULL);
+    info->w32.end = object_property_get_int(pci_host,
+                                            PCI_HOST_PROP_PCI_HOLE_END,
+                                            NULL);
+    info->w64.begin = object_property_get_int(pci_host,
+                                              PCI_HOST_PROP_PCI_HOLE64_START,
+                                              NULL);
+    info->w64.end = object_property_get_int(pci_host,
+                                            PCI_HOST_PROP_PCI_HOLE64_END,
+                                            NULL);
+}
+
+#define ACPI_BUILD_APPNAME  "Bochs"
+#define ACPI_BUILD_APPNAME6 "BOCHS "
+#define ACPI_BUILD_APPNAME4 "BXPC"
+
+#define ACPI_BUILD_DPRINTF(level, fmt, ...) do {} while (0)
+
+#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
+#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
+
+static void
+build_header(GArray *linker, GArray *table_data,
+             AcpiTableHeader *h, uint32_t sig, int len, uint8_t rev)
+{
+    h->signature = cpu_to_le32(sig);
+    h->length = cpu_to_le32(len);
+    h->revision = rev;
+    memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
+    memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
+    memcpy(h->oem_table_id + 4, (void *)&sig, 4);
+    h->oem_revision = cpu_to_le32(1);
+    memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
+    h->asl_compiler_revision = cpu_to_le32(1);
+    h->checksum = 0;
+    /* Checksum to be filled in by Guest linker */
+    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
+                                    table_data->data, h, len, &h->checksum);
+}
+
+static inline GArray *build_alloc_array(void)
+{
+        return g_array_new(false, true /* clear */, 1);
+}
+
+static inline void build_free_array(GArray *array)
+{
+        g_array_free(array, true);
+}
+
+static inline void build_prepend_byte(GArray *array, uint8_t val)
+{
+    g_array_prepend_val(array, val);
+}
+
+static inline void build_append_byte(GArray *array, uint8_t val)
+{
+    g_array_append_val(array, val);
+}
+
+static inline void build_append_array(GArray *array, GArray *val)
+{
+    g_array_append_vals(array, val->data, val->len);
+}
+
+static void build_append_nameseg(GArray *array, const char *format, ...)
+{
+    GString *s = g_string_new("");
+    va_list args;
+
+    va_start(args, format);
+    g_string_vprintf(s, format, args);
+    va_end(args);
+
+    assert(s->len == 4);
+    g_array_append_vals(array, s->str, s->len);
+    g_string_free(s, true);
+}
+
+/* 5.4 Definition Block Encoding */
+enum {
+    PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
+    PACKAGE_LENGTH_2BYTE_SHIFT = 4,
+    PACKAGE_LENGTH_3BYTE_SHIFT = 12,
+    PACKAGE_LENGTH_4BYTE_SHIFT = 20,
+};
+
+static void build_prepend_package_length(GArray *package, unsigned min_bytes)
+{
+    uint8_t byte;
+    unsigned length = package->len;
+    unsigned length_bytes;
+
+    if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) {
+        length_bytes = 1;
+    } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) {
+        length_bytes = 2;
+    } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) {
+        length_bytes = 3;
+    } else {
+        length_bytes = 4;
+    }
+
+    /* Force length to at least min_bytes.
+     * This wastes memory but that's how bios did it.
+     */
+    length_bytes = MAX(length_bytes, min_bytes);
+
+    /* PkgLength is the length of the inclusive length of the data. */
+    length += length_bytes;
+
+    switch (length_bytes) {
+    case 1:
+        byte = length;
+        build_prepend_byte(package, byte);
+        return;
+    case 4:
+        byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
+        /* fall through */
+    case 3:
+        byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
+        /* fall through */
+    case 2:
+        byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
+        /* fall through */
+    }
+    /*
+     * Most significant two bits of byte zero indicate how many following bytes
+     * are in PkgLength encoding.
+     */
+    byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
+    build_prepend_byte(package, byte);
+}
+
+static void build_package(GArray *package, uint8_t op, unsigned min_bytes)
+{
+    build_prepend_package_length(package, min_bytes);
+    build_prepend_byte(package, op);
+}
+
+static void build_append_value(GArray *table, uint32_t value, int size)
+{
+    uint8_t prefix;
+    int i;
+
+    switch (size) {
+    case 1:
+        prefix = 0x0A; /* BytePrefix */
+        break;
+    case 2:
+        prefix = 0x0B; /* WordPrefix */
+        break;
+    case 4:
+        prefix = 0x0C; /* DWordPrefix */
+        break;
+    default:
+        assert(0);
+        return;
+    }
+    build_append_byte(table, prefix);
+    for (i = 0; i < size; ++i) {
+        build_append_byte(table, value & 0xFF);
+        value = value >> 8;
+    }
+}
+
+static void build_append_notify_target(GArray *method, GArray *target_name,
+                                       uint32_t value, int size)
+{
+    GArray *notify = build_alloc_array();
+    uint8_t op = 0xA0; /* IfOp */
+
+    build_append_byte(notify, 0x93); /* LEqualOp */
+    build_append_byte(notify, 0x68); /* Arg0Op */
+    build_append_value(notify, value, size);
+    build_append_byte(notify, 0x86); /* NotifyOp */
+    build_append_array(notify, target_name);
+    build_append_byte(notify, 0x69); /* Arg1Op */
+
+    /* Pack it up */
+    build_package(notify, op, 1);
+
+    build_append_array(method, notify);
+
+    build_free_array(notify);
+}
+
+#define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT */
+
+static inline void *acpi_data_push(GArray *table_data, unsigned size)
+{
+    unsigned off = table_data->len;
+    g_array_set_size(table_data, off + size);
+    return table_data->data + off;
+}
+
+static unsigned acpi_data_len(GArray *table)
+{
+    return table->len * g_array_get_element_size(table);
+}
+
+static void acpi_align_size(GArray *blob, unsigned align)
+{
+    /* Align size to multiple of given size. This reduces the chance
+     * we need to change size in the future (breaking cross version migration).
+     */
+    g_array_set_size(blob, (ROUND_UP(acpi_data_len(blob), align) +
+                            g_array_get_element_size(blob) - 1) /
+                             g_array_get_element_size(blob));
+}
+
+/* Get pointer within table in a safe manner */
+#define ACPI_BUILD_PTR(table, size, off, type) \
+    ((type *)(acpi_data_get_ptr(table, size, off, sizeof(type))))
+
+static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size,
+                                      unsigned off, unsigned size)
+{
+    assert(off + size > off);
+    assert(off + size <= table_size);
+    return table_data + off;
+}
+
+static inline void acpi_add_table(GArray *table_offsets, GArray *table_data)
+{
+    uint32_t offset = cpu_to_le32(table_data->len);
+    g_array_append_val(table_offsets, offset);
+}
+
+/* FACS */
+static void
+build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
+{
+    AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
+    facs->signature = cpu_to_le32(ACPI_FACS_SIGNATURE);
+    facs->length = cpu_to_le32(sizeof(*facs));
+}
+
+/* Load chipset information in FADT */
+static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm)
+{
+    fadt->model = 1;
+    fadt->reserved1 = 0;
+    fadt->sci_int = cpu_to_le16(pm->sci_int);
+    fadt->smi_cmd = cpu_to_le32(ACPI_PORT_SMI_CMD);
+    fadt->acpi_enable = pm->acpi_enable_cmd;
+    fadt->acpi_disable = pm->acpi_disable_cmd;
+    /* EVT, CNT, TMR offset matches hw/acpi/core.c */
+    fadt->pm1a_evt_blk = cpu_to_le32(pm->io_base);
+    fadt->pm1a_cnt_blk = cpu_to_le32(pm->io_base + 0x04);
+    fadt->pm_tmr_blk = cpu_to_le32(pm->io_base + 0x08);
+    fadt->gpe0_blk = cpu_to_le32(pm->gpe0_blk);
+    /* EVT, CNT, TMR length matches hw/acpi/core.c */
+    fadt->pm1_evt_len = 4;
+    fadt->pm1_cnt_len = 2;
+    fadt->pm_tmr_len = 4;
+    fadt->gpe0_blk_len = pm->gpe0_blk_len;
+    fadt->plvl2_lat = cpu_to_le16(0xfff); /* C2 state not supported */
+    fadt->plvl3_lat = cpu_to_le16(0xfff); /* C3 state not supported */
+    fadt->flags = cpu_to_le32((1 << ACPI_FADT_F_WBINVD) |
+                              (1 << ACPI_FADT_F_PROC_C1) |
+                              (1 << ACPI_FADT_F_SLP_BUTTON) |
+                              (1 << ACPI_FADT_F_RTC_S4));
+    fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_USE_PLATFORM_CLOCK);
+}
+
+
+/* FADT */
+static void
+build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
+           unsigned facs, unsigned dsdt)
+{
+    AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
+
+    fadt->firmware_ctrl = cpu_to_le32(facs);
+    /* FACS address to be filled by Guest linker */
+    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+                                   ACPI_BUILD_TABLE_FILE,
+                                   table_data, &fadt->firmware_ctrl,
+                                   sizeof fadt->firmware_ctrl);
+
+    fadt->dsdt = cpu_to_le32(dsdt);
+    /* DSDT address to be filled by Guest linker */
+    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+                                   ACPI_BUILD_TABLE_FILE,
+                                   table_data, &fadt->dsdt,
+                                   sizeof fadt->dsdt);
+
+    fadt_setup(fadt, pm);
+
+    build_header(linker, table_data,
+                 (void *)fadt, ACPI_FACP_SIGNATURE, sizeof(*fadt), 1);
+}
+
+static void
+build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
+           PcGuestInfo *guest_info)
+{
+    int madt_start = table_data->len;
+
+    AcpiMultipleApicTable *madt;
+    AcpiMadtIoApic *io_apic;
+    AcpiMadtIntsrcovr *intsrcovr;
+    AcpiMadtLocalNmi *local_nmi;
+    int i;
+
+    madt = acpi_data_push(table_data, sizeof *madt);
+    madt->local_apic_address = cpu_to_le32(APIC_DEFAULT_ADDRESS);
+    madt->flags = cpu_to_le32(1);
+
+    for (i = 0; i < guest_info->apic_id_limit; i++) {
+        AcpiMadtProcessorApic *apic = acpi_data_push(table_data, sizeof *apic);
+        apic->type = ACPI_APIC_PROCESSOR;
+        apic->length = sizeof(*apic);
+        apic->processor_id = i;
+        apic->local_apic_id = i;
+        if (test_bit(i, cpu->found_cpus)) {
+            apic->flags = cpu_to_le32(1);
+        } else {
+            apic->flags = cpu_to_le32(0);
+        }
+    }
+    io_apic = acpi_data_push(table_data, sizeof *io_apic);
+    io_apic->type = ACPI_APIC_IO;
+    io_apic->length = sizeof(*io_apic);
+#define ACPI_BUILD_IOAPIC_ID 0x0
+    io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID;
+    io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
+    io_apic->interrupt = cpu_to_le32(0);
+
+    if (guest_info->apic_xrupt_override) {
+        intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
+        intsrcovr->type   = ACPI_APIC_XRUPT_OVERRIDE;
+        intsrcovr->length = sizeof(*intsrcovr);
+        intsrcovr->source = 0;
+        intsrcovr->gsi    = cpu_to_le32(2);
+        intsrcovr->flags  = cpu_to_le16(0); /* conforms to bus specifications */
+    }
+    for (i = 1; i < 16; i++) {
+#define ACPI_BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11))
+        if (!(ACPI_BUILD_PCI_IRQS & (1 << i))) {
+            /* No need for a INT source override structure. */
+            continue;
+        }
+        intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
+        intsrcovr->type   = ACPI_APIC_XRUPT_OVERRIDE;
+        intsrcovr->length = sizeof(*intsrcovr);
+        intsrcovr->source = i;
+        intsrcovr->gsi    = cpu_to_le32(i);
+        intsrcovr->flags  = cpu_to_le16(0xd); /* active high, level triggered */
+    }
+
+    local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
+    local_nmi->type         = ACPI_APIC_LOCAL_NMI;
+    local_nmi->length       = sizeof(*local_nmi);
+    local_nmi->processor_id = 0xff; /* all processors */
+    local_nmi->flags        = cpu_to_le16(0);
+    local_nmi->lint         = 1; /* ACPI_LINT1 */
+
+    build_header(linker, table_data,
+                 (void *)(table_data->data + madt_start), ACPI_APIC_SIGNATURE,
+                 table_data->len - madt_start, 1);
+}
+
+/* Encode a hex value */
+static inline char acpi_get_hex(uint32_t val)
+{
+    val &= 0x0f;
+    return (val <= 9) ? ('0' + val) : ('A' + val - 10);
+}
+
+#include "hw/i386/ssdt-proc.hex"
+
+/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */
+#define ACPI_PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2)
+#define ACPI_PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4)
+#define ACPI_PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start)
+#define ACPI_PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
+#define ACPI_PROC_AML (ssdp_proc_aml + *ssdt_proc_start)
+
+/* 0x5B 0x82 DeviceOp PkgLength NameString */
+#define ACPI_PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1)
+#define ACPI_PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start)
+#define ACPI_PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start)
+#define ACPI_PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start)
+#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
+#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
+
+#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
+#define ACPI_SSDT_HEADER_LENGTH 36
+
+#include "hw/i386/ssdt-misc.hex"
+#include "hw/i386/ssdt-pcihp.hex"
+
+static void
+build_append_notify(GArray *device, const char *name,
+                    const char *format, int skip, int count)
+{
+    int i;
+    GArray *method = build_alloc_array();
+    uint8_t op = 0x14; /* MethodOp */
+
+    build_append_nameseg(method, name);
+    build_append_byte(method, 0x02); /* MethodFlags: ArgCount */
+    for (i = skip; i < count; i++) {
+        GArray *target = build_alloc_array();
+        build_append_nameseg(target, format, i);
+        assert(i < 256); /* Fits in 1 byte */
+        build_append_notify_target(method, target, i, 1);
+        build_free_array(target);
+    }
+    build_package(method, op, 2);
+
+    build_append_array(device, method);
+    build_free_array(method);
+}
+
+static void patch_pcihp(int slot, uint8_t *ssdt_ptr, uint32_t eject)
+{
+    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(slot >> 4);
+    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX + 1] = acpi_get_hex(slot);
+    ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot;
+    ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
+
+    /* Runtime patching of ACPI_EJ0: to disable hotplug for a slot,
+     * replace the method name: _EJ0 by ACPI_EJ0_.
+     */
+    /* Sanity check */
+    assert(!memcmp(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "_EJ0", 4));
+
+    if (!eject) {
+        memcpy(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "EJ0_", 4);
+    }
+}
+
+static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
+{
+    *ACPI_BUILD_PTR(start, size, acpi_pci32_start[0], uint32_t) =
+        cpu_to_le32(pci->w32.begin);
+
+    *ACPI_BUILD_PTR(start, size, acpi_pci32_end[0], uint32_t) =
+        cpu_to_le32(pci->w32.end - 1);
+
+    if (pci->w64.end || pci->w64.begin) {
+        *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 1;
+        *ACPI_BUILD_PTR(start, size, acpi_pci64_start[0], uint64_t) =
+            cpu_to_le64(pci->w64.begin);
+        *ACPI_BUILD_PTR(start, size, acpi_pci64_end[0], uint64_t) =
+            cpu_to_le64(pci->w64.end - 1);
+        *ACPI_BUILD_PTR(start, size, acpi_pci64_length[0], uint64_t) =
+            cpu_to_le64(pci->w64.end - pci->w64.begin);
+    } else {
+        *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 0;
+    }
+}
+
+static void
+build_ssdt(GArray *table_data, GArray *linker,
+           AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc,
+           PcPciInfo *pci, PcGuestInfo *guest_info)
+{
+    int acpi_cpus = MIN(0xff, guest_info->apic_id_limit);
+    int ssdt_start = table_data->len;
+    uint8_t *ssdt_ptr;
+    int i;
+
+    /* Copy header and patch values in the S3_ / S4_ / S5_ packages */
+    ssdt_ptr = acpi_data_push(table_data, sizeof(ssdp_misc_aml));
+    memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
+    if (pm->s3_disabled) {
+        ssdt_ptr[acpi_s3_name[0]] = 'X';
+    }
+    if (pm->s4_disabled) {
+        ssdt_ptr[acpi_s4_name[0]] = 'X';
+    } else {
+        ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt_ptr[acpi_s4_pkg[0] + 3] =
+            pm->s4_val;
+    }
+
+    patch_pci_windows(pci, ssdt_ptr, sizeof(ssdp_misc_aml));
+
+    *(uint16_t *)(ssdt_ptr + *ssdt_isa_pest) =
+        cpu_to_le16(misc->pvpanic_port);
+
+    {
+        GArray *sb_scope = build_alloc_array();
+        uint8_t op = 0x10; /* ScopeOp */
+
+        build_append_nameseg(sb_scope, "_SB_");
+
+        /* build Processor object for each processor */
+        for (i = 0; i < acpi_cpus; i++) {
+            uint8_t *proc = acpi_data_push(sb_scope, ACPI_PROC_SIZEOF);
+            memcpy(proc, ACPI_PROC_AML, ACPI_PROC_SIZEOF);
+            proc[ACPI_PROC_OFFSET_CPUHEX] = acpi_get_hex(i >> 4);
+            proc[ACPI_PROC_OFFSET_CPUHEX+1] = acpi_get_hex(i);
+            proc[ACPI_PROC_OFFSET_CPUID1] = i;
+            proc[ACPI_PROC_OFFSET_CPUID2] = i;
+        }
+
+        /* build this code:
+         *   Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
+         */
+        /* Arg0 = Processor ID = APIC ID */
+        build_append_notify(sb_scope, "NTFY", "CP%0.02X", 0, acpi_cpus);
+
+        /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */
+        build_append_byte(sb_scope, 0x08); /* NameOp */
+        build_append_nameseg(sb_scope, "CPON");
+
+        {
+            GArray *package = build_alloc_array();
+            uint8_t op = 0x12; /* PackageOp */
+
+            build_append_byte(package, acpi_cpus); /* NumElements */
+            for (i = 0; i < acpi_cpus; i++) {
+                uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00;
+                build_append_byte(package, b);
+            }
+
+            build_package(package, op, 2);
+            build_append_array(sb_scope, package);
+            build_free_array(package);
+        }
+
+        {
+            GArray *pci0 = build_alloc_array();
+            uint8_t op = 0x10; /* ScopeOp */;
+
+            build_append_nameseg(pci0, "PCI0");
+
+            /* build Device object for each slot */
+            for (i = 1; i < PCI_SLOT_MAX; i++) {
+                bool eject = test_bit(i, misc->slot_hotplug_enable);
+                void *pcihp = acpi_data_push(pci0, ACPI_PCIHP_SIZEOF);
+
+                memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
+                patch_pcihp(i, pcihp, eject);
+            }
+
+            build_append_notify(pci0, "PCNT", "S%0.02X_", 1, PCI_SLOT_MAX);
+            build_package(pci0, op, 3);
+            build_append_array(sb_scope, pci0);
+            build_free_array(pci0);
+        }
+
+        build_package(sb_scope, op, 3);
+        build_append_array(table_data, sb_scope);
+        build_free_array(sb_scope);
+    }
+
+    build_header(linker, table_data,
+                 (void *)(table_data->data + ssdt_start),
+                 ACPI_SSDT_SIGNATURE, table_data->len - ssdt_start, 1);
+}
+
+static void
+build_hpet(GArray *table_data, GArray *linker)
+{
+    Acpi20Hpet *hpet;
+
+    hpet = acpi_data_push(table_data, sizeof(*hpet));
+    /* Note timer_block_id value must be kept in sync with value advertised by
+     * emulated hpet
+     */
+    hpet->timer_block_id = cpu_to_le32(0x8086a201);
+    hpet->addr.address = cpu_to_le64(HPET_BASE);
+    build_header(linker, table_data,
+                 (void *)hpet, ACPI_HPET_SIGNATURE, sizeof(*hpet), 1);
+}
+
+static void
+acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem,
+                       uint64_t base, uint64_t len, int node, int enabled)
+{
+    numamem->type = ACPI_SRAT_MEMORY;
+    numamem->length = sizeof(*numamem);
+    memset(numamem->proximity, 0, 4);
+    numamem->proximity[0] = node;
+    numamem->flags = cpu_to_le32(!!enabled);
+    numamem->base_addr = cpu_to_le64(base);
+    numamem->range_length = cpu_to_le64(len);
+}
+
+static void
+build_srat(GArray *table_data, GArray *linker,
+           AcpiCpuInfo *cpu, PcGuestInfo *guest_info)
+{
+    AcpiSystemResourceAffinityTable *srat;
+    AcpiSratProcessorAffinity *core;
+    AcpiSratMemoryAffinity *numamem;
+
+    int i;
+    uint64_t curnode;
+    int srat_start, numa_start, slots;
+    uint64_t mem_len, mem_base, next_base;
+
+    srat_start = table_data->len;
+
+    srat = acpi_data_push(table_data, sizeof *srat);
+    srat->reserved1 = cpu_to_le32(1);
+    core = (void *)(srat + 1);
+
+    for (i = 0; i < guest_info->apic_id_limit; ++i) {
+        core = acpi_data_push(table_data, sizeof *core);
+        core->type = ACPI_SRAT_PROCESSOR;
+        core->length = sizeof(*core);
+        core->local_apic_id = i;
+        curnode = guest_info->node_cpu[i];
+        core->proximity_lo = curnode;
+        memset(core->proximity_hi, 0, 3);
+        core->local_sapic_eid = 0;
+        if (test_bit(i, cpu->found_cpus)) {
+            core->flags = cpu_to_le32(1);
+        } else {
+            core->flags = cpu_to_le32(0);
+        }
+    }
+
+
+    /* the memory map is a bit tricky, it contains at least one hole
+     * from 640k-1M and possibly another one from 3.5G-4G.
+     */
+    next_base = 0;
+    numa_start = table_data->len;
+
+    numamem = acpi_data_push(table_data, sizeof *numamem);
+    acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
+    next_base = 1024 * 1024;
+    for (i = 1; i < guest_info->numa_nodes + 1; ++i) {
+        mem_base = next_base;
+        mem_len = guest_info->node_mem[i - 1];
+        if (i == 1) {
+            mem_len -= 1024 * 1024;
+        }
+        next_base = mem_base + mem_len;
+
+        /* Cut out the ACPI_PCI hole */
+        if (mem_base <= guest_info->ram_size &&
+            next_base > guest_info->ram_size) {
+            mem_len -= next_base - guest_info->ram_size;
+            if (mem_len > 0) {
+                numamem = acpi_data_push(table_data, sizeof *numamem);
+                acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
+            }
+            mem_base = 1ULL << 32;
+            mem_len = next_base - guest_info->ram_size;
+            next_base += (1ULL << 32) - guest_info->ram_size;
+        }
+        numamem = acpi_data_push(table_data, sizeof *numamem);
+        acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1, 1);
+    }
+    slots = (table_data->len - numa_start) / sizeof *numamem;
+    for (; slots < guest_info->numa_nodes + 2; slots++) {
+        numamem = acpi_data_push(table_data, sizeof *numamem);
+        acpi_build_srat_memory(numamem, 0, 0, 0, 0);
+    }
+
+    build_header(linker, table_data,
+                 (void *)(table_data->data + srat_start),
+                 ACPI_SRAT_SIGNATURE,
+                 table_data->len - srat_start, 1);
+}
+
+static void
+build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
+{
+    AcpiTableMcfg *mcfg;
+    uint32_t sig;
+    int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
+
+    mcfg = acpi_data_push(table_data, len);
+    mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
+    /* Only a single allocation so no need to play with segments */
+    mcfg->allocation[0].pci_segment = cpu_to_le16(0);
+    mcfg->allocation[0].start_bus_number = 0;
+    mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
+
+    /* MCFG is used for ECAM which can be enabled or disabled by guest.
+     * To avoid table size changes (which create migration issues),
+     * always create the table even if there are no allocations,
+     * but set the signature to a reserved value in this case.
+     * ACPI spec requires OSPMs to ignore such tables.
+     */
+    if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
+        sig = ACPI_RSRV_SIGNATURE;
+    } else {
+        sig = ACPI_MCFG_SIGNATURE;
+    }
+    build_header(linker, table_data, (void *)mcfg, sig, len, 1);
+}
+
+static void
+build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
+{
+    void *dsdt;
+    assert(misc->dsdt_code && misc->dsdt_size);
+    dsdt = acpi_data_push(table_data, misc->dsdt_size);
+    memcpy(dsdt, misc->dsdt_code, misc->dsdt_size);
+}
+
+/* Build final rsdt table */
+static void
+build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
+{
+    AcpiRsdtDescriptorRev1 *rsdt;
+    size_t rsdt_len;
+    int i;
+
+    rsdt_len = sizeof(*rsdt) + sizeof(uint32_t) * table_offsets->len;
+    rsdt = acpi_data_push(table_data, rsdt_len);
+    memcpy(rsdt->table_offset_entry, table_offsets->data,
+           sizeof(uint32_t) * table_offsets->len);
+    for (i = 0; i < table_offsets->len; ++i) {
+        /* rsdt->table_offset_entry to be filled by Guest linker */
+        bios_linker_loader_add_pointer(linker,
+                                       ACPI_BUILD_TABLE_FILE,
+                                       ACPI_BUILD_TABLE_FILE,
+                                       table_data, &rsdt->table_offset_entry[i],
+                                       sizeof(uint32_t));
+    }
+    build_header(linker, table_data,
+                 (void *)rsdt, ACPI_RSDT_SIGNATURE, rsdt_len, 1);
+}
+
+static GArray *
+build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
+{
+    AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
+
+    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 1,
+                             true /* fseg memory */);
+
+    rsdp->signature = cpu_to_le64(ACPI_RSDP_SIGNATURE);
+    memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
+    rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
+    /* Address to be filled by Guest linker */
+    bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
+                                   ACPI_BUILD_TABLE_FILE,
+                                   rsdp_table, &rsdp->rsdt_physical_address,
+                                   sizeof rsdp->rsdt_physical_address);
+    rsdp->checksum = 0;
+    /* Checksum to be filled by Guest linker */
+    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
+                                    rsdp, rsdp, sizeof *rsdp, &rsdp->checksum);
+
+    return rsdp_table;
+}
+
+typedef
+struct AcpiBuildTables {
+    GArray *table_data;
+    GArray *rsdp;
+    GArray *linker;
+} AcpiBuildTables;
+
+static inline void acpi_build_tables_init(AcpiBuildTables *tables)
+{
+    tables->rsdp = g_array_new(false, true /* clear */, 1);
+    tables->table_data = g_array_new(false, true /* clear */, 1);
+    tables->linker = bios_linker_loader_init();
+}
+
+static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
+{
+    void *linker_data = bios_linker_loader_cleanup(tables->linker);
+    if (mfre) {
+        g_free(linker_data);
+    }
+    g_array_free(tables->rsdp, mfre);
+    g_array_free(tables->table_data, mfre);
+}
+
+typedef
+struct AcpiBuildState {
+    /* Copy of table in RAM (for patching). */
+    uint8_t *table_ram;
+    uint32_t table_size;
+    /* Is table patched? */
+    uint8_t patched;
+    PcGuestInfo *guest_info;
+} AcpiBuildState;
+
+static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
+{
+    Object *pci_host;
+    QObject *o;
+    bool ambiguous;
+
+    pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
+    g_assert(!ambiguous);
+    g_assert(pci_host);
+
+    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
+    if (!o) {
+        return false;
+    }
+    mcfg->mcfg_base = qint_get_int(qobject_to_qint(o));
+
+    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
+    assert(o);
+    mcfg->mcfg_size = qint_get_int(qobject_to_qint(o));
+    return true;
+}
+
+static
+void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
+{
+    GArray *table_offsets;
+    unsigned facs, dsdt, rsdt;
+    AcpiCpuInfo cpu;
+    AcpiPmInfo pm;
+    AcpiMiscInfo misc;
+    AcpiMcfgInfo mcfg;
+    PcPciInfo pci;
+    uint8_t *u;
+
+    acpi_get_cpu_info(&cpu);
+    acpi_get_pm_info(&pm);
+    acpi_get_dsdt(&misc);
+    acpi_get_hotplug_info(&misc);
+    acpi_get_misc_info(&misc);
+    acpi_get_pci_info(&pci);
+
+    table_offsets = g_array_new(false, true /* clear */,
+                                        sizeof(uint32_t));
+    ACPI_BUILD_DPRINTF(3, "init ACPI tables\n");
+
+    bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,
+                             64 /* Ensure FACS is aligned */,
+                             false /* high memory */);
+
+    /*
+     * FACS is pointed to by FADT.
+     * We place it first since it's the only table that has alignment
+     * requirements.
+     */
+    facs = tables->table_data->len;
+    build_facs(tables->table_data, tables->linker, guest_info);
+
+    /* DSDT is pointed to by FADT */
+    dsdt = tables->table_data->len;
+    build_dsdt(tables->table_data, tables->linker, &misc);
+
+    /* ACPI tables pointed to by RSDT */
+    acpi_add_table(table_offsets, tables->table_data);
+    build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt);
+    acpi_add_table(table_offsets, tables->table_data);
+
+    build_ssdt(tables->table_data, tables->linker, &cpu, &pm, &misc, &pci,
+               guest_info);
+    acpi_add_table(table_offsets, tables->table_data);
+
+    build_madt(tables->table_data, tables->linker, &cpu, guest_info);
+    acpi_add_table(table_offsets, tables->table_data);
+    if (misc.has_hpet) {
+        build_hpet(tables->table_data, tables->linker);
+    }
+    if (guest_info->numa_nodes) {
+        acpi_add_table(table_offsets, tables->table_data);
+        build_srat(tables->table_data, tables->linker, &cpu, guest_info);
+    }
+    if (acpi_get_mcfg(&mcfg)) {
+        acpi_add_table(table_offsets, tables->table_data);
+        build_mcfg_q35(tables->table_data, tables->linker, &mcfg);
+    }
+
+    /* Add tables supplied by user (if any) */
+    for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
+        unsigned len = acpi_table_len(u);
+
+        acpi_add_table(table_offsets, tables->table_data);
+        g_array_append_vals(tables->table_data, u, len);
+    }
+
+    /* RSDT is pointed to by RSDP */
+    rsdt = tables->table_data->len;
+    build_rsdt(tables->table_data, tables->linker, table_offsets);
+
+    /* RSDP is in FSEG memory, so allocate it separately */
+    build_rsdp(tables->rsdp, tables->linker, rsdt);
+
+    /* We'll expose it all to Guest so align size to reduce
+     * chance of size changes.
+     * RSDP is small so it's easy to keep it immutable, no need to
+     * bother with alignment.
+     */
+    acpi_align_size(tables->table_data, 0x1000);
+
+    acpi_align_size(tables->linker, 0x1000);
+
+    /* Cleanup memory that's no longer used. */
+    g_array_free(table_offsets, true);
+}
+
+static void acpi_build_update(void *build_opaque, uint32_t offset)
+{
+    AcpiBuildState *build_state = build_opaque;
+    AcpiBuildTables tables;
+
+    /* No state to update or already patched? Nothing to do. */
+    if (!build_state || build_state->patched) {
+        return;
+    }
+    build_state->patched = 1;
+
+    acpi_build_tables_init(&tables);
+
+    acpi_build(build_state->guest_info, &tables);
+
+    assert(acpi_data_len(tables.table_data) == build_state->table_size);
+    memcpy(build_state->table_ram, tables.table_data->data,
+           build_state->table_size);
+
+    acpi_build_tables_cleanup(&tables, true);
+}
+
+static void acpi_build_reset(void *build_opaque)
+{
+    AcpiBuildState *build_state = build_opaque;
+    build_state->patched = 0;
+}
+
+static void *acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
+                               const char *name)
+{
+    return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, name,
+                        acpi_build_update, build_state);
+}
+
+static const VMStateDescription vmstate_acpi_build = {
+    .name = "acpi_build",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(patched, AcpiBuildState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+void acpi_setup(PcGuestInfo *guest_info)
+{
+    AcpiBuildTables tables;
+    AcpiBuildState *build_state;
+
+    if (!guest_info->fw_cfg) {
+        ACPI_BUILD_DPRINTF(3, "No fw cfg. Bailing out.\n");
+        return;
+    }
+
+    if (!guest_info->has_acpi_build) {
+        ACPI_BUILD_DPRINTF(3, "ACPI build disabled. Bailing out.\n");
+        return;
+    }
+
+    if (!acpi_enabled) {
+        ACPI_BUILD_DPRINTF(3, "ACPI disabled. Bailing out.\n");
+        return;
+    }
+
+    build_state = g_malloc0(sizeof *build_state);
+
+    build_state->guest_info = guest_info;
+
+    acpi_build_tables_init(&tables);
+    acpi_build(build_state->guest_info, &tables);
+
+    /* Now expose it all to Guest */
+    build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data,
+                                               ACPI_BUILD_TABLE_FILE);
+    build_state->table_size = acpi_data_len(tables.table_data);
+
+    acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader");
+
+    /*
+     * RSDP is small so it's easy to keep it immutable, no need to
+     * bother with ROM blobs.
+     */
+    fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
+                    tables.rsdp->data, acpi_data_len(tables.rsdp));
+
+    qemu_register_reset(acpi_build_reset, build_state);
+    acpi_build_reset(build_state);
+    vmstate_register(NULL, 0, &vmstate_acpi_build, build_state);
+
+    /* Cleanup tables but don't free the memory: we track it
+     * in build_state.
+     */
+    acpi_build_tables_cleanup(&tables, false);
+}
diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h
new file mode 100644
index 0000000..e57b1aa
--- /dev/null
+++ b/hw/i386/acpi-build.h
@@ -0,0 +1,9 @@
+
+#ifndef HW_I386_ACPI_BUILD_H
+#define HW_I386_ACPI_BUILD_H
+
+#include "qemu/typedefs.h"
+
+void acpi_setup(PcGuestInfo *);
+
+#endif
diff --git a/hw/i386/acpi-defs.h b/hw/i386/acpi-defs.h
new file mode 100644
index 0000000..78ca204
--- /dev/null
+++ b/hw/i386/acpi-defs.h
@@ -0,0 +1,331 @@
+/*
+ * 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/>.
+ */
+#ifndef QEMU_ACPI_DEFS_H
+#define QEMU_ACPI_DEFS_H
+
+enum {
+    ACPI_FADT_F_WBINVD,
+    ACPI_FADT_F_WBINVD_FLUSH,
+    ACPI_FADT_F_PROC_C1,
+    ACPI_FADT_F_P_LVL2_UP,
+    ACPI_FADT_F_PWR_BUTTON,
+    ACPI_FADT_F_SLP_BUTTON,
+    ACPI_FADT_F_FIX_RTC,
+    ACPI_FADT_F_RTC_S4,
+    ACPI_FADT_F_TMR_VAL_EXT,
+    ACPI_FADT_F_DCK_CAP,
+    ACPI_FADT_F_RESET_REG_SUP,
+    ACPI_FADT_F_SEALED_CASE,
+    ACPI_FADT_F_HEADLESS,
+    ACPI_FADT_F_CPU_SW_SLP,
+    ACPI_FADT_F_PCI_EXP_WAK,
+    ACPI_FADT_F_USE_PLATFORM_CLOCK,
+    ACPI_FADT_F_S4_RTC_STS_VALID,
+    ACPI_FADT_F_REMOTE_POWER_ON_CAPABLE,
+    ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL,
+    ACPI_FADT_F_FORCE_APIC_PHYSICAL_DESTINATION_MODE,
+    ACPI_FADT_F_HW_REDUCED_ACPI,
+    ACPI_FADT_F_LOW_POWER_S0_IDLE_CAPABLE,
+};
+
+/*
+ * ACPI 2.0 Generic Address Space definition.
+ */
+struct Acpi20GenericAddress {
+    uint8_t  address_space_id;
+    uint8_t  register_bit_width;
+    uint8_t  register_bit_offset;
+    uint8_t  reserved;
+    uint64_t address;
+} QEMU_PACKED;
+typedef struct Acpi20GenericAddress Acpi20GenericAddress;
+
+#define ACPI_RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
+
+struct AcpiRsdpDescriptor {        /* Root System Descriptor Pointer */
+    uint64_t signature;              /* ACPI signature, contains "RSD PTR " */
+    uint8_t  checksum;               /* To make sum of struct == 0 */
+    uint8_t  oem_id [6];             /* OEM identification */
+    uint8_t  revision;               /* Must be 0 for 1.0, 2 for 2.0 */
+    uint32_t rsdt_physical_address;  /* 32-bit physical address of RSDT */
+    uint32_t length;                 /* XSDT Length in bytes including hdr */
+    uint64_t xsdt_physical_address;  /* 64-bit physical address of XSDT */
+    uint8_t  extended_checksum;      /* Checksum of entire table */
+    uint8_t  reserved [3];           /* Reserved field must be 0 */
+} QEMU_PACKED;
+typedef struct AcpiRsdpDescriptor AcpiRsdpDescriptor;
+
+/* Table structure from Linux kernel (the ACPI tables are under the
+   BSD license) */
+
+
+#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
+    uint32_t signature;          /* ACPI signature (4 ASCII characters) */ \
+    uint32_t length;                 /* Length of table, in bytes, including header */ \
+    uint8_t  revision;               /* ACPI Specification minor version # */ \
+    uint8_t  checksum;               /* To make sum of entire table == 0 */ \
+    uint8_t  oem_id [6];             /* OEM identification */ \
+    uint8_t  oem_table_id [8];       /* OEM table identification */ \
+    uint32_t oem_revision;           /* OEM revision number */ \
+    uint8_t  asl_compiler_id [4];    /* ASL compiler vendor ID */ \
+    uint32_t asl_compiler_revision;  /* ASL compiler revision number */
+
+
+struct AcpiTableHeader         /* ACPI common table header */
+{
+    ACPI_TABLE_HEADER_DEF
+} QEMU_PACKED;
+typedef struct AcpiTableHeader AcpiTableHeader;
+
+/*
+ * ACPI 1.0 Fixed ACPI Description Table (FADT)
+ */
+#define ACPI_FACP_SIGNATURE 0x50434146 // FACP
+struct AcpiFadtDescriptorRev1
+{
+    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
+    uint32_t firmware_ctrl;          /* Physical address of FACS */
+    uint32_t dsdt;                   /* Physical address of DSDT */
+    uint8_t  model;                  /* System Interrupt Model */
+    uint8_t  reserved1;              /* Reserved */
+    uint16_t sci_int;                /* System vector of SCI interrupt */
+    uint32_t smi_cmd;                /* Port address of SMI command port */
+    uint8_t  acpi_enable;            /* Value to write to smi_cmd to enable ACPI */
+    uint8_t  acpi_disable;           /* Value to write to smi_cmd to disable ACPI */
+    uint8_t  S4bios_req;             /* Value to write to SMI CMD to enter S4BIOS state */
+    uint8_t  reserved2;              /* Reserved - must be zero */
+    uint32_t pm1a_evt_blk;           /* Port address of Power Mgt 1a acpi_event Reg Blk */
+    uint32_t pm1b_evt_blk;           /* Port address of Power Mgt 1b acpi_event Reg Blk */
+    uint32_t pm1a_cnt_blk;           /* Port address of Power Mgt 1a Control Reg Blk */
+    uint32_t pm1b_cnt_blk;           /* Port address of Power Mgt 1b Control Reg Blk */
+    uint32_t pm2_cnt_blk;            /* Port address of Power Mgt 2 Control Reg Blk */
+    uint32_t pm_tmr_blk;             /* Port address of Power Mgt Timer Ctrl Reg Blk */
+    uint32_t gpe0_blk;               /* Port addr of General Purpose acpi_event 0 Reg Blk */
+    uint32_t gpe1_blk;               /* Port addr of General Purpose acpi_event 1 Reg Blk */
+    uint8_t  pm1_evt_len;            /* Byte length of ports at pm1_x_evt_blk */
+    uint8_t  pm1_cnt_len;            /* Byte length of ports at pm1_x_cnt_blk */
+    uint8_t  pm2_cnt_len;            /* Byte Length of ports at pm2_cnt_blk */
+    uint8_t  pm_tmr_len;             /* Byte Length of ports at pm_tm_blk */
+    uint8_t  gpe0_blk_len;           /* Byte Length of ports at gpe0_blk */
+    uint8_t  gpe1_blk_len;           /* Byte Length of ports at gpe1_blk */
+    uint8_t  gpe1_base;              /* Offset in gpe model where gpe1 events start */
+    uint8_t  reserved3;              /* Reserved */
+    uint16_t plvl2_lat;              /* Worst case HW latency to enter/exit C2 state */
+    uint16_t plvl3_lat;              /* Worst case HW latency to enter/exit C3 state */
+    uint16_t flush_size;             /* Size of area read to flush caches */
+    uint16_t flush_stride;           /* Stride used in flushing caches */
+    uint8_t  duty_offset;            /* Bit location of duty cycle field in p_cnt reg */
+    uint8_t  duty_width;             /* Bit width of duty cycle field in p_cnt reg */
+    uint8_t  day_alrm;               /* Index to day-of-month alarm in RTC CMOS RAM */
+    uint8_t  mon_alrm;               /* Index to month-of-year alarm in RTC CMOS RAM */
+    uint8_t  century;                /* Index to century in RTC CMOS RAM */
+    uint8_t  reserved4;              /* Reserved */
+    uint8_t  reserved4a;             /* Reserved */
+    uint8_t  reserved4b;             /* Reserved */
+    uint32_t flags;
+} QEMU_PACKED;
+typedef struct AcpiFadtDescriptorRev1 AcpiFadtDescriptorRev1;
+
+/*
+ * ACPI 1.0 Root System Description Table (RSDT)
+ */
+#define ACPI_RSDT_SIGNATURE 0x54445352 // RSDT
+struct AcpiRsdtDescriptorRev1
+{
+    ACPI_TABLE_HEADER_DEF       /* ACPI common table header */
+    uint32_t table_offset_entry[0];  /* Array of pointers to other */
+    /* ACPI tables */
+} QEMU_PACKED;
+typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1;
+
+/*
+ * ACPI 1.0 Firmware ACPI Control Structure (FACS)
+ */
+#define ACPI_FACS_SIGNATURE 0x53434146 // FACS
+struct AcpiFacsDescriptorRev1
+{
+    uint32_t signature;           /* ACPI Signature */
+    uint32_t length;                 /* Length of structure, in bytes */
+    uint32_t hardware_signature;     /* Hardware configuration signature */
+    uint32_t firmware_waking_vector; /* ACPI OS waking vector */
+    uint32_t global_lock;            /* Global Lock */
+    uint32_t flags;
+    uint8_t  resverved3 [40];        /* Reserved - must be zero */
+} QEMU_PACKED;
+typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
+
+/*
+ * Differentiated System Description Table (DSDT)
+ */
+#define ACPI_DSDT_SIGNATURE 0x54445344 // DSDT
+
+/*
+ * MADT values and structures
+ */
+
+/* Values for MADT PCATCompat */
+
+#define ACPI_DUAL_PIC                0
+#define ACPI_MULTIPLE_APIC           1
+
+/* Master MADT */
+
+#define ACPI_APIC_SIGNATURE 0x43495041 // APIC
+struct AcpiMultipleApicTable
+{
+    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
+    uint32_t local_apic_address;     /* Physical address of local APIC */
+    uint32_t flags;
+} QEMU_PACKED;
+typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
+
+/* Values for Type in APIC sub-headers */
+
+#define ACPI_APIC_PROCESSOR          0
+#define ACPI_APIC_IO                 1
+#define ACPI_APIC_XRUPT_OVERRIDE     2
+#define ACPI_APIC_NMI                3
+#define ACPI_APIC_LOCAL_NMI          4
+#define ACPI_APIC_ADDRESS_OVERRIDE   5
+#define ACPI_APIC_IO_SAPIC           6
+#define ACPI_APIC_LOCAL_SAPIC        7
+#define ACPI_APIC_XRUPT_SOURCE       8
+#define ACPI_APIC_RESERVED           9           /* 9 and greater are reserved */
+
+/*
+ * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
+ */
+#define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
+    uint8_t  type;                               \
+    uint8_t  length;
+
+/* Sub-structures for MADT */
+
+struct AcpiMadtProcessorApic
+{
+    ACPI_SUB_HEADER_DEF
+    uint8_t  processor_id;           /* ACPI processor id */
+    uint8_t  local_apic_id;          /* Processor's local APIC id */
+    uint32_t flags;
+} QEMU_PACKED;
+typedef struct AcpiMadtProcessorApic AcpiMadtProcessorApic;
+
+struct AcpiMadtIoApic
+{
+    ACPI_SUB_HEADER_DEF
+    uint8_t  io_apic_id;             /* I/O APIC ID */
+    uint8_t  reserved;               /* Reserved - must be zero */
+    uint32_t address;                /* APIC physical address */
+    uint32_t interrupt;              /* Global system interrupt where INTI
+                                 * lines start */
+} QEMU_PACKED;
+typedef struct AcpiMadtIoApic AcpiMadtIoApic;
+
+struct AcpiMadtIntsrcovr {
+    ACPI_SUB_HEADER_DEF
+    uint8_t  bus;
+    uint8_t  source;
+    uint32_t gsi;
+    uint16_t flags;
+} QEMU_PACKED;
+typedef struct AcpiMadtIntsrcovr AcpiMadtIntsrcovr;
+
+struct AcpiMadtLocalNmi {
+    ACPI_SUB_HEADER_DEF
+    uint8_t  processor_id;           /* ACPI processor id */
+    uint16_t flags;                  /* MPS INTI flags */
+    uint8_t  lint;                   /* Local APIC LINT# */
+} QEMU_PACKED;
+typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
+
+/*
+ * HPET Description Table
+ */
+#define ACPI_HPET_SIGNATURE 0x54455048 // HPET
+struct Acpi20Hpet {
+    ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */
+    uint32_t           timer_block_id;
+    Acpi20GenericAddress addr;
+    uint8_t            hpet_number;
+    uint16_t           min_tick;
+    uint8_t            page_protect;
+} QEMU_PACKED;
+typedef struct Acpi20Hpet Acpi20Hpet;
+
+/*
+ * SRAT (NUMA topology description) table
+ */
+
+#define ACPI_SRAT_SIGNATURE 0x54415253 // SRAT
+struct AcpiSystemResourceAffinityTable
+{
+    ACPI_TABLE_HEADER_DEF
+    uint32_t    reserved1;
+    uint32_t    reserved2[2];
+} QEMU_PACKED;
+typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
+
+#define ACPI_SRAT_PROCESSOR          0
+#define ACPI_SRAT_MEMORY             1
+
+struct AcpiSratProcessorAffinity
+{
+    ACPI_SUB_HEADER_DEF
+    uint8_t     proximity_lo;
+    uint8_t     local_apic_id;
+    uint32_t    flags;
+    uint8_t     local_sapic_eid;
+    uint8_t     proximity_hi[3];
+    uint32_t    reserved;
+} QEMU_PACKED;
+typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity;
+
+struct AcpiSratMemoryAffinity
+{
+    ACPI_SUB_HEADER_DEF
+    uint8_t     proximity[4];
+    uint16_t    reserved1;
+    uint64_t    base_addr;
+    uint64_t    range_length;
+    uint32_t    reserved2;
+    uint32_t    flags;
+    uint32_t    reserved3[2];
+} QEMU_PACKED;
+typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity;
+
+/* PCI fw r3.0 MCFG table. */
+/* Subtable */
+struct AcpiMcfgAllocation {
+    uint64_t address;                /* Base address, processor-relative */
+    uint16_t pci_segment;            /* PCI segment group number */
+    uint8_t start_bus_number;       /* Starting PCI Bus number */
+    uint8_t end_bus_number;         /* Final PCI Bus number */
+    uint32_t reserved;
+} QEMU_PACKED;
+typedef struct AcpiMcfgAllocation AcpiMcfgAllocation;
+
+#define ACPI_MCFG_SIGNATURE 0x4746434d       // MCFG
+
+/* Reserved signature: ignored by OSPM */
+#define ACPI_RSRV_SIGNATURE 0x554d4551       // QEMU
+
+struct AcpiTableMcfg {
+    ACPI_TABLE_HEADER_DEF;
+    uint8_t reserved[8];
+    AcpiMcfgAllocation allocation[0];
+} QEMU_PACKED;
+typedef struct AcpiTableMcfg AcpiTableMcfg;
+
+#endif
diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
new file mode 100644
index 0000000..c96ac42
--- /dev/null
+++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
@@ -0,0 +1,93 @@
+/*
+ * 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/>.
+ */
+
+/****************************************************************
+ * CPU hotplug
+ ****************************************************************/
+
+Scope(\_SB) {
+    /* Objects filled in by run-time generated SSDT */
+    External(NTFY, MethodObj)
+    External(CPON, PkgObj)
+
+    /* Methods called by run-time generated SSDT Processor objects */
+    Method(CPMA, 1, NotSerialized) {
+        // _MAT method - create an madt apic buffer
+        // Arg0 = Processor ID = Local APIC ID
+        // Local0 = CPON flag for this cpu
+        Store(DerefOf(Index(CPON, Arg0)), Local0)
+        // Local1 = Buffer (in madt apic form) to return
+        Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1)
+        // Update the processor id, lapic id, and enable/disable status
+        Store(Arg0, Index(Local1, 2))
+        Store(Arg0, Index(Local1, 3))
+        Store(Local0, Index(Local1, 4))
+        Return (Local1)
+    }
+    Method(CPST, 1, NotSerialized) {
+        // _STA method - return ON status of cpu
+        // Arg0 = Processor ID = Local APIC ID
+        // Local0 = CPON flag for this cpu
+        Store(DerefOf(Index(CPON, Arg0)), Local0)
+        If (Local0) {
+            Return (0xF)
+        } Else {
+            Return (0x0)
+        }
+    }
+    Method(CPEJ, 2, NotSerialized) {
+        // _EJ0 method - eject callback
+        Sleep(200)
+    }
+
+    /* CPU hotplug notify method */
+    OperationRegion(PRST, SystemIO, 0xaf00, 32)
+    Field(PRST, ByteAcc, NoLock, Preserve) {
+        PRS, 256
+    }
+    Method(PRSC, 0) {
+        // Local5 = active cpu bitmap
+        Store(PRS, Local5)
+        // Local2 = last read byte from bitmap
+        Store(Zero, Local2)
+        // Local0 = Processor ID / APIC ID iterator
+        Store(Zero, Local0)
+        While (LLess(Local0, SizeOf(CPON))) {
+            // Local1 = CPON flag for this cpu
+            Store(DerefOf(Index(CPON, Local0)), Local1)
+            If (And(Local0, 0x07)) {
+                // Shift down previously read bitmap byte
+                ShiftRight(Local2, 1, Local2)
+            } Else {
+                // Read next byte from cpu bitmap
+                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
+            }
+            // Local3 = active state for this cpu
+            Store(And(Local2, 1), Local3)
+
+            If (LNotEqual(Local1, Local3)) {
+                // State change - update CPON with new state
+                Store(Local3, Index(CPON, Local0))
+                // Do CPU notify
+                If (LEqual(Local3, 1)) {
+                    NTFY(Local0, 1)
+                } Else {
+                    NTFY(Local0, 3)
+                }
+            }
+            Increment(Local0)
+        }
+    }
+}
diff --git a/hw/i386/acpi-dsdt-dbug.dsl b/hw/i386/acpi-dsdt-dbug.dsl
new file mode 100644
index 0000000..86230f7
--- /dev/null
+++ b/hw/i386/acpi-dsdt-dbug.dsl
@@ -0,0 +1,41 @@
+/*
+ * 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/>.
+ */
+
+/****************************************************************
+ * Debugging
+ ****************************************************************/
+
+Scope(\) {
+    /* Debug Output */
+    OperationRegion(DBG, SystemIO, 0x0402, 0x01)
+    Field(DBG, ByteAcc, NoLock, Preserve) {
+        DBGB,   8,
+    }
+
+    /* Debug method - use this method to send output to the QEMU
+     * BIOS debug port.  This method handles strings, integers,
+     * and buffers.  For example: DBUG("abc") DBUG(0x123) */
+    Method(DBUG, 1) {
+        ToHexString(Arg0, Local0)
+        ToBuffer(Local0, Local0)
+        Subtract(SizeOf(Local0), 1, Local1)
+        Store(Zero, Local2)
+        While (LLess(Local2, Local1)) {
+            Store(DerefOf(Index(Local0, Local2)), DBGB)
+            Increment(Local2)
+        }
+        Store(0x0A, DBGB)
+    }
+}
diff --git a/hw/i386/acpi-dsdt-hpet.dsl b/hw/i386/acpi-dsdt-hpet.dsl
new file mode 100644
index 0000000..dfde174
--- /dev/null
+++ b/hw/i386/acpi-dsdt-hpet.dsl
@@ -0,0 +1,51 @@
+/*
+ * 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/>.
+ */
+
+/****************************************************************
+ * HPET
+ ****************************************************************/
+
+Scope(\_SB) {
+    Device(HPET) {
+        Name(_HID, EISAID("PNP0103"))
+        Name(_UID, 0)
+        OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400)
+        Field(HPTM, DWordAcc, Lock, Preserve) {
+            VEND, 32,
+            PRD, 32,
+        }
+        Method(_STA, 0, NotSerialized) {
+            Store(VEND, Local0)
+            Store(PRD, Local1)
+            ShiftRight(Local0, 16, Local0)
+            If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) {
+                Return (0x0)
+            }
+            If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) {
+                Return (0x0)
+            }
+            Return (0x0F)
+        }
+        Name(_CRS, ResourceTemplate() {
+#if 0       /* This makes WinXP BSOD for not yet figured reasons. */
+            IRQNoFlags() {2, 8}
+#endif
+            Memory32Fixed(ReadOnly,
+                0xFED00000,         // Address Base
+                0x00000400,         // Address Length
+                )
+        })
+    }
+}
diff --git a/hw/i386/acpi-dsdt-isa.dsl b/hw/i386/acpi-dsdt-isa.dsl
new file mode 100644
index 0000000..89caa16
--- /dev/null
+++ b/hw/i386/acpi-dsdt-isa.dsl
@@ -0,0 +1,117 @@
+/*
+ * 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/>.
+ */
+
+/* Common legacy ISA style devices. */
+Scope(\_SB.PCI0.ISA) {
+
+    Device(RTC) {
+        Name(_HID, EisaId("PNP0B00"))
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x0070, 0x0070, 0x10, 0x02)
+            IRQNoFlags() { 8 }
+            IO(Decode16, 0x0072, 0x0072, 0x02, 0x06)
+        })
+    }
+
+    Device(KBD) {
+        Name(_HID, EisaId("PNP0303"))
+        Method(_STA, 0, NotSerialized) {
+            Return (0x0f)
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x0060, 0x0060, 0x01, 0x01)
+            IO(Decode16, 0x0064, 0x0064, 0x01, 0x01)
+            IRQNoFlags() { 1 }
+        })
+    }
+
+    Device(MOU) {
+        Name(_HID, EisaId("PNP0F13"))
+        Method(_STA, 0, NotSerialized) {
+            Return (0x0f)
+        }
+        Name(_CRS, ResourceTemplate() {
+            IRQNoFlags() { 12 }
+        })
+    }
+
+    Device(FDC0) {
+        Name(_HID, EisaId("PNP0700"))
+        Method(_STA, 0, NotSerialized) {
+            Store(FDEN, Local0)
+            If (LEqual(Local0, 0)) {
+                Return (0x00)
+            } Else {
+                Return (0x0F)
+            }
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
+            IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
+            IRQNoFlags() { 6 }
+            DMA(Compatibility, NotBusMaster, Transfer8) { 2 }
+        })
+    }
+
+    Device(LPT) {
+        Name(_HID, EisaId("PNP0400"))
+        Method(_STA, 0, NotSerialized) {
+            Store(LPEN, Local0)
+            If (LEqual(Local0, 0)) {
+                Return (0x00)
+            } Else {
+                Return (0x0F)
+            }
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x0378, 0x0378, 0x08, 0x08)
+            IRQNoFlags() { 7 }
+        })
+    }
+
+    Device(COM1) {
+        Name(_HID, EisaId("PNP0501"))
+        Name(_UID, 0x01)
+        Method(_STA, 0, NotSerialized) {
+            Store(CAEN, Local0)
+            If (LEqual(Local0, 0)) {
+                Return (0x00)
+            } Else {
+                Return (0x0F)
+            }
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
+            IRQNoFlags() { 4 }
+        })
+    }
+
+    Device(COM2) {
+        Name(_HID, EisaId("PNP0501"))
+        Name(_UID, 0x02)
+        Method(_STA, 0, NotSerialized) {
+            Store(CBEN, Local0)
+            If (LEqual(Local0, 0)) {
+                Return (0x00)
+            } Else {
+                Return (0x0F)
+            }
+        }
+        Name(_CRS, ResourceTemplate() {
+            IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
+            IRQNoFlags() { 3 }
+        })
+    }
+}
diff --git a/hw/i386/acpi-dsdt-pci-crs.dsl b/hw/i386/acpi-dsdt-pci-crs.dsl
new file mode 100644
index 0000000..b375a19
--- /dev/null
+++ b/hw/i386/acpi-dsdt-pci-crs.dsl
@@ -0,0 +1,105 @@
+/*
+ * 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/>.
+ */
+
+/* PCI CRS (current resources) definition. */
+Scope(\_SB.PCI0) {
+
+    Name(CRES, ResourceTemplate() {
+        WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
+            0x0000,             // Address Space Granularity
+            0x0000,             // Address Range Minimum
+            0x00FF,             // Address Range Maximum
+            0x0000,             // Address Translation Offset
+            0x0100,             // Address Length
+            ,, )
+        IO(Decode16,
+            0x0CF8,             // Address Range Minimum
+            0x0CF8,             // Address Range Maximum
+            0x01,               // Address Alignment
+            0x08,               // Address Length
+            )
+        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+            0x0000,             // Address Space Granularity
+            0x0000,             // Address Range Minimum
+            0x0CF7,             // Address Range Maximum
+            0x0000,             // Address Translation Offset
+            0x0CF8,             // Address Length
+            ,, , TypeStatic)
+        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+            0x0000,             // Address Space Granularity
+            0x0D00,             // Address Range Minimum
+            0xFFFF,             // Address Range Maximum
+            0x0000,             // Address Translation Offset
+            0xF300,             // Address Length
+            ,, , TypeStatic)
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+            0x00000000,         // Address Space Granularity
+            0x000A0000,         // Address Range Minimum
+            0x000BFFFF,         // Address Range Maximum
+            0x00000000,         // Address Translation Offset
+            0x00020000,         // Address Length
+            ,, , AddressRangeMemory, TypeStatic)
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+            0x00000000,         // Address Space Granularity
+            0xE0000000,         // Address Range Minimum
+            0xFEBFFFFF,         // Address Range Maximum
+            0x00000000,         // Address Translation Offset
+            0x1EC00000,         // Address Length
+            ,, PW32, AddressRangeMemory, TypeStatic)
+    })
+
+    Name(CR64, ResourceTemplate() {
+        QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+            0x00000000,          // Address Space Granularity
+            0x8000000000,        // Address Range Minimum
+            0xFFFFFFFFFF,        // Address Range Maximum
+            0x00000000,          // Address Translation Offset
+            0x8000000000,        // Address Length
+            ,, PW64, AddressRangeMemory, TypeStatic)
+    })
+
+    Method(_CRS, 0) {
+        /* Fields provided by dynamically created ssdt */
+        External(P0S, IntObj)
+        External(P0E, IntObj)
+        External(P1V, IntObj)
+        External(P1S, BuffObj)
+        External(P1E, BuffObj)
+        External(P1L, BuffObj)
+
+        /* fixup 32bit pci io window */
+        CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32)
+        CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32)
+        CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32)
+        Store(P0S, PS32)
+        Store(P0E, PE32)
+        Store(Add(Subtract(P0E, P0S), 1), PL32)
+
+        If (LEqual(P1V, Zero)) {
+            Return (CRES)
+        }
+
+        /* fixup 64bit pci io window */
+        CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64)
+        CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64)
+        CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64)
+        Store(P1S, PS64)
+        Store(P1E, PE64)
+        Store(P1L, PL64)
+        /* add window and return result */
+        ConcatenateResTemplate(CRES, CR64, Local0)
+        Return (Local0)
+    }
+}
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
new file mode 100644
index 0000000..90efce0
--- /dev/null
+++ b/hw/i386/acpi-dsdt.dsl
@@ -0,0 +1,343 @@
+/*
+ * Bochs/QEMU ACPI DSDT ASL definition
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+ACPI_EXTRACT_ALL_CODE AcpiDsdtAmlCode
+
+DefinitionBlock (
+    "acpi-dsdt.aml",    // Output Filename
+    "DSDT",             // Signature
+    0x01,               // DSDT Compliance Revision
+    "BXPC",             // OEMID
+    "BXDSDT",           // TABLE ID
+    0x1                 // OEM Revision
+    )
+{
+
+#include "acpi-dsdt-dbug.dsl"
+
+
+/****************************************************************
+ * PCI Bus definition
+ ****************************************************************/
+
+    Scope(\_SB) {
+        Device(PCI0) {
+            Name(_HID, EisaId("PNP0A03"))
+            Name(_ADR, 0x00)
+            Name(_UID, 1)
+        }
+    }
+
+#include "acpi-dsdt-pci-crs.dsl"
+#include "acpi-dsdt-hpet.dsl"
+
+
+/****************************************************************
+ * VGA
+ ****************************************************************/
+
+    Scope(\_SB.PCI0) {
+        Device(VGA) {
+            Name(_ADR, 0x00020000)
+            OperationRegion(PCIC, PCI_Config, Zero, 0x4)
+            Field(PCIC, DWordAcc, NoLock, Preserve) {
+                VEND, 32
+            }
+            Method(_S1D, 0, NotSerialized) {
+                Return (0x00)
+            }
+            Method(_S2D, 0, NotSerialized) {
+                Return (0x00)
+            }
+            Method(_S3D, 0, NotSerialized) {
+                If (LEqual(VEND, 0x1001b36)) {
+                    Return (0x03)           // QXL
+                } Else {
+                    Return (0x00)
+                }
+            }
+        }
+    }
+
+
+/****************************************************************
+ * PIIX4 PM
+ ****************************************************************/
+
+    Scope(\_SB.PCI0) {
+        Device(PX13) {
+            Name(_ADR, 0x00010003)
+            OperationRegion(P13C, PCI_Config, 0x00, 0xff)
+        }
+    }
+
+
+/****************************************************************
+ * PIIX3 ISA bridge
+ ****************************************************************/
+
+    Scope(\_SB.PCI0) {
+        Device(ISA) {
+            Name(_ADR, 0x00010000)
+
+            /* PIIX PCI to ISA irq remapping */
+            OperationRegion(P40C, PCI_Config, 0x60, 0x04)
+
+            /* enable bits */
+            Field(\_SB.PCI0.PX13.P13C, AnyAcc, NoLock, Preserve) {
+                Offset(0x5f),
+                , 7,
+                LPEN, 1,         // LPT
+                Offset(0x67),
+                , 3,
+                CAEN, 1,         // COM1
+                , 3,
+                CBEN, 1,         // COM2
+            }
+            Name(FDEN, 1)
+        }
+    }
+
+#include "acpi-dsdt-isa.dsl"
+
+
+/****************************************************************
+ * PCI hotplug
+ ****************************************************************/
+
+    Scope(\_SB.PCI0) {
+        OperationRegion(PCST, SystemIO, 0xae00, 0x08)
+        Field(PCST, DWordAcc, NoLock, WriteAsZeros) {
+            PCIU, 32,
+            PCID, 32,
+        }
+
+        OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
+        Field(SEJ, DWordAcc, NoLock, WriteAsZeros) {
+            B0EJ, 32,
+        }
+
+        /* Methods called by bulk generated PCI devices below */
+
+        /* Methods called by hotplug devices */
+        Method(PCEJ, 1, NotSerialized) {
+            // _EJ0 method - eject callback
+            Store(ShiftLeft(1, Arg0), B0EJ)
+            Return (0x0)
+        }
+
+        /* Hotplug notification method supplied by SSDT */
+        External(\_SB.PCI0.PCNT, MethodObj)
+
+        /* PCI hotplug notify method */
+        Method(PCNF, 0) {
+            // Local0 = iterator
+            Store(Zero, Local0)
+            While (LLess(Local0, 31)) {
+                Increment(Local0)
+                If (And(PCIU, ShiftLeft(1, Local0))) {
+                    PCNT(Local0, 1)
+                }
+                If (And(PCID, ShiftLeft(1, Local0))) {
+                    PCNT(Local0, 3)
+                }
+            }
+        }
+    }
+
+
+/****************************************************************
+ * PCI IRQs
+ ****************************************************************/
+
+    Scope(\_SB) {
+        Scope(PCI0) {
+            Name(_PRT, Package() {
+                /* PCI IRQ routing table, example from ACPI 2.0a specification,
+                   section 6.2.8.1 */
+                /* Note: we provide the same info as the PCI routing
+                   table of the Bochs BIOS */
+
+#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
+    Package() { nr##ffff, 0, lnk0, 0 }, \
+    Package() { nr##ffff, 1, lnk1, 0 }, \
+    Package() { nr##ffff, 2, lnk2, 0 }, \
+    Package() { nr##ffff, 3, lnk3, 0 }
+
+#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
+#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
+#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
+#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
+
+                prt_slot0(0x0000),
+                /* Device 1 is power mgmt device, and can only use irq 9 */
+                prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD),
+                prt_slot2(0x0002),
+                prt_slot3(0x0003),
+                prt_slot0(0x0004),
+                prt_slot1(0x0005),
+                prt_slot2(0x0006),
+                prt_slot3(0x0007),
+                prt_slot0(0x0008),
+                prt_slot1(0x0009),
+                prt_slot2(0x000a),
+                prt_slot3(0x000b),
+                prt_slot0(0x000c),
+                prt_slot1(0x000d),
+                prt_slot2(0x000e),
+                prt_slot3(0x000f),
+                prt_slot0(0x0010),
+                prt_slot1(0x0011),
+                prt_slot2(0x0012),
+                prt_slot3(0x0013),
+                prt_slot0(0x0014),
+                prt_slot1(0x0015),
+                prt_slot2(0x0016),
+                prt_slot3(0x0017),
+                prt_slot0(0x0018),
+                prt_slot1(0x0019),
+                prt_slot2(0x001a),
+                prt_slot3(0x001b),
+                prt_slot0(0x001c),
+                prt_slot1(0x001d),
+                prt_slot2(0x001e),
+                prt_slot3(0x001f),
+            })
+        }
+
+        Field(PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) {
+            PRQ0,   8,
+            PRQ1,   8,
+            PRQ2,   8,
+            PRQ3,   8
+        }
+
+        Method(IQST, 1, NotSerialized) {
+            // _STA method - get status
+            If (And(0x80, Arg0)) {
+                Return (0x09)
+            }
+            Return (0x0B)
+        }
+        Method(IQCR, 1, NotSerialized) {
+            // _CRS method - get current settings
+            Name(PRR0, ResourceTemplate() {
+                Interrupt(, Level, ActiveHigh, Shared) { 0 }
+            })
+            CreateDWordField(PRR0, 0x05, PRRI)
+            If (LLess(Arg0, 0x80)) {
+                Store(Arg0, PRRI)
+            }
+            Return (PRR0)
+        }
+
+#define define_link(link, uid, reg)                             \
+        Device(link) {                                          \
+            Name(_HID, EISAID("PNP0C0F"))                       \
+            Name(_UID, uid)                                     \
+            Name(_PRS, ResourceTemplate() {                     \
+                Interrupt(, Level, ActiveHigh, Shared) {        \
+                    5, 10, 11                                   \
+                }                                               \
+            })                                                  \
+            Method(_STA, 0, NotSerialized) {                    \
+                Return (IQST(reg))                              \
+            }                                                   \
+            Method(_DIS, 0, NotSerialized) {                    \
+                Or(reg, 0x80, reg)                              \
+            }                                                   \
+            Method(_CRS, 0, NotSerialized) {                    \
+                Return (IQCR(reg))                              \
+            }                                                   \
+            Method(_SRS, 1, NotSerialized) {                    \
+                CreateDWordField(Arg0, 0x05, PRRI)              \
+                Store(PRRI, reg)                                \
+            }                                                   \
+        }
+
+        define_link(LNKA, 0, PRQ0)
+        define_link(LNKB, 1, PRQ1)
+        define_link(LNKC, 2, PRQ2)
+        define_link(LNKD, 3, PRQ3)
+
+        Device(LNKS) {
+            Name(_HID, EISAID("PNP0C0F"))
+            Name(_UID, 4)
+            Name(_PRS, ResourceTemplate() {
+                Interrupt(, Level, ActiveHigh, Shared) { 9 }
+            })
+
+            // The SCI cannot be disabled and is always attached to GSI 9,
+            // so these are no-ops.  We only need this link to override the
+            // polarity to active high and match the content of the MADT.
+            Method(_STA, 0, NotSerialized) { Return (0x0b) }
+            Method(_DIS, 0, NotSerialized) { }
+            Method(_CRS, 0, NotSerialized) { Return (_PRS) }
+            Method(_SRS, 1, NotSerialized) { }
+        }
+    }
+
+#include "acpi-dsdt-cpu-hotplug.dsl"
+
+
+/****************************************************************
+ * General purpose events
+ ****************************************************************/
+
+    Scope(\_GPE) {
+        Name(_HID, "ACPI0006")
+
+        Method(_L00) {
+        }
+        Method(_E01) {
+            // PCI hotplug event
+            \_SB.PCI0.PCNF()
+        }
+        Method(_E02) {
+            // CPU hotplug event
+            \_SB.PRSC()
+        }
+        Method(_L03) {
+        }
+        Method(_L04) {
+        }
+        Method(_L05) {
+        }
+        Method(_L06) {
+        }
+        Method(_L07) {
+        }
+        Method(_L08) {
+        }
+        Method(_L09) {
+        }
+        Method(_L0A) {
+        }
+        Method(_L0B) {
+        }
+        Method(_L0C) {
+        }
+        Method(_L0D) {
+        }
+        Method(_L0E) {
+        }
+        Method(_L0F) {
+        }
+    }
+}
diff --git a/hw/i386/acpi-dsdt.hex.generated b/hw/i386/acpi-dsdt.hex.generated
new file mode 100644
index 0000000..2c01107
--- /dev/null
+++ b/hw/i386/acpi-dsdt.hex.generated
@@ -0,0 +1,4409 @@
+static unsigned char AcpiDsdtAmlCode[] = {
+0x44,
+0x53,
+0x44,
+0x54,
+0x37,
+0x11,
+0x0,
+0x0,
+0x1,
+0xe0,
+0x42,
+0x58,
+0x50,
+0x43,
+0x0,
+0x0,
+0x42,
+0x58,
+0x44,
+0x53,
+0x44,
+0x54,
+0x0,
+0x0,
+0x1,
+0x0,
+0x0,
+0x0,
+0x49,
+0x4e,
+0x54,
+0x4c,
+0x23,
+0x8,
+0x13,
+0x20,
+0x10,
+0x49,
+0x4,
+0x5c,
+0x0,
+0x5b,
+0x80,
+0x44,
+0x42,
+0x47,
+0x5f,
+0x1,
+0xb,
+0x2,
+0x4,
+0x1,
+0x5b,
+0x81,
+0xb,
+0x44,
+0x42,
+0x47,
+0x5f,
+0x1,
+0x44,
+0x42,
+0x47,
+0x42,
+0x8,
+0x14,
+0x2c,
+0x44,
+0x42,
+0x55,
+0x47,
+0x1,
+0x98,
+0x68,
+0x60,
+0x96,
+0x60,
+0x60,
+0x74,
+0x87,
+0x60,
+0x1,
+0x61,
+0x70,
+0x0,
+0x62,
+0xa2,
+0x10,
+0x95,
+0x62,
+0x61,
+0x70,
+0x83,
+0x88,
+0x60,
+0x62,
+0x0,
+0x44,
+0x42,
+0x47,
+0x42,
+0x75,
+0x62,
+0x70,
+0xa,
+0xa,
+0x44,
+0x42,
+0x47,
+0x42,
+0x10,
+0x22,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x5b,
+0x82,
+0x1b,
+0x50,
+0x43,
+0x49,
+0x30,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xa,
+0x3,
+0x8,
+0x5f,
+0x41,
+0x44,
+0x52,
+0x0,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x1,
+0x10,
+0x4e,
+0x15,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x8,
+0x43,
+0x52,
+0x45,
+0x53,
+0x11,
+0x42,
+0x7,
+0xa,
+0x6e,
+0x88,
+0xd,
+0x0,
+0x2,
+0xc,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xff,
+0x0,
+0x0,
+0x0,
+0x0,
+0x1,
+0x47,
+0x1,
+0xf8,
+0xc,
+0xf8,
+0xc,
+0x1,
+0x8,
+0x88,
+0xd,
+0x0,
+0x1,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0xf7,
+0xc,
+0x0,
+0x0,
+0xf8,
+0xc,
+0x88,
+0xd,
+0x0,
+0x1,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0xd,
+0xff,
+0xff,
+0x0,
+0x0,
+0x0,
+0xf3,
+0x87,
+0x17,
+0x0,
+0x0,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0xff,
+0xff,
+0xb,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x2,
+0x0,
+0x87,
+0x17,
+0x0,
+0x0,
+0xc,
+0x1,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xe0,
+0xff,
+0xff,
+0xbf,
+0xfe,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xc0,
+0x1e,
+0x79,
+0x0,
+0x8,
+0x43,
+0x52,
+0x36,
+0x34,
+0x11,
+0x33,
+0xa,
+0x30,
+0x8a,
+0x2b,
+0x0,
+0x0,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x80,
+0x0,
+0x0,
+0x0,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x80,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x41,
+0xa,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0x8a,
+0x43,
+0x52,
+0x45,
+0x53,
+0xa,
+0x5c,
+0x50,
+0x53,
+0x33,
+0x32,
+0x8a,
+0x43,
+0x52,
+0x45,
+0x53,
+0xa,
+0x60,
+0x50,
+0x45,
+0x33,
+0x32,
+0x8a,
+0x43,
+0x52,
+0x45,
+0x53,
+0xa,
+0x68,
+0x50,
+0x4c,
+0x33,
+0x32,
+0x70,
+0x50,
+0x30,
+0x53,
+0x5f,
+0x50,
+0x53,
+0x33,
+0x32,
+0x70,
+0x50,
+0x30,
+0x45,
+0x5f,
+0x50,
+0x45,
+0x33,
+0x32,
+0x70,
+0x72,
+0x74,
+0x50,
+0x30,
+0x45,
+0x5f,
+0x50,
+0x30,
+0x53,
+0x5f,
+0x0,
+0x1,
+0x0,
+0x50,
+0x4c,
+0x33,
+0x32,
+0xa0,
+0xc,
+0x93,
+0x50,
+0x31,
+0x56,
+0x5f,
+0x0,
+0xa4,
+0x43,
+0x52,
+0x45,
+0x53,
+0x8f,
+0x43,
+0x52,
+0x36,
+0x34,
+0xa,
+0xe,
+0x50,
+0x53,
+0x36,
+0x34,
+0x8f,
+0x43,
+0x52,
+0x36,
+0x34,
+0xa,
+0x16,
+0x50,
+0x45,
+0x36,
+0x34,
+0x8f,
+0x43,
+0x52,
+0x36,
+0x34,
+0xa,
+0x26,
+0x50,
+0x4c,
+0x36,
+0x34,
+0x70,
+0x50,
+0x31,
+0x53,
+0x5f,
+0x50,
+0x53,
+0x36,
+0x34,
+0x70,
+0x50,
+0x31,
+0x45,
+0x5f,
+0x50,
+0x45,
+0x36,
+0x34,
+0x70,
+0x50,
+0x31,
+0x4c,
+0x5f,
+0x50,
+0x4c,
+0x36,
+0x34,
+0x84,
+0x43,
+0x52,
+0x45,
+0x53,
+0x43,
+0x52,
+0x36,
+0x34,
+0x60,
+0xa4,
+0x60,
+0x10,
+0x4d,
+0x8,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x5b,
+0x82,
+0x45,
+0x8,
+0x48,
+0x50,
+0x45,
+0x54,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x1,
+0x3,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x5b,
+0x80,
+0x48,
+0x50,
+0x54,
+0x4d,
+0x0,
+0xc,
+0x0,
+0x0,
+0xd0,
+0xfe,
+0xb,
+0x0,
+0x4,
+0x5b,
+0x81,
+0x10,
+0x48,
+0x50,
+0x54,
+0x4d,
+0x13,
+0x56,
+0x45,
+0x4e,
+0x44,
+0x20,
+0x50,
+0x52,
+0x44,
+0x5f,
+0x20,
+0x14,
+0x36,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x56,
+0x45,
+0x4e,
+0x44,
+0x60,
+0x70,
+0x50,
+0x52,
+0x44,
+0x5f,
+0x61,
+0x7a,
+0x60,
+0xa,
+0x10,
+0x60,
+0xa0,
+0xc,
+0x91,
+0x93,
+0x60,
+0x0,
+0x93,
+0x60,
+0xb,
+0xff,
+0xff,
+0xa4,
+0x0,
+0xa0,
+0xe,
+0x91,
+0x93,
+0x61,
+0x0,
+0x94,
+0x61,
+0xc,
+0x0,
+0xe1,
+0xf5,
+0x5,
+0xa4,
+0x0,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x11,
+0xa,
+0xe,
+0x86,
+0x9,
+0x0,
+0x0,
+0x0,
+0x0,
+0xd0,
+0xfe,
+0x0,
+0x4,
+0x0,
+0x0,
+0x79,
+0x0,
+0x10,
+0x40,
+0x6,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x82,
+0x43,
+0x5,
+0x56,
+0x47,
+0x41,
+0x5f,
+0x8,
+0x5f,
+0x41,
+0x44,
+0x52,
+0xc,
+0x0,
+0x0,
+0x2,
+0x0,
+0x5b,
+0x80,
+0x50,
+0x43,
+0x49,
+0x43,
+0x2,
+0x0,
+0xa,
+0x4,
+0x5b,
+0x81,
+0xb,
+0x50,
+0x43,
+0x49,
+0x43,
+0x3,
+0x56,
+0x45,
+0x4e,
+0x44,
+0x20,
+0x14,
+0x8,
+0x5f,
+0x53,
+0x31,
+0x44,
+0x0,
+0xa4,
+0x0,
+0x14,
+0x8,
+0x5f,
+0x53,
+0x32,
+0x44,
+0x0,
+0xa4,
+0x0,
+0x14,
+0x19,
+0x5f,
+0x53,
+0x33,
+0x44,
+0x0,
+0xa0,
+0xe,
+0x93,
+0x56,
+0x45,
+0x4e,
+0x44,
+0xc,
+0x36,
+0x1b,
+0x0,
+0x1,
+0xa4,
+0xa,
+0x3,
+0xa1,
+0x3,
+0xa4,
+0x0,
+0x10,
+0x25,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x82,
+0x19,
+0x50,
+0x58,
+0x31,
+0x33,
+0x8,
+0x5f,
+0x41,
+0x44,
+0x52,
+0xc,
+0x3,
+0x0,
+0x1,
+0x0,
+0x5b,
+0x80,
+0x50,
+0x31,
+0x33,
+0x43,
+0x2,
+0x0,
+0xa,
+0xff,
+0x10,
+0x46,
+0x5,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x82,
+0x49,
+0x4,
+0x49,
+0x53,
+0x41,
+0x5f,
+0x8,
+0x5f,
+0x41,
+0x44,
+0x52,
+0xc,
+0x0,
+0x0,
+0x1,
+0x0,
+0x5b,
+0x80,
+0x50,
+0x34,
+0x30,
+0x43,
+0x2,
+0xa,
+0x60,
+0xa,
+0x4,
+0x5b,
+0x81,
+0x26,
+0x5e,
+0x2e,
+0x50,
+0x58,
+0x31,
+0x33,
+0x50,
+0x31,
+0x33,
+0x43,
+0x0,
+0x0,
+0x48,
+0x2f,
+0x0,
+0x7,
+0x4c,
+0x50,
+0x45,
+0x4e,
+0x1,
+0x0,
+0x38,
+0x0,
+0x3,
+0x43,
+0x41,
+0x45,
+0x4e,
+0x1,
+0x0,
+0x3,
+0x43,
+0x42,
+0x45,
+0x4e,
+0x1,
+0x8,
+0x46,
+0x44,
+0x45,
+0x4e,
+0x1,
+0x10,
+0x4c,
+0x1b,
+0x2f,
+0x3,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x49,
+0x53,
+0x41,
+0x5f,
+0x5b,
+0x82,
+0x2d,
+0x52,
+0x54,
+0x43,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xb,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x18,
+0xa,
+0x15,
+0x47,
+0x1,
+0x70,
+0x0,
+0x70,
+0x0,
+0x10,
+0x2,
+0x22,
+0x0,
+0x1,
+0x47,
+0x1,
+0x72,
+0x0,
+0x72,
+0x0,
+0x2,
+0x6,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x37,
+0x4b,
+0x42,
+0x44,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x3,
+0x3,
+0x14,
+0x9,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x18,
+0xa,
+0x15,
+0x47,
+0x1,
+0x60,
+0x0,
+0x60,
+0x0,
+0x1,
+0x1,
+0x47,
+0x1,
+0x64,
+0x0,
+0x64,
+0x0,
+0x1,
+0x1,
+0x22,
+0x2,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x27,
+0x4d,
+0x4f,
+0x55,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xf,
+0x13,
+0x14,
+0x9,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x8,
+0xa,
+0x5,
+0x22,
+0x0,
+0x10,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x4a,
+0x4,
+0x46,
+0x44,
+0x43,
+0x30,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x7,
+0x0,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x46,
+0x44,
+0x45,
+0x4e,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x1b,
+0xa,
+0x18,
+0x47,
+0x1,
+0xf2,
+0x3,
+0xf2,
+0x3,
+0x0,
+0x4,
+0x47,
+0x1,
+0xf7,
+0x3,
+0xf7,
+0x3,
+0x0,
+0x1,
+0x22,
+0x40,
+0x0,
+0x2a,
+0x4,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x3e,
+0x4c,
+0x50,
+0x54,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x4,
+0x0,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x4c,
+0x50,
+0x45,
+0x4e,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x10,
+0xa,
+0xd,
+0x47,
+0x1,
+0x78,
+0x3,
+0x78,
+0x3,
+0x8,
+0x8,
+0x22,
+0x80,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x43,
+0x4f,
+0x4d,
+0x31,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x5,
+0x1,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x1,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x43,
+0x41,
+0x45,
+0x4e,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x10,
+0xa,
+0xd,
+0x47,
+0x1,
+0xf8,
+0x3,
+0xf8,
+0x3,
+0x0,
+0x8,
+0x22,
+0x10,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x46,
+0x4,
+0x43,
+0x4f,
+0x4d,
+0x32,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x5,
+0x1,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x2,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x43,
+0x42,
+0x45,
+0x4e,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x10,
+0xa,
+0xd,
+0x47,
+0x1,
+0xf8,
+0x2,
+0xf8,
+0x2,
+0x0,
+0x8,
+0x22,
+0x8,
+0x0,
+0x79,
+0x0,
+0x10,
+0x4b,
+0x8,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x80,
+0x50,
+0x43,
+0x53,
+0x54,
+0x1,
+0xb,
+0x0,
+0xae,
+0xa,
+0x8,
+0x5b,
+0x81,
+0x10,
+0x50,
+0x43,
+0x53,
+0x54,
+0x43,
+0x50,
+0x43,
+0x49,
+0x55,
+0x20,
+0x50,
+0x43,
+0x49,
+0x44,
+0x20,
+0x5b,
+0x80,
+0x53,
+0x45,
+0x4a,
+0x5f,
+0x1,
+0xb,
+0x8,
+0xae,
+0xa,
+0x4,
+0x5b,
+0x81,
+0xb,
+0x53,
+0x45,
+0x4a,
+0x5f,
+0x43,
+0x42,
+0x30,
+0x45,
+0x4a,
+0x20,
+0x14,
+0x11,
+0x50,
+0x43,
+0x45,
+0x4a,
+0x1,
+0x70,
+0x79,
+0x1,
+0x68,
+0x0,
+0x42,
+0x30,
+0x45,
+0x4a,
+0xa4,
+0x0,
+0x14,
+0x36,
+0x50,
+0x43,
+0x4e,
+0x46,
+0x0,
+0x70,
+0x0,
+0x60,
+0xa2,
+0x2c,
+0x95,
+0x60,
+0xa,
+0x1f,
+0x75,
+0x60,
+0xa0,
+0x11,
+0x7b,
+0x50,
+0x43,
+0x49,
+0x55,
+0x79,
+0x1,
+0x60,
+0x0,
+0x0,
+0x50,
+0x43,
+0x4e,
+0x54,
+0x60,
+0x1,
+0xa0,
+0x12,
+0x7b,
+0x50,
+0x43,
+0x49,
+0x44,
+0x79,
+0x1,
+0x60,
+0x0,
+0x0,
+0x50,
+0x43,
+0x4e,
+0x54,
+0x60,
+0xa,
+0x3,
+0x10,
+0x4a,
+0xa0,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x10,
+0x47,
+0x74,
+0x50,
+0x43,
+0x49,
+0x30,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x54,
+0x12,
+0x4b,
+0x73,
+0x80,
+0x12,
+0xb,
+0x4,
+0xb,
+0xff,
+0xff,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xb,
+0x4,
+0xb,
+0xff,
+0xff,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xc,
+0x4,
+0xb,
+0xff,
+0xff,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xc,
+0x4,
+0xb,
+0xff,
+0xff,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x53,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x5b,
+0x81,
+0x24,
+0x2f,
+0x3,
+0x50,
+0x43,
+0x49,
+0x30,
+0x49,
+0x53,
+0x41,
+0x5f,
+0x50,
+0x34,
+0x30,
+0x43,
+0x1,
+0x50,
+0x52,
+0x51,
+0x30,
+0x8,
+0x50,
+0x52,
+0x51,
+0x31,
+0x8,
+0x50,
+0x52,
+0x51,
+0x32,
+0x8,
+0x50,
+0x52,
+0x51,
+0x33,
+0x8,
+0x14,
+0x13,
+0x49,
+0x51,
+0x53,
+0x54,
+0x1,
+0xa0,
+0x9,
+0x7b,
+0xa,
+0x80,
+0x68,
+0x0,
+0xa4,
+0xa,
+0x9,
+0xa4,
+0xa,
+0xb,
+0x14,
+0x36,
+0x49,
+0x51,
+0x43,
+0x52,
+0x1,
+0x8,
+0x50,
+0x52,
+0x52,
+0x30,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x0,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8a,
+0x50,
+0x52,
+0x52,
+0x30,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0xa0,
+0xb,
+0x95,
+0x68,
+0xa,
+0x80,
+0x70,
+0x68,
+0x50,
+0x52,
+0x52,
+0x49,
+0xa4,
+0x50,
+0x52,
+0x52,
+0x30,
+0x5b,
+0x82,
+0x4c,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x30,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x30,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x30,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x30,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x30,
+0x5b,
+0x82,
+0x4c,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x1,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x31,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x31,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x31,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x31,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x31,
+0x5b,
+0x82,
+0x4d,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x2,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x32,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x32,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x32,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x32,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x32,
+0x5b,
+0x82,
+0x4d,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x3,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x33,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x33,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x33,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x33,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x33,
+0x5b,
+0x82,
+0x4f,
+0x4,
+0x4c,
+0x4e,
+0x4b,
+0x53,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x4,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x9,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x9,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0xa,
+0xb,
+0x14,
+0x6,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x14,
+0xb,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x10,
+0x47,
+0xe,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x14,
+0x35,
+0x43,
+0x50,
+0x4d,
+0x41,
+0x1,
+0x70,
+0x83,
+0x88,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x68,
+0x0,
+0x60,
+0x70,
+0x11,
+0xb,
+0xa,
+0x8,
+0x0,
+0x8,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x61,
+0x70,
+0x68,
+0x88,
+0x61,
+0xa,
+0x2,
+0x0,
+0x70,
+0x68,
+0x88,
+0x61,
+0xa,
+0x3,
+0x0,
+0x70,
+0x60,
+0x88,
+0x61,
+0xa,
+0x4,
+0x0,
+0xa4,
+0x61,
+0x14,
+0x1a,
+0x43,
+0x50,
+0x53,
+0x54,
+0x1,
+0x70,
+0x83,
+0x88,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x68,
+0x0,
+0x60,
+0xa0,
+0x5,
+0x60,
+0xa4,
+0xa,
+0xf,
+0xa1,
+0x3,
+0xa4,
+0x0,
+0x14,
+0xa,
+0x43,
+0x50,
+0x45,
+0x4a,
+0x2,
+0x5b,
+0x22,
+0xa,
+0xc8,
+0x5b,
+0x80,
+0x50,
+0x52,
+0x53,
+0x54,
+0x1,
+0xb,
+0x0,
+0xaf,
+0xa,
+0x20,
+0x5b,
+0x81,
+0xc,
+0x50,
+0x52,
+0x53,
+0x54,
+0x1,
+0x50,
+0x52,
+0x53,
+0x5f,
+0x40,
+0x10,
+0x14,
+0x4a,
+0x6,
+0x50,
+0x52,
+0x53,
+0x43,
+0x0,
+0x70,
+0x50,
+0x52,
+0x53,
+0x5f,
+0x65,
+0x70,
+0x0,
+0x62,
+0x70,
+0x0,
+0x60,
+0xa2,
+0x46,
+0x5,
+0x95,
+0x60,
+0x87,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x70,
+0x83,
+0x88,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x60,
+0x0,
+0x61,
+0xa0,
+0xa,
+0x7b,
+0x60,
+0xa,
+0x7,
+0x0,
+0x7a,
+0x62,
+0x1,
+0x62,
+0xa1,
+0xc,
+0x70,
+0x83,
+0x88,
+0x65,
+0x7a,
+0x60,
+0xa,
+0x3,
+0x0,
+0x0,
+0x62,
+0x70,
+0x7b,
+0x62,
+0x1,
+0x0,
+0x63,
+0xa0,
+0x22,
+0x92,
+0x93,
+0x61,
+0x63,
+0x70,
+0x63,
+0x88,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x60,
+0x0,
+0xa0,
+0xa,
+0x93,
+0x63,
+0x1,
+0x4e,
+0x54,
+0x46,
+0x59,
+0x60,
+0x1,
+0xa1,
+0x8,
+0x4e,
+0x54,
+0x46,
+0x59,
+0x60,
+0xa,
+0x3,
+0x75,
+0x60,
+0x10,
+0x4e,
+0x9,
+0x5f,
+0x47,
+0x50,
+0x45,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xd,
+0x41,
+0x43,
+0x50,
+0x49,
+0x30,
+0x30,
+0x30,
+0x36,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x30,
+0x0,
+0x14,
+0x15,
+0x5f,
+0x45,
+0x30,
+0x31,
+0x0,
+0x5c,
+0x2f,
+0x3,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x50,
+0x43,
+0x4e,
+0x46,
+0x14,
+0x10,
+0x5f,
+0x45,
+0x30,
+0x32,
+0x0,
+0x5c,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x43,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x33,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x34,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x35,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x36,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x37,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x38,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x39,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x41,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x42,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x43,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x44,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x45,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x46,
+0x0
+};
diff --git a/hw/i386/bios-linker-loader.c b/hw/i386/bios-linker-loader.c
new file mode 100644
index 0000000..0833853
--- /dev/null
+++ b/hw/i386/bios-linker-loader.c
@@ -0,0 +1,158 @@
+/* Dynamic linker/loader of ACPI tables
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "bios-linker-loader.h"
+#include "hw/nvram/fw_cfg.h"
+
+#include <string.h>
+#include <assert.h>
+#include "qemu/bswap.h"
+
+#define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH
+
+struct BiosLinkerLoaderEntry {
+    uint32_t command;
+    union {
+        /*
+         * COMMAND_ALLOCATE - allocate a table from @alloc.file
+         * subject to @alloc.align alignment (must be power of 2)
+         * and @alloc.zone (can be HIGH or FSEG) requirements.
+         *
+         * Must appear exactly once for each file, and before
+         * this file is referenced by any other command.
+         */
+        struct {
+            char file[BIOS_LINKER_LOADER_FILESZ];
+            uint32_t align;
+            uint8_t zone;
+        } alloc;
+
+        /*
+         * COMMAND_ADD_POINTER - patch the table (originating from
+         * @dest_file) at @pointer.offset, by adding a pointer to the table
+         * originating from @src_file. 1,2,4 or 8 byte unsigned
+         * addition is used depending on @pointer.size.
+         */
+        struct {
+            char dest_file[BIOS_LINKER_LOADER_FILESZ];
+            char src_file[BIOS_LINKER_LOADER_FILESZ];
+            uint32_t offset;
+            uint8_t size;
+        } pointer;
+
+        /*
+         * COMMAND_ADD_CHECKSUM - calculate checksum of the range specified by
+         * @cksum_start and @cksum_length fields,
+         * and then add the value at @cksum.offset.
+         * Checksum simply sums -X for each byte X in the range
+         * using 8-bit math.
+         */
+        struct {
+            char file[BIOS_LINKER_LOADER_FILESZ];
+            uint32_t offset;
+            uint32_t start;
+            uint32_t length;
+        } cksum;
+
+        /* padding */
+        char pad[124];
+    };
+} QEMU_PACKED;
+typedef struct BiosLinkerLoaderEntry BiosLinkerLoaderEntry;
+
+enum {
+    BIOS_LINKER_LOADER_COMMAND_ALLOCATE     = 0x1,
+    BIOS_LINKER_LOADER_COMMAND_ADD_POINTER  = 0x2,
+    BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3,
+};
+
+enum {
+    BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1,
+    BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2,
+};
+
+GArray *bios_linker_loader_init(void)
+{
+    return g_array_new(false, true /* clear */, sizeof(BiosLinkerLoaderEntry));
+}
+
+/* Free linker wrapper and return the linker array. */
+void *bios_linker_loader_cleanup(GArray *linker)
+{
+    return g_array_free(linker, false);
+}
+
+void bios_linker_loader_alloc(GArray *linker,
+                              const char *file,
+                              uint32_t alloc_align,
+                              bool alloc_fseg)
+{
+    BiosLinkerLoaderEntry entry;
+
+    memset(&entry, 0, sizeof entry);
+    strncpy(entry.alloc.file, file, sizeof entry.alloc.file - 1);
+    entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ALLOCATE);
+    entry.alloc.align = cpu_to_le32(alloc_align);
+    entry.alloc.zone = cpu_to_le32(alloc_fseg ?
+                                    BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG :
+                                    BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH);
+
+    /* Alloc entries must come first, so prepend them */
+    g_array_prepend_val(linker, entry);
+}
+
+void bios_linker_loader_add_checksum(GArray *linker, const char *file,
+                                     void *table,
+                                     void *start, unsigned size,
+                                     uint8_t *checksum)
+{
+    BiosLinkerLoaderEntry entry;
+
+    memset(&entry, 0, sizeof entry);
+    strncpy(entry.cksum.file, file, sizeof entry.cksum.file - 1);
+    entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM);
+    entry.cksum.offset = cpu_to_le32(checksum - (uint8_t *)table);
+    entry.cksum.start = cpu_to_le32((uint8_t *)start - (uint8_t *)table);
+    entry.cksum.length = cpu_to_le32(size);
+
+    g_array_append_val(linker, entry);
+}
+
+void bios_linker_loader_add_pointer(GArray *linker,
+                                    const char *dest_file,
+                                    const char *src_file,
+                                    GArray *table, void *pointer,
+                                    uint8_t pointer_size)
+{
+    BiosLinkerLoaderEntry entry;
+
+    memset(&entry, 0, sizeof entry);
+    strncpy(entry.pointer.dest_file, dest_file,
+            sizeof entry.pointer.dest_file - 1);
+    strncpy(entry.pointer.src_file, src_file,
+            sizeof entry.pointer.src_file - 1);
+    entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER);
+    entry.pointer.offset = cpu_to_le32((gchar *)pointer - table->data);
+    entry.pointer.size = pointer_size;
+    assert(pointer_size == 1 || pointer_size == 2 ||
+           pointer_size == 4 || pointer_size == 8);
+
+    g_array_append_val(linker, entry);
+}
diff --git a/hw/i386/bios-linker-loader.h b/hw/i386/bios-linker-loader.h
new file mode 100644
index 0000000..498c0af
--- /dev/null
+++ b/hw/i386/bios-linker-loader.h
@@ -0,0 +1,27 @@
+#ifndef BIOS_LINKER_LOADER_H
+#define BIOS_LINKER_LOADER_H
+
+#include <glib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+GArray *bios_linker_loader_init(void);
+
+void bios_linker_loader_alloc(GArray *linker,
+                              const char *file,
+                              uint32_t alloc_align,
+                              bool alloc_fseg);
+
+void bios_linker_loader_add_checksum(GArray *linker, const char *file,
+                                     void *table,
+                                     void *start, unsigned size,
+                                     uint8_t *checksum);
+
+void bios_linker_loader_add_pointer(GArray *linker,
+                                    const char *dest_file,
+                                    const char *src_file,
+                                    GArray *table, void *pointer,
+                                    uint8_t pointer_size);
+
+void *bios_linker_loader_cleanup(GArray *linker);
+#endif
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index 4e65110..9686801 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -755,26 +755,22 @@
         goto fail;
     }
 
-    error_report("*** The driver '%s' is occupying your device "
-                 "%04x:%02x:%02x.%x.",
-                 ns, dev->host.domain, dev->host.bus, dev->host.slot,
-                 dev->host.function);
-    error_report("***");
-    error_report("*** You can try the following commands to free it:");
-    error_report("***");
-    error_report("*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub/"
-                 "new_id", vendor_id, device_id);
-    error_report("*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/"
-                 "%s/unbind",
-                 dev->host.domain, dev->host.bus, dev->host.slot,
-                 dev->host.function, ns);
-    error_report("*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/"
-                 "pci-stub/bind",
-                 dev->host.domain, dev->host.bus, dev->host.slot,
-                 dev->host.function);
-    error_report("*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub"
-                 "/remove_id", vendor_id, device_id);
-    error_report("***");
+    error_printf("*** The driver '%s' is occupying your device "
+        "%04x:%02x:%02x.%x.\n"
+        "***\n"
+        "*** You can try the following commands to free it:\n"
+        "***\n"
+        "*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub/new_id\n"
+        "*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/%s/unbind\n"
+        "*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/"
+        "pci-stub/bind\n"
+        "*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub/remove_id\n"
+        "***",
+        ns, dev->host.domain, dev->host.bus, dev->host.slot,
+        dev->host.function, vendor_id, device_id,
+        dev->host.domain, dev->host.bus, dev->host.slot, dev->host.function,
+        ns, dev->host.domain, dev->host.bus, dev->host.slot,
+        dev->host.function, vendor_id, device_id);
 
     return;
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 0c313fe..12c436e 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -56,6 +56,7 @@
 #include "hw/cpu/icc_bus.h"
 #include "hw/boards.h"
 #include "hw/pci/pci_host.h"
+#include "acpi-build.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -89,7 +90,9 @@
     struct e820_entry entry[E820_NR_ENTRIES];
 } QEMU_PACKED __attribute((__aligned__(4)));
 
-static struct e820_table e820_table;
+static struct e820_table e820_reserve;
+static struct e820_entry *e820_table;
+static unsigned e820_entries;
 struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
 
 void gsi_handler(void *opaque, int n, int level)
@@ -576,19 +579,32 @@
 
 int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
 {
-    int index = le32_to_cpu(e820_table.count);
+    int index = le32_to_cpu(e820_reserve.count);
     struct e820_entry *entry;
 
-    if (index >= E820_NR_ENTRIES)
-        return -EBUSY;
-    entry = &e820_table.entry[index++];
+    if (type != E820_RAM) {
+        /* old FW_CFG_E820_TABLE entry -- reservations only */
+        if (index >= E820_NR_ENTRIES) {
+            return -EBUSY;
+        }
+        entry = &e820_reserve.entry[index++];
 
-    entry->address = cpu_to_le64(address);
-    entry->length = cpu_to_le64(length);
-    entry->type = cpu_to_le32(type);
+        entry->address = cpu_to_le64(address);
+        entry->length = cpu_to_le64(length);
+        entry->type = cpu_to_le32(type);
 
-    e820_table.count = cpu_to_le32(index);
-    return index;
+        e820_reserve.count = cpu_to_le32(index);
+    }
+
+    /* new "etc/e820" file -- include ram too */
+    e820_table = g_realloc(e820_table,
+                           sizeof(struct e820_entry) * (e820_entries+1));
+    e820_table[e820_entries].address = cpu_to_le64(address);
+    e820_table[e820_entries].length = cpu_to_le64(length);
+    e820_table[e820_entries].type = cpu_to_le32(type);
+    e820_entries++;
+
+    return e820_entries;
 }
 
 /* Calculates the limit to CPU APIC ID values
@@ -639,7 +655,9 @@
         fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
                          smbios_table, smbios_len);
     fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
-                     &e820_table, sizeof(e820_table));
+                     &e820_reserve, sizeof(e820_reserve));
+    fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
+                    sizeof(struct e820_entry) * e820_entries);
 
     fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_cfg, sizeof(hpet_cfg));
     /* allocate memory for the NUMA channel: one (64bit) word for the number
@@ -1040,6 +1058,7 @@
                                                       PcGuestInfoState,
                                                       machine_done);
     pc_fw_cfg_guest_info(&guest_info_state->info);
+    acpi_setup(&guest_info_state->info);
 }
 
 PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
@@ -1047,6 +1066,27 @@
 {
     PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
     PcGuestInfo *guest_info = &guest_info_state->info;
+    int i, j;
+
+    guest_info->ram_size = below_4g_mem_size + above_4g_mem_size;
+    guest_info->apic_id_limit = pc_apic_id_limit(max_cpus);
+    guest_info->apic_xrupt_override = kvm_allows_irq0_override();
+    guest_info->numa_nodes = nb_numa_nodes;
+    guest_info->node_mem = g_memdup(node_mem, guest_info->numa_nodes *
+                                    sizeof *guest_info->node_mem);
+    guest_info->node_cpu = g_malloc0(guest_info->apic_id_limit *
+                                     sizeof *guest_info->node_cpu);
+
+    for (i = 0; i < max_cpus; i++) {
+        unsigned int apic_id = x86_cpu_apic_id_from_index(i);
+        assert(apic_id < guest_info->apic_id_limit);
+        for (j = 0; j < nb_numa_nodes; j++) {
+            if (test_bit(i, node_cpumask[j])) {
+                guest_info->node_cpu[apic_id] = j;
+                break;
+            }
+        }
+    }
 
     guest_info_state->machine_done.notify = pc_guest_info_machine_done;
     qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
@@ -1093,7 +1133,7 @@
         opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
         g_assert(opts != NULL);
 
-        acpi_table_add(opts, &err);
+        acpi_table_add_builtin(opts, &err);
         if (err) {
             error_report("WARNING: failed to load %s: %s", filename,
                          error_get_pretty(err));
@@ -1134,12 +1174,14 @@
     memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
                              0, below_4g_mem_size);
     memory_region_add_subregion(system_memory, 0, ram_below_4g);
+    e820_add_entry(0, below_4g_mem_size, E820_RAM);
     if (above_4g_mem_size > 0) {
         ram_above_4g = g_malloc(sizeof(*ram_above_4g));
         memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram,
                                  below_4g_mem_size, above_4g_mem_size);
         memory_region_add_subregion(system_memory, 0x100000000ULL,
                                     ram_above_4g);
+        e820_add_entry(0x100000000ULL, above_4g_mem_size, E820_RAM);
     }
 
 
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index c6042c7..094c421 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -58,7 +58,8 @@
 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 
 static bool has_pvpanic;
-static bool has_pci_info = true;
+static bool has_pci_info;
+static bool has_acpi_build = true;
 
 /* PC hardware initialisation */
 static void pc_init1(QEMUMachineInitArgs *args,
@@ -122,6 +123,9 @@
     }
 
     guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
+
+    guest_info->has_acpi_build = has_acpi_build;
+
     guest_info->has_pci_info = has_pci_info;
     guest_info->isapc_ram_fw = !pci_enabled;
 
@@ -240,6 +244,7 @@
 {
     has_pci_info = false;
     rom_file_in_ram = false;
+    has_acpi_build = false;
 }
 
 static void pc_compat_1_5(QEMUMachineInitArgs *args)
@@ -304,6 +309,7 @@
 static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
 {
     has_pci_info = false;
+    has_acpi_build = false;
     disable_kvm_pv_eoi();
     enable_compat_apic_id_mode();
     pc_init1(args, 1, 0);
@@ -312,6 +318,7 @@
 static void pc_init_isa(QEMUMachineInitArgs *args)
 {
     has_pci_info = false;
+    has_acpi_build = false;
     if (!args->cpu_model) {
         args->cpu_model = "486";
     }
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index ca84e1c..1af8e2b 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -48,7 +48,8 @@
 #define MAX_SATA_PORTS     6
 
 static bool has_pvpanic;
-static bool has_pci_info = true;
+static bool has_pci_info;
+static bool has_acpi_build = true;
 
 /* PC hardware initialisation */
 static void pc_q35_init(QEMUMachineInitArgs *args)
@@ -111,6 +112,7 @@
     guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
     guest_info->has_pci_info = has_pci_info;
     guest_info->isapc_ram_fw = false;
+    guest_info->has_acpi_build = has_acpi_build;
 
     /* allocate ram and load rom/bios */
     if (!xen_enabled()) {
@@ -224,6 +226,7 @@
 {
     has_pci_info = false;
     rom_file_in_ram = false;
+    has_acpi_build = false;
 }
 
 static void pc_compat_1_5(QEMUMachineInitArgs *args)
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
new file mode 100644
index 0000000..21c89b0
--- /dev/null
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -0,0 +1,452 @@
+/*
+ * Bochs/QEMU ACPI DSDT ASL definition
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+/*
+ * Copyright (c) 2010 Isaku Yamahata
+ *                    yamahata at valinux co jp
+ * Based on acpi-dsdt.dsl, but heavily modified for q35 chipset.
+ */
+
+ACPI_EXTRACT_ALL_CODE Q35AcpiDsdtAmlCode
+
+DefinitionBlock (
+    "q35-acpi-dsdt.aml",// Output Filename
+    "DSDT",             // Signature
+    0x01,               // DSDT Compliance Revision
+    "BXPC",             // OEMID
+    "BXDSDT",           // TABLE ID
+    0x2                 // OEM Revision
+    )
+{
+
+#include "acpi-dsdt-dbug.dsl"
+
+    Scope(\_SB) {
+        OperationRegion(PCST, SystemIO, 0xae00, 0x0c)
+        OperationRegion(PCSB, SystemIO, 0xae0c, 0x01)
+        Field(PCSB, AnyAcc, NoLock, WriteAsZeros) {
+            PCIB, 8,
+        }
+    }
+
+
+/****************************************************************
+ * PCI Bus definition
+ ****************************************************************/
+
+    Scope(\_SB) {
+        Device(PCI0) {
+            Name(_HID, EisaId("PNP0A08"))
+            Name(_CID, EisaId("PNP0A03"))
+            Name(_ADR, 0x00)
+            Name(_UID, 1)
+
+            // _OSC: based on sample of ACPI3.0b spec
+            Name(SUPP, 0) // PCI _OSC Support Field value
+            Name(CTRL, 0) // PCI _OSC Control Field value
+            Method(_OSC, 4) {
+                // Create DWORD-addressable fields from the Capabilities Buffer
+                CreateDWordField(Arg3, 0, CDW1)
+
+                // Check for proper UUID
+                If (LEqual(Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
+                    // Create DWORD-addressable fields from the Capabilities Buffer
+                    CreateDWordField(Arg3, 4, CDW2)
+                    CreateDWordField(Arg3, 8, CDW3)
+
+                    // Save Capabilities DWORD2 & 3
+                    Store(CDW2, SUPP)
+                    Store(CDW3, CTRL)
+
+                    // Always allow native PME, AER (no dependencies)
+                    // Never allow SHPC (no SHPC controller in this system)
+                    And(CTRL, 0x1D, CTRL)
+
+#if 0 // For now, nothing to do
+                    If (Not(And(CDW1, 1))) { // Query flag clear?
+                        // Disable GPEs for features granted native control.
+                        If (And(CTRL, 0x01)) { // Hot plug control granted?
+                            Store(0, HPCE) // clear the hot plug SCI enable bit
+                            Store(1, HPCS) // clear the hot plug SCI status bit
+                        }
+                        If (And(CTRL, 0x04)) { // PME control granted?
+                            Store(0, PMCE) // clear the PME SCI enable bit
+                            Store(1, PMCS) // clear the PME SCI status bit
+                        }
+                        If (And(CTRL, 0x10)) { // OS restoring PCI Express cap structure?
+                            // Set status to not restore PCI Express cap structure
+                            // upon resume from S3
+                            Store(1, S3CR)
+                        }
+                    }
+#endif
+                    If (LNotEqual(Arg1, One)) {
+                        // Unknown revision
+                        Or(CDW1, 0x08, CDW1)
+                    }
+                    If (LNotEqual(CDW3, CTRL)) {
+                        // Capabilities bits were masked
+                        Or(CDW1, 0x10, CDW1)
+                    }
+                    // Update DWORD3 in the buffer
+                    Store(CTRL, CDW3)
+                } Else {
+                    Or(CDW1, 4, CDW1) // Unrecognized UUID
+                }
+                Return (Arg3)
+            }
+        }
+    }
+
+#include "acpi-dsdt-pci-crs.dsl"
+#include "acpi-dsdt-hpet.dsl"
+
+
+/****************************************************************
+ * VGA
+ ****************************************************************/
+
+    Scope(\_SB.PCI0) {
+        Device(VGA) {
+            Name(_ADR, 0x00010000)
+            Method(_S1D, 0, NotSerialized) {
+                Return (0x00)
+            }
+            Method(_S2D, 0, NotSerialized) {
+                Return (0x00)
+            }
+            Method(_S3D, 0, NotSerialized) {
+                Return (0x00)
+            }
+        }
+    }
+
+
+/****************************************************************
+ * LPC ISA bridge
+ ****************************************************************/
+
+    Scope(\_SB.PCI0) {
+        /* PCI D31:f0 LPC ISA bridge */
+        Device(ISA) {
+            /* PCI D31:f0 */
+            Name(_ADR, 0x001f0000)
+
+            /* ICH9 PCI to ISA irq remapping */
+            OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
+
+            OperationRegion(LPCD, PCI_Config, 0x80, 0x2)
+            Field(LPCD, AnyAcc, NoLock, Preserve) {
+                COMA,   3,
+                    ,   1,
+                COMB,   3,
+
+                Offset(0x01),
+                LPTD,   2,
+                    ,   2,
+                FDCD,   2
+            }
+            OperationRegion(LPCE, PCI_Config, 0x82, 0x2)
+            Field(LPCE, AnyAcc, NoLock, Preserve) {
+                CAEN,   1,
+                CBEN,   1,
+                LPEN,   1,
+                FDEN,   1
+            }
+        }
+    }
+
+#include "acpi-dsdt-isa.dsl"
+
+
+/****************************************************************
+ * PCI IRQs
+ ****************************************************************/
+
+    /* Zero => PIC mode, One => APIC Mode */
+    Name(\PICF, Zero)
+    Method(\_PIC, 1, NotSerialized) {
+        Store(Arg0, \PICF)
+    }
+
+    Scope(\_SB) {
+        Scope(PCI0) {
+#define prt_slot_lnk(nr, lnk0, lnk1, lnk2, lnk3)  \
+    Package() { nr##ffff, 0, lnk0, 0 },           \
+    Package() { nr##ffff, 1, lnk1, 0 },           \
+    Package() { nr##ffff, 2, lnk2, 0 },           \
+    Package() { nr##ffff, 3, lnk3, 0 }
+
+#define prt_slot_lnkA(nr) prt_slot_lnk(nr, LNKA, LNKB, LNKC, LNKD)
+#define prt_slot_lnkB(nr) prt_slot_lnk(nr, LNKB, LNKC, LNKD, LNKA)
+#define prt_slot_lnkC(nr) prt_slot_lnk(nr, LNKC, LNKD, LNKA, LNKB)
+#define prt_slot_lnkD(nr) prt_slot_lnk(nr, LNKD, LNKA, LNKB, LNKC)
+
+#define prt_slot_lnkE(nr) prt_slot_lnk(nr, LNKE, LNKF, LNKG, LNKH)
+#define prt_slot_lnkF(nr) prt_slot_lnk(nr, LNKF, LNKG, LNKH, LNKE)
+#define prt_slot_lnkG(nr) prt_slot_lnk(nr, LNKG, LNKH, LNKE, LNKF)
+#define prt_slot_lnkH(nr) prt_slot_lnk(nr, LNKH, LNKE, LNKF, LNKG)
+
+            Name(PRTP, package() {
+                prt_slot_lnkE(0x0000),
+                prt_slot_lnkF(0x0001),
+                prt_slot_lnkG(0x0002),
+                prt_slot_lnkH(0x0003),
+                prt_slot_lnkE(0x0004),
+                prt_slot_lnkF(0x0005),
+                prt_slot_lnkG(0x0006),
+                prt_slot_lnkH(0x0007),
+                prt_slot_lnkE(0x0008),
+                prt_slot_lnkF(0x0009),
+                prt_slot_lnkG(0x000a),
+                prt_slot_lnkH(0x000b),
+                prt_slot_lnkE(0x000c),
+                prt_slot_lnkF(0x000d),
+                prt_slot_lnkG(0x000e),
+                prt_slot_lnkH(0x000f),
+                prt_slot_lnkE(0x0010),
+                prt_slot_lnkF(0x0011),
+                prt_slot_lnkG(0x0012),
+                prt_slot_lnkH(0x0013),
+                prt_slot_lnkE(0x0014),
+                prt_slot_lnkF(0x0015),
+                prt_slot_lnkG(0x0016),
+                prt_slot_lnkH(0x0017),
+                prt_slot_lnkE(0x0018),
+
+                /* INTA -> PIRQA for slot 25 - 31
+                   see the default value of D<N>IR */
+                prt_slot_lnkA(0x0019),
+                prt_slot_lnkA(0x001a),
+                prt_slot_lnkA(0x001b),
+                prt_slot_lnkA(0x001c),
+                prt_slot_lnkA(0x001d),
+
+                /* PCIe->PCI bridge. use PIRQ[E-H] */
+                prt_slot_lnkE(0x001e),
+
+                prt_slot_lnkA(0x001f)
+            })
+
+#define prt_slot_gsi(nr, gsi0, gsi1, gsi2, gsi3)  \
+    Package() { nr##ffff, 0, gsi0, 0 },           \
+    Package() { nr##ffff, 1, gsi1, 0 },           \
+    Package() { nr##ffff, 2, gsi2, 0 },           \
+    Package() { nr##ffff, 3, gsi3, 0 }
+
+#define prt_slot_gsiA(nr) prt_slot_gsi(nr, GSIA, GSIB, GSIC, GSID)
+#define prt_slot_gsiB(nr) prt_slot_gsi(nr, GSIB, GSIC, GSID, GSIA)
+#define prt_slot_gsiC(nr) prt_slot_gsi(nr, GSIC, GSID, GSIA, GSIB)
+#define prt_slot_gsiD(nr) prt_slot_gsi(nr, GSID, GSIA, GSIB, GSIC)
+
+#define prt_slot_gsiE(nr) prt_slot_gsi(nr, GSIE, GSIF, GSIG, GSIH)
+#define prt_slot_gsiF(nr) prt_slot_gsi(nr, GSIF, GSIG, GSIH, GSIE)
+#define prt_slot_gsiG(nr) prt_slot_gsi(nr, GSIG, GSIH, GSIE, GSIF)
+#define prt_slot_gsiH(nr) prt_slot_gsi(nr, GSIH, GSIE, GSIF, GSIG)
+
+            Name(PRTA, package() {
+                prt_slot_gsiE(0x0000),
+                prt_slot_gsiF(0x0001),
+                prt_slot_gsiG(0x0002),
+                prt_slot_gsiH(0x0003),
+                prt_slot_gsiE(0x0004),
+                prt_slot_gsiF(0x0005),
+                prt_slot_gsiG(0x0006),
+                prt_slot_gsiH(0x0007),
+                prt_slot_gsiE(0x0008),
+                prt_slot_gsiF(0x0009),
+                prt_slot_gsiG(0x000a),
+                prt_slot_gsiH(0x000b),
+                prt_slot_gsiE(0x000c),
+                prt_slot_gsiF(0x000d),
+                prt_slot_gsiG(0x000e),
+                prt_slot_gsiH(0x000f),
+                prt_slot_gsiE(0x0010),
+                prt_slot_gsiF(0x0011),
+                prt_slot_gsiG(0x0012),
+                prt_slot_gsiH(0x0013),
+                prt_slot_gsiE(0x0014),
+                prt_slot_gsiF(0x0015),
+                prt_slot_gsiG(0x0016),
+                prt_slot_gsiH(0x0017),
+                prt_slot_gsiE(0x0018),
+
+                /* INTA -> PIRQA for slot 25 - 31, but 30
+                   see the default value of D<N>IR */
+                prt_slot_gsiA(0x0019),
+                prt_slot_gsiA(0x001a),
+                prt_slot_gsiA(0x001b),
+                prt_slot_gsiA(0x001c),
+                prt_slot_gsiA(0x001d),
+
+                /* PCIe->PCI bridge. use PIRQ[E-H] */
+                prt_slot_gsiE(0x001e),
+
+                prt_slot_gsiA(0x001f)
+            })
+
+            Method(_PRT, 0, NotSerialized) {
+                /* PCI IRQ routing table, example from ACPI 2.0a specification,
+                   section 6.2.8.1 */
+                /* Note: we provide the same info as the PCI routing
+                   table of the Bochs BIOS */
+                If (LEqual(\PICF, Zero)) {
+                    Return (PRTP)
+                } Else {
+                    Return (PRTA)
+                }
+            }
+        }
+
+        Field(PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
+            PRQA,   8,
+            PRQB,   8,
+            PRQC,   8,
+            PRQD,   8,
+
+            Offset(0x08),
+            PRQE,   8,
+            PRQF,   8,
+            PRQG,   8,
+            PRQH,   8
+        }
+
+        Method(IQST, 1, NotSerialized) {
+            // _STA method - get status
+            If (And(0x80, Arg0)) {
+                Return (0x09)
+            }
+            Return (0x0B)
+        }
+        Method(IQCR, 1, NotSerialized) {
+            // _CRS method - get current settings
+            Name(PRR0, ResourceTemplate() {
+                Interrupt(, Level, ActiveHigh, Shared) { 0 }
+            })
+            CreateDWordField(PRR0, 0x05, PRRI)
+            Store(And(Arg0, 0x0F), PRRI)
+            Return (PRR0)
+        }
+
+#define define_link(link, uid, reg)                             \
+        Device(link) {                                          \
+            Name(_HID, EISAID("PNP0C0F"))                       \
+            Name(_UID, uid)                                     \
+            Name(_PRS, ResourceTemplate() {                     \
+                Interrupt(, Level, ActiveHigh, Shared) {        \
+                    5, 10, 11                                   \
+                }                                               \
+            })                                                  \
+            Method(_STA, 0, NotSerialized) {                    \
+                Return (IQST(reg))                              \
+            }                                                   \
+            Method(_DIS, 0, NotSerialized) {                    \
+                Or(reg, 0x80, reg)                              \
+            }                                                   \
+            Method(_CRS, 0, NotSerialized) {                    \
+                Return (IQCR(reg))                              \
+            }                                                   \
+            Method(_SRS, 1, NotSerialized) {                    \
+                CreateDWordField(Arg0, 0x05, PRRI)              \
+                Store(PRRI, reg)                                \
+            }                                                   \
+        }
+
+        define_link(LNKA, 0, PRQA)
+        define_link(LNKB, 1, PRQB)
+        define_link(LNKC, 2, PRQC)
+        define_link(LNKD, 3, PRQD)
+        define_link(LNKE, 4, PRQE)
+        define_link(LNKF, 5, PRQF)
+        define_link(LNKG, 6, PRQG)
+        define_link(LNKH, 7, PRQH)
+
+#define define_gsi_link(link, uid, gsi)                         \
+        Device(link) {                                          \
+            Name(_HID, EISAID("PNP0C0F"))                       \
+            Name(_UID, uid)                                     \
+            Name(_PRS, ResourceTemplate() {                     \
+                Interrupt(, Level, ActiveHigh, Shared) {        \
+                    gsi                                         \
+                }                                               \
+            })                                                  \
+            Name(_CRS, ResourceTemplate() {                     \
+                Interrupt(, Level, ActiveHigh, Shared) {        \
+                    gsi                                         \
+                }                                               \
+            })                                                  \
+            Method(_SRS, 1, NotSerialized) {                    \
+            }                                                   \
+        }
+
+        define_gsi_link(GSIA, 0, 0x10)
+        define_gsi_link(GSIB, 0, 0x11)
+        define_gsi_link(GSIC, 0, 0x12)
+        define_gsi_link(GSID, 0, 0x13)
+        define_gsi_link(GSIE, 0, 0x14)
+        define_gsi_link(GSIF, 0, 0x15)
+        define_gsi_link(GSIG, 0, 0x16)
+        define_gsi_link(GSIH, 0, 0x17)
+    }
+
+#include "acpi-dsdt-cpu-hotplug.dsl"
+
+
+/****************************************************************
+ * General purpose events
+ ****************************************************************/
+
+    Scope(\_GPE) {
+        Name(_HID, "ACPI0006")
+
+        Method(_L00) {
+        }
+        Method(_L01) {
+            // CPU hotplug event
+            \_SB.PRSC()
+        }
+        Method(_L02) {
+        }
+        Method(_L03) {
+        }
+        Method(_L04) {
+        }
+        Method(_L05) {
+        }
+        Method(_L06) {
+        }
+        Method(_L07) {
+        }
+        Method(_L08) {
+        }
+        Method(_L09) {
+        }
+        Method(_L0A) {
+        }
+        Method(_L0B) {
+        }
+        Method(_L0C) {
+        }
+        Method(_L0D) {
+        }
+        Method(_L0E) {
+        }
+        Method(_L0F) {
+        }
+    }
+}
diff --git a/hw/i386/q35-acpi-dsdt.hex.generated b/hw/i386/q35-acpi-dsdt.hex.generated
new file mode 100644
index 0000000..32c16ff
--- /dev/null
+++ b/hw/i386/q35-acpi-dsdt.hex.generated
@@ -0,0 +1,7346 @@
+static unsigned char Q35AcpiDsdtAmlCode[] = {
+0x44,
+0x53,
+0x44,
+0x54,
+0xb0,
+0x1c,
+0x0,
+0x0,
+0x1,
+0x6,
+0x42,
+0x58,
+0x50,
+0x43,
+0x0,
+0x0,
+0x42,
+0x58,
+0x44,
+0x53,
+0x44,
+0x54,
+0x0,
+0x0,
+0x2,
+0x0,
+0x0,
+0x0,
+0x49,
+0x4e,
+0x54,
+0x4c,
+0x23,
+0x8,
+0x13,
+0x20,
+0x10,
+0x49,
+0x4,
+0x5c,
+0x0,
+0x5b,
+0x80,
+0x44,
+0x42,
+0x47,
+0x5f,
+0x1,
+0xb,
+0x2,
+0x4,
+0x1,
+0x5b,
+0x81,
+0xb,
+0x44,
+0x42,
+0x47,
+0x5f,
+0x1,
+0x44,
+0x42,
+0x47,
+0x42,
+0x8,
+0x14,
+0x2c,
+0x44,
+0x42,
+0x55,
+0x47,
+0x1,
+0x98,
+0x68,
+0x60,
+0x96,
+0x60,
+0x60,
+0x74,
+0x87,
+0x60,
+0x1,
+0x61,
+0x70,
+0x0,
+0x62,
+0xa2,
+0x10,
+0x95,
+0x62,
+0x61,
+0x70,
+0x83,
+0x88,
+0x60,
+0x62,
+0x0,
+0x44,
+0x42,
+0x47,
+0x42,
+0x75,
+0x62,
+0x70,
+0xa,
+0xa,
+0x44,
+0x42,
+0x47,
+0x42,
+0x10,
+0x29,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x5b,
+0x80,
+0x50,
+0x43,
+0x53,
+0x54,
+0x1,
+0xb,
+0x0,
+0xae,
+0xa,
+0xc,
+0x5b,
+0x80,
+0x50,
+0x43,
+0x53,
+0x42,
+0x1,
+0xb,
+0xc,
+0xae,
+0x1,
+0x5b,
+0x81,
+0xb,
+0x50,
+0x43,
+0x53,
+0x42,
+0x40,
+0x50,
+0x43,
+0x49,
+0x42,
+0x8,
+0x10,
+0x4f,
+0xc,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x5b,
+0x82,
+0x47,
+0xc,
+0x50,
+0x43,
+0x49,
+0x30,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xa,
+0x8,
+0x8,
+0x5f,
+0x43,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xa,
+0x3,
+0x8,
+0x5f,
+0x41,
+0x44,
+0x52,
+0x0,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x1,
+0x8,
+0x53,
+0x55,
+0x50,
+0x50,
+0x0,
+0x8,
+0x43,
+0x54,
+0x52,
+0x4c,
+0x0,
+0x14,
+0x44,
+0x9,
+0x5f,
+0x4f,
+0x53,
+0x43,
+0x4,
+0x8a,
+0x6b,
+0x0,
+0x43,
+0x44,
+0x57,
+0x31,
+0xa0,
+0x46,
+0x7,
+0x93,
+0x68,
+0x11,
+0x13,
+0xa,
+0x10,
+0x5b,
+0x4d,
+0xdb,
+0x33,
+0xf7,
+0x1f,
+0x1c,
+0x40,
+0x96,
+0x57,
+0x74,
+0x41,
+0xc0,
+0x3d,
+0xd7,
+0x66,
+0x8a,
+0x6b,
+0xa,
+0x4,
+0x43,
+0x44,
+0x57,
+0x32,
+0x8a,
+0x6b,
+0xa,
+0x8,
+0x43,
+0x44,
+0x57,
+0x33,
+0x70,
+0x43,
+0x44,
+0x57,
+0x32,
+0x53,
+0x55,
+0x50,
+0x50,
+0x70,
+0x43,
+0x44,
+0x57,
+0x33,
+0x43,
+0x54,
+0x52,
+0x4c,
+0x7b,
+0x43,
+0x54,
+0x52,
+0x4c,
+0xa,
+0x1d,
+0x43,
+0x54,
+0x52,
+0x4c,
+0xa0,
+0x10,
+0x92,
+0x93,
+0x69,
+0x1,
+0x7d,
+0x43,
+0x44,
+0x57,
+0x31,
+0xa,
+0x8,
+0x43,
+0x44,
+0x57,
+0x31,
+0xa0,
+0x16,
+0x92,
+0x93,
+0x43,
+0x44,
+0x57,
+0x33,
+0x43,
+0x54,
+0x52,
+0x4c,
+0x7d,
+0x43,
+0x44,
+0x57,
+0x31,
+0xa,
+0x10,
+0x43,
+0x44,
+0x57,
+0x31,
+0x70,
+0x43,
+0x54,
+0x52,
+0x4c,
+0x43,
+0x44,
+0x57,
+0x33,
+0xa1,
+0xc,
+0x7d,
+0x43,
+0x44,
+0x57,
+0x31,
+0xa,
+0x4,
+0x43,
+0x44,
+0x57,
+0x31,
+0xa4,
+0x6b,
+0x10,
+0x4e,
+0x15,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x8,
+0x43,
+0x52,
+0x45,
+0x53,
+0x11,
+0x42,
+0x7,
+0xa,
+0x6e,
+0x88,
+0xd,
+0x0,
+0x2,
+0xc,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xff,
+0x0,
+0x0,
+0x0,
+0x0,
+0x1,
+0x47,
+0x1,
+0xf8,
+0xc,
+0xf8,
+0xc,
+0x1,
+0x8,
+0x88,
+0xd,
+0x0,
+0x1,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0xf7,
+0xc,
+0x0,
+0x0,
+0xf8,
+0xc,
+0x88,
+0xd,
+0x0,
+0x1,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0xd,
+0xff,
+0xff,
+0x0,
+0x0,
+0x0,
+0xf3,
+0x87,
+0x17,
+0x0,
+0x0,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0xff,
+0xff,
+0xb,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x2,
+0x0,
+0x87,
+0x17,
+0x0,
+0x0,
+0xc,
+0x1,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xe0,
+0xff,
+0xff,
+0xbf,
+0xfe,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xc0,
+0x1e,
+0x79,
+0x0,
+0x8,
+0x43,
+0x52,
+0x36,
+0x34,
+0x11,
+0x33,
+0xa,
+0x30,
+0x8a,
+0x2b,
+0x0,
+0x0,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x80,
+0x0,
+0x0,
+0x0,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x80,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x41,
+0xa,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0x8a,
+0x43,
+0x52,
+0x45,
+0x53,
+0xa,
+0x5c,
+0x50,
+0x53,
+0x33,
+0x32,
+0x8a,
+0x43,
+0x52,
+0x45,
+0x53,
+0xa,
+0x60,
+0x50,
+0x45,
+0x33,
+0x32,
+0x8a,
+0x43,
+0x52,
+0x45,
+0x53,
+0xa,
+0x68,
+0x50,
+0x4c,
+0x33,
+0x32,
+0x70,
+0x50,
+0x30,
+0x53,
+0x5f,
+0x50,
+0x53,
+0x33,
+0x32,
+0x70,
+0x50,
+0x30,
+0x45,
+0x5f,
+0x50,
+0x45,
+0x33,
+0x32,
+0x70,
+0x72,
+0x74,
+0x50,
+0x30,
+0x45,
+0x5f,
+0x50,
+0x30,
+0x53,
+0x5f,
+0x0,
+0x1,
+0x0,
+0x50,
+0x4c,
+0x33,
+0x32,
+0xa0,
+0xc,
+0x93,
+0x50,
+0x31,
+0x56,
+0x5f,
+0x0,
+0xa4,
+0x43,
+0x52,
+0x45,
+0x53,
+0x8f,
+0x43,
+0x52,
+0x36,
+0x34,
+0xa,
+0xe,
+0x50,
+0x53,
+0x36,
+0x34,
+0x8f,
+0x43,
+0x52,
+0x36,
+0x34,
+0xa,
+0x16,
+0x50,
+0x45,
+0x36,
+0x34,
+0x8f,
+0x43,
+0x52,
+0x36,
+0x34,
+0xa,
+0x26,
+0x50,
+0x4c,
+0x36,
+0x34,
+0x70,
+0x50,
+0x31,
+0x53,
+0x5f,
+0x50,
+0x53,
+0x36,
+0x34,
+0x70,
+0x50,
+0x31,
+0x45,
+0x5f,
+0x50,
+0x45,
+0x36,
+0x34,
+0x70,
+0x50,
+0x31,
+0x4c,
+0x5f,
+0x50,
+0x4c,
+0x36,
+0x34,
+0x84,
+0x43,
+0x52,
+0x45,
+0x53,
+0x43,
+0x52,
+0x36,
+0x34,
+0x60,
+0xa4,
+0x60,
+0x10,
+0x4d,
+0x8,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x5b,
+0x82,
+0x45,
+0x8,
+0x48,
+0x50,
+0x45,
+0x54,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x1,
+0x3,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x5b,
+0x80,
+0x48,
+0x50,
+0x54,
+0x4d,
+0x0,
+0xc,
+0x0,
+0x0,
+0xd0,
+0xfe,
+0xb,
+0x0,
+0x4,
+0x5b,
+0x81,
+0x10,
+0x48,
+0x50,
+0x54,
+0x4d,
+0x13,
+0x56,
+0x45,
+0x4e,
+0x44,
+0x20,
+0x50,
+0x52,
+0x44,
+0x5f,
+0x20,
+0x14,
+0x36,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x56,
+0x45,
+0x4e,
+0x44,
+0x60,
+0x70,
+0x50,
+0x52,
+0x44,
+0x5f,
+0x61,
+0x7a,
+0x60,
+0xa,
+0x10,
+0x60,
+0xa0,
+0xc,
+0x91,
+0x93,
+0x60,
+0x0,
+0x93,
+0x60,
+0xb,
+0xff,
+0xff,
+0xa4,
+0x0,
+0xa0,
+0xe,
+0x91,
+0x93,
+0x61,
+0x0,
+0x94,
+0x61,
+0xc,
+0x0,
+0xe1,
+0xf5,
+0x5,
+0xa4,
+0x0,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x11,
+0xa,
+0xe,
+0x86,
+0x9,
+0x0,
+0x0,
+0x0,
+0x0,
+0xd0,
+0xfe,
+0x0,
+0x4,
+0x0,
+0x0,
+0x79,
+0x0,
+0x10,
+0x36,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x82,
+0x2a,
+0x56,
+0x47,
+0x41,
+0x5f,
+0x8,
+0x5f,
+0x41,
+0x44,
+0x52,
+0xc,
+0x0,
+0x0,
+0x1,
+0x0,
+0x14,
+0x8,
+0x5f,
+0x53,
+0x31,
+0x44,
+0x0,
+0xa4,
+0x0,
+0x14,
+0x8,
+0x5f,
+0x53,
+0x32,
+0x44,
+0x0,
+0xa4,
+0x0,
+0x14,
+0x8,
+0x5f,
+0x53,
+0x33,
+0x44,
+0x0,
+0xa4,
+0x0,
+0x10,
+0x4c,
+0x7,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x82,
+0x4f,
+0x6,
+0x49,
+0x53,
+0x41,
+0x5f,
+0x8,
+0x5f,
+0x41,
+0x44,
+0x52,
+0xc,
+0x0,
+0x0,
+0x1f,
+0x0,
+0x5b,
+0x80,
+0x50,
+0x49,
+0x52,
+0x51,
+0x2,
+0xa,
+0x60,
+0xa,
+0xc,
+0x5b,
+0x80,
+0x4c,
+0x50,
+0x43,
+0x44,
+0x2,
+0xa,
+0x80,
+0xa,
+0x2,
+0x5b,
+0x81,
+0x20,
+0x4c,
+0x50,
+0x43,
+0x44,
+0x0,
+0x43,
+0x4f,
+0x4d,
+0x41,
+0x3,
+0x0,
+0x1,
+0x43,
+0x4f,
+0x4d,
+0x42,
+0x3,
+0x0,
+0x1,
+0x4c,
+0x50,
+0x54,
+0x44,
+0x2,
+0x0,
+0x2,
+0x46,
+0x44,
+0x43,
+0x44,
+0x2,
+0x5b,
+0x80,
+0x4c,
+0x50,
+0x43,
+0x45,
+0x2,
+0xa,
+0x82,
+0xa,
+0x2,
+0x5b,
+0x81,
+0x1a,
+0x4c,
+0x50,
+0x43,
+0x45,
+0x0,
+0x43,
+0x41,
+0x45,
+0x4e,
+0x1,
+0x43,
+0x42,
+0x45,
+0x4e,
+0x1,
+0x4c,
+0x50,
+0x45,
+0x4e,
+0x1,
+0x46,
+0x44,
+0x45,
+0x4e,
+0x1,
+0x10,
+0x4c,
+0x1b,
+0x2f,
+0x3,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x49,
+0x53,
+0x41,
+0x5f,
+0x5b,
+0x82,
+0x2d,
+0x52,
+0x54,
+0x43,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xb,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x18,
+0xa,
+0x15,
+0x47,
+0x1,
+0x70,
+0x0,
+0x70,
+0x0,
+0x10,
+0x2,
+0x22,
+0x0,
+0x1,
+0x47,
+0x1,
+0x72,
+0x0,
+0x72,
+0x0,
+0x2,
+0x6,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x37,
+0x4b,
+0x42,
+0x44,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x3,
+0x3,
+0x14,
+0x9,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x18,
+0xa,
+0x15,
+0x47,
+0x1,
+0x60,
+0x0,
+0x60,
+0x0,
+0x1,
+0x1,
+0x47,
+0x1,
+0x64,
+0x0,
+0x64,
+0x0,
+0x1,
+0x1,
+0x22,
+0x2,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x27,
+0x4d,
+0x4f,
+0x55,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xf,
+0x13,
+0x14,
+0x9,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x8,
+0xa,
+0x5,
+0x22,
+0x0,
+0x10,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x4a,
+0x4,
+0x46,
+0x44,
+0x43,
+0x30,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x7,
+0x0,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x46,
+0x44,
+0x45,
+0x4e,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x1b,
+0xa,
+0x18,
+0x47,
+0x1,
+0xf2,
+0x3,
+0xf2,
+0x3,
+0x0,
+0x4,
+0x47,
+0x1,
+0xf7,
+0x3,
+0xf7,
+0x3,
+0x0,
+0x1,
+0x22,
+0x40,
+0x0,
+0x2a,
+0x4,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x3e,
+0x4c,
+0x50,
+0x54,
+0x5f,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x4,
+0x0,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x4c,
+0x50,
+0x45,
+0x4e,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x10,
+0xa,
+0xd,
+0x47,
+0x1,
+0x78,
+0x3,
+0x78,
+0x3,
+0x8,
+0x8,
+0x22,
+0x80,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x43,
+0x4f,
+0x4d,
+0x31,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x5,
+0x1,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x1,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x43,
+0x41,
+0x45,
+0x4e,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x10,
+0xa,
+0xd,
+0x47,
+0x1,
+0xf8,
+0x3,
+0xf8,
+0x3,
+0x0,
+0x8,
+0x22,
+0x10,
+0x0,
+0x79,
+0x0,
+0x5b,
+0x82,
+0x46,
+0x4,
+0x43,
+0x4f,
+0x4d,
+0x32,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0x5,
+0x1,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x2,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x43,
+0x42,
+0x45,
+0x4e,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0x10,
+0xa,
+0xd,
+0x47,
+0x1,
+0xf8,
+0x2,
+0xf8,
+0x2,
+0x0,
+0x8,
+0x22,
+0x8,
+0x0,
+0x79,
+0x0,
+0x8,
+0x50,
+0x49,
+0x43,
+0x46,
+0x0,
+0x14,
+0xc,
+0x5f,
+0x50,
+0x49,
+0x43,
+0x1,
+0x70,
+0x68,
+0x50,
+0x49,
+0x43,
+0x46,
+0x10,
+0x8e,
+0x55,
+0x1,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x10,
+0x43,
+0xea,
+0x50,
+0x43,
+0x49,
+0x30,
+0x8,
+0x50,
+0x52,
+0x54,
+0x50,
+0x12,
+0x4b,
+0x73,
+0x80,
+0x12,
+0xb,
+0x4,
+0xb,
+0xff,
+0xff,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xb,
+0x4,
+0xb,
+0xff,
+0xff,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xc,
+0x4,
+0xb,
+0xff,
+0xff,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xc,
+0x4,
+0xb,
+0xff,
+0xff,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0x0,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0x1,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0xa,
+0x2,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0xa,
+0x3,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x0,
+0x8,
+0x50,
+0x52,
+0x54,
+0x41,
+0x12,
+0x4b,
+0x73,
+0x80,
+0x12,
+0xb,
+0x4,
+0xb,
+0xff,
+0xff,
+0x0,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xb,
+0x4,
+0xb,
+0xff,
+0xff,
+0x1,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xc,
+0x4,
+0xb,
+0xff,
+0xff,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xc,
+0x4,
+0xb,
+0xff,
+0xff,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x2,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x3,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x4,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x5,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x6,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x7,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x8,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x9,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xa,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xb,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xc,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xd,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xe,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0xf,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x10,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x11,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x12,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x13,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x14,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x15,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x16,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x17,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x18,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x19,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1a,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1b,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1c,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1d,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x44,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x45,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x46,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x47,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1e,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x48,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0x0,
+0x47,
+0x53,
+0x49,
+0x41,
+0x0,
+0x12,
+0xd,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0x1,
+0x47,
+0x53,
+0x49,
+0x42,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0xa,
+0x2,
+0x47,
+0x53,
+0x49,
+0x43,
+0x0,
+0x12,
+0xe,
+0x4,
+0xc,
+0xff,
+0xff,
+0x1f,
+0x0,
+0xa,
+0x3,
+0x47,
+0x53,
+0x49,
+0x44,
+0x0,
+0x14,
+0x1a,
+0x5f,
+0x50,
+0x52,
+0x54,
+0x0,
+0xa0,
+0xc,
+0x93,
+0x50,
+0x49,
+0x43,
+0x46,
+0x0,
+0xa4,
+0x50,
+0x52,
+0x54,
+0x50,
+0xa1,
+0x6,
+0xa4,
+0x50,
+0x52,
+0x54,
+0x41,
+0x5b,
+0x81,
+0x3a,
+0x2f,
+0x3,
+0x50,
+0x43,
+0x49,
+0x30,
+0x49,
+0x53,
+0x41,
+0x5f,
+0x50,
+0x49,
+0x52,
+0x51,
+0x1,
+0x50,
+0x52,
+0x51,
+0x41,
+0x8,
+0x50,
+0x52,
+0x51,
+0x42,
+0x8,
+0x50,
+0x52,
+0x51,
+0x43,
+0x8,
+0x50,
+0x52,
+0x51,
+0x44,
+0x8,
+0x0,
+0x20,
+0x50,
+0x52,
+0x51,
+0x45,
+0x8,
+0x50,
+0x52,
+0x51,
+0x46,
+0x8,
+0x50,
+0x52,
+0x51,
+0x47,
+0x8,
+0x50,
+0x52,
+0x51,
+0x48,
+0x8,
+0x14,
+0x13,
+0x49,
+0x51,
+0x53,
+0x54,
+0x1,
+0xa0,
+0x9,
+0x7b,
+0xa,
+0x80,
+0x68,
+0x0,
+0xa4,
+0xa,
+0x9,
+0xa4,
+0xa,
+0xb,
+0x14,
+0x34,
+0x49,
+0x51,
+0x43,
+0x52,
+0x1,
+0x8,
+0x50,
+0x52,
+0x52,
+0x30,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x0,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8a,
+0x50,
+0x52,
+0x52,
+0x30,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x7b,
+0x68,
+0xa,
+0xf,
+0x0,
+0x50,
+0x52,
+0x52,
+0x49,
+0xa4,
+0x50,
+0x52,
+0x52,
+0x30,
+0x5b,
+0x82,
+0x4c,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x41,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x41,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x41,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x41,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x41,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x41,
+0x5b,
+0x82,
+0x4c,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x42,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x1,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x42,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x42,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x42,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x42,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x42,
+0x5b,
+0x82,
+0x4d,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x43,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x2,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x43,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x43,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x43,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x43,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x43,
+0x5b,
+0x82,
+0x4d,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x44,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x3,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x44,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x44,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x44,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x44,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x44,
+0x5b,
+0x82,
+0x4d,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x45,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x4,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x45,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x45,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x45,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x45,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x45,
+0x5b,
+0x82,
+0x4d,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x46,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x5,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x46,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x46,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x46,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x46,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x46,
+0x5b,
+0x82,
+0x4d,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x47,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x6,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x47,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x47,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x47,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x47,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x47,
+0x5b,
+0x82,
+0x4d,
+0x7,
+0x4c,
+0x4e,
+0x4b,
+0x48,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xa,
+0x7,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0x16,
+0xa,
+0x13,
+0x89,
+0xe,
+0x0,
+0x9,
+0x3,
+0x5,
+0x0,
+0x0,
+0x0,
+0xa,
+0x0,
+0x0,
+0x0,
+0xb,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x53,
+0x54,
+0x50,
+0x52,
+0x51,
+0x48,
+0x14,
+0x11,
+0x5f,
+0x44,
+0x49,
+0x53,
+0x0,
+0x7d,
+0x50,
+0x52,
+0x51,
+0x48,
+0xa,
+0x80,
+0x50,
+0x52,
+0x51,
+0x48,
+0x14,
+0xf,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x0,
+0xa4,
+0x49,
+0x51,
+0x43,
+0x52,
+0x50,
+0x52,
+0x51,
+0x48,
+0x14,
+0x17,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x8a,
+0x68,
+0xa,
+0x5,
+0x50,
+0x52,
+0x52,
+0x49,
+0x70,
+0x50,
+0x52,
+0x52,
+0x49,
+0x50,
+0x52,
+0x51,
+0x48,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x47,
+0x53,
+0x49,
+0x41,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x10,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x10,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x47,
+0x53,
+0x49,
+0x42,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x11,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x11,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x47,
+0x53,
+0x49,
+0x43,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x12,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x12,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x47,
+0x53,
+0x49,
+0x44,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x13,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x13,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x47,
+0x53,
+0x49,
+0x45,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x14,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x14,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x47,
+0x53,
+0x49,
+0x46,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x15,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x15,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x47,
+0x53,
+0x49,
+0x47,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x16,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x16,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x5b,
+0x82,
+0x45,
+0x4,
+0x47,
+0x53,
+0x49,
+0x48,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xc,
+0x41,
+0xd0,
+0xc,
+0xf,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0x0,
+0x8,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x17,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xe,
+0xa,
+0xb,
+0x89,
+0x6,
+0x0,
+0x9,
+0x1,
+0x17,
+0x0,
+0x0,
+0x0,
+0x79,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x53,
+0x52,
+0x53,
+0x1,
+0x10,
+0x47,
+0xe,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x14,
+0x35,
+0x43,
+0x50,
+0x4d,
+0x41,
+0x1,
+0x70,
+0x83,
+0x88,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x68,
+0x0,
+0x60,
+0x70,
+0x11,
+0xb,
+0xa,
+0x8,
+0x0,
+0x8,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x61,
+0x70,
+0x68,
+0x88,
+0x61,
+0xa,
+0x2,
+0x0,
+0x70,
+0x68,
+0x88,
+0x61,
+0xa,
+0x3,
+0x0,
+0x70,
+0x60,
+0x88,
+0x61,
+0xa,
+0x4,
+0x0,
+0xa4,
+0x61,
+0x14,
+0x1a,
+0x43,
+0x50,
+0x53,
+0x54,
+0x1,
+0x70,
+0x83,
+0x88,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x68,
+0x0,
+0x60,
+0xa0,
+0x5,
+0x60,
+0xa4,
+0xa,
+0xf,
+0xa1,
+0x3,
+0xa4,
+0x0,
+0x14,
+0xa,
+0x43,
+0x50,
+0x45,
+0x4a,
+0x2,
+0x5b,
+0x22,
+0xa,
+0xc8,
+0x5b,
+0x80,
+0x50,
+0x52,
+0x53,
+0x54,
+0x1,
+0xb,
+0x0,
+0xaf,
+0xa,
+0x20,
+0x5b,
+0x81,
+0xc,
+0x50,
+0x52,
+0x53,
+0x54,
+0x1,
+0x50,
+0x52,
+0x53,
+0x5f,
+0x40,
+0x10,
+0x14,
+0x4a,
+0x6,
+0x50,
+0x52,
+0x53,
+0x43,
+0x0,
+0x70,
+0x50,
+0x52,
+0x53,
+0x5f,
+0x65,
+0x70,
+0x0,
+0x62,
+0x70,
+0x0,
+0x60,
+0xa2,
+0x46,
+0x5,
+0x95,
+0x60,
+0x87,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x70,
+0x83,
+0x88,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x60,
+0x0,
+0x61,
+0xa0,
+0xa,
+0x7b,
+0x60,
+0xa,
+0x7,
+0x0,
+0x7a,
+0x62,
+0x1,
+0x62,
+0xa1,
+0xc,
+0x70,
+0x83,
+0x88,
+0x65,
+0x7a,
+0x60,
+0xa,
+0x3,
+0x0,
+0x0,
+0x62,
+0x70,
+0x7b,
+0x62,
+0x1,
+0x0,
+0x63,
+0xa0,
+0x22,
+0x92,
+0x93,
+0x61,
+0x63,
+0x70,
+0x63,
+0x88,
+0x43,
+0x50,
+0x4f,
+0x4e,
+0x60,
+0x0,
+0xa0,
+0xa,
+0x93,
+0x63,
+0x1,
+0x4e,
+0x54,
+0x46,
+0x59,
+0x60,
+0x1,
+0xa1,
+0x8,
+0x4e,
+0x54,
+0x46,
+0x59,
+0x60,
+0xa,
+0x3,
+0x75,
+0x60,
+0x10,
+0x4f,
+0x8,
+0x5f,
+0x47,
+0x50,
+0x45,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xd,
+0x41,
+0x43,
+0x50,
+0x49,
+0x30,
+0x30,
+0x30,
+0x36,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x30,
+0x0,
+0x14,
+0x10,
+0x5f,
+0x4c,
+0x30,
+0x31,
+0x0,
+0x5c,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x52,
+0x53,
+0x43,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x32,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x33,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x34,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x35,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x36,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x37,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x38,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x39,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x41,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x42,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x43,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x44,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x45,
+0x0,
+0x14,
+0x6,
+0x5f,
+0x4c,
+0x30,
+0x46,
+0x0
+};
diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
new file mode 100644
index 0000000..a4484b8
--- /dev/null
+++ b/hw/i386/ssdt-misc.dsl
@@ -0,0 +1,119 @@
+/*
+ * 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/>.
+ */
+
+ACPI_EXTRACT_ALL_CODE ssdp_misc_aml
+
+DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
+{
+
+/****************************************************************
+ * PCI memory ranges
+ ****************************************************************/
+
+    Scope(\) {
+       ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start
+       Name(P0S, 0x12345678)
+       ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end
+       Name(P0E, 0x12345678)
+       ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid
+       Name(P1V, 0x12)
+       ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start
+       Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
+       ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end
+       Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
+       ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
+       Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
+    }
+
+
+/****************************************************************
+ * Suspend
+ ****************************************************************/
+
+    Scope(\) {
+    /*
+     * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
+     * must match piix4 emulation.
+     */
+
+        ACPI_EXTRACT_NAME_STRING acpi_s3_name
+        Name(_S3, Package(0x04) {
+            One,  /* PM1a_CNT.SLP_TYP */
+            One,  /* PM1b_CNT.SLP_TYP */
+            Zero,  /* reserved */
+            Zero   /* reserved */
+        })
+        ACPI_EXTRACT_NAME_STRING acpi_s4_name
+        ACPI_EXTRACT_PKG_START acpi_s4_pkg
+        Name(_S4, Package(0x04) {
+            0x2,  /* PM1a_CNT.SLP_TYP */
+            0x2,  /* PM1b_CNT.SLP_TYP */
+            Zero,  /* reserved */
+            Zero   /* reserved */
+        })
+        Name(_S5, Package(0x04) {
+            Zero,  /* PM1a_CNT.SLP_TYP */
+            Zero,  /* PM1b_CNT.SLP_TYP */
+            Zero,  /* reserved */
+            Zero   /* reserved */
+        })
+    }
+
+    External(\_SB.PCI0, DeviceObj)
+    External(\_SB.PCI0.ISA, DeviceObj)
+
+    Scope(\_SB.PCI0.ISA) {
+        Device(PEVT) {
+            Name(_HID, "QEMU0001")
+            /* PEST will be patched to be Zero if no such device */
+            ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest
+            Name(PEST, 0xFFFF)
+            OperationRegion(PEOR, SystemIO, PEST, 0x01)
+            Field(PEOR, ByteAcc, NoLock, Preserve) {
+                PEPT,   8,
+            }
+
+            Method(_STA, 0, NotSerialized) {
+                Store(PEST, Local0)
+                If (LEqual(Local0, Zero)) {
+                    Return (0x00)
+                } Else {
+                    Return (0x0F)
+                }
+            }
+
+            Method(RDPT, 0, NotSerialized) {
+                Store(PEPT, Local0)
+                Return (Local0)
+            }
+
+            Method(WRPT, 1, NotSerialized) {
+                Store(Arg0, PEPT)
+            }
+
+            Name(_CRS, ResourceTemplate() {
+                IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO)
+            })
+
+            CreateWordField(_CRS, IO._MIN, IOMN)
+            CreateWordField(_CRS, IO._MAX, IOMX)
+
+            Method(_INI, 0, NotSerialized) {
+                Store(PEST, IOMN)
+                Store(PEST, IOMX)
+            }
+        }
+    }
+}
diff --git a/hw/i386/ssdt-misc.hex.generated b/hw/i386/ssdt-misc.hex.generated
new file mode 100644
index 0000000..55e3bd2
--- /dev/null
+++ b/hw/i386/ssdt-misc.hex.generated
@@ -0,0 +1,386 @@
+static unsigned char acpi_pci64_length[] = {
+0x6f
+};
+static unsigned char acpi_s4_pkg[] = {
+0x8f
+};
+static unsigned char acpi_s3_name[] = {
+0x7c
+};
+static unsigned char acpi_pci32_start[] = {
+0x2f
+};
+static unsigned char acpi_pci64_valid[] = {
+0x43
+};
+static unsigned char ssdp_misc_aml[] = {
+0x53,
+0x53,
+0x44,
+0x54,
+0x62,
+0x1,
+0x0,
+0x0,
+0x1,
+0x76,
+0x42,
+0x58,
+0x50,
+0x43,
+0x0,
+0x0,
+0x42,
+0x58,
+0x53,
+0x53,
+0x44,
+0x54,
+0x53,
+0x55,
+0x1,
+0x0,
+0x0,
+0x0,
+0x49,
+0x4e,
+0x54,
+0x4c,
+0x23,
+0x8,
+0x13,
+0x20,
+0x10,
+0x42,
+0x5,
+0x5c,
+0x0,
+0x8,
+0x50,
+0x30,
+0x53,
+0x5f,
+0xc,
+0x78,
+0x56,
+0x34,
+0x12,
+0x8,
+0x50,
+0x30,
+0x45,
+0x5f,
+0xc,
+0x78,
+0x56,
+0x34,
+0x12,
+0x8,
+0x50,
+0x31,
+0x56,
+0x5f,
+0xa,
+0x12,
+0x8,
+0x50,
+0x31,
+0x53,
+0x5f,
+0x11,
+0xb,
+0xa,
+0x8,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x8,
+0x50,
+0x31,
+0x45,
+0x5f,
+0x11,
+0xb,
+0xa,
+0x8,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x8,
+0x50,
+0x31,
+0x4c,
+0x5f,
+0x11,
+0xb,
+0xa,
+0x8,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x10,
+0x29,
+0x5c,
+0x0,
+0x8,
+0x5f,
+0x53,
+0x33,
+0x5f,
+0x12,
+0x6,
+0x4,
+0x1,
+0x1,
+0x0,
+0x0,
+0x8,
+0x5f,
+0x53,
+0x34,
+0x5f,
+0x12,
+0x8,
+0x4,
+0xa,
+0x2,
+0xa,
+0x2,
+0x0,
+0x0,
+0x8,
+0x5f,
+0x53,
+0x35,
+0x5f,
+0x12,
+0x6,
+0x4,
+0x0,
+0x0,
+0x0,
+0x0,
+0x10,
+0x40,
+0xc,
+0x5c,
+0x2f,
+0x3,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x49,
+0x53,
+0x41,
+0x5f,
+0x5b,
+0x82,
+0x4d,
+0xa,
+0x50,
+0x45,
+0x56,
+0x54,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xd,
+0x51,
+0x45,
+0x4d,
+0x55,
+0x30,
+0x30,
+0x30,
+0x31,
+0x0,
+0x8,
+0x50,
+0x45,
+0x53,
+0x54,
+0xb,
+0xff,
+0xff,
+0x5b,
+0x80,
+0x50,
+0x45,
+0x4f,
+0x52,
+0x1,
+0x50,
+0x45,
+0x53,
+0x54,
+0x1,
+0x5b,
+0x81,
+0xb,
+0x50,
+0x45,
+0x4f,
+0x52,
+0x1,
+0x50,
+0x45,
+0x50,
+0x54,
+0x8,
+0x14,
+0x18,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0x70,
+0x50,
+0x45,
+0x53,
+0x54,
+0x60,
+0xa0,
+0x6,
+0x93,
+0x60,
+0x0,
+0xa4,
+0x0,
+0xa1,
+0x4,
+0xa4,
+0xa,
+0xf,
+0x14,
+0xe,
+0x52,
+0x44,
+0x50,
+0x54,
+0x0,
+0x70,
+0x50,
+0x45,
+0x50,
+0x54,
+0x60,
+0xa4,
+0x60,
+0x14,
+0xc,
+0x57,
+0x52,
+0x50,
+0x54,
+0x1,
+0x70,
+0x68,
+0x50,
+0x45,
+0x50,
+0x54,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xd,
+0xa,
+0xa,
+0x47,
+0x1,
+0x0,
+0x0,
+0x0,
+0x0,
+0x1,
+0x1,
+0x79,
+0x0,
+0x8b,
+0x5f,
+0x43,
+0x52,
+0x53,
+0xa,
+0x2,
+0x49,
+0x4f,
+0x4d,
+0x4e,
+0x8b,
+0x5f,
+0x43,
+0x52,
+0x53,
+0xa,
+0x4,
+0x49,
+0x4f,
+0x4d,
+0x58,
+0x14,
+0x18,
+0x5f,
+0x49,
+0x4e,
+0x49,
+0x0,
+0x70,
+0x50,
+0x45,
+0x53,
+0x54,
+0x49,
+0x4f,
+0x4d,
+0x4e,
+0x70,
+0x50,
+0x45,
+0x53,
+0x54,
+0x49,
+0x4f,
+0x4d,
+0x58
+};
+static unsigned char ssdt_isa_pest[] = {
+0xd0
+};
+static unsigned char acpi_s4_name[] = {
+0x88
+};
+static unsigned char acpi_pci64_start[] = {
+0x4d
+};
+static unsigned char acpi_pci64_end[] = {
+0x5e
+};
+static unsigned char acpi_pci32_end[] = {
+0x39
+};
diff --git a/hw/i386/ssdt-pcihp.dsl b/hw/i386/ssdt-pcihp.dsl
new file mode 100644
index 0000000..d29a5b9
--- /dev/null
+++ b/hw/i386/ssdt-pcihp.dsl
@@ -0,0 +1,51 @@
+/*
+ * 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/>.
+ */
+
+ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml
+
+DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
+{
+
+/****************************************************************
+ * PCI hotplug
+ ****************************************************************/
+
+    /* Objects supplied by DSDT */
+    External(\_SB.PCI0, DeviceObj)
+    External(\_SB.PCI0.PCEJ, MethodObj)
+
+    Scope(\_SB.PCI0) {
+
+        /* Bulk generated PCI hotplug devices */
+        ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start
+        ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
+        ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
+
+        // Method _EJ0 can be patched by BIOS to EJ0_
+        // at runtime, if the slot is detected to not support hotplug.
+        // Extract the offset of the address dword and the
+        // _EJ0 name to allow this patching.
+        Device(SAA) {
+            ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
+            Name(_SUN, 0xAA)
+            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
+            Name(_ADR, 0xAA0000)
+            ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
+            Method(_EJ0, 1) {
+                Return (PCEJ(_SUN))
+            }
+        }
+    }
+}
diff --git a/hw/i386/ssdt-pcihp.hex.generated b/hw/i386/ssdt-pcihp.hex.generated
new file mode 100644
index 0000000..b3c2cd5
--- /dev/null
+++ b/hw/i386/ssdt-pcihp.hex.generated
@@ -0,0 +1,108 @@
+static unsigned char ssdt_pcihp_name[] = {
+0x33
+};
+static unsigned char ssdt_pcihp_adr[] = {
+0x44
+};
+static unsigned char ssdt_pcihp_end[] = {
+0x58
+};
+static unsigned char ssdp_pcihp_aml[] = {
+0x53,
+0x53,
+0x44,
+0x54,
+0x58,
+0x0,
+0x0,
+0x0,
+0x1,
+0x76,
+0x42,
+0x58,
+0x50,
+0x43,
+0x0,
+0x0,
+0x42,
+0x58,
+0x53,
+0x53,
+0x44,
+0x54,
+0x50,
+0x43,
+0x1,
+0x0,
+0x0,
+0x0,
+0x49,
+0x4e,
+0x54,
+0x4c,
+0x23,
+0x8,
+0x13,
+0x20,
+0x10,
+0x33,
+0x5c,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x82,
+0x26,
+0x53,
+0x41,
+0x41,
+0x5f,
+0x8,
+0x5f,
+0x53,
+0x55,
+0x4e,
+0xa,
+0xaa,
+0x8,
+0x5f,
+0x41,
+0x44,
+0x52,
+0xc,
+0x0,
+0x0,
+0xaa,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x45,
+0x4a,
+0x30,
+0x1,
+0xa4,
+0x50,
+0x43,
+0x45,
+0x4a,
+0x5f,
+0x53,
+0x55,
+0x4e
+};
+static unsigned char ssdt_pcihp_start[] = {
+0x30
+};
+static unsigned char ssdt_pcihp_id[] = {
+0x3d
+};
+static unsigned char ssdt_pcihp_ej0[] = {
+0x4a
+};
diff --git a/hw/i386/ssdt-proc.dsl b/hw/i386/ssdt-proc.dsl
new file mode 100644
index 0000000..8229bfd
--- /dev/null
+++ b/hw/i386/ssdt-proc.dsl
@@ -0,0 +1,63 @@
+/*
+ * 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/>.
+ */
+
+/* This file is the basis for the ssdt table generated in src/acpi.c.
+ * It defines the contents of the per-cpu Processor() object.  At
+ * runtime, a dynamically generated SSDT will contain one copy of this
+ * AML snippet for every possible cpu in the system.  The objects will
+ * be placed in the \_SB_ namespace.
+ *
+ * In addition to the aml code generated from this file, the
+ * src/acpi.c file creates a NTFY method with an entry for each cpu:
+ *     Method(NTFY, 2) {
+ *         If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) }
+ *         If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) }
+ *         ...
+ *     }
+ * and a CPON array with the list of active and inactive cpus:
+ *     Name(CPON, Package() { One, One, ..., Zero, Zero, ... })
+ */
+
+ACPI_EXTRACT_ALL_CODE ssdp_proc_aml
+
+DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1)
+{
+    ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start
+    ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end
+    ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name
+    Processor(CPAA, 0xAA, 0x00000000, 0x0) {
+        ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id
+        Name(ID, 0xAA)
+/*
+ * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update
+ * CPAA and 0xAA with the appropriate CPU id (see
+ * SD_OFFSET_CPUHEX/CPUID1/CPUID2).  Don't change the above without
+ * also updating the C code.
+ */
+        Name(_HID, "ACPI0007")
+        External(CPMA, MethodObj)
+        External(CPST, MethodObj)
+        External(CPEJ, MethodObj)
+        Method(_MAT, 0) {
+            Return (CPMA(ID))
+        }
+        Method(_STA, 0) {
+            Return (CPST(ID))
+        }
+        Method(_EJ0, 1, NotSerialized) {
+            CPEJ(ID, Arg0)
+        }
+    }
+}
diff --git a/hw/i386/ssdt-proc.hex.generated b/hw/i386/ssdt-proc.hex.generated
new file mode 100644
index 0000000..bb9920d
--- /dev/null
+++ b/hw/i386/ssdt-proc.hex.generated
@@ -0,0 +1,134 @@
+static unsigned char ssdt_proc_name[] = {
+0x28
+};
+static unsigned char ssdp_proc_aml[] = {
+0x53,
+0x53,
+0x44,
+0x54,
+0x78,
+0x0,
+0x0,
+0x0,
+0x1,
+0xb8,
+0x42,
+0x58,
+0x50,
+0x43,
+0x0,
+0x0,
+0x42,
+0x58,
+0x53,
+0x53,
+0x44,
+0x54,
+0x0,
+0x0,
+0x1,
+0x0,
+0x0,
+0x0,
+0x49,
+0x4e,
+0x54,
+0x4c,
+0x23,
+0x8,
+0x13,
+0x20,
+0x5b,
+0x83,
+0x42,
+0x5,
+0x43,
+0x50,
+0x41,
+0x41,
+0xaa,
+0x10,
+0xb0,
+0x0,
+0x0,
+0x0,
+0x8,
+0x49,
+0x44,
+0x5f,
+0x5f,
+0xa,
+0xaa,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xd,
+0x41,
+0x43,
+0x50,
+0x49,
+0x30,
+0x30,
+0x30,
+0x37,
+0x0,
+0x14,
+0xf,
+0x5f,
+0x4d,
+0x41,
+0x54,
+0x0,
+0xa4,
+0x43,
+0x50,
+0x4d,
+0x41,
+0x49,
+0x44,
+0x5f,
+0x5f,
+0x14,
+0xf,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa4,
+0x43,
+0x50,
+0x53,
+0x54,
+0x49,
+0x44,
+0x5f,
+0x5f,
+0x14,
+0xf,
+0x5f,
+0x45,
+0x4a,
+0x30,
+0x1,
+0x43,
+0x50,
+0x45,
+0x4a,
+0x49,
+0x44,
+0x5f,
+0x5f,
+0x68
+};
+static unsigned char ssdt_proc_id[] = {
+0x38
+};
+static unsigned char ssdt_proc_end[] = {
+0x78
+};
+static unsigned char ssdt_proc_start[] = {
+0x24
+};
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index a8be62c..fbea9e8 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -961,7 +961,8 @@
         /* We're ready to process the command in FIS byte 2. */
         ide_exec_cmd(&s->dev[port].port, cmd_fis[2]);
 
-        if (s->dev[port].port.ifs[0].status & READY_STAT) {
+        if ((s->dev[port].port.ifs[0].status & (READY_STAT|DRQ_STAT|BUSY_STAT)) ==
+            READY_STAT) {
             ahci_write_fis_d2h(&s->dev[port], cmd_fis);
         }
     }
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 05e60b1..f7d2009 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -437,7 +437,7 @@
                 cpu_to_ube32(buf + 16, total_sectors - 1); /* l0 end sector */
 
                 /* Size of buffer, not including 2 byte size field */
-                cpu_to_be16wu((uint16_t *)buf, 2048 + 2);
+                stw_be_p(buf, 2048 + 2);
 
                 /* 2k data + 4 byte header */
                 return (2048 + 4);
@@ -448,7 +448,7 @@
             buf[5] = 0; /* no region restrictions */
 
             /* Size of buffer, not including 2 byte size field */
-            cpu_to_be16wu((uint16_t *)buf, 4 + 2);
+            stw_be_p(buf, 4 + 2);
 
             /* 4 byte header + 4 byte data */
             return (4 + 4);
@@ -458,7 +458,7 @@
 
         case 0x04: /* DVD disc manufacturing information */
             /* Size of buffer, not including 2 byte size field */
-            cpu_to_be16wu((uint16_t *)buf, 2048 + 2);
+            stw_be_p(buf, 2048 + 2);
 
             /* 2k data + 4 byte header */
             return (2048 + 4);
@@ -471,22 +471,22 @@
 
             buf[4] = 0x00; /* Physical format */
             buf[5] = 0x40; /* Not writable, is readable */
-            cpu_to_be16wu((uint16_t *)(buf + 6), 2048 + 4);
+            stw_be_p(buf + 6, 2048 + 4);
 
             buf[8] = 0x01; /* Copyright info */
             buf[9] = 0x40; /* Not writable, is readable */
-            cpu_to_be16wu((uint16_t *)(buf + 10), 4 + 4);
+            stw_be_p(buf + 10, 4 + 4);
 
             buf[12] = 0x03; /* BCA info */
             buf[13] = 0x40; /* Not writable, is readable */
-            cpu_to_be16wu((uint16_t *)(buf + 14), 188 + 4);
+            stw_be_p(buf + 14, 188 + 4);
 
             buf[16] = 0x04; /* Manufacturing info */
             buf[17] = 0x40; /* Not writable, is readable */
-            cpu_to_be16wu((uint16_t *)(buf + 18), 2048 + 4);
+            stw_be_p(buf + 18, 2048 + 4);
 
             /* Size of buffer, not including 2 byte size field */
-            cpu_to_be16wu((uint16_t *)buf, 16 + 2);
+            stw_be_p(buf, 16 + 2);
 
             /* data written + 4 byte header */
             return (16 + 4);
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 0500a7a..a8e35fe 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -230,7 +230,7 @@
                  !(pd->config[MRDMODE] & MRDMODE_BLK_CH0)) ||
         ((pd->config[MRDMODE] & MRDMODE_INTR_CH1) &&
          !(pd->config[MRDMODE] & MRDMODE_BLK_CH1));
-    qemu_set_irq(pd->irq[0], pci_level);
+    pci_set_irq(pd, pci_level);
 }
 
 /* the PCI irq level is the logical OR of the two channels */
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 399b1ba..e1f4c33 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2215,55 +2215,6 @@
     bus->dma = &ide_dma_nop;
 }
 
-/* TODO convert users to qdev and remove */
-void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
-                                    DriveInfo *hd1, qemu_irq irq)
-{
-    int i, trans;
-    DriveInfo *dinfo;
-    uint32_t cyls, heads, secs;
-
-    for(i = 0; i < 2; i++) {
-        dinfo = i == 0 ? hd0 : hd1;
-        ide_init1(bus, i);
-        if (dinfo) {
-            cyls  = dinfo->cyls;
-            heads = dinfo->heads;
-            secs  = dinfo->secs;
-            trans = dinfo->trans;
-            if (!cyls && !heads && !secs) {
-                hd_geometry_guess(dinfo->bdrv, &cyls, &heads, &secs, &trans);
-            } else if (trans == BIOS_ATA_TRANSLATION_AUTO) {
-                trans = hd_bios_chs_auto_trans(cyls, heads, secs);
-            }
-            if (cyls < 1 || cyls > 65535) {
-                error_report("cyls must be between 1 and 65535");
-                exit(1);
-            }
-            if (heads < 1 || heads > 16) {
-                error_report("heads must be between 1 and 16");
-                exit(1);
-            }
-            if (secs < 1 || secs > 255) {
-                error_report("secs must be between 1 and 255");
-                exit(1);
-            }
-            if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
-                               dinfo->media_cd ? IDE_CD : IDE_HD,
-                               NULL, dinfo->serial, NULL, 0,
-                               cyls, heads, secs, trans) < 0) {
-                error_report("Can't set up IDE drive %s", dinfo->id);
-                exit(1);
-            }
-            bdrv_attach_dev_nofail(dinfo->bdrv, &bus->ifs[i]);
-        } else {
-            ide_reset(&bus->ifs[i]);
-        }
-    }
-    bus->irq = irq;
-    bus->dma = &ide_dma_nop;
-}
-
 static const MemoryRegionPortio ide_portio_list[] = {
     { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
     { 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew },
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index bff952b..1c7c058 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -116,7 +116,7 @@
     dev->config[0x90]   = 1 << 6; /* Address Map Register - AHCI mode */
 
     msi_init(dev, 0x50, 1, true, false);
-    d->ahci.irq = dev->irq[0];
+    d->ahci.irq = pci_allocate_irq(dev);
 
     pci_register_bar(dev, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
                      &d->ahci.idp);
@@ -145,6 +145,7 @@
 
     msi_uninit(dev);
     ahci_uninit(&d->ahci);
+    qemu_free_irq(d->ahci.irq);
 }
 
 static void ich_ahci_class_init(ObjectClass *klass, void *data)
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 5d1cf87..0567a52 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -553,8 +553,6 @@
                    uint32_t cylinders, uint32_t heads, uint32_t secs,
                    int chs_trans);
 void ide_init2(IDEBus *bus, qemu_irq irq);
-void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
-                                    DriveInfo *hd1, qemu_irq irq);
 void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
 
 void ide_exec_cmd(IDEBus *bus, uint32_t val);
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index 92c1df0..21d6495 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -30,15 +30,22 @@
 
 #include <hw/ide/internal.h>
 
+#define TYPE_MICRODRIVE "microdrive"
+#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE)
+
 /***********************************************************/
 /* CF-ATA Microdrive */
 
 #define METADATA_SIZE	0x20
 
 /* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.  */
-typedef struct {
+
+typedef struct MicroDriveState {
+    /*< private >*/
+    PCMCIACardState parent_obj;
+    /*< public >*/
+
     IDEBus bus;
-    PCMCIACardState card;
     uint32_t attr_base;
     uint32_t io_base;
 
@@ -81,10 +88,13 @@
 
 static inline void md_interrupt_update(MicroDriveState *s)
 {
-    if (!s->card.slot)
-        return;
+    PCMCIACardState *card = PCMCIA_CARD(s);
 
-    qemu_set_irq(s->card.slot->irq,
+    if (card->slot == NULL) {
+        return;
+    }
+
+    qemu_set_irq(card->slot->irq,
                     !(s->stat & STAT_INT) &&	/* Inverted */
                     !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
                     !(s->opt & OPT_SRESET));
@@ -93,16 +103,20 @@
 static void md_set_irq(void *opaque, int irq, int level)
 {
     MicroDriveState *s = opaque;
-    if (level)
+
+    if (level) {
         s->stat |= STAT_INT;
-    else
+    } else {
         s->stat &= ~STAT_INT;
+    }
 
     md_interrupt_update(s);
 }
 
-static void md_reset(MicroDriveState *s)
+static void md_reset(DeviceState *dev)
 {
+    MicroDriveState *s = MICRODRIVE(dev);
+
     s->opt = OPT_MODE_MMAP;
     s->stat = 0;
     s->pins = 0;
@@ -111,14 +125,17 @@
     ide_bus_reset(&s->bus);
 }
 
-static uint8_t md_attr_read(void *opaque, uint32_t at)
+static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at)
 {
-    MicroDriveState *s = opaque;
+    MicroDriveState *s = MICRODRIVE(card);
+    PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
+
     if (at < s->attr_base) {
-        if (at < s->card.cis_len)
-            return s->card.cis[at];
-        else
+        if (at < pcc->cis_len) {
+            return pcc->cis[at];
+        } else {
             return 0x00;
+        }
     }
 
     at -= s->attr_base;
@@ -127,10 +144,11 @@
     case 0x00:	/* Configuration Option Register */
         return s->opt;
     case 0x02:	/* Card Configuration Status Register */
-        if (s->ctrl & CTRL_IEN)
+        if (s->ctrl & CTRL_IEN) {
             return s->stat & ~STAT_INT;
-        else
+        } else {
             return s->stat;
+        }
     case 0x04:	/* Pin Replacement Register */
         return (s->pins & PINS_CRDY) | 0x0c;
     case 0x06:	/* Socket and Copy Register */
@@ -144,21 +162,24 @@
     return 0;
 }
 
-static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
+static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
 {
-    MicroDriveState *s = opaque;
+    MicroDriveState *s = MICRODRIVE(card);
+
     at -= s->attr_base;
 
     switch (at) {
     case 0x00:	/* Configuration Option Register */
         s->opt = value & 0xcf;
-        if (value & OPT_SRESET)
-            md_reset(s);
+        if (value & OPT_SRESET) {
+            device_reset(DEVICE(s));
+        }
         md_interrupt_update(s);
         break;
     case 0x02:	/* Card Configuration Status Register */
-        if ((s->stat ^ value) & STAT_PWRDWN)
+        if ((s->stat ^ value) & STAT_PWRDWN) {
             s->pins |= PINS_CRDY;
+        }
         s->stat &= 0x82;
         s->stat |= value & 0x74;
         md_interrupt_update(s);
@@ -175,32 +196,35 @@
     }
 }
 
-static uint16_t md_common_read(void *opaque, uint32_t at)
+static uint16_t md_common_read(PCMCIACardState *card, uint32_t at)
 {
-    MicroDriveState *s = opaque;
+    MicroDriveState *s = MICRODRIVE(card);
     IDEState *ifs;
     uint16_t ret;
     at -= s->io_base;
 
     switch (s->opt & OPT_MODE) {
     case OPT_MODE_MMAP:
-        if ((at & ~0x3ff) == 0x400)
+        if ((at & ~0x3ff) == 0x400) {
             at = 0;
+        }
         break;
     case OPT_MODE_IOMAP16:
         at &= 0xf;
         break;
     case OPT_MODE_IOMAP1:
-        if ((at & ~0xf) == 0x3f0)
+        if ((at & ~0xf) == 0x3f0) {
             at -= 0x3e8;
-        else if ((at & ~0xf) == 0x1f0)
+        } else if ((at & ~0xf) == 0x1f0) {
             at -= 0x1f0;
+        }
         break;
     case OPT_MODE_IOMAP2:
-        if ((at & ~0xf) == 0x370)
+        if ((at & ~0xf) == 0x370) {
             at -= 0x368;
-        else if ((at & ~0xf) == 0x170)
+        } else if ((at & ~0xf) == 0x170) {
             at -= 0x170;
+        }
     }
 
     switch (at) {
@@ -209,9 +233,9 @@
         return ide_data_readw(&s->bus, 0);
 
         /* TODO: 8-bit accesses */
-        if (s->cycle)
+        if (s->cycle) {
             ret = s->io >> 8;
-        else {
+        } else {
             s->io = ide_data_readw(&s->bus, 0);
             ret = s->io & 0xff;
         }
@@ -223,10 +247,11 @@
         return ide_ioport_read(&s->bus, 0x1);
     case 0xe:	/* Alternate Status */
         ifs = idebus_active_if(&s->bus);
-        if (ifs->bs)
+        if (ifs->bs) {
             return ifs->status;
-        else
+        } else {
             return 0;
+        }
     case 0xf:	/* Device Address */
         ifs = idebus_active_if(&s->bus);
         return 0xc2 | ((~ifs->select << 2) & 0x3c);
@@ -237,30 +262,33 @@
     return 0;
 }
 
-static void md_common_write(void *opaque, uint32_t at, uint16_t value)
+static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
 {
-    MicroDriveState *s = opaque;
+    MicroDriveState *s = MICRODRIVE(card);
     at -= s->io_base;
 
     switch (s->opt & OPT_MODE) {
     case OPT_MODE_MMAP:
-        if ((at & ~0x3ff) == 0x400)
+        if ((at & ~0x3ff) == 0x400) {
             at = 0;
+        }
         break;
     case OPT_MODE_IOMAP16:
         at &= 0xf;
         break;
     case OPT_MODE_IOMAP1:
-        if ((at & ~0xf) == 0x3f0)
+        if ((at & ~0xf) == 0x3f0) {
             at -= 0x3e8;
-        else if ((at & ~0xf) == 0x1f0)
+        } else if ((at & ~0xf) == 0x1f0) {
             at -= 0x1f0;
+        }
         break;
     case OPT_MODE_IOMAP2:
-        if ((at & ~0xf) == 0x370)
+        if ((at & ~0xf) == 0x370) {
             at -= 0x368;
-        else if ((at & ~0xf) == 0x170)
+        } else if ((at & ~0xf) == 0x170) {
             at -= 0x170;
+        }
     }
 
     switch (at) {
@@ -270,10 +298,11 @@
         break;
 
         /* TODO: 8-bit accesses */
-        if (s->cycle)
+        if (s->cycle) {
             ide_data_writew(&s->bus, 0, s->io | (value << 8));
-        else
+        } else {
             s->io = value & 0xff;
+        }
         s->cycle = !s->cycle;
         break;
     case 0x9:
@@ -285,8 +314,9 @@
         break;
     case 0xe:	/* Device Control */
         s->ctrl = value;
-        if (value & CTRL_SRST)
-            md_reset(s);
+        if (value & CTRL_SRST) {
+            device_reset(DEVICE(s));
+        }
         md_interrupt_update(s);
         break;
     default:
@@ -501,49 +531,109 @@
     [0x146] = CISTPL_END,	/* Tuple End */
 };
 
-static int dscm1xxxx_attach(void *opaque)
-{
-    MicroDriveState *md = opaque;
-    md->card.attr_read = md_attr_read;
-    md->card.attr_write = md_attr_write;
-    md->card.common_read = md_common_read;
-    md->card.common_write = md_common_write;
-    md->card.io_read = md_common_read;
-    md->card.io_write = md_common_write;
+#define TYPE_DSCM1XXXX "dscm1xxxx"
 
-    md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8);
+static int dscm1xxxx_attach(PCMCIACardState *card)
+{
+    MicroDriveState *md = MICRODRIVE(card);
+    PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
+
+    md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
     md->io_base = 0x0;
 
-    md_reset(md);
+    device_reset(DEVICE(md));
     md_interrupt_update(md);
 
-    md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
+    card->slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
     return 0;
 }
 
-static int dscm1xxxx_detach(void *opaque)
+static int dscm1xxxx_detach(PCMCIACardState *card)
 {
-    MicroDriveState *md = opaque;
-    md_reset(md);
+    MicroDriveState *md = MICRODRIVE(card);
+
+    device_reset(DEVICE(md));
     return 0;
 }
 
-PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
+PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
 {
-    MicroDriveState *md = (MicroDriveState *) g_malloc0(sizeof(MicroDriveState));
-    md->card.state = md;
-    md->card.attach = dscm1xxxx_attach;
-    md->card.detach = dscm1xxxx_detach;
-    md->card.cis = dscm1xxxx_cis;
-    md->card.cis_len = sizeof(dscm1xxxx_cis);
+    MicroDriveState *md;
 
-    ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL,
-                                   qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+    md = MICRODRIVE(object_new(TYPE_DSCM1XXXX));
+    qdev_init_nofail(DEVICE(md));
+
+    if (dinfo != NULL) {
+        ide_create_drive(&md->bus, 0, dinfo);
+    }
     md->bus.ifs[0].drive_kind = IDE_CFATA;
     md->bus.ifs[0].mdata_size = METADATA_SIZE;
     md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(METADATA_SIZE);
 
-    vmstate_register(NULL, -1, &vmstate_microdrive, md);
-
-    return &md->card;
+    return PCMCIA_CARD(md);
 }
+
+static void dscm1xxxx_class_init(ObjectClass *oc, void *data)
+{
+    PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
+
+    pcc->cis = dscm1xxxx_cis;
+    pcc->cis_len = sizeof(dscm1xxxx_cis);
+
+    pcc->attach = dscm1xxxx_attach;
+    pcc->detach = dscm1xxxx_detach;
+}
+
+static const TypeInfo dscm1xxxx_type_info = {
+    .name = TYPE_DSCM1XXXX,
+    .parent = TYPE_MICRODRIVE,
+    .class_init = dscm1xxxx_class_init,
+};
+
+static void microdrive_realize(DeviceState *dev, Error **errp)
+{
+    MicroDriveState *md = MICRODRIVE(dev);
+
+    ide_init2(&md->bus, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+}
+
+static void microdrive_init(Object *obj)
+{
+    MicroDriveState *md = MICRODRIVE(obj);
+
+    ide_bus_new(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1);
+}
+
+static void microdrive_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
+
+    pcc->attr_read = md_attr_read;
+    pcc->attr_write = md_attr_write;
+    pcc->common_read = md_common_read;
+    pcc->common_write = md_common_write;
+    pcc->io_read = md_common_read;
+    pcc->io_write = md_common_write;
+
+    dc->realize = microdrive_realize;
+    dc->reset = md_reset;
+    dc->vmsd = &vmstate_microdrive;
+}
+
+static const TypeInfo microdrive_type_info = {
+    .name = TYPE_MICRODRIVE,
+    .parent = TYPE_PCMCIA_CARD,
+    .instance_size = sizeof(MicroDriveState),
+    .instance_init = microdrive_init,
+    .abstract = true,
+    .class_init = microdrive_class_init,
+};
+
+static void microdrive_register_types(void)
+{
+    type_register_static(&microdrive_type_info);
+    type_register_static(&dscm1xxxx_type_info);
+}
+
+type_init(microdrive_register_types)
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 2851eed..47ac442 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -23,3 +23,4 @@
 obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
 obj-$(CONFIG_SH4) += sh_intc.o
 obj-$(CONFIG_XICS) += xics.o
+obj-$(CONFIG_XICS_KVM) += xics_kvm.o
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index 709b5c2..c765850 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -64,17 +64,17 @@
     .post_load = gic_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_BOOL(enabled, GICState),
-        VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU),
+        VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU),
         VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
                              vmstate_gic_irq_state, gic_irq_state),
         VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
-        VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU),
+        VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU),
         VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
-        VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU),
-        VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU),
-        VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU),
-        VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU),
-        VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU),
+        VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU),
+        VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU),
+        VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU),
+        VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
+        VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -84,9 +84,9 @@
     GICState *s = ARM_GIC_COMMON(dev);
     int num_irq = s->num_irq;
 
-    if (s->num_cpu > NCPU) {
+    if (s->num_cpu > GIC_NCPU) {
         error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
-                   s->num_cpu, NCPU);
+                   s->num_cpu, GIC_NCPU);
         return;
     }
     s->num_irq += GIC_BASE_IRQ;
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 1426437..3989fd1 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -21,16 +21,9 @@
 #ifndef QEMU_ARM_GIC_INTERNAL_H
 #define QEMU_ARM_GIC_INTERNAL_H
 
-#include "hw/sysbus.h"
+#include "hw/intc/arm_gic.h"
 
-/* Maximum number of possible interrupts, determined by the GIC architecture */
-#define GIC_MAXIRQ 1020
-/* First 32 are private to each CPU (SGIs and PPIs). */
-#define GIC_INTERNAL 32
-/* Maximum number of possible CPU interfaces, determined by GIC architecture */
-#define NCPU 8
-
-#define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1)))
+#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
 
 /* The NVIC has 16 internal vectors.  However these are not exposed
    through the normal GIC interface.  */
@@ -59,48 +52,6 @@
                                     s->priority2[(irq) - GIC_INTERNAL])
 #define GIC_TARGET(irq) s->irq_target[irq]
 
-typedef struct gic_irq_state {
-    /* The enable bits are only banked for per-cpu interrupts.  */
-    uint8_t enabled;
-    uint8_t pending;
-    uint8_t active;
-    uint8_t level;
-    bool model; /* 0 = N:N, 1 = 1:N */
-    bool trigger; /* nonzero = edge triggered.  */
-} gic_irq_state;
-
-typedef struct GICState {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    qemu_irq parent_irq[NCPU];
-    bool enabled;
-    bool cpu_enabled[NCPU];
-
-    gic_irq_state irq_state[GIC_MAXIRQ];
-    uint8_t irq_target[GIC_MAXIRQ];
-    uint8_t priority1[GIC_INTERNAL][NCPU];
-    uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
-    uint16_t last_active[GIC_MAXIRQ][NCPU];
-
-    uint16_t priority_mask[NCPU];
-    uint16_t running_irq[NCPU];
-    uint16_t running_priority[NCPU];
-    uint16_t current_pending[NCPU];
-
-    uint32_t num_cpu;
-
-    MemoryRegion iomem; /* Distributor */
-    /* This is just so we can have an opaque pointer which identifies
-     * both this GIC and which CPU interface we should be accessing.
-     */
-    struct GICState *backref[NCPU];
-    MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
-    uint32_t num_irq;
-    uint32_t revision;
-} GICState;
-
 /* The special cases for the revision property: */
 #define REV_11MPCORE 0
 #define REV_NVIC 0xffffffff
@@ -111,31 +62,4 @@
 void gic_update(GICState *s);
 void gic_init_irqs_and_distributor(GICState *s, int num_irq);
 
-#define TYPE_ARM_GIC_COMMON "arm_gic_common"
-#define ARM_GIC_COMMON(obj) \
-     OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
-#define ARM_GIC_COMMON_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
-#define ARM_GIC_COMMON_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
-
-typedef struct ARMGICCommonClass {
-    SysBusDeviceClass parent_class;
-    void (*pre_save)(GICState *s);
-    void (*post_load)(GICState *s);
-} ARMGICCommonClass;
-
-#define TYPE_ARM_GIC "arm_gic"
-#define ARM_GIC(obj) \
-     OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
-#define ARM_GIC_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
-#define ARM_GIC_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
-
-typedef struct ARMGICClass {
-    ARMGICCommonClass parent_class;
-    DeviceRealize parent_realize;
-} ARMGICClass;
-
 #endif /* !QEMU_ARM_GIC_INTERNAL_H */
diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c
index ce80447..6c81296 100644
--- a/hw/intc/realview_gic.c
+++ b/hw/intc/realview_gic.c
@@ -7,41 +7,34 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw/sysbus.h"
-
-#define TYPE_REALVIEW_GIC "realview_gic"
-#define REALVIEW_GIC(obj) \
-    OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC)
-
-typedef struct {
-    SysBusDevice parent_obj;
-
-    DeviceState *gic;
-    MemoryRegion container;
-} RealViewGICState;
+#include "hw/intc/realview_gic.h"
 
 static void realview_gic_set_irq(void *opaque, int irq, int level)
 {
     RealViewGICState *s = (RealViewGICState *)opaque;
-    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+
+    qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
 }
 
-static int realview_gic_init(SysBusDevice *sbd)
+static void realview_gic_realize(DeviceState *dev, Error **errp)
 {
-    DeviceState *dev = DEVICE(sbd);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     RealViewGICState *s = REALVIEW_GIC(dev);
     SysBusDevice *busdev;
+    Error *err = NULL;
     /* The GICs on the RealView boards have a fixed nonconfigurable
      * number of interrupt lines, so we don't need to expose this as
      * a qdev property.
      */
     int numirq = 96;
 
-    s->gic = qdev_create(NULL, "arm_gic");
-    qdev_prop_set_uint32(s->gic, "num-cpu", 1);
-    qdev_prop_set_uint32(s->gic, "num-irq", numirq);
-    qdev_init_nofail(s->gic);
-    busdev = SYS_BUS_DEVICE(s->gic);
+    qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", numirq);
+    object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(&s->gic);
 
     /* Pass through outbound IRQ lines from the GIC */
     sysbus_pass_irq(sbd, busdev);
@@ -49,27 +42,40 @@
     /* Pass through inbound GPIO lines to the GIC */
     qdev_init_gpio_in(dev, realview_gic_set_irq, numirq - 32);
 
-    memory_region_init(&s->container, OBJECT(s),
-                       "realview-gic-container", 0x2000);
     memory_region_add_subregion(&s->container, 0,
                                 sysbus_mmio_get_region(busdev, 1));
     memory_region_add_subregion(&s->container, 0x1000,
                                 sysbus_mmio_get_region(busdev, 0));
-    sysbus_init_mmio(sbd, &s->container);
-    return 0;
 }
 
-static void realview_gic_class_init(ObjectClass *klass, void *data)
+static void realview_gic_init(Object *obj)
 {
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    RealViewGICState *s = REALVIEW_GIC(obj);
+    DeviceState *gicdev;
 
-    sdc->init = realview_gic_init;
+    memory_region_init(&s->container, OBJECT(s),
+                       "realview-gic-container", 0x2000);
+    sysbus_init_mmio(sbd, &s->container);
+
+    object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
+    gicdev = DEVICE(&s->gic);
+    qdev_set_parent_bus(gicdev, sysbus_get_default());
+    qdev_prop_set_uint32(gicdev, "num-cpu", 1);
+}
+
+static void realview_gic_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = realview_gic_realize;
 }
 
 static const TypeInfo realview_gic_info = {
     .name          = TYPE_REALVIEW_GIC,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(RealViewGICState),
+    .instance_init = realview_gic_init,
     .class_init    = realview_gic_class_init,
 };
 
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index bb018d1..a333305 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -27,8 +27,148 @@
 
 #include "hw/hw.h"
 #include "trace.h"
+#include "qemu/timer.h"
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/xics.h"
+#include "qemu/error-report.h"
+#include "qapi/visitor.h"
+
+void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
+{
+    CPUState *cs = CPU(cpu);
+    CPUPPCState *env = &cpu->env;
+    ICPState *ss = &icp->ss[cs->cpu_index];
+    XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
+
+    assert(cs->cpu_index < icp->nr_servers);
+
+    if (info->cpu_setup) {
+        info->cpu_setup(icp, cpu);
+    }
+
+    switch (PPC_INPUT(env)) {
+    case PPC_FLAGS_INPUT_POWER7:
+        ss->output = env->irq_inputs[POWER7_INPUT_INT];
+        break;
+
+    case PPC_FLAGS_INPUT_970:
+        ss->output = env->irq_inputs[PPC970_INPUT_INT];
+        break;
+
+    default:
+        error_report("XICS interrupt controller does not support this CPU "
+                     "bus model");
+        abort();
+    }
+}
+
+/*
+ * XICS Common class - parent for emulated XICS and KVM-XICS
+ */
+static void xics_common_reset(DeviceState *d)
+{
+    XICSState *icp = XICS_COMMON(d);
+    int i;
+
+    for (i = 0; i < icp->nr_servers; i++) {
+        device_reset(DEVICE(&icp->ss[i]));
+    }
+
+    device_reset(DEVICE(icp->ics));
+}
+
+static void xics_prop_get_nr_irqs(Object *obj, Visitor *v,
+                                  void *opaque, const char *name, Error **errp)
+{
+    XICSState *icp = XICS_COMMON(obj);
+    int64_t value = icp->nr_irqs;
+
+    visit_type_int(v, &value, name, errp);
+}
+
+static void xics_prop_set_nr_irqs(Object *obj, Visitor *v,
+                                  void *opaque, const char *name, Error **errp)
+{
+    XICSState *icp = XICS_COMMON(obj);
+    XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
+    Error *error = NULL;
+    int64_t value;
+
+    visit_type_int(v, &value, name, &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
+    if (icp->nr_irqs) {
+        error_setg(errp, "Number of interrupts is already set to %u",
+                   icp->nr_irqs);
+        return;
+    }
+
+    assert(info->set_nr_irqs);
+    assert(icp->ics);
+    info->set_nr_irqs(icp, value, errp);
+}
+
+static void xics_prop_get_nr_servers(Object *obj, Visitor *v,
+                                     void *opaque, const char *name,
+                                     Error **errp)
+{
+    XICSState *icp = XICS_COMMON(obj);
+    int64_t value = icp->nr_servers;
+
+    visit_type_int(v, &value, name, errp);
+}
+
+static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
+                                     void *opaque, const char *name,
+                                     Error **errp)
+{
+    XICSState *icp = XICS_COMMON(obj);
+    XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
+    Error *error = NULL;
+    int64_t value;
+
+    visit_type_int(v, &value, name, &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
+    if (icp->nr_servers) {
+        error_setg(errp, "Number of servers is already set to %u",
+                   icp->nr_servers);
+        return;
+    }
+
+    assert(info->set_nr_servers);
+    info->set_nr_servers(icp, value, errp);
+}
+
+static void xics_common_initfn(Object *obj)
+{
+    object_property_add(obj, "nr_irqs", "int",
+                        xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
+                        NULL, NULL, NULL);
+    object_property_add(obj, "nr_servers", "int",
+                        xics_prop_get_nr_servers, xics_prop_set_nr_servers,
+                        NULL, NULL, NULL);
+}
+
+static void xics_common_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->reset = xics_common_reset;
+}
+
+static const TypeInfo xics_common_info = {
+    .name          = TYPE_XICS_COMMON,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(XICSState),
+    .class_size    = sizeof(XICSStateClass),
+    .instance_init = xics_common_initfn,
+    .class_init    = xics_common_class_init,
+};
 
 /*
  * ICP: Presentation layer
@@ -153,11 +293,35 @@
     }
 }
 
+static void icp_dispatch_pre_save(void *opaque)
+{
+    ICPState *ss = opaque;
+    ICPStateClass *info = ICP_GET_CLASS(ss);
+
+    if (info->pre_save) {
+        info->pre_save(ss);
+    }
+}
+
+static int icp_dispatch_post_load(void *opaque, int version_id)
+{
+    ICPState *ss = opaque;
+    ICPStateClass *info = ICP_GET_CLASS(ss);
+
+    if (info->post_load) {
+        return info->post_load(ss, version_id);
+    }
+
+    return 0;
+}
+
 static const VMStateDescription vmstate_icp_server = {
     .name = "icp/server",
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
+    .pre_save = icp_dispatch_pre_save,
+    .post_load = icp_dispatch_post_load,
     .fields      = (VMStateField []) {
         /* Sanity check */
         VMSTATE_UINT32(xirr, ICPState),
@@ -187,11 +351,12 @@
     dc->vmsd = &vmstate_icp_server;
 }
 
-static TypeInfo icp_info = {
+static const TypeInfo icp_info = {
     .name = TYPE_ICP,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(ICPState),
     .class_init = icp_class_init,
+    .class_size = sizeof(ICPStateClass),
 };
 
 /*
@@ -353,10 +518,9 @@
     }
 }
 
-static int ics_post_load(void *opaque, int version_id)
+static int ics_post_load(ICSState *ics, int version_id)
 {
     int i;
-    ICSState *ics = opaque;
 
     for (i = 0; i < ics->icp->nr_servers; i++) {
         icp_resend(ics->icp, i);
@@ -365,6 +529,28 @@
     return 0;
 }
 
+static void ics_dispatch_pre_save(void *opaque)
+{
+    ICSState *ics = opaque;
+    ICSStateClass *info = ICS_GET_CLASS(ics);
+
+    if (info->pre_save) {
+        info->pre_save(ics);
+    }
+}
+
+static int ics_dispatch_post_load(void *opaque, int version_id)
+{
+    ICSState *ics = opaque;
+    ICSStateClass *info = ICS_GET_CLASS(ics);
+
+    if (info->post_load) {
+        return info->post_load(ics, version_id);
+    }
+
+    return 0;
+}
+
 static const VMStateDescription vmstate_ics_irq = {
     .name = "ics/irq",
     .version_id = 1,
@@ -384,7 +570,8 @@
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
-    .post_load = ics_post_load,
+    .pre_save = ics_dispatch_pre_save,
+    .post_load = ics_dispatch_post_load,
     .fields      = (VMStateField []) {
         /* Sanity check */
         VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
@@ -395,31 +582,44 @@
     },
 };
 
-static int ics_realize(DeviceState *dev)
+static void ics_initfn(Object *obj)
+{
+    ICSState *ics = ICS(obj);
+
+    ics->offset = XICS_IRQ_BASE;
+}
+
+static void ics_realize(DeviceState *dev, Error **errp)
 {
     ICSState *ics = ICS(dev);
 
+    if (!ics->nr_irqs) {
+        error_setg(errp, "Number of interrupts needs to be greater 0");
+        return;
+    }
     ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
     ics->islsi = g_malloc0(ics->nr_irqs * sizeof(bool));
     ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
-
-    return 0;
 }
 
 static void ics_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    ICSStateClass *isc = ICS_CLASS(klass);
 
-    dc->init = ics_realize;
+    dc->realize = ics_realize;
     dc->vmsd = &vmstate_ics;
     dc->reset = ics_reset;
+    isc->post_load = ics_post_load;
 }
 
-static TypeInfo ics_info = {
+static const TypeInfo ics_info = {
     .name = TYPE_ICS,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(ICSState),
     .class_init = ics_class_init,
+    .class_size = sizeof(ICSStateClass),
+    .instance_init = ics_initfn,
 };
 
 /*
@@ -480,6 +680,18 @@
     return H_SUCCESS;
 }
 
+static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                             target_ulong opcode, target_ulong *args)
+{
+    CPUState *cs = CPU(cpu);
+    ICPState *ss = &spapr->icp->ss[cs->cpu_index];
+    uint32_t xirr = icp_accept(ss);
+
+    args[0] = xirr;
+    args[1] = cpu_get_real_ticks();
+    return H_SUCCESS;
+}
+
 static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                           target_ulong opcode, target_ulong *args)
 {
@@ -490,6 +702,18 @@
     return H_SUCCESS;
 }
 
+static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                            target_ulong opcode, target_ulong *args)
+{
+    CPUState *cs = CPU(cpu);
+    ICPState *ss = &spapr->icp->ss[cs->cpu_index];
+
+    args[0] = ss->xirr;
+    args[1] = ss->mfrr;
+
+    return H_SUCCESS;
+}
+
 static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                           uint32_t token,
                           uint32_t nargs, target_ulong args,
@@ -600,48 +824,39 @@
  * XICS
  */
 
-static void xics_reset(DeviceState *d)
+static void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp)
 {
-    XICSState *icp = XICS(d);
-    int i;
-
-    for (i = 0; i < icp->nr_servers; i++) {
-        device_reset(DEVICE(&icp->ss[i]));
-    }
-
-    device_reset(DEVICE(icp->ics));
+    icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
 }
 
-void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
+static void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers,
+                                Error **errp)
 {
-    CPUState *cs = CPU(cpu);
-    CPUPPCState *env = &cpu->env;
-    ICPState *ss = &icp->ss[cs->cpu_index];
+    int i;
 
-    assert(cs->cpu_index < icp->nr_servers);
+    icp->nr_servers = nr_servers;
 
-    switch (PPC_INPUT(env)) {
-    case PPC_FLAGS_INPUT_POWER7:
-        ss->output = env->irq_inputs[POWER7_INPUT_INT];
-        break;
-
-    case PPC_FLAGS_INPUT_970:
-        ss->output = env->irq_inputs[PPC970_INPUT_INT];
-        break;
-
-    default:
-        fprintf(stderr, "XICS interrupt controller does not support this CPU "
-                "bus model\n");
-        abort();
+    icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
+    for (i = 0; i < icp->nr_servers; i++) {
+        char buffer[32];
+        object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_ICP);
+        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
+        object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
+                                  errp);
     }
 }
 
 static void xics_realize(DeviceState *dev, Error **errp)
 {
     XICSState *icp = XICS(dev);
-    ICSState *ics = icp->ics;
+    Error *error = NULL;
     int i;
 
+    if (!icp->nr_servers) {
+        error_setg(errp, "Number of servers needs to be greater 0");
+        return;
+    }
+
     /* Registration of global state belongs into realize */
     spapr_rtas_register("ibm,set-xive", rtas_set_xive);
     spapr_rtas_register("ibm,get-xive", rtas_get_xive);
@@ -651,20 +866,22 @@
     spapr_register_hypercall(H_CPPR, h_cppr);
     spapr_register_hypercall(H_IPI, h_ipi);
     spapr_register_hypercall(H_XIRR, h_xirr);
+    spapr_register_hypercall(H_XIRR_X, h_xirr_x);
     spapr_register_hypercall(H_EOI, h_eoi);
+    spapr_register_hypercall(H_IPOLL, h_ipoll);
 
-    ics->nr_irqs = icp->nr_irqs;
-    ics->offset = XICS_IRQ_BASE;
-    ics->icp = icp;
-    qdev_init_nofail(DEVICE(ics));
+    object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
 
-    icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
     for (i = 0; i < icp->nr_servers; i++) {
-        char buffer[32];
-        object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_ICP);
-        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
-        object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]), NULL);
-        qdev_init_nofail(DEVICE(&icp->ss[i]));
+        object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
+        if (error) {
+            error_propagate(errp, error);
+            return;
+        }
     }
 }
 
@@ -674,33 +891,31 @@
 
     xics->ics = ICS(object_new(TYPE_ICS));
     object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
+    xics->ics->icp = xics;
 }
 
-static Property xics_properties[] = {
-    DEFINE_PROP_UINT32("nr_servers", XICSState, nr_servers, -1),
-    DEFINE_PROP_UINT32("nr_irqs", XICSState, nr_irqs, -1),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
 static void xics_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
+    XICSStateClass *xsc = XICS_CLASS(oc);
 
     dc->realize = xics_realize;
-    dc->props = xics_properties;
-    dc->reset = xics_reset;
+    xsc->set_nr_irqs = xics_set_nr_irqs;
+    xsc->set_nr_servers = xics_set_nr_servers;
 }
 
 static const TypeInfo xics_info = {
     .name          = TYPE_XICS,
-    .parent        = TYPE_SYS_BUS_DEVICE,
+    .parent        = TYPE_XICS_COMMON,
     .instance_size = sizeof(XICSState),
+    .class_size = sizeof(XICSStateClass),
     .class_init    = xics_class_init,
     .instance_init = xics_initfn,
 };
 
 static void xics_register_types(void)
 {
+    type_register_static(&xics_common_info);
     type_register_static(&xics_info);
     type_register_static(&ics_info);
     type_register_static(&icp_info);
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
new file mode 100644
index 0000000..c203646
--- /dev/null
+++ b/hw/intc/xics_kvm.c
@@ -0,0 +1,494 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics, in-kernel emulation
+ *
+ * Copyright (c) 2013 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "hw/hw.h"
+#include "trace.h"
+#include "hw/ppc/spapr.h"
+#include "hw/ppc/xics.h"
+#include "kvm_ppc.h"
+#include "qemu/config-file.h"
+#include "qemu/error-report.h"
+
+#include <sys/ioctl.h>
+
+typedef struct KVMXICSState {
+    XICSState parent_obj;
+
+    uint32_t set_xive_token;
+    uint32_t get_xive_token;
+    uint32_t int_off_token;
+    uint32_t int_on_token;
+    int kernel_xics_fd;
+} KVMXICSState;
+
+/*
+ * ICP-KVM
+ */
+static void icp_get_kvm_state(ICPState *ss)
+{
+    uint64_t state;
+    struct kvm_one_reg reg = {
+        .id = KVM_REG_PPC_ICP_STATE,
+        .addr = (uintptr_t)&state,
+    };
+    int ret;
+
+    /* ICP for this CPU thread is not in use, exiting */
+    if (!ss->cs) {
+        return;
+    }
+
+    ret = kvm_vcpu_ioctl(ss->cs, KVM_GET_ONE_REG, &reg);
+    if (ret != 0) {
+        error_report("Unable to retrieve KVM interrupt controller state"
+                " for CPU %d: %s", ss->cs->cpu_index, strerror(errno));
+        exit(1);
+    }
+
+    ss->xirr = state >> KVM_REG_PPC_ICP_XISR_SHIFT;
+    ss->mfrr = (state >> KVM_REG_PPC_ICP_MFRR_SHIFT)
+        & KVM_REG_PPC_ICP_MFRR_MASK;
+    ss->pending_priority = (state >> KVM_REG_PPC_ICP_PPRI_SHIFT)
+        & KVM_REG_PPC_ICP_PPRI_MASK;
+}
+
+static int icp_set_kvm_state(ICPState *ss, int version_id)
+{
+    uint64_t state;
+    struct kvm_one_reg reg = {
+        .id = KVM_REG_PPC_ICP_STATE,
+        .addr = (uintptr_t)&state,
+    };
+    int ret;
+
+    /* ICP for this CPU thread is not in use, exiting */
+    if (!ss->cs) {
+        return 0;
+    }
+
+    state = ((uint64_t)ss->xirr << KVM_REG_PPC_ICP_XISR_SHIFT)
+        | ((uint64_t)ss->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT)
+        | ((uint64_t)ss->pending_priority << KVM_REG_PPC_ICP_PPRI_SHIFT);
+
+    ret = kvm_vcpu_ioctl(ss->cs, KVM_SET_ONE_REG, &reg);
+    if (ret != 0) {
+        error_report("Unable to restore KVM interrupt controller state (0x%"
+                PRIx64 ") for CPU %d: %s", state, ss->cs->cpu_index,
+                strerror(errno));
+        return ret;
+    }
+
+    return 0;
+}
+
+static void icp_kvm_reset(DeviceState *dev)
+{
+    ICPState *icp = ICP(dev);
+
+    icp->xirr = 0;
+    icp->pending_priority = 0xff;
+    icp->mfrr = 0xff;
+
+    /* Make all outputs are deasserted */
+    qemu_set_irq(icp->output, 0);
+
+    icp_set_kvm_state(icp, 1);
+}
+
+static void icp_kvm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ICPStateClass *icpc = ICP_CLASS(klass);
+
+    dc->reset = icp_kvm_reset;
+    icpc->pre_save = icp_get_kvm_state;
+    icpc->post_load = icp_set_kvm_state;
+}
+
+static const TypeInfo icp_kvm_info = {
+    .name = TYPE_KVM_ICP,
+    .parent = TYPE_ICP,
+    .instance_size = sizeof(ICPState),
+    .class_init = icp_kvm_class_init,
+    .class_size = sizeof(ICPStateClass),
+};
+
+/*
+ * ICS-KVM
+ */
+static void ics_get_kvm_state(ICSState *ics)
+{
+    KVMXICSState *icpkvm = KVM_XICS(ics->icp);
+    uint64_t state;
+    struct kvm_device_attr attr = {
+        .flags = 0,
+        .group = KVM_DEV_XICS_GRP_SOURCES,
+        .addr = (uint64_t)(uintptr_t)&state,
+    };
+    int i;
+
+    for (i = 0; i < ics->nr_irqs; i++) {
+        ICSIRQState *irq = &ics->irqs[i];
+        int ret;
+
+        attr.attr = i + ics->offset;
+
+        ret = ioctl(icpkvm->kernel_xics_fd, KVM_GET_DEVICE_ATTR, &attr);
+        if (ret != 0) {
+            error_report("Unable to retrieve KVM interrupt controller state"
+                    " for IRQ %d: %s", i + ics->offset, strerror(errno));
+            exit(1);
+        }
+
+        irq->server = state & KVM_XICS_DESTINATION_MASK;
+        irq->saved_priority = (state >> KVM_XICS_PRIORITY_SHIFT)
+            & KVM_XICS_PRIORITY_MASK;
+        /*
+         * To be consistent with the software emulation in xics.c, we
+         * split out the masked state + priority that we get from the
+         * kernel into 'current priority' (0xff if masked) and
+         * 'saved priority' (if masked, this is the priority the
+         * interrupt had before it was masked).  Masking and unmasking
+         * are done with the ibm,int-off and ibm,int-on RTAS calls.
+         */
+        if (state & KVM_XICS_MASKED) {
+            irq->priority = 0xff;
+        } else {
+            irq->priority = irq->saved_priority;
+        }
+
+        if (state & KVM_XICS_PENDING) {
+            if (state & KVM_XICS_LEVEL_SENSITIVE) {
+                irq->status |= XICS_STATUS_ASSERTED;
+            } else {
+                /*
+                 * A pending edge-triggered interrupt (or MSI)
+                 * must have been rejected previously when we
+                 * first detected it and tried to deliver it,
+                 * so mark it as pending and previously rejected
+                 * for consistency with how xics.c works.
+                 */
+                irq->status |= XICS_STATUS_MASKED_PENDING
+                    | XICS_STATUS_REJECTED;
+            }
+        }
+    }
+}
+
+static int ics_set_kvm_state(ICSState *ics, int version_id)
+{
+    KVMXICSState *icpkvm = KVM_XICS(ics->icp);
+    uint64_t state;
+    struct kvm_device_attr attr = {
+        .flags = 0,
+        .group = KVM_DEV_XICS_GRP_SOURCES,
+        .addr = (uint64_t)(uintptr_t)&state,
+    };
+    int i;
+
+    for (i = 0; i < ics->nr_irqs; i++) {
+        ICSIRQState *irq = &ics->irqs[i];
+        int ret;
+
+        attr.attr = i + ics->offset;
+
+        state = irq->server;
+        state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK)
+            << KVM_XICS_PRIORITY_SHIFT;
+        if (irq->priority != irq->saved_priority) {
+            assert(irq->priority == 0xff);
+            state |= KVM_XICS_MASKED;
+        }
+
+        if (ics->islsi[i]) {
+            state |= KVM_XICS_LEVEL_SENSITIVE;
+            if (irq->status & XICS_STATUS_ASSERTED) {
+                state |= KVM_XICS_PENDING;
+            }
+        } else {
+            if (irq->status & XICS_STATUS_MASKED_PENDING) {
+                state |= KVM_XICS_PENDING;
+            }
+        }
+
+        ret = ioctl(icpkvm->kernel_xics_fd, KVM_SET_DEVICE_ATTR, &attr);
+        if (ret != 0) {
+            error_report("Unable to restore KVM interrupt controller state"
+                    " for IRQs %d: %s", i + ics->offset, strerror(errno));
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+static void ics_kvm_set_irq(void *opaque, int srcno, int val)
+{
+    ICSState *ics = opaque;
+    struct kvm_irq_level args;
+    int rc;
+
+    args.irq = srcno + ics->offset;
+    if (!ics->islsi[srcno]) {
+        if (!val) {
+            return;
+        }
+        args.level = KVM_INTERRUPT_SET;
+    } else {
+        args.level = val ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET;
+    }
+    rc = kvm_vm_ioctl(kvm_state, KVM_IRQ_LINE, &args);
+    if (rc < 0) {
+        perror("kvm_irq_line");
+    }
+}
+
+static void ics_kvm_reset(DeviceState *dev)
+{
+    ics_set_kvm_state(ICS(dev), 1);
+}
+
+static void ics_kvm_realize(DeviceState *dev, Error **errp)
+{
+    ICSState *ics = ICS(dev);
+
+    if (!ics->nr_irqs) {
+        error_setg(errp, "Number of interrupts needs to be greater 0");
+        return;
+    }
+    ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
+    ics->islsi = g_malloc0(ics->nr_irqs * sizeof(bool));
+    ics->qirqs = qemu_allocate_irqs(ics_kvm_set_irq, ics, ics->nr_irqs);
+}
+
+static void ics_kvm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ICSStateClass *icsc = ICS_CLASS(klass);
+
+    dc->realize = ics_kvm_realize;
+    dc->reset = ics_kvm_reset;
+    icsc->pre_save = ics_get_kvm_state;
+    icsc->post_load = ics_set_kvm_state;
+}
+
+static const TypeInfo ics_kvm_info = {
+    .name = TYPE_KVM_ICS,
+    .parent = TYPE_ICS,
+    .instance_size = sizeof(ICSState),
+    .class_init = ics_kvm_class_init,
+};
+
+/*
+ * XICS-KVM
+ */
+static void xics_kvm_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
+{
+    CPUState *cs;
+    ICPState *ss;
+    KVMXICSState *icpkvm = KVM_XICS(icp);
+
+    cs = CPU(cpu);
+    ss = &icp->ss[cs->cpu_index];
+
+    assert(cs->cpu_index < icp->nr_servers);
+    if (icpkvm->kernel_xics_fd == -1) {
+        abort();
+    }
+
+    if (icpkvm->kernel_xics_fd != -1) {
+        int ret;
+        struct kvm_enable_cap xics_enable_cap = {
+            .cap = KVM_CAP_IRQ_XICS,
+            .flags = 0,
+            .args = {icpkvm->kernel_xics_fd, cs->cpu_index, 0, 0},
+        };
+
+        ss->cs = cs;
+
+        ret = kvm_vcpu_ioctl(ss->cs, KVM_ENABLE_CAP, &xics_enable_cap);
+        if (ret < 0) {
+            error_report("Unable to connect CPU%d to kernel XICS: %s",
+                    cs->cpu_index, strerror(errno));
+            exit(1);
+        }
+    }
+}
+
+static void xics_kvm_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp)
+{
+    icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
+}
+
+static void xics_kvm_set_nr_servers(XICSState *icp, uint32_t nr_servers,
+                                    Error **errp)
+{
+    int i;
+
+    icp->nr_servers = nr_servers;
+
+    icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
+    for (i = 0; i < icp->nr_servers; i++) {
+        char buffer[32];
+        object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_KVM_ICP);
+        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
+        object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
+                                  errp);
+    }
+}
+
+static void rtas_dummy(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                       uint32_t token,
+                       uint32_t nargs, target_ulong args,
+                       uint32_t nret, target_ulong rets)
+{
+    error_report("pseries: %s must never be called for in-kernel XICS",
+                 __func__);
+}
+
+static void xics_kvm_realize(DeviceState *dev, Error **errp)
+{
+    KVMXICSState *icpkvm = KVM_XICS(dev);
+    XICSState *icp = XICS_COMMON(dev);
+    int i, rc;
+    Error *error = NULL;
+    struct kvm_create_device xics_create_device = {
+        .type = KVM_DEV_TYPE_XICS,
+        .flags = 0,
+    };
+
+    if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_IRQ_XICS)) {
+        error_setg(errp,
+                   "KVM and IRQ_XICS capability must be present for in-kernel XICS");
+        goto fail;
+    }
+
+    icpkvm->set_xive_token = spapr_rtas_register("ibm,set-xive", rtas_dummy);
+    icpkvm->get_xive_token = spapr_rtas_register("ibm,get-xive", rtas_dummy);
+    icpkvm->int_off_token = spapr_rtas_register("ibm,int-off", rtas_dummy);
+    icpkvm->int_on_token = spapr_rtas_register("ibm,int-on", rtas_dummy);
+
+    rc = kvmppc_define_rtas_kernel_token(icpkvm->set_xive_token,
+                                         "ibm,set-xive");
+    if (rc < 0) {
+        error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,set-xive");
+        goto fail;
+    }
+
+    rc = kvmppc_define_rtas_kernel_token(icpkvm->get_xive_token,
+                                         "ibm,get-xive");
+    if (rc < 0) {
+        error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,get-xive");
+        goto fail;
+    }
+
+    rc = kvmppc_define_rtas_kernel_token(icpkvm->int_on_token, "ibm,int-on");
+    if (rc < 0) {
+        error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,int-on");
+        goto fail;
+    }
+
+    rc = kvmppc_define_rtas_kernel_token(icpkvm->int_off_token, "ibm,int-off");
+    if (rc < 0) {
+        error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,int-off");
+        goto fail;
+    }
+
+    /* Create the kernel ICP */
+    rc = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &xics_create_device);
+    if (rc < 0) {
+        error_setg_errno(errp, -rc, "Error on KVM_CREATE_DEVICE for XICS");
+        goto fail;
+    }
+
+    icpkvm->kernel_xics_fd = xics_create_device.fd;
+
+    object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
+    if (error) {
+        error_propagate(errp, error);
+        goto fail;
+    }
+
+    assert(icp->nr_servers);
+    for (i = 0; i < icp->nr_servers; i++) {
+        object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
+        if (error) {
+            error_propagate(errp, error);
+            goto fail;
+        }
+    }
+
+    kvm_kernel_irqchip = true;
+    kvm_irqfds_allowed = true;
+    kvm_msi_via_irqfd_allowed = true;
+    kvm_gsi_direct_mapping = true;
+
+    return;
+
+fail:
+    kvmppc_define_rtas_kernel_token(0, "ibm,set-xive");
+    kvmppc_define_rtas_kernel_token(0, "ibm,get-xive");
+    kvmppc_define_rtas_kernel_token(0, "ibm,int-on");
+    kvmppc_define_rtas_kernel_token(0, "ibm,int-off");
+}
+
+static void xics_kvm_initfn(Object *obj)
+{
+    XICSState *xics = XICS_COMMON(obj);
+
+    xics->ics = ICS(object_new(TYPE_KVM_ICS));
+    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
+    xics->ics->icp = xics;
+}
+
+static void xics_kvm_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    XICSStateClass *xsc = XICS_COMMON_CLASS(oc);
+
+    dc->realize = xics_kvm_realize;
+    xsc->cpu_setup = xics_kvm_cpu_setup;
+    xsc->set_nr_irqs = xics_kvm_set_nr_irqs;
+    xsc->set_nr_servers = xics_kvm_set_nr_servers;
+}
+
+static const TypeInfo xics_kvm_info = {
+    .name          = TYPE_KVM_XICS,
+    .parent        = TYPE_XICS_COMMON,
+    .instance_size = sizeof(KVMXICSState),
+    .class_init    = xics_kvm_class_init,
+    .instance_init = xics_kvm_initfn,
+};
+
+static void xics_kvm_register_types(void)
+{
+    type_register_static(&xics_kvm_info);
+    type_register_static(&ics_kvm_info);
+    type_register_static(&icp_kvm_info);
+}
+
+type_init(xics_kvm_register_types)
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 5633d08..19b2198 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -29,6 +29,7 @@
  */
 #include "qemu-common.h"
 #include "hw/hw.h"
+#include "qapi/visitor.h"
 #include "qemu/range.h"
 #include "hw/isa/isa.h"
 #include "hw/sysbus.h"
@@ -525,6 +526,43 @@
     .endianness = DEVICE_LITTLE_ENDIAN
 };
 
+Object *ich9_lpc_find(void)
+{
+    bool ambig;
+    Object *o = object_resolve_path_type("", TYPE_ICH9_LPC_DEVICE, &ambig);
+
+    if (ambig) {
+        return NULL;
+    }
+    return o;
+}
+
+static void ich9_lpc_get_sci_int(Object *obj, Visitor *v,
+                                 void *opaque, const char *name,
+                                 Error **errp)
+{
+    ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj);
+    uint32_t value = ich9_lpc_sci_irq(lpc);
+
+    visit_type_uint32(v, &value, name, errp);
+}
+
+static void ich9_lpc_add_properties(ICH9LPCState *lpc)
+{
+    static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE;
+    static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE;
+
+    object_property_add(OBJECT(lpc), ACPI_PM_PROP_SCI_INT, "uint32",
+                        ich9_lpc_get_sci_int,
+                        NULL, NULL, NULL, NULL);
+    object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD,
+                                  &acpi_enable_cmd, NULL);
+    object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD,
+                                  &acpi_disable_cmd, NULL);
+
+    ich9_pm_add_properties(OBJECT(lpc), &lpc->pm, NULL);
+}
+
 static int ich9_lpc_initfn(PCIDevice *d)
 {
     ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
@@ -552,6 +590,8 @@
                                         ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
                                         1);
 
+    ich9_lpc_add_properties(lpc);
+
     return 0;
 }
 
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 8fe4fcb..5fb8086 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -185,7 +185,7 @@
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
                    ACPI_BITMASK_TIMER_ENABLE)) != 0);
-    qemu_set_irq(s->dev.irq[0], sci_level);
+    pci_set_irq(&s->dev, sci_level);
     /* schedule a timer interruption if needed */
     acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
                        !(pmsts & ACPI_BITMASK_TIMER_STATUS));
diff --git a/hw/lm32/lm32_hwsetup.h b/hw/lm32/lm32_hwsetup.h
index 3449bd8..9fd5e69 100644
--- a/hw/lm32/lm32_hwsetup.h
+++ b/hw/lm32/lm32_hwsetup.h
@@ -73,7 +73,7 @@
 static inline void hwsetup_create_rom(HWSetup *hw,
         hwaddr base)
 {
-    rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base);
+    rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base, NULL, NULL, NULL);
 }
 
 static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u)
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index f1744ec..15053c4 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -21,6 +21,7 @@
 #include "hw/hw.h"
 #include "hw/block/flash.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
 #include "hw/devices.h"
 #include "hw/boards.h"
 #include "hw/loader.h"
@@ -143,7 +144,7 @@
     reset_info->bootstrap_pc = BIOS_OFFSET;
 
     /* if no kernel is given no valid bios rom is a fatal error */
-    if (!kernel_filename && !dinfo && !bios_filename) {
+    if (!kernel_filename && !dinfo && !bios_filename && !qtest_enabled()) {
         fprintf(stderr, "qemu: could not load Milkymist One bios '%s'\n",
                 bios_name);
         exit(1);
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
index a8eee44..24f2068 100644
--- a/hw/m68k/an5206.c
+++ b/hw/m68k/an5206.c
@@ -12,6 +12,7 @@
 #include "hw/loader.h"
 #include "elf.h"
 #include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
 
 #define KERNEL_LOAD_ADDR 0x10000
 #define AN5206_MBAR_ADDR 0x10000000
@@ -62,6 +63,9 @@
 
     /* Load kernel.  */
     if (!kernel_filename) {
+        if (qtest_enabled()) {
+            return;
+        }
         fprintf(stderr, "Kernel image must be specified\n");
         exit(1);
     }
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index fb96fe8..6e30c0b 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -10,6 +10,7 @@
 #include "qemu/timer.h"
 #include "hw/ptimer.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
 #include "net/net.h"
 #include "hw/boards.h"
 #include "hw/loader.h"
@@ -267,6 +268,9 @@
 
     /* Load kernel.  */
     if (!kernel_filename) {
+        if (qtest_enabled()) {
+            return;
+        }
         fprintf(stderr, "Kernel image must be specified\n");
         exit(1);
     }
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 5b057f7..2a7ea5c 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -26,6 +26,7 @@
 
 #include "qemu/option.h"
 #include "qemu/config-file.h"
+#include "qemu/error-report.h"
 #include "qemu-common.h"
 #include "sysemu/device_tree.h"
 #include "sysemu/sysemu.h"
@@ -39,6 +40,8 @@
     void (*machine_cpu_reset)(MicroBlazeCPU *);
     uint32_t bootstrap_pc;
     uint32_t cmdline;
+    uint32_t initrd_start;
+    uint32_t initrd_end;
     uint32_t fdt;
 } boot_info;
 
@@ -49,6 +52,7 @@
 
     cpu_reset(CPU(cpu));
     env->regs[5] = boot_info.cmdline;
+    env->regs[6] = boot_info.initrd_start;
     env->regs[7] = boot_info.fdt;
     env->sregs[SR_PC] = boot_info.bootstrap_pc;
     if (boot_info.machine_cpu_reset) {
@@ -57,9 +61,11 @@
 }
 
 static int microblaze_load_dtb(hwaddr addr,
-                                      uint32_t ramsize,
-                                      const char *kernel_cmdline,
-                                      const char *dtb_filename)
+                               uint32_t ramsize,
+                               uint32_t initrd_start,
+                               uint32_t initrd_end,
+                               const char *kernel_cmdline,
+                               const char *dtb_filename)
 {
     int fdt_size;
     void *fdt = NULL;
@@ -80,6 +86,14 @@
         }
     }
 
+    if (initrd_start) {
+        qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                  initrd_start);
+
+        qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                                  initrd_end);
+    }
+
     cpu_physical_memory_write(addr, fdt, fdt_size);
     return fdt_size;
 }
@@ -90,7 +104,9 @@
 }
 
 void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
-                            uint32_t ramsize, const char *dtb_filename,
+                            uint32_t ramsize,
+                            const char *initrd_filename,
+                            const char *dtb_filename,
                             void (*machine_cpu_reset)(MicroBlazeCPU *))
 {
     QemuOpts *machine_opts;
@@ -151,14 +167,36 @@
             high = (ddr_base + kernel_size + 3) & ~3;
         }
 
+        if (initrd_filename) {
+            int initrd_size;
+            uint32_t initrd_offset;
+
+            high = ROUND_UP(high + kernel_size, 4);
+            boot_info.initrd_start = high;
+            initrd_offset = boot_info.initrd_start - ddr_base;
+            initrd_size = load_image_targphys(initrd_filename,
+                                              boot_info.initrd_start,
+                                              ram_size - initrd_offset);
+            if (initrd_size < 0) {
+                error_report("qemu: could not load initrd '%s'\n",
+                             initrd_filename);
+                exit(EXIT_FAILURE);
+            }
+            boot_info.initrd_end = boot_info.initrd_start + initrd_size;
+            high = ROUND_UP(high + initrd_size, 4);
+        }
+
         boot_info.cmdline = high + 4096;
         if (kernel_cmdline && strlen(kernel_cmdline)) {
             pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
         }
         /* Provide a device-tree.  */
         boot_info.fdt = boot_info.cmdline + 4096;
-        microblaze_load_dtb(boot_info.fdt, ram_size, kernel_cmdline,
-                                                     dtb_filename);
+        microblaze_load_dtb(boot_info.fdt, ram_size,
+                            boot_info.initrd_start,
+                            boot_info.initrd_end,
+                            kernel_cmdline,
+                            dtb_filename);
     }
 
 }
diff --git a/hw/microblaze/boot.h b/hw/microblaze/boot.h
index b14ef2b..0eb7f8e 100644
--- a/hw/microblaze/boot.h
+++ b/hw/microblaze/boot.h
@@ -4,7 +4,9 @@
 #include "hw/hw.h"
 
 void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
-                            uint32_t ramsize, const char *dtb_filename,
+                            uint32_t ramsize,
+                            const char *initrd_filename,
+                            const char *dtb_filename,
                             void (*machine_cpu_reset)(MicroBlazeCPU *));
 
 #endif /* __MICROBLAZE_BOOT __ */
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index e003c7c..10970e0 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -176,8 +176,10 @@
         }
     }
 
-    microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
-                                                            machine_cpu_reset);
+    microblaze_load_kernel(cpu, ddr_base, ram_size,
+                           args->initrd_filename,
+                           BINARY_DEVICE_TREE_FILE,
+                           machine_cpu_reset);
 
 }
 
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index 00af2b5..ec6489c 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -108,7 +108,9 @@
     xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0);
 
     microblaze_load_kernel(cpu, ddr_base, ram_size,
-                    BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
+                           args->initrd_filename,
+                           BINARY_DEVICE_TREE_FILE,
+                           machine_cpu_reset);
 }
 
 static QEMUMachine petalogix_s3adsp1800_machine = {
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
index 242bab9..239aa6a 100644
--- a/hw/mips/mips_mipssim.c
+++ b/hw/mips/mips_mipssim.c
@@ -38,6 +38,7 @@
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 #include "qemu/error-report.h"
+#include "sysemu/qtest.h"
 
 static struct _loaderparams {
     int ram_size;
@@ -190,7 +191,8 @@
     } else {
         bios_size = -1;
     }
-    if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+    if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
+        !kernel_filename && !qtest_enabled()) {
         /* Bail out if we have neither a kernel image nor boot vector code. */
         error_report("Could not load MIPS bios '%s', and no "
                      "-kernel argument was specified", filename);
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 2578e29..f674365 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -10,6 +10,9 @@
 
 # ARM devices
 common-obj-$(CONFIG_PL310) += arm_l2x0.o
+common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o
+common-obj-$(CONFIG_A9SCU) += a9scu.o
+common-obj-$(CONFIG_ARM11SCU) += arm11scu.o
 
 # PKUnity SoC devices
 common-obj-$(CONFIG_PUV3) += puv3_pm.o
@@ -22,7 +25,6 @@
 endif
 
 obj-$(CONFIG_REALVIEW) += arm_sysctl.o
-obj-$(CONFIG_A9SCU) += a9scu.o
 obj-$(CONFIG_NSERIES) += cbus.o
 obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
@@ -36,7 +38,6 @@
 obj-$(CONFIG_OMAP) += omap_l4.o
 obj-$(CONFIG_OMAP) += omap_sdrc.o
 obj-$(CONFIG_OMAP) += omap_tap.o
-obj-$(CONFIG_PXA2XX) += pxa2xx_pcmcia.o
 obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
index 601b573..4434945 100644
--- a/hw/misc/a9scu.c
+++ b/hw/misc/a9scu.c
@@ -8,20 +8,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw/sysbus.h"
-
-/* A9MP private memory region.  */
-
-typedef struct A9SCUState {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t control;
-    uint32_t status;
-    uint32_t num_cpu;
-} A9SCUState;
-
-#define TYPE_A9_SCU "a9-scu"
-#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
+#include "hw/misc/a9scu.h"
 
 static uint64_t a9_scu_read(void *opaque, hwaddr offset,
                             unsigned size)
@@ -114,12 +101,12 @@
     s->control = 0;
 }
 
-static void a9_scu_realize(DeviceState *dev, Error ** errp)
+static void a9_scu_init(Object *obj)
 {
-    A9SCUState *s = A9_SCU(dev);
-    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    A9SCUState *s = A9_SCU(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
-    memory_region_init_io(&s->iomem, OBJECT(dev), &a9_scu_ops, s,
+    memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
                           "a9-scu", 0x100);
     sysbus_init_mmio(sbd, &s->iomem);
 }
@@ -144,7 +131,6 @@
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->realize = a9_scu_realize;
     dc->props = a9_scu_properties;
     dc->vmsd = &vmstate_a9_scu;
     dc->reset = a9_scu_reset;
@@ -154,6 +140,7 @@
     .name          = TYPE_A9_SCU,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(A9SCUState),
+    .instance_init = a9_scu_init,
     .class_init    = a9_scu_class_init,
 };
 
diff --git a/hw/misc/arm11scu.c b/hw/misc/arm11scu.c
new file mode 100644
index 0000000..a791675
--- /dev/null
+++ b/hw/misc/arm11scu.c
@@ -0,0 +1,100 @@
+/*
+ * ARM11MPCore Snoop Control Unit (SCU) emulation
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2013 SUSE LINUX Products GmbH
+ * Written by Paul Brook and Andreas Färber
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/misc/arm11scu.h"
+
+static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
+                                unsigned size)
+{
+    ARM11SCUState *s = (ARM11SCUState *)opaque;
+    int id;
+    /* SCU */
+    switch (offset) {
+    case 0x00: /* Control.  */
+        return s->control;
+    case 0x04: /* Configuration.  */
+        id = ((1 << s->num_cpu) - 1) << 4;
+        return id | (s->num_cpu - 1);
+    case 0x08: /* CPU status.  */
+        return 0;
+    case 0x0c: /* Invalidate all.  */
+        return 0;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "mpcore_priv_read: Bad offset %x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void mpcore_scu_write(void *opaque, hwaddr offset,
+                             uint64_t value, unsigned size)
+{
+    ARM11SCUState *s = (ARM11SCUState *)opaque;
+    /* SCU */
+    switch (offset) {
+    case 0: /* Control register.  */
+        s->control = value & 1;
+        break;
+    case 0x0c: /* Invalidate all.  */
+        /* This is a no-op as cache is not emulated.  */
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "mpcore_priv_read: Bad offset %x\n", (int)offset);
+    }
+}
+
+static const MemoryRegionOps mpcore_scu_ops = {
+    .read = mpcore_scu_read,
+    .write = mpcore_scu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void arm11_scu_realize(DeviceState *dev, Error **errp)
+{
+}
+
+static void arm11_scu_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    ARM11SCUState *s = ARM11_SCU(obj);
+
+    memory_region_init_io(&s->iomem, OBJECT(s),
+                          &mpcore_scu_ops, s, "mpcore-scu", 0x100);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static Property arm11_scu_properties[] = {
+    DEFINE_PROP_UINT32("num-cpu", ARM11SCUState, num_cpu, 1),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void arm11_scu_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = arm11_scu_realize;
+    dc->props = arm11_scu_properties;
+}
+
+static const TypeInfo arm11_scu_type_info = {
+    .name          = TYPE_ARM11_SCU,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(ARM11SCUState),
+    .instance_init = arm11_scu_init,
+    .class_init    = arm11_scu_class_init,
+};
+
+static void arm11_scu_register_types(void)
+{
+    type_register_static(&arm11_scu_type_info);
+}
+
+type_init(arm11_scu_register_types)
diff --git a/hw/misc/arm_integrator_debug.c b/hw/misc/arm_integrator_debug.c
new file mode 100644
index 0000000..99b720f
--- /dev/null
+++ b/hw/misc/arm_integrator_debug.c
@@ -0,0 +1,99 @@
+/*
+ * LED, Switch and Debug control registers for ARM Integrator Boards
+ *
+ * This is currently a stub for this functionality but at least
+ * ensures something other than unassigned_mem_read() handles access
+ * to this area.
+ *
+ * The real h/w is described at:
+ *  http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0159b/Babbfijf.html
+ *
+ * Copyright (c) 2013 Alex Bennée <alex@bennee.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 "hw/hw.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+#include "hw/misc/arm_integrator_debug.h"
+
+#define INTEGRATOR_DEBUG(obj) \
+    OBJECT_CHECK(IntegratorDebugState, (obj), TYPE_INTEGRATOR_DEBUG)
+
+typedef struct {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+} IntegratorDebugState;
+
+static uint64_t intdbg_control_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    switch (offset >> 2) {
+    case 0: /* ALPHA */
+    case 1: /* LEDS */
+    case 2: /* SWITCHES */
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: returning zero from %" HWADDR_PRIx ":%u\n",
+                      __func__, offset, size);
+        return 0;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset %" HWADDR_PRIx,
+                      __func__, offset);
+        return 0;
+    }
+}
+
+static void intdbg_control_write(void *opaque, hwaddr offset,
+                                 uint64_t value, unsigned size)
+{
+    switch (offset >> 2) {
+    case 1: /* ALPHA */
+    case 2: /* LEDS */
+    case 3: /* SWITCHES */
+        /* Nothing interesting implemented yet.  */
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: ignoring write of %" PRIu64
+                      " to %" HWADDR_PRIx ":%u\n",
+                      __func__, value, offset, size);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: write of %" PRIu64
+                      " to bad offset %" HWADDR_PRIx "\n",
+                      __func__, value, offset);
+    }
+}
+
+static const MemoryRegionOps intdbg_control_ops = {
+    .read = intdbg_control_read,
+    .write = intdbg_control_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void intdbg_control_init(Object *obj)
+{
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    IntegratorDebugState *s = INTEGRATOR_DEBUG(obj);
+
+    memory_region_init_io(&s->iomem, NULL, &intdbg_control_ops,
+                          NULL, "dbg-leds", 0x1000000);
+    sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const TypeInfo intdbg_info = {
+    .name          = TYPE_INTEGRATOR_DEBUG,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(IntegratorDebugState),
+    .instance_init = intdbg_control_init,
+};
+
+static void intdbg_register_types(void)
+{
+    type_register_static(&intdbg_info);
+}
+
+type_init(intdbg_register_types)
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 2838866..8d144ba 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -133,7 +133,7 @@
            isr ? 1 : 0, s->intrstatus, s->intrmask);
     }
 
-    qemu_set_irq(d->irq[0], (isr != 0));
+    pci_set_irq(d, (isr != 0));
 }
 
 static void ivshmem_IntrMask_write(IVShmemState *s, uint32_t val)
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index b64e3bb..226e298 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -117,8 +117,19 @@
     isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE);
 }
 
+#define PVPANIC_IOPORT_PROP "ioport"
+
+uint16_t pvpanic_port(void)
+{
+    Object *o = object_resolve_path_type("", TYPE_ISA_PVPANIC_DEVICE, NULL);
+    if (!o) {
+        return 0;
+    }
+    return object_property_get_int(o, PVPANIC_IOPORT_PROP, NULL);
+}
+
 static Property pvpanic_isa_properties[] = {
-    DEFINE_PROP_UINT16("ioport", PVPanicState, ioport, 0x505),
+    DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index a2d5283..fe95e03 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -302,7 +302,7 @@
             'A' + vdev->intx.pin);
 
     vdev->intx.pending = true;
-    qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 1);
+    pci_irq_assert(&vdev->pdev);
     vfio_mmap_set_enabled(vdev, false);
     if (vdev->intx.mmap_timeout) {
         timer_mod(vdev->intx.mmap_timer,
@@ -320,7 +320,7 @@
             vdev->host.bus, vdev->host.slot, vdev->host.function);
 
     vdev->intx.pending = false;
-    qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
+    pci_irq_deassert(&vdev->pdev);
     vfio_unmask_intx(vdev);
 }
 
@@ -346,7 +346,7 @@
     qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev);
     vfio_mask_intx(vdev);
     vdev->intx.pending = false;
-    qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
+    pci_irq_deassert(&vdev->pdev);
 
     /* Get an eventfd for resample/unmask */
     if (event_notifier_init(&vdev->intx.unmask, 0)) {
@@ -422,7 +422,7 @@
      */
     vfio_mask_intx(vdev);
     vdev->intx.pending = false;
-    qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
+    pci_irq_deassert(&vdev->pdev);
 
     /* Tell KVM to stop listening for an INTx irqfd */
     if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) {
@@ -493,6 +493,7 @@
     vfio_disable_interrupts(vdev);
 
     vdev->intx.pin = pin - 1; /* Pin A (1) -> irq[0] */
+    pci_config_set_interrupt_pin(vdev->pdev.config, pin);
 
 #ifdef CONFIG_KVM
     /*
@@ -552,7 +553,7 @@
     vfio_disable_intx_kvm(vdev);
     vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
     vdev->intx.pending = false;
-    qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
+    pci_irq_deassert(&vdev->pdev);
     vfio_mmap_set_enabled(vdev, true);
 
     fd = event_notifier_get_fd(&vdev->intx.interrupt);
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 70a59fd..ae63591 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -328,7 +328,7 @@
     }
 
     s->mit_irq_level = (pending_ints != 0);
-    qemu_set_irq(d->irq[0], s->mit_irq_level);
+    pci_set_irq(d, s->mit_irq_level);
 }
 
 static void
@@ -528,8 +528,7 @@
         n = cse + 1;
     if (sloc < n-1) {
         sum = net_checksum_add(n-css, data+css);
-        cpu_to_be16wu((uint16_t *)(data + sloc),
-                      net_checksum_finish(sum));
+        stw_be_p(data + sloc, net_checksum_finish(sum));
     }
 }
 
@@ -590,31 +589,28 @@
         DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
                frames, tp->size, css);
         if (tp->ip) {		// IPv4
-            cpu_to_be16wu((uint16_t *)(tp->data+css+2),
-                          tp->size - css);
-            cpu_to_be16wu((uint16_t *)(tp->data+css+4),
+            stw_be_p(tp->data+css+2, tp->size - css);
+            stw_be_p(tp->data+css+4,
                           be16_to_cpup((uint16_t *)(tp->data+css+4))+frames);
         } else			// IPv6
-            cpu_to_be16wu((uint16_t *)(tp->data+css+4),
-                          tp->size - css);
+            stw_be_p(tp->data+css+4, tp->size - css);
         css = tp->tucss;
         len = tp->size - css;
         DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->tcp, css, len);
         if (tp->tcp) {
             sofar = frames * tp->mss;
-            cpu_to_be32wu((uint32_t *)(tp->data+css+4),	// seq
-                be32_to_cpupu((uint32_t *)(tp->data+css+4))+sofar);
+            stl_be_p(tp->data+css+4, ldl_be_p(tp->data+css+4)+sofar); /* seq */
             if (tp->paylen - sofar > tp->mss)
                 tp->data[css + 13] &= ~9;		// PSH, FIN
         } else	// UDP
-            cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
+            stw_be_p(tp->data+css+4, len);
         if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
             unsigned int phsum;
             // add pseudo-header length before checksum calculation
             sp = (uint16_t *)(tp->data + tp->tucso);
             phsum = be16_to_cpup(sp) + len;
             phsum = (phsum >> 16) + (phsum & 0xffff);
-            cpu_to_be16wu(sp, phsum);
+            stw_be_p(sp, phsum);
         }
         tp->tso_frames++;
     }
@@ -684,9 +680,9 @@
     if (vlan_enabled(s) && is_vlan_txd(txd_lower) &&
         (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
         tp->vlan_needed = 1;
-        cpu_to_be16wu((uint16_t *)(tp->vlan_header),
+        stw_be_p(tp->vlan_header,
                       le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
-        cpu_to_be16wu((uint16_t *)(tp->vlan_header + 2),
+        stw_be_p(tp->vlan_header + 2,
                       le16_to_cpu(dp->upper.fields.special));
     }
         
@@ -1110,7 +1106,7 @@
 
     s->mac_reg[index] = val;
 
-    if (index == RA + 1) {
+    if (index == RA || index == RA + 1) {
         macaddr[0] = cpu_to_le32(s->mac_reg[RA]);
         macaddr[1] = cpu_to_le32(s->mac_reg[RA + 1]);
         qemu_format_nic_info_str(qemu_get_queue(s->nic), (uint8_t *)macaddr);
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index ffa60d5..3b891ca 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -409,7 +409,7 @@
 {
     if (s->int_stat) {
         TRACE(INT, logout("interrupt disabled\n"));
-        qemu_irq_lower(s->dev.irq[0]);
+        pci_irq_deassert(&s->dev);
         s->int_stat = 0;
     }
 }
@@ -418,7 +418,7 @@
 {
     if (!s->int_stat) {
         TRACE(INT, logout("interrupt enabled\n"));
-        qemu_irq_raise(s->dev.irq[0]);
+        pci_irq_assert(&s->dev);
         s->int_stat = 1;
     }
 }
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
index c961258..4c32e9e 100644
--- a/hw/net/ne2000.c
+++ b/hw/net/ne2000.c
@@ -467,7 +467,7 @@
     addr &= ~1; /* XXX: check exact behaviour if not even */
     if (addr < 32 ||
         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
-        cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
+        stl_le_p(s->mem + addr, val);
     }
 }
 
@@ -497,7 +497,7 @@
     addr &= ~1; /* XXX: check exact behaviour if not even */
     if (addr < 32 ||
         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
-        return le32_to_cpupu((uint32_t *)(s->mem + addr));
+        return ldl_le_p(s->mem + addr);
     } else {
         return 0xffffffff;
     }
@@ -731,7 +731,7 @@
     s = &d->ne2000;
     ne2000_setup_io(s, DEVICE(pci_dev), 0x100);
     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
-    s->irq = d->dev.irq[0];
+    s->irq = pci_allocate_irq(&d->dev);
 
     qemu_macaddr_default_if_unset(&s->c.macaddr);
     ne2000_reset(s);
@@ -752,6 +752,7 @@
 
     memory_region_destroy(&s->io);
     qemu_del_nic(s->nic);
+    qemu_free_irq(s->irq);
 }
 
 static Property ne2000_properties[] = {
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index 865f2f0..6a5d806 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -282,6 +282,7 @@
 {
     PCIPCNetState *d = PCI_PCNET(dev);
 
+    qemu_free_irq(d->state.irq);
     memory_region_destroy(&d->state.mmio);
     memory_region_destroy(&d->io_bar);
     timer_del(d->state.poll_timer);
@@ -331,7 +332,7 @@
 
     pci_register_bar(pci_dev, 1, 0, &s->mmio);
 
-    s->irq = pci_dev->irq[0];
+    s->irq = pci_allocate_irq(pci_dev);
     s->phys_mem_read = pci_physical_memory_read;
     s->phys_mem_write = pci_physical_memory_write;
     s->dma_opaque = pci_dev;
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 3225f3d..7f2b4db 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -716,7 +716,7 @@
     DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus,
         s->IntrMask);
 
-    qemu_set_irq(d->irq[0], (isr != 0));
+    pci_set_irq(d, (isr != 0));
 }
 
 static int rtl8139_RxWrap(RTL8139State *s)
@@ -2741,10 +2741,7 @@
 
     switch (addr)
     {
-        case MAC0 ... MAC0+4:
-            s->phys[addr - MAC0] = val;
-            break;
-        case MAC0+5:
+        case MAC0 ... MAC0+5:
             s->phys[addr - MAC0] = val;
             qemu_format_nic_info_str(qemu_get_queue(s->nic), s->phys);
             break;
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
index f5963e2..a8e29b3 100644
--- a/hw/net/smc91c111.c
+++ b/hw/net/smc91c111.c
@@ -185,6 +185,7 @@
     s->allocated &= ~(1 << packet);
     if (s->tx_alloc == 0x80)
         smc91c111_tx_alloc(s);
+    qemu_flush_queued_packets(qemu_get_queue(s->nic));
 }
 
 /* Flush the TX FIFO.  */
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index 4ff0411..1bd6f50 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -531,6 +531,7 @@
     k->dt_type = "network";
     k->dt_compatible = "IBM,l-lan";
     k->signal_mask = 0x1;
+    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
     dc->props = spapr_vlan_properties;
     k->rtce_window_size = 0x10000000;
     dc->vmsd = &vmstate_spapr_llan;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 22dbd05..b75c753 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -200,16 +200,16 @@
     VirtIONet *n = qemu_get_nic_opaque(nc);
 
     if (nc->rxfilter_notify_enabled) {
+        gchar *path = object_get_canonical_path(OBJECT(n->qdev));
         if (n->netclient_name) {
             event_data = qobject_from_jsonf("{ 'name': %s, 'path': %s }",
-                                    n->netclient_name,
-                                    object_get_canonical_path(OBJECT(n->qdev)));
+                                    n->netclient_name, path);
         } else {
-            event_data = qobject_from_jsonf("{ 'path': %s }",
-                                    object_get_canonical_path(OBJECT(n->qdev)));
+            event_data = qobject_from_jsonf("{ 'path': %s }", path);
         }
         monitor_protocol_event(QEVENT_NIC_RX_FILTER_CHANGED, event_data);
         qobject_decref(event_data);
+        g_free(path);
 
         /* disable event notification to avoid events flooding */
         nc->rxfilter_notify_enabled = 0;
@@ -657,7 +657,8 @@
     }
 
     if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
-        s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
+        s = iov_to_buf(iov, iov_cnt, 0,
+                       &n->mac_table.macs[n->mac_table.in_use * ETH_ALEN],
                        mac_data.entries * ETH_ALEN);
         if (s != mac_data.entries * ETH_ALEN) {
             goto error;
@@ -1601,7 +1602,7 @@
         if (q->tx_timer) {
             timer_del(q->tx_timer);
             timer_free(q->tx_timer);
-        } else {
+        } else if (q->tx_bh) {
             qemu_bh_delete(q->tx_bh);
         }
     }
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 49c2466..19687aa 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -336,7 +336,7 @@
     }
 
     VMW_IRPRN("Asserting line for interrupt %u", int_idx);
-    qemu_set_irq(d->irq[int_idx], 1);
+    pci_irq_assert(d);
     return true;
 }
 
@@ -356,7 +356,7 @@
     assert(!s->msi_used || !msi_enabled(d));
 
     VMW_IRPRN("Deasserting line for interrupt %u", lidx);
-    qemu_set_irq(d->irq[lidx], 0);
+    pci_irq_deassert(d);
 }
 
 static void vmxnet3_update_interrupt_line_state(VMXNET3State *s, int lidx)
@@ -1299,6 +1299,12 @@
     }
 }
 
+static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
+{
+    return s->msix_used || s->msi_used || (intx ==
+           (pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
+}
+
 static void vmxnet3_activate_device(VMXNET3State *s)
 {
     int i;
@@ -1332,6 +1338,7 @@
 
     s->event_int_idx =
         VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.eventIntrIdx);
+    assert(vmxnet3_verify_intx(s, s->event_int_idx));
     VMW_CFPRN("Events interrupt line is %u", s->event_int_idx);
 
     s->auto_int_masking =
@@ -1364,6 +1371,7 @@
         /* Read interrupt number for this TX queue */
         s->txq_descr[i].intr_idx =
             VMXNET3_READ_TX_QUEUE_DESCR8(qdescr_pa, conf.intrIdx);
+        assert(vmxnet3_verify_intx(s, s->txq_descr[i].intr_idx));
 
         VMW_CFPRN("TX Queue %d interrupt: %d", i, s->txq_descr[i].intr_idx);
 
@@ -1411,6 +1419,7 @@
         /* Read interrupt number for this RX queue */
         s->rxq_descr[i].intr_idx =
             VMXNET3_READ_TX_QUEUE_DESCR8(qd_pa, conf.intrIdx);
+        assert(vmxnet3_verify_intx(s, s->rxq_descr[i].intr_idx));
 
         VMW_CFPRN("RX Queue %d interrupt: %d", i, s->rxq_descr[i].intr_idx);
 
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index d0820e5..f5dc3ea 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -42,6 +42,7 @@
     uint8_t *data;
     void *callback_opaque;
     FWCfgCallback callback;
+    FWCfgReadCallback read_callback;
 } FWCfgEntry;
 
 struct FWCfgState {
@@ -249,8 +250,12 @@
 
     if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len)
         ret = 0;
-    else
+    else {
+        if (e->read_callback) {
+            e->read_callback(e->callback_opaque, s->cur_offset);
+        }
         ret = e->data[s->cur_offset++];
+    }
 
     trace_fw_cfg_read(s, ret);
     return ret;
@@ -381,7 +386,10 @@
     }
 };
 
-void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
+static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
+                                           FWCfgReadCallback callback,
+                                           void *callback_opaque,
+                                           void *data, size_t len)
 {
     int arch = !!(key & FW_CFG_ARCH_LOCAL);
 
@@ -391,6 +399,13 @@
 
     s->entries[arch][key].data = data;
     s->entries[arch][key].len = (uint32_t)len;
+    s->entries[arch][key].read_callback = callback;
+    s->entries[arch][key].callback_opaque = callback_opaque;
+}
+
+void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
+{
+    fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
 }
 
 void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
@@ -444,8 +459,9 @@
     s->entries[arch][key].callback = callback;
 }
 
-void fw_cfg_add_file(FWCfgState *s,  const char *filename,
-                     void *data, size_t len)
+void fw_cfg_add_file_callback(FWCfgState *s,  const char *filename,
+                              FWCfgReadCallback callback, void *callback_opaque,
+                              void *data, size_t len)
 {
     int i, index;
     size_t dsize;
@@ -459,7 +475,8 @@
     index = be32_to_cpu(s->files->count);
     assert(index < FW_CFG_FILE_SLOTS);
 
-    fw_cfg_add_bytes(s, FW_CFG_FILE_FIRST + index, data, len);
+    fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
+                                   callback, callback_opaque, data, len);
 
     pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
             filename);
@@ -477,6 +494,12 @@
     s->files->count = cpu_to_be32(index+1);
 }
 
+void fw_cfg_add_file(FWCfgState *s,  const char *filename,
+                     void *data, size_t len)
+{
+    fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
+}
+
 static void fw_cfg_machine_ready(struct Notifier *n, void *data)
 {
     size_t len;
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
index eb4500e..beaad68 100644
--- a/hw/nvram/spapr_nvram.c
+++ b/hw/nvram/spapr_nvram.c
@@ -182,6 +182,7 @@
     k->dt_name = "nvram";
     k->dt_type = "nvram";
     k->dt_compatible = "qemu,spapr-nvram";
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
     dc->props = spapr_nvram_properties;
 }
 
diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index 988ca20..9c54945 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -30,19 +30,28 @@
 
 void cpu_openrisc_count_update(OpenRISCCPU *cpu)
 {
-    uint64_t now, next;
-    uint32_t wait;
+    uint64_t now;
 
-    now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
     if (!is_counting) {
-        timer_del(cpu->env.timer);
-        last_clk = now;
         return;
     }
-
+    now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
     cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
                                         get_ticks_per_sec());
     last_clk = now;
+}
+
+void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
+{
+    uint32_t wait;
+    uint64_t now, next;
+
+    if (!is_counting) {
+        return;
+    }
+
+    cpu_openrisc_count_update(cpu);
+    now = last_clk;
 
     if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
         wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
@@ -50,7 +59,6 @@
     } else {
         wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
     }
-
     next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
     timer_mod(cpu->env.timer, next);
 }
@@ -63,8 +71,9 @@
 
 void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
 {
-    is_counting = 0;
+    timer_del(cpu->env.timer);
     cpu_openrisc_count_update(cpu);
+    is_counting = 0;
 }
 
 static void openrisc_timer_cb(void *opaque)
@@ -84,15 +93,15 @@
         break;
     case TIMER_INTR:
         cpu->env.ttcr = 0;
-        cpu_openrisc_count_start(cpu);
         break;
     case TIMER_SHOT:
         cpu_openrisc_count_stop(cpu);
         break;
     case TIMER_CONT:
-        cpu_openrisc_count_start(cpu);
         break;
     }
+
+    cpu_openrisc_timer_update(cpu);
 }
 
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
index a9392c7..440e187 100644
--- a/hw/pci-bridge/pci_bridge_dev.c
+++ b/hw/pci-bridge/pci_bridge_dev.c
@@ -53,6 +53,7 @@
     if (err) {
         goto bridge_error;
     }
+    dev->config[PCI_INTERRUPT_PIN] = 0x1;
     memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar", shpc_bar_size(dev));
     err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
     if (err) {
@@ -73,7 +74,6 @@
      * Check whether that works well. */
     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
 		     PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
-    dev->config[PCI_INTERRUPT_PIN] = 0x1;
     return 0;
 msi_error:
     slotid_cap_cleanup(dev);
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index c041149..edc974e 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -48,6 +48,7 @@
     PCIHostState parent_obj;
     PcPciInfo pci_info;
     uint64_t pci_hole64_size;
+    uint32_t short_root_bus;
 } I440FXState;
 
 #define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
@@ -416,6 +417,14 @@
     return b;
 }
 
+PCIBus *find_i440fx(void)
+{
+    PCIHostState *s = OBJECT_CHECK(PCIHostState,
+                                   object_resolve_path("/machine/i440fx", NULL),
+                                   TYPE_PCI_HOST_BRIDGE);
+    return s ? s->bus : NULL;
+}
+
 /* PIIX3 PCI to ISA bridge */
 static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
 {
@@ -712,13 +721,19 @@
 static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge,
                                                 PCIBus *rootbus)
 {
+    I440FXState *s = I440FX_PCI_HOST_BRIDGE(host_bridge);
+
     /* For backwards compat with old device paths */
-    return "0000";
+    if (s->short_root_bus) {
+        return "0000";
+    }
+    return "0000:00";
 }
 
 static Property i440fx_props[] = {
     DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState,
                      pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
+    DEFINE_PROP_UINT32("short_root_bus", I440FXState, short_root_bus, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index ad703a4..c043998 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -61,8 +61,13 @@
 static const char *q35_host_root_bus_path(PCIHostState *host_bridge,
                                           PCIBus *rootbus)
 {
-    /* For backwards compat with old device paths */
-    return "0000";
+    Q35PCIHost *s = Q35_HOST_DEVICE(host_bridge);
+
+     /* For backwards compat with old device paths */
+    if (s->mch.short_root_bus) {
+        return "0000";
+    }
+    return "0000:00";
 }
 
 static void q35_host_get_pci_hole_start(Object *obj, Visitor *v,
@@ -109,11 +114,22 @@
     visit_type_uint64(v, &w64.end, name, errp);
 }
 
+static void q35_host_get_mmcfg_size(Object *obj, Visitor *v,
+                                    void *opaque, const char *name,
+                                    Error **errp)
+{
+    PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
+    uint32_t value = e->size;
+
+    visit_type_uint32(v, &value, name, errp);
+}
+
 static Property mch_props[] = {
-    DEFINE_PROP_UINT64("MCFG", Q35PCIHost, parent_obj.base_addr,
+    DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_addr,
                         MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
     DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,
                      mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
+    DEFINE_PROP_UINT32("short_root_bus", Q35PCIHost, mch.short_root_bus, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -160,6 +176,10 @@
                         q35_host_get_pci_hole64_end,
                         NULL, NULL, NULL, NULL);
 
+    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "int",
+                        q35_host_get_mmcfg_size,
+                        NULL, NULL, NULL, NULL);
+
     /* Leave enough space for the biggest MCFG BAR */
     /* TODO: this matches current bios behaviour, but
      * it's not a power of two, which means an MTRR
@@ -375,6 +395,16 @@
     return 0;
 }
 
+uint64_t mch_mcfg_base(void)
+{
+    bool ambiguous;
+    Object *o = object_resolve_path_type("", TYPE_MCH_PCI_DEVICE, &ambiguous);
+    if (!o) {
+        return 0;
+    }
+    return MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
+}
+
 static void mch_class_init(ObjectClass *klass, void *data)
 {
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c
index 619fe47..8dbc3c1 100644
--- a/hw/pci/pci-hotplug-old.c
+++ b/hw/pci/pci-hotplug-old.c
@@ -248,7 +248,7 @@
         }
         dev = pci_create(bus, devfn, "virtio-blk-pci");
         if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
-            qdev_free(&dev->qdev);
+            object_unparent(OBJECT(dev));
             dev = NULL;
             break;
         }
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 00554a0..ed32059 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -83,7 +83,7 @@
 
 static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
 static void pci_update_mappings(PCIDevice *d);
-static void pci_set_irq(void *opaque, int irq_num, int level);
+static void pci_irq_handler(void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
 static void pci_del_option_rom(PCIDevice *pdev);
 
@@ -161,7 +161,7 @@
 {
     int i;
     for (i = 0; i < PCI_NUM_PINS; ++i) {
-        qemu_set_irq(dev->irq[i], 0);
+        pci_irq_handler(dev, i, 0);
     }
 }
 
@@ -863,14 +863,12 @@
     pci_dev->config_read = config_read;
     pci_dev->config_write = config_write;
     bus->devices[devfn] = pci_dev;
-    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
     pci_dev->version_id = 2; /* Current pci device vmstate version */
     return pci_dev;
 }
 
 static void do_pci_unregister_device(PCIDevice *pci_dev)
 {
-    qemu_free_irqs(pci_dev->irq);
     pci_dev->bus->devices[pci_dev->devfn] = NULL;
     pci_config_free(pci_dev);
 
@@ -1175,7 +1173,7 @@
 /* generic PCI irq support */
 
 /* 0 <= irq_num <= 3. level must be 0 or 1 */
-static void pci_set_irq(void *opaque, int irq_num, int level)
+static void pci_irq_handler(void *opaque, int irq_num, int level)
 {
     PCIDevice *pci_dev = opaque;
     int change;
@@ -1191,6 +1189,24 @@
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
+static inline int pci_intx(PCIDevice *pci_dev)
+{
+    return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
+}
+
+qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
+{
+    int intx = pci_intx(pci_dev);
+
+    return qemu_allocate_irq(pci_irq_handler, pci_dev, intx);
+}
+
+void pci_set_irq(PCIDevice *pci_dev, int level)
+{
+    int intx = pci_intx(pci_dev);
+    pci_irq_handler(pci_dev, intx, level);
+}
+
 /* Special hooks used by device assignment */
 void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
 {
@@ -2264,7 +2280,7 @@
     Range *range = opaque;
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
     uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND);
-    int r;
+    int i;
 
     if (!(cmd & PCI_COMMAND_MEMORY)) {
         return;
@@ -2283,17 +2299,21 @@
             range_extend(range, &pref_range);
         }
     }
-    for (r = 0; r < PCI_NUM_REGIONS; ++r) {
-        PCIIORegion *region = &dev->io_regions[r];
+    for (i = 0; i < PCI_NUM_REGIONS; ++i) {
+        PCIIORegion *r = &dev->io_regions[i];
         Range region_range;
 
-        if (!region->size ||
-            (region->type & PCI_BASE_ADDRESS_SPACE_IO) ||
-            !(region->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+        if (!r->size ||
+            (r->type & PCI_BASE_ADDRESS_SPACE_IO) ||
+            !(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
             continue;
         }
-        region_range.begin = pci_get_quad(dev->config + pci_bar(dev, r));
-        region_range.end = region_range.begin + region->size;
+        region_range.begin = pci_bar_address(dev, i, r->type, r->size);
+        region_range.end = region_range.begin + r->size;
+
+        if (region_range.begin == PCI_BAR_UNMAPPED) {
+            continue;
+        }
 
         region_range.begin = MAX(region_range.begin, 0x1ULL << 32);
 
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index e6b22b8..290abab 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -391,7 +391,7 @@
     pci_bridge_region_cleanup(s, s->windows);
     memory_region_destroy(&s->address_space_mem);
     memory_region_destroy(&s->address_space_io);
-    /* qbus_free() is called automatically by qdev_free() */
+    /* qbus_free() is called automatically during device deletion */
 }
 
 /*
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 50af3c1..ca60cf2 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -187,7 +187,7 @@
     } else if (msi_enabled(dev)) {
         msi_notify(dev, pcie_cap_flags_get_vector(dev));
     } else {
-        qemu_set_irq(dev->irq[dev->exp.hpev_intx], dev->exp.hpev_notified);
+        pci_set_irq(dev, dev->exp.hpev_notified);
     }
 }
 
@@ -195,7 +195,7 @@
 {
     hotplug_event_update_event_status(dev);
     if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) {
-        qemu_set_irq(dev->irq[dev->exp.hpev_intx], 0);
+        pci_irq_deassert(dev);
     }
 }
 
@@ -251,7 +251,7 @@
                                    PCI_EXP_SLTSTA_PDS);
         pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
     } else {
-        qdev_free(&pci_dev->qdev);
+        object_unparent(OBJECT(pci_dev));
         pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
                                      PCI_EXP_SLTSTA_PDS);
         pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index ca762ab..991502e 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -285,7 +285,7 @@
     } else if (msi_enabled(dev)) {
         msi_notify(dev, pcie_aer_root_get_vector(dev));
     } else {
-        qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
+        pci_irq_assert(dev);
     }
 }
 
@@ -425,7 +425,7 @@
             /* 7.10.8 Header Log Register */
             uint8_t *header_log =
                 aer_cap + PCI_ERR_HEADER_LOG + i * sizeof err->header[0];
-            cpu_to_be32wu((uint32_t*)header_log, err->header[i]);
+            stl_be_p(header_log, err->header[i]);
         }
     } else {
         assert(!(err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT));
@@ -439,7 +439,7 @@
             /* 7.10.12 tlp prefix log register */
             uint8_t *prefix_log =
                 aer_cap + PCI_ERR_TLP_PREFIX_LOG + i * sizeof err->prefix[0];
-            cpu_to_be32wu((uint32_t*)prefix_log, err->prefix[i]);
+            stl_be_p(prefix_log, err->prefix[i]);
         }
         errcap |= PCI_ERR_CAP_TLP;
     } else {
@@ -768,7 +768,7 @@
     uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
     /* 6.2.4.1.2 Interrupt Generation */
     if (!msix_enabled(dev) && !msi_enabled(dev)) {
-        qemu_set_irq(dev->irq[dev->exp.aer_intx], !!(root_cmd & enabled_cmd));
+        pci_set_irq(dev, !!(root_cmd & enabled_cmd));
         return;
     }
 
diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c
index b70e5ad..c6e1b57 100644
--- a/hw/pci/pcie_host.c
+++ b/hw/pci/pcie_host.c
@@ -24,27 +24,6 @@
 #include "hw/pci/pcie_host.h"
 #include "exec/address-spaces.h"
 
-/*
- * PCI express mmcfig address
- * bit 20 - 28: bus number
- * bit 15 - 19: device number
- * bit 12 - 14: function number
- * bit  0 - 11: offset in configuration space of a given device
- */
-#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28)
-#define PCIE_MMCFG_SIZE_MIN             (1ULL << 20)
-#define PCIE_MMCFG_BUS_BIT              20
-#define PCIE_MMCFG_BUS_MASK             0x1ff
-#define PCIE_MMCFG_DEVFN_BIT            12
-#define PCIE_MMCFG_DEVFN_MASK           0xff
-#define PCIE_MMCFG_CONFOFFSET_MASK      0xfff
-#define PCIE_MMCFG_BUS(addr)            (((addr) >> PCIE_MMCFG_BUS_BIT) & \
-                                         PCIE_MMCFG_BUS_MASK)
-#define PCIE_MMCFG_DEVFN(addr)          (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
-                                         PCIE_MMCFG_DEVFN_MASK)
-#define PCIE_MMCFG_CONFOFFSET(addr)     ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
-
-
 /* a helper function to get a PCIDevice for a given mmconfig address */
 static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
                                                      uint32_t mmcfg_addr)
@@ -104,9 +83,6 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
-#define PCIE_BASE_ADDR_UNMAPPED  ((hwaddr)-1ULL)
-
 int pcie_host_init(PCIExpressHost *e)
 {
     e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index eb092fd..576244b 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -172,7 +172,7 @@
     if (msi_enabled(d) && shpc->msi_requested != level)
         msi_notify(d, 0);
     else
-        qemu_set_irq(d->irq[0], level);
+        pci_set_irq(d, level);
     shpc->msi_requested = level;
 }
 
@@ -254,7 +254,7 @@
          ++devfn) {
         PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
         if (affected_dev) {
-            qdev_free(&affected_dev->qdev);
+            object_unparent(OBJECT(affected_dev));
         }
     }
 }
diff --git a/hw/pcmcia/Makefile.objs b/hw/pcmcia/Makefile.objs
new file mode 100644
index 0000000..4eac060
--- /dev/null
+++ b/hw/pcmcia/Makefile.objs
@@ -0,0 +1,2 @@
+common-obj-y += pcmcia.o
+obj-$(CONFIG_PXA2XX) += pxa2xx.o
diff --git a/hw/pcmcia/pcmcia.c b/hw/pcmcia/pcmcia.c
new file mode 100644
index 0000000..78efe5a
--- /dev/null
+++ b/hw/pcmcia/pcmcia.c
@@ -0,0 +1,24 @@
+/*
+ * PCMCIA emulation
+ *
+ * Copyright 2013 SUSE LINUX Products GmbH
+ */
+
+#include "qemu-common.h"
+#include "hw/hw.h"
+#include "hw/pcmcia.h"
+
+static const TypeInfo pcmcia_card_type_info = {
+    .name = TYPE_PCMCIA_CARD,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(PCMCIACardState),
+    .abstract = true,
+    .class_size = sizeof(PCMCIACardClass),
+};
+
+static void pcmcia_register_types(void)
+{
+    type_register_static(&pcmcia_card_type_info);
+}
+
+type_init(pcmcia_register_types)
diff --git a/hw/misc/pxa2xx_pcmcia.c b/hw/pcmcia/pxa2xx.c
similarity index 61%
rename from hw/misc/pxa2xx_pcmcia.c
rename to hw/pcmcia/pxa2xx.c
index ef71a2a..8f17596 100644
--- a/hw/misc/pxa2xx_pcmcia.c
+++ b/hw/pcmcia/pxa2xx.c
@@ -11,28 +11,38 @@
  */
 
 #include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "hw/pcmcia.h"
 #include "hw/arm/pxa.h"
 
+#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia"
+#define PXA2XX_PCMCIA(obj) \
+    OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA)
 
 struct PXA2xxPCMCIAState {
+    SysBusDevice parent_obj;
+
     PCMCIASocket slot;
-    PCMCIACardState *card;
+    MemoryRegion container_mem;
     MemoryRegion common_iomem;
     MemoryRegion attr_iomem;
     MemoryRegion iomem;
 
     qemu_irq irq;
     qemu_irq cd_irq;
+
+    PCMCIACardState *card;
 };
 
 static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
                 hwaddr offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
 
     if (s->slot.attached) {
-        return s->card->common_read(s->card->state, offset);
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        return pcc->common_read(s->card, offset);
     }
 
     return 0;
@@ -42,9 +52,11 @@
                                        uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
 
     if (s->slot.attached) {
-        s->card->common_write(s->card->state, offset, value);
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        pcc->common_write(s->card, offset, value);
     }
 }
 
@@ -52,9 +64,11 @@
                 hwaddr offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
 
     if (s->slot.attached) {
-        return s->card->attr_read(s->card->state, offset);
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        return pcc->attr_read(s->card, offset);
     }
 
     return 0;
@@ -64,9 +78,11 @@
                                      uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
 
     if (s->slot.attached) {
-        s->card->attr_write(s->card->state, offset, value);
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        pcc->attr_write(s->card, offset, value);
     }
 }
 
@@ -74,9 +90,11 @@
                 hwaddr offset, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
 
     if (s->slot.attached) {
-        return s->card->io_read(s->card->state, offset);
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        return pcc->io_read(s->card, offset);
     }
 
     return 0;
@@ -86,9 +104,11 @@
                                    uint64_t value, unsigned size)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
 
     if (s->slot.attached) {
-        s->card->io_write(s->card->state, offset, value);
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        pcc->io_write(s->card, offset, value);
     }
 }
 
@@ -122,15 +142,43 @@
 PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
                                       hwaddr base)
 {
+    DeviceState *dev;
     PXA2xxPCMCIAState *s;
 
-    s = (PXA2xxPCMCIAState *)
-            g_malloc0(sizeof(PXA2xxPCMCIAState));
+    dev = qdev_create(NULL, TYPE_PXA2XX_PCMCIA);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    s = PXA2XX_PCMCIA(dev);
+
+    if (base == 0x30000000) {
+        s->slot.slot_string = "PXA PC Card Socket 1";
+    } else {
+        s->slot.slot_string = "PXA PC Card Socket 0";
+    }
+
+    qdev_init_nofail(dev);
+
+    return s;
+}
+
+static void pxa2xx_pcmcia_realize(DeviceState *dev, Error **errp)
+{
+    PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(dev);
+
+    pcmcia_socket_register(&s->slot);
+}
+
+static void pxa2xx_pcmcia_initfn(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(obj);
+
+    memory_region_init(&s->container_mem, obj, "container", 0x10000000);
+    sysbus_init_mmio(sbd, &s->container_mem);
 
     /* Socket I/O Memory Space */
     memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
                           "pxa2xx-pcmcia-io", 0x04000000);
-    memory_region_add_subregion(sysmem, base | 0x00000000,
+    memory_region_add_subregion(&s->container_mem, 0x00000000,
                                 &s->iomem);
 
     /* Then next 64 MB is reserved */
@@ -138,62 +186,68 @@
     /* Socket Attribute Memory Space */
     memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
                           "pxa2xx-pcmcia-attribute", 0x04000000);
-    memory_region_add_subregion(sysmem, base | 0x08000000,
+    memory_region_add_subregion(&s->container_mem, 0x08000000,
                                 &s->attr_iomem);
 
     /* Socket Common Memory Space */
     memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
                           "pxa2xx-pcmcia-common", 0x04000000);
-    memory_region_add_subregion(sysmem, base | 0x0c000000,
+    memory_region_add_subregion(&s->container_mem, 0x0c000000,
                                 &s->common_iomem);
 
-    if (base == 0x30000000)
-        s->slot.slot_string = "PXA PC Card Socket 1";
-    else
-        s->slot.slot_string = "PXA PC Card Socket 0";
     s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
-    pcmcia_socket_register(&s->slot);
 
-    return s;
+    object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
+                             (Object **)&s->card, NULL);
 }
 
 /* Insert a new card into a slot */
 int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-    if (s->slot.attached)
+    PCMCIACardClass *pcc;
+
+    if (s->slot.attached) {
         return -EEXIST;
+    }
 
     if (s->cd_irq) {
         qemu_irq_raise(s->cd_irq);
     }
 
     s->card = card;
+    pcc = PCMCIA_CARD_GET_CLASS(s->card);
 
-    s->slot.attached = 1;
+    s->slot.attached = true;
     s->card->slot = &s->slot;
-    s->card->attach(s->card->state);
+    pcc->attach(s->card);
 
     return 0;
 }
 
 /* Eject card from the slot */
-int pxa2xx_pcmcia_dettach(void *opaque)
+int pxa2xx_pcmcia_detach(void *opaque)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-    if (!s->slot.attached)
-        return -ENOENT;
+    PCMCIACardClass *pcc;
 
-    s->card->detach(s->card->state);
+    if (!s->slot.attached) {
+        return -ENOENT;
+    }
+
+    pcc = PCMCIA_CARD_GET_CLASS(s->card);
+    pcc->detach(s->card);
     s->card->slot = NULL;
     s->card = NULL;
 
-    s->slot.attached = 0;
+    s->slot.attached = false;
 
-    if (s->irq)
+    if (s->irq) {
         qemu_irq_lower(s->irq);
-    if (s->cd_irq)
+    }
+    if (s->cd_irq) {
         qemu_irq_lower(s->cd_irq);
+    }
 
     return 0;
 }
@@ -205,3 +259,25 @@
     s->irq = irq;
     s->cd_irq = cd_irq;
 }
+
+static void pxa2xx_pcmcia_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = pxa2xx_pcmcia_realize;
+}
+
+static const TypeInfo pxa2xx_pcmcia_type_info = {
+    .name = TYPE_PXA2XX_PCMCIA,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxPCMCIAState),
+    .instance_init = pxa2xx_pcmcia_initfn,
+    .class_init = pxa2xx_pcmcia_class_init,
+};
+
+static void pxa2xx_pcmcia_register_types(void)
+{
+    type_register_static(&pxa2xx_pcmcia_type_info);
+}
+
+type_init(pxa2xx_pcmcia_register_types)
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 655e499..67597df 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -110,8 +110,9 @@
     qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
                               tb_freq);
 
-    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
+    rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
     g_free(fdt);
+    return 0;
 
 out:
 
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 004184d..7e53a5f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -62,7 +62,7 @@
  *
  * We load our kernel at 4M, leaving space for SLOF initial image
  */
-#define FDT_MAX_SIZE            0x10000
+#define FDT_MAX_SIZE            0x40000
 #define RTAS_MAX_SIZE           0x10000
 #define FW_MAX_SIZE             0x400000
 #define FW_FILE_NAME            "slof.bin"
@@ -120,7 +120,7 @@
      * it has to be aligned to num to support multiple
      * MSI vectors. MSI-X is not affected by this.
      * The hint is used for the first IRQ, the rest should
-     * be allocated continously.
+     * be allocated continuously.
      */
     if (msi) {
         assert((num == 1) || (num == 2) || (num == 4) ||
@@ -161,14 +161,33 @@
         return NULL;
     }
 
-    return XICS(dev);
+    return XICS_COMMON(dev);
 }
 
 static XICSState *xics_system_init(int nr_servers, int nr_irqs)
 {
     XICSState *icp = NULL;
 
-    icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs);
+    if (kvm_enabled()) {
+        QemuOpts *machine_opts = qemu_get_machine_opts();
+        bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
+                                                "kernel_irqchip", true);
+        bool irqchip_required = qemu_opt_get_bool(machine_opts,
+                                                  "kernel_irqchip", false);
+        if (irqchip_allowed) {
+            icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs);
+        }
+
+        if (irqchip_required && !icp) {
+            perror("Failed to create in-kernel XICS\n");
+            abort();
+        }
+    }
+
+    if (!icp) {
+        icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs);
+    }
+
     if (!icp) {
         perror("Failed to create XICS\n");
         abort();
@@ -185,9 +204,8 @@
     int smt = kvmppc_smt_threads();
     uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
 
-    assert(spapr->cpu_model);
-
     CPU_FOREACH(cpu) {
+        DeviceClass *dc = DEVICE_GET_CLASS(cpu);
         uint32_t associativity[] = {cpu_to_be32(0x5),
                                     cpu_to_be32(0x0),
                                     cpu_to_be32(0x0),
@@ -199,7 +217,7 @@
             continue;
         }
 
-        snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
+        snprintf(cpu_model, 32, "/cpus/%s@%x", dc->fw_name,
                  cpu->cpu_index);
 
         offset = fdt_path_offset(fdt, cpu_model);
@@ -269,10 +287,10 @@
     } while (0)
 
 
-static void *spapr_create_fdt_skel(const char *cpu_model,
-                                   hwaddr initrd_base,
+static void *spapr_create_fdt_skel(hwaddr initrd_base,
                                    hwaddr initrd_size,
                                    hwaddr kernel_size,
+                                   bool little_endian,
                                    const char *boot_device,
                                    const char *kernel_cmdline,
                                    uint32_t epow_irq)
@@ -286,7 +304,6 @@
     char qemu_hypertas_prop[] = "hcall-memop1";
     uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
     uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
-    char *modelname;
     int i, smt = kvmppc_smt_threads();
     unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
 
@@ -326,6 +343,9 @@
                               cpu_to_be64(kernel_size) };
 
         _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
+        if (little_endian) {
+            _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
+        }
     }
     if (boot_device) {
         _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
@@ -342,18 +362,10 @@
     _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
     _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
 
-    modelname = g_strdup(cpu_model);
-
-    for (i = 0; i < strlen(modelname); i++) {
-        modelname[i] = toupper(modelname[i]);
-    }
-
-    /* This is needed during FDT finalization */
-    spapr->cpu_model = g_strdup(modelname);
-
     CPU_FOREACH(cs) {
         PowerPCCPU *cpu = POWERPC_CPU(cs);
         CPUPPCState *env = &cpu->env;
+        DeviceClass *dc = DEVICE_GET_CLASS(cs);
         PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
         int index = cs->cpu_index;
         uint32_t servers_prop[smp_threads];
@@ -370,7 +382,7 @@
             continue;
         }
 
-        nodename = g_strdup_printf("%s@%x", modelname, index);
+        nodename = g_strdup_printf("%s@%x", dc->fw_name, index);
 
         _FDT((fdt_begin_node(fdt, nodename)));
 
@@ -418,6 +430,10 @@
         _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
                            gservers_prop, sizeof(gservers_prop))));
 
+        if (env->spr_cb[SPR_PURR].oea_read) {
+            _FDT((fdt_property(fdt, "ibm,purr", NULL, 0)));
+        }
+
         if (env->mmu_model & POWERPC_MMU_1TSEG) {
             _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
                                segs, sizeof(segs))));
@@ -450,8 +466,6 @@
         _FDT((fdt_end_node(fdt)));
     }
 
-    g_free(modelname);
-
     _FDT((fdt_end_node(fdt)));
 
     /* RTAS */
@@ -1102,6 +1116,7 @@
     uint32_t initrd_base = 0;
     long kernel_size = 0, initrd_size = 0;
     long load_limit, rtas_limit, fw_size;
+    bool kernel_le = false;
     char *filename;
 
     msi_supported = true;
@@ -1175,8 +1190,6 @@
         }
         env = &cpu->env;
 
-        xics_cpu_setup(spapr->icp, cpu);
-
         /* Set time-base frequency to 512 MHz */
         cpu_ppc_tb_init(env, TIMEBASE_FREQ);
 
@@ -1190,6 +1203,8 @@
             kvmppc_set_papr(cpu);
         }
 
+        xics_cpu_setup(spapr->icp, cpu);
+
         qemu_register_reset(spapr_cpu_reset, cpu);
     }
 
@@ -1282,6 +1297,12 @@
         kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
                                NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
         if (kernel_size < 0) {
+            kernel_size = load_elf(kernel_filename,
+                                   translate_kernel_address, NULL,
+                                   NULL, &lowaddr, NULL, 0, ELF_MACHINE, 0);
+            kernel_le = kernel_size > 0;
+        }
+        if (kernel_size < 0) {
             kernel_size = load_image_targphys(kernel_filename,
                                               KERNEL_LOAD_ADDR,
                                               load_limit - KERNEL_LOAD_ADDR);
@@ -1329,9 +1350,8 @@
                          &savevm_htab_handlers, spapr);
 
     /* Prepare the device tree */
-    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
-                                            initrd_base, initrd_size,
-                                            kernel_size,
+    spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size,
+                                            kernel_size, kernel_le,
                                             boot_device, kernel_cmdline,
                                             spapr->epow_irq);
     assert(spapr->fdt_skel != NULL);
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index f10ba8a..f755a53 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -521,9 +521,9 @@
                            target_ulong opcode, target_ulong *args)
 {
     target_ulong rtas_r3 = args[0];
-    uint32_t token = ldl_be_phys(rtas_r3);
-    uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
-    uint32_t nret = ldl_be_phys(rtas_r3 + 8);
+    uint32_t token = rtas_ld(rtas_r3, 0);
+    uint32_t nargs = rtas_ld(rtas_r3, 1);
+    uint32_t nret = rtas_ld(rtas_r3, 2);
 
     return spapr_rtas_call(cpu, spapr, token, nargs, rtas_r3 + 12,
                            nret, rtas_r3 + 12 + 4*nargs);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 9b6ee32..edb4cb0 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -432,6 +432,17 @@
     qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
 }
 
+static PCIINTxRoute spapr_route_intx_pin_to_irq(void *opaque, int pin)
+{
+    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(opaque);
+    PCIINTxRoute route;
+
+    route.mode = PCI_INTX_ENABLED;
+    route.irq = sphb->lsi_table[pin].irq;
+
+    return route;
+}
+
 /*
  * MSI/MSIX memory region implementation.
  * The handler handles both MSI and MSIX.
@@ -610,6 +621,8 @@
 
     pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
 
+    pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq);
+
     QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
 
     /* Initialize the LSI table */
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index cd67db5..f93a81c 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1239,7 +1239,7 @@
 
     css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
 
-    qdev_free(dev);
+    object_unparent(OBJECT(dev));
     return 0;
 }
 
diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
index 99bf8ec..48c8b82 100644
--- a/hw/scsi/esp-pci.c
+++ b/hw/scsi/esp-pci.c
@@ -361,7 +361,7 @@
                           "esp-io", 0x80);
 
     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
-    s->irq = dev->irq[0];
+    s->irq = pci_allocate_irq(dev);
 
     scsi_bus_new(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info, NULL);
     if (!d->hotplugged) {
@@ -378,6 +378,7 @@
 {
     PCIESPState *pci = PCI_ESP(d);
 
+    qemu_free_irq(pci->esp.irq);
     memory_region_destroy(&pci->io);
 }
 
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 36e5f50..cb30414 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -437,7 +437,7 @@
                 level, s->dstat, s->sist1, s->sist0);
         last_level = level;
     }
-    qemu_set_irq(d->irq[0], level);
+    pci_set_irq(d, level);
 
     if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
         DPRINTF("Handled IRQs & disconnected, looking for pending "
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 09b51b3..7c5a1a2 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -535,7 +535,7 @@
                 msix_notify(pci_dev, 0);
             } else {
                 trace_megasas_irq_raise();
-                qemu_irq_raise(pci_dev->irq[0]);
+                pci_irq_assert(pci_dev);
             }
         }
     } else {
@@ -1936,7 +1936,7 @@
         s->intr_mask = val;
         if (!megasas_intr_enabled(s) && !msix_enabled(pci_dev)) {
             trace_megasas_irq_lower();
-            qemu_irq_lower(pci_dev->irq[0]);
+            pci_irq_deassert(pci_dev);
         }
         if (megasas_intr_enabled(s)) {
             trace_megasas_intr_enabled();
@@ -1952,7 +1952,7 @@
             stl_le_phys(s->producer_pa, s->reply_queue_head);
             if (!msix_enabled(pci_dev)) {
                 trace_megasas_irq_lower();
-                qemu_irq_lower(pci_dev->irq[0]);
+                pci_irq_deassert(pci_dev);
             }
         }
         break;
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 24ec52f..ea916d1 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -178,7 +178,7 @@
         d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
         assert(d);
         if (d->lun == dev->lun && dev != d) {
-            qdev_free(&d->qdev);
+            object_unparent(OBJECT(d));
         }
     }
 
@@ -231,13 +231,13 @@
     }
     if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
         error_setg(errp, "Setting drive property failed");
-        qdev_free(dev);
+        object_unparent(OBJECT(dev));
         return NULL;
     }
     object_property_set_bool(OBJECT(dev), true, "realized", &err);
     if (err != NULL) {
         error_propagate(errp, err);
-        qdev_free(dev);
+        object_unparent(OBJECT(dev));
         return NULL;
     }
     return SCSI_DEVICE(dev);
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index 2a26042..c0c46d7 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -1223,6 +1223,7 @@
     k->dt_type = "vscsi";
     k->dt_compatible = "IBM,v-scsi";
     k->signal_mask = 0x00000001;
+    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     dc->props = spapr_vscsi_properties;
     k->rtce_window_size = 0x10000000;
     dc->vmsd = &vmstate_spapr_vscsi;
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 819d671..94b328f 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -330,7 +330,7 @@
         return;
     }
 
-    qemu_set_irq(d->irq[0], !!should_raise);
+    pci_set_irq(d, !!should_raise);
 }
 
 static void
diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c
index 1ff37f5..904a966 100644
--- a/hw/sh4/shix.c
+++ b/hw/sh4/shix.c
@@ -30,9 +30,11 @@
 #include "hw/hw.h"
 #include "hw/sh4/sh.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
 #include "hw/boards.h"
 #include "hw/loader.h"
 #include "exec/address-spaces.h"
+#include "qemu/error-report.h"
 
 #define BIOS_FILENAME "shix_bios.bin"
 #define BIOS_ADDRESS 0xA0000000
@@ -50,7 +52,6 @@
     if (!cpu_model)
         cpu_model = "any";
 
-    printf("Initializing CPU\n");
     cpu = cpu_sh4_init(cpu_model);
     if (cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
@@ -58,16 +59,13 @@
     }
 
     /* Allocate memory space */
-    printf("Allocating ROM\n");
     memory_region_init_ram(rom, NULL, "shix.rom", 0x4000);
     vmstate_register_ram_global(rom);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(sysmem, 0x00000000, rom);
-    printf("Allocating SDRAM 1\n");
     memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000);
     vmstate_register_ram_global(&sdram[0]);
     memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
-    printf("Allocating SDRAM 2\n");
     memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000);
     vmstate_register_ram_global(&sdram[1]);
     memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
@@ -75,20 +73,16 @@
     /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
     if (bios_name == NULL)
         bios_name = BIOS_FILENAME;
-    printf("%s: load BIOS '%s'\n", __func__, bios_name);
     ret = load_image_targphys(bios_name, 0, 0x4000);
-    if (ret < 0) {		/* Check bios size */
-	fprintf(stderr, "ret=%d\n", ret);
-	fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
-		bios_name);
-	exit(1);
+    if (ret < 0 && !qtest_enabled()) {
+        error_report("Could not load SHIX bios '%s'", bios_name);
+        exit(1);
     }
 
     /* Register peripherals */
     s = sh7750_init(cpu, sysmem);
     /* XXXXX Check success */
     tc58128_init(s, "shix_linux_nand.bin", NULL);
-    fprintf(stderr, "initialization terminated\n");
 }
 
 static QEMUMachine shix_machine = {
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 390f3e4..c583c3d 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -26,6 +26,7 @@
 #include "hw/ptimer.h"
 #include "sysemu/char.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
 #include "hw/boards.h"
 #include "hw/loader.h"
 #include "elf.h"
@@ -178,7 +179,7 @@
             fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
             exit(1);
         }
-    } else if (kernel_filename == NULL) {
+    } else if (kernel_filename == NULL && !qtest_enabled()) {
         fprintf(stderr, "Can't read bios image %s\n", filename);
         exit(1);
     }
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 8020c9f..d9f9494 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -19,7 +19,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw/sysbus.h"
+#include "hw/timer/arm_mptimer.h"
 #include "qemu/timer.h"
 #include "qom/cpu.h"
 
@@ -27,34 +27,6 @@
  * which is used in both the ARM11MPCore and Cortex-A9MP.
  */
 
-#define MAX_CPUS 4
-
-/* State of a single timer or watchdog block */
-typedef struct {
-    uint32_t count;
-    uint32_t load;
-    uint32_t control;
-    uint32_t status;
-    int64_t tick;
-    QEMUTimer *timer;
-    qemu_irq irq;
-    MemoryRegion iomem;
-} TimerBlock;
-
-#define TYPE_ARM_MPTIMER "arm_mptimer"
-#define ARM_MPTIMER(obj) \
-    OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER)
-
-typedef struct {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    uint32_t num_cpu;
-    TimerBlock timerblock[MAX_CPUS];
-    MemoryRegion iomem;
-} ARMMPTimerState;
-
 static inline int get_current_cpu(ARMMPTimerState *s)
 {
     if (current_cpu->cpu_index >= s->num_cpu) {
@@ -225,13 +197,24 @@
     }
 }
 
-static int arm_mptimer_init(SysBusDevice *dev)
+static void arm_mptimer_init(Object *obj)
 {
+    ARMMPTimerState *s = ARM_MPTIMER(obj);
+
+    memory_region_init_io(&s->iomem, obj, &arm_thistimer_ops, s,
+                          "arm_mptimer_timer", 0x20);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static void arm_mptimer_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     ARMMPTimerState *s = ARM_MPTIMER(dev);
     int i;
 
-    if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) {
-        hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS);
+    if (s->num_cpu < 1 || s->num_cpu > ARM_MPTIMER_MAX_CPUS) {
+        hw_error("%s: num-cpu must be between 1 and %d\n",
+                 __func__, ARM_MPTIMER_MAX_CPUS);
     }
     /* We implement one timer block per CPU, and expose multiple MMIO regions:
      *  * region 0 is "timer for this core"
@@ -243,19 +226,14 @@
      *  * timer for core 1
      * and so on.
      */
-    memory_region_init_io(&s->iomem, OBJECT(s), &arm_thistimer_ops, s,
-                          "arm_mptimer_timer", 0x20);
-    sysbus_init_mmio(dev, &s->iomem);
     for (i = 0; i < s->num_cpu; i++) {
         TimerBlock *tb = &s->timerblock[i];
         tb->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, timerblock_tick, tb);
-        sysbus_init_irq(dev, &tb->irq);
+        sysbus_init_irq(sbd, &tb->irq);
         memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
                               "arm_mptimer_timerblock", 0x20);
-        sysbus_init_mmio(dev, &tb->iomem);
+        sysbus_init_mmio(sbd, &tb->iomem);
     }
-
-    return 0;
 }
 
 static const VMStateDescription vmstate_timerblock = {
@@ -292,9 +270,8 @@
 static void arm_mptimer_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
 
-    sbc->init = arm_mptimer_init;
+    dc->realize = arm_mptimer_realize;
     dc->vmsd = &vmstate_arm_mptimer;
     dc->reset = arm_mptimer_reset;
     dc->no_user = 1;
@@ -305,6 +282,7 @@
     .name          = TYPE_ARM_MPTIMER,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ARMMPTimerState),
+    .instance_init = arm_mptimer_init,
     .class_init    = arm_mptimer_class_init,
 };
 
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index fcd22ae..2eb75ea 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -757,6 +757,11 @@
     dc->props = hpet_device_properties;
 }
 
+bool hpet_find(void)
+{
+    return object_resolve_path_type("", TYPE_HPET, NULL);
+}
+
 static const TypeInfo hpet_device_info = {
     .name          = TYPE_HPET,
     .parent        = TYPE_SYS_BUS_DEVICE,
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 7230a6e..b011638 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -70,7 +70,6 @@
     uint64_t last_update;
     int64_t offset;
     qemu_irq irq;
-    qemu_irq sqw_irq;
     int it_shift;
     /* periodic timer */
     QEMUTimer *periodic_timer;
@@ -151,8 +150,7 @@
 
     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
     if (period_code != 0
-        && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
-            || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
+        && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
         if (period_code <= 2)
             period_code += 7;
         /* period in 32 Khz cycles */
@@ -202,11 +200,6 @@
 #endif
         qemu_irq_raise(s->irq);
     }
-    if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
-        /* Not square wave at all but we don't want 2048Hz interrupts!
-           Must be seen as a pulse.  */
-        qemu_irq_raise(s->sqw_irq);
-    }
 }
 
 /* handle update-ended timer */
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index a900061..e05cbc1 100644
--- a/hw/unicore32/puv3.c
+++ b/hw/unicore32/puv3.c
@@ -17,6 +17,7 @@
 #include "hw/boards.h"
 #include "hw/loader.h"
 #include "hw/i386/pc.h"
+#include "sysemu/qtest.h"
 
 #undef DEBUG_PUV3
 #include "hw/unicore32/puv3.h"
@@ -84,6 +85,9 @@
 {
     int size;
 
+    if (kernel_filename == NULL && qtest_enabled()) {
+        return;
+    }
     assert(kernel_filename != NULL);
 
     /* only zImage format supported */
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 72d5b92..ca329be 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -356,8 +356,9 @@
 
 void usb_unregister_port(USBBus *bus, USBPort *port)
 {
-    if (port->dev)
-        qdev_free(&port->dev->qdev);
+    if (port->dev) {
+        object_unparent(OBJECT(port->dev));
+    }
     QTAILQ_REMOVE(&bus->free, port, next);
     bus->nfree--;
 }
@@ -505,7 +506,7 @@
         return -1;
     dev = port->dev;
 
-    qdev_free(&dev->qdev);
+    object_unparent(OBJECT(dev));
     return 0;
 }
 
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 660d774..4c532b7 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -637,7 +637,6 @@
     unsigned int out_ptr;
     uint8_t out_buf[2048];
 
-    USBPacket *inpkt;
     unsigned int in_ptr, in_len;
     uint8_t in_buf[2048];
 
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 1d81ac2..c434c56 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -703,7 +703,7 @@
         return NULL;
     }
     if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
-        qdev_free(&dev->qdev);
+        object_unparent(OBJECT(dev));
         return NULL;
     }
     if (qdev_init(&dev->qdev) < 0)
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 4d21a0b..0c98594 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -60,7 +60,7 @@
     pci_conf[0x6e] = 0x00;
     pci_conf[0x6f] = 0xc0;  /* USBLEFCTLSTS */
 
-    s->irq = dev->irq[3];
+    s->irq = pci_allocate_irq(dev);
     s->as = pci_get_address_space(dev);
 
     usb_ehci_realize(s, DEVICE(dev), NULL);
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 0396e33..e38cdeb 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1946,7 +1946,7 @@
                       pci_get_address_space(dev)) != 0) {
         return -1;
     }
-    ohci->state.irq = dev->irq[0];
+    ohci->state.irq = pci_allocate_irq(dev);
 
     pci_register_bar(dev, 0, 0, &ohci->state.mem);
     return 0;
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index becc7fa..238d1d2 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -164,7 +164,6 @@
 
     /* Interrupts that should be raised at the end of the current frame.  */
     uint32_t pending_int_mask;
-    int irq_pin;
 
     /* Active packets */
     QTAILQ_HEAD(, UHCIQueue) queues;
@@ -381,7 +380,7 @@
     } else {
         level = 0;
     }
-    qemu_set_irq(s->dev.irq[s->irq_pin], level);
+    pci_set_irq(&s->dev, level);
 }
 
 static void uhci_reset(void *opaque)
@@ -1240,8 +1239,7 @@
     /* TODO: reset value should be 0. */
     pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
 
-    s->irq_pin = u->info.irq_pin;
-    pci_config_set_interrupt_pin(pci_conf, s->irq_pin + 1);
+    pci_config_set_interrupt_pin(pci_conf, u->info.irq_pin + 1);
 
     if (s->masterbus) {
         USBPort *ports[NB_PORTS];
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 469c24d..835f65e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -346,7 +346,6 @@
     QEMUSGList sgl;
     bool running_async;
     bool running_retry;
-    bool cancelled;
     bool complete;
     bool int_req;
     unsigned int iso_pkts;
@@ -374,7 +373,6 @@
     dma_addr_t pctx;
     unsigned int sct;
     XHCIRing ring;
-    XHCIStreamContext *sstreams;
 };
 
 struct XHCIEPContext {
@@ -449,7 +447,6 @@
     /*< public >*/
 
     USBBus bus;
-    qemu_irq irq;
     MemoryRegion mem;
     MemoryRegion mem_cap;
     MemoryRegion mem_oper;
@@ -507,6 +504,7 @@
                          unsigned int epid, unsigned int streamid);
 static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
                                 unsigned int epid);
+static void xhci_xfer_report(XHCITransfer *xfer);
 static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v);
 static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v);
 static USBEndpoint *xhci_epid_to_usbep(XHCIState *xhci,
@@ -739,7 +737,7 @@
     }
 
     trace_usb_xhci_irq_intx(level);
-    qemu_set_irq(xhci->irq, level);
+    pci_set_irq(pci_dev, level);
 }
 
 static void xhci_msix_update(XHCIState *xhci, int v)
@@ -797,7 +795,7 @@
 
     if (v == 0) {
         trace_usb_xhci_irq_intx(1);
-        qemu_set_irq(xhci->irq, 1);
+        pci_irq_assert(pci_dev);
     }
 }
 
@@ -1133,7 +1131,6 @@
 
     for (i = 0; i < epctx->nr_pstreams; i++) {
         epctx->pstreams[i].sct = -1;
-        g_free(epctx->pstreams[i].sstreams);
     }
 }
 
@@ -1146,15 +1143,8 @@
 
 static void xhci_free_streams(XHCIEPContext *epctx)
 {
-    int i;
-
     assert(epctx->pstreams != NULL);
 
-    if (!epctx->lsa) {
-        for (i = 0; i < epctx->nr_pstreams; i++) {
-            g_free(epctx->pstreams[i].sstreams);
-        }
-    }
     g_free(epctx->pstreams);
     epctx->pstreams = NULL;
     epctx->nr_pstreams = 0;
@@ -1196,6 +1186,7 @@
 static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
                               XHCIStreamContext *sctx, uint32_t state)
 {
+    XHCIRing *ring = NULL;
     uint32_t ctx[5];
     uint32_t ctx2[2];
 
@@ -1206,6 +1197,7 @@
     /* update ring dequeue ptr */
     if (epctx->nr_pstreams) {
         if (sctx != NULL) {
+            ring = &sctx->ring;
             xhci_dma_read_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2));
             ctx2[0] &= 0xe;
             ctx2[0] |= sctx->ring.dequeue | sctx->ring.ccs;
@@ -1213,8 +1205,12 @@
             xhci_dma_write_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2));
         }
     } else {
-        ctx[2] = epctx->ring.dequeue | epctx->ring.ccs;
-        ctx[3] = (epctx->ring.dequeue >> 16) >> 16;
+        ring = &epctx->ring;
+    }
+    if (ring) {
+        ctx[2] = ring->dequeue | ring->ccs;
+        ctx[3] = (ring->dequeue >> 16) >> 16;
+
         DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n",
                 epctx->pctx, state, ctx[3], ctx[2]);
     }
@@ -1312,15 +1308,18 @@
     return CC_SUCCESS;
 }
 
-static int xhci_ep_nuke_one_xfer(XHCITransfer *t)
+static int xhci_ep_nuke_one_xfer(XHCITransfer *t, TRBCCode report)
 {
     int killed = 0;
 
+    if (report && (t->running_async || t->running_retry)) {
+        t->status = report;
+        xhci_xfer_report(t);
+    }
+
     if (t->running_async) {
         usb_cancel_packet(&t->packet);
         t->running_async = 0;
-        t->cancelled = 1;
-        DPRINTF("xhci: cancelling transfer, waiting for it to complete\n");
         killed = 1;
     }
     if (t->running_retry) {
@@ -1330,6 +1329,7 @@
             timer_del(epctx->kick_timer);
         }
         t->running_retry = 0;
+        killed = 1;
     }
     if (t->trbs) {
         g_free(t->trbs);
@@ -1342,7 +1342,7 @@
 }
 
 static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
-                               unsigned int epid)
+                               unsigned int epid, TRBCCode report)
 {
     XHCISlot *slot;
     XHCIEPContext *epctx;
@@ -1363,7 +1363,10 @@
 
     xferi = epctx->next_xfer;
     for (i = 0; i < TD_QUEUE; i++) {
-        killed += xhci_ep_nuke_one_xfer(&epctx->transfers[xferi]);
+        killed += xhci_ep_nuke_one_xfer(&epctx->transfers[xferi], report);
+        if (killed) {
+            report = 0; /* Only report once */
+        }
         epctx->transfers[xferi].packet.ep = NULL;
         xferi = (xferi + 1) % TD_QUEUE;
     }
@@ -1393,7 +1396,7 @@
         return CC_SUCCESS;
     }
 
-    xhci_ep_nuke_xfers(xhci, slotid, epid);
+    xhci_ep_nuke_xfers(xhci, slotid, epid, 0);
 
     epctx = slot->eps[epid-1];
 
@@ -1435,7 +1438,7 @@
         return CC_EP_NOT_ENABLED_ERROR;
     }
 
-    if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) {
+    if (xhci_ep_nuke_xfers(xhci, slotid, epid, CC_STOPPED) > 0) {
         fprintf(stderr, "xhci: FIXME: endpoint stopped w/ xfers running, "
                 "data might be lost\n");
     }
@@ -1480,7 +1483,7 @@
         return CC_CONTEXT_STATE_ERROR;
     }
 
-    if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) {
+    if (xhci_ep_nuke_xfers(xhci, slotid, epid, 0) > 0) {
         fprintf(stderr, "xhci: FIXME: endpoint reset w/ xfers running, "
                 "data might be lost\n");
     }
@@ -1737,14 +1740,12 @@
         xfer->running_async = 1;
         xfer->running_retry = 0;
         xfer->complete = 0;
-        xfer->cancelled = 0;
         return 0;
     } else if (xfer->packet.status == USB_RET_NAK) {
         trace_usb_xhci_xfer_nak(xfer);
         xfer->running_async = 0;
         xfer->running_retry = 1;
         xfer->complete = 0;
-        xfer->cancelled = 0;
         return 0;
     } else {
         xfer->running_async = 0;
@@ -2475,7 +2476,7 @@
 
     for (ep = 0; ep < 31; ep++) {
         if (xhci->slots[slot].eps[ep]) {
-            xhci_ep_nuke_xfers(xhci, slot+1, ep+1);
+            xhci_ep_nuke_xfers(xhci, slot + 1, ep + 1, 0);
         }
     }
     xhci->slots[slot].uport = NULL;
@@ -3290,7 +3291,7 @@
     XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
 
     if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
-        xhci_ep_nuke_one_xfer(xfer);
+        xhci_ep_nuke_one_xfer(xfer, 0);
         return;
     }
     xhci_complete_packet(xfer);
@@ -3433,8 +3434,6 @@
 
     xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);
 
-    xhci->irq = dev->irq[0];
-
     memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);
     memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci,
                           "capabilities", LEN_CAP);
diff --git a/hw/usb/host-legacy.c b/hw/usb/host-legacy.c
index 3a5f705..3cc9c42 100644
--- a/hw/usb/host-legacy.c
+++ b/hw/usb/host-legacy.c
@@ -132,7 +132,7 @@
     return dev;
 
 fail:
-    qdev_free(&dev->qdev);
+    object_unparent(OBJECT(dev));
     return NULL;
 }
 
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 128955d..fd320cd8 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -137,6 +137,7 @@
 static void usb_host_auto_check(void *unused);
 static void usb_host_release_interfaces(USBHostDevice *s);
 static void usb_host_nodev(USBHostDevice *s);
+static void usb_host_detach_kernel(USBHostDevice *s);
 static void usb_host_attach_kernel(USBHostDevice *s);
 
 /* ------------------------------------------------------------------------ */
@@ -787,10 +788,13 @@
         goto fail;
     }
 
-    libusb_get_device_descriptor(dev, &s->ddesc);
     s->dev     = dev;
     s->bus_num = bus_num;
     s->addr    = addr;
+
+    usb_host_detach_kernel(s);
+
+    libusb_get_device_descriptor(dev, &s->ddesc);
     usb_host_get_port(s->dev, s->port, sizeof(s->port));
 
     usb_ep_init(udev);
@@ -992,15 +996,14 @@
     udev->ninterfaces   = 0;
     udev->configuration = 0;
 
-    if (configuration == 0) {
-        /* address state - ignore */
-        return USB_RET_SUCCESS;
-    }
-
     usb_host_detach_kernel(s);
 
     rc = libusb_get_active_config_descriptor(s->dev, &conf);
     if (rc != 0) {
+        if (rc == LIBUSB_ERROR_NOT_FOUND) {
+            /* address state - ignore */
+            return USB_RET_SUCCESS;
+        }
         return USB_RET_STALL;
     }
 
@@ -1052,7 +1055,6 @@
     trace_usb_host_set_config(s->bus_num, s->addr, config);
 
     usb_host_release_interfaces(s);
-    usb_host_detach_kernel(s);
     rc = libusb_set_configuration(s->dh, config);
     if (rc != 0) {
         usb_host_libusb_error("libusb_set_configuration", rc);
@@ -1256,16 +1258,14 @@
 static void usb_host_handle_reset(USBDevice *udev)
 {
     USBHostDevice *s = USB_HOST_DEVICE(udev);
+    int rc;
 
     trace_usb_host_reset(s->bus_num, s->addr);
 
-    if (udev->configuration == 0) {
-        return;
+    rc = libusb_reset_device(s->dh);
+    if (rc != 0) {
+        usb_host_nodev(s);
     }
-    usb_host_release_interfaces(s);
-    libusb_reset_device(s->dh);
-    usb_host_claim_interfaces(s, 0);
-    usb_host_ep_update(s);
 }
 
 /*
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 6849a01..e6b103c 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -67,7 +67,6 @@
 /* Destroy the VirtIODevice */
 void virtio_bus_destroy_device(VirtioBusState *bus)
 {
-    DeviceState *qdev;
     BusState *qbus = BUS(bus);
     VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
     DPRINTF("%s: remove device.\n", qbus->name);
@@ -76,8 +75,7 @@
         if (klass->device_unplug != NULL) {
             klass->device_unplug(qbus->parent);
         }
-        qdev = DEVICE(bus->vdev);
-        qdev_free(qdev);
+        object_unparent(OBJECT(bus->vdev));
         bus->vdev = NULL;
     }
 }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 4825802..7647be8 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -116,7 +116,7 @@
     if (msix_enabled(&proxy->pci_dev))
         msix_notify(&proxy->pci_dev, vector);
     else
-        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
+        pci_set_irq(&proxy->pci_dev, proxy->vdev->isr & 1);
 }
 
 static void virtio_pci_save_config(DeviceState *d, QEMUFile *f)
@@ -362,7 +362,7 @@
         /* reading from the ISR also clears it. */
         ret = vdev->isr;
         vdev->isr = 0;
-        qemu_set_irq(proxy->pci_dev.irq[0], 0);
+        pci_irq_deassert(&proxy->pci_dev);
         break;
     case VIRTIO_MSI_CONFIG_VECTOR:
         ret = vdev->config_vector;
diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c
index 79bf0b3..70875e4 100644
--- a/hw/xen/xen_platform.c
+++ b/hw/xen/xen_platform.c
@@ -95,7 +95,7 @@
     if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
             PCI_CLASS_NETWORK_ETHERNET
             && strcmp(d->name, "xen-pci-passthrough") != 0) {
-        qdev_free(DEVICE(d));
+        object_unparent(OBJECT(d));
     }
 }
 
diff --git a/include/block/block_int.h b/include/block/block_int.h
index a48731d..1666066 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -156,8 +156,11 @@
 
     const char *protocol_name;
     int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
+
     int64_t (*bdrv_getlength)(BlockDriverState *bs);
+    bool has_variable_length;
     int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
+
     int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
                                  const uint8_t *buf, int nb_sectors);
 
diff --git a/include/block/coroutine.h b/include/block/coroutine.h
index 4232569..4d5c0cf 100644
--- a/include/block/coroutine.h
+++ b/include/block/coroutine.h
@@ -216,6 +216,15 @@
 void coroutine_fn co_sleep_ns(QEMUClockType type, int64_t ns);
 
 /**
+ * Yield the coroutine for a given duration
+ *
+ * Behaves similarly to co_sleep_ns(), but the sleeping coroutine will be
+ * resumed when using qemu_aio_wait().
+ */
+void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
+                                  int64_t ns);
+
+/**
  * Yield until a file descriptor becomes readable
  *
  * Note that this function clobbers the handlers for the file descriptor.
diff --git a/include/elf.h b/include/elf.h
index 58bfbf8..b818091 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1359,6 +1359,9 @@
 #define NT_S390_TODPREG 0x303           /* s390 TOD programmable register */
 #define NT_S390_TODCMP  0x302           /* s390 TOD clock comparator register */
 #define NT_S390_TIMER   0x301           /* s390 timer register */
+#define NT_PPC_VMX       0x100          /* PowerPC Altivec/VMX registers */
+#define NT_PPC_SPE       0x101          /* PowerPC SPE/EVR registers */
+#define NT_PPC_VSX       0x102          /* PowerPC VSX registers */
 
 
 /* Note header in a PT_NOTE section */
diff --git a/include/exec/memory.h b/include/exec/memory.h
index ebe0d24..480dfbf 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -153,7 +153,7 @@
     bool flush_coalesced_mmio;
     MemoryRegion *alias;
     hwaddr alias_offset;
-    unsigned priority;
+    int priority;
     bool may_overlap;
     QTAILQ_HEAD(subregions, MemoryRegion) subregions;
     QTAILQ_ENTRY(MemoryRegion) subregions_link;
@@ -779,7 +779,7 @@
 void memory_region_add_subregion_overlap(MemoryRegion *mr,
                                          hwaddr offset,
                                          MemoryRegion *subregion,
-                                         unsigned priority);
+                                         int priority);
 
 /**
  * memory_region_get_ram_addr: Get the ram address associated with a memory
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index 51733d3..6bbcb17 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -165,6 +165,10 @@
 extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
+uint8_t *acpi_table_first(void);
+uint8_t *acpi_table_next(uint8_t *current);
+unsigned acpi_table_len(void *current);
 void acpi_table_add(const QemuOpts *opts, Error **errp);
+void acpi_table_add_builtin(const QemuOpts *opts, Error **errp);
 
 #endif /* !QEMU_HW_ACPI_H */
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index b1fe71f..82fcf9f 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -49,4 +49,6 @@
 void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
 extern const VMStateDescription vmstate_ich9_pm;
 
+void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp);
+
 #endif /* HW_ACPI_ICH9_H */
diff --git a/include/hw/acpi/piix4.h b/include/hw/acpi/piix4.h
new file mode 100644
index 0000000..65e6fd7
--- /dev/null
+++ b/include/hw/acpi/piix4.h
@@ -0,0 +1,8 @@
+#ifndef HW_ACPI_PIIX4_H
+#define HW_ACPI_PIIX4_H
+
+#include "qemu/typedefs.h"
+
+Object *piix4_pm_find(void);
+
+#endif
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
index 668232c..a4e1a66 100644
--- a/include/hw/arm/pxa.h
+++ b/include/hw/arm/pxa.h
@@ -97,7 +97,7 @@
 PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
                                       hwaddr base);
 int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card);
-int pxa2xx_pcmcia_dettach(void *opaque);
+int pxa2xx_pcmcia_detach(void *opaque);
 void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq);
 
 /* pxa2xx_keypad.c */
diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h
new file mode 100644
index 0000000..b423533
--- /dev/null
+++ b/include/hw/cpu/a15mpcore.h
@@ -0,0 +1,44 @@
+/*
+ * Cortex-A15MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2012 Linaro Limited.
+ * Written by Peter Maydell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef HW_CPU_A15MPCORE_H
+#define HW_CPU_A15MPCORE_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic.h"
+
+/* A15MP private memory region.  */
+
+#define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
+#define A15MPCORE_PRIV(obj) \
+    OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV)
+
+typedef struct A15MPPrivState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    uint32_t num_cpu;
+    uint32_t num_irq;
+    MemoryRegion container;
+
+    GICState gic;
+} A15MPPrivState;
+
+#endif
diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h
new file mode 100644
index 0000000..010489b
--- /dev/null
+++ b/include/hw/cpu/a9mpcore.h
@@ -0,0 +1,37 @@
+/*
+ * Cortex-A9MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2009 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited.
+ * Written by Paul Brook, Peter Maydell.
+ *
+ * This code is licensed under the GPL.
+ */
+#ifndef HW_CPU_A9MPCORE_H
+#define HW_CPU_A9MPCORE_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/misc/a9scu.h"
+#include "hw/timer/arm_mptimer.h"
+
+#define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
+#define A9MPCORE_PRIV(obj) \
+    OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV)
+
+typedef struct A9MPPrivState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    uint32_t num_cpu;
+    MemoryRegion container;
+    uint32_t num_irq;
+
+    GICState gic;
+    A9SCUState scu;
+    ARMMPTimerState mptimer;
+    ARMMPTimerState wdt;
+} A9MPPrivState;
+
+#endif
diff --git a/include/hw/cpu/arm11mpcore.h b/include/hw/cpu/arm11mpcore.h
new file mode 100644
index 0000000..6196109
--- /dev/null
+++ b/include/hw/cpu/arm11mpcore.h
@@ -0,0 +1,35 @@
+/*
+ * ARM11MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_CPU_ARM11MPCORE_H
+#define HW_CPU_ARM11MPCORE_H
+
+#include "hw/sysbus.h"
+#include "hw/misc/arm11scu.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/timer/arm_mptimer.h"
+
+#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
+#define ARM11MPCORE_PRIV(obj) \
+    OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV)
+
+typedef struct ARM11MPCorePriveState {
+    SysBusDevice parent_obj;
+
+    uint32_t num_cpu;
+    MemoryRegion container;
+    uint32_t num_irq;
+
+    ARM11SCUState scu;
+    GICState gic;
+    ARMMPTimerState mptimer;
+    ARMMPTimerState wdtimer;
+} ARM11MPCorePriveState;
+
+#endif
diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h
index c5f637b..4a68b35 100644
--- a/include/hw/i386/ich9.h
+++ b/include/hw/i386/ich9.h
@@ -66,6 +66,8 @@
     qemu_irq *ioapic;
 } ICH9LPCState;
 
+Object *ich9_lpc_find(void);
+
 #define Q35_MASK(bit, ms_bit, ls_bit) \
 ((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
 
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 6083839..57e8d16 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -9,6 +9,9 @@
 #include "hw/i386/ioapic.h"
 
 #include "qemu/range.h"
+#include "qemu/bitmap.h"
+#include "sysemu/sysemu.h"
+#include "hw/pci/pci.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -17,10 +20,27 @@
     Range w64;
 } PcPciInfo;
 
+#define ACPI_PM_PROP_S3_DISABLED "disable_s3"
+#define ACPI_PM_PROP_S4_DISABLED "disable_s4"
+#define ACPI_PM_PROP_S4_VAL "s4_val"
+#define ACPI_PM_PROP_SCI_INT "sci_int"
+#define ACPI_PM_PROP_ACPI_ENABLE_CMD "acpi_enable_cmd"
+#define ACPI_PM_PROP_ACPI_DISABLE_CMD "acpi_disable_cmd"
+#define ACPI_PM_PROP_PM_IO_BASE "pm_io_base"
+#define ACPI_PM_PROP_GPE0_BLK "gpe0_blk"
+#define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len"
+
 struct PcGuestInfo {
     bool has_pci_info;
     bool isapc_ram_fw;
+    hwaddr ram_size;
+    unsigned apic_id_limit;
+    bool apic_xrupt_override;
+    uint64_t numa_nodes;
+    uint64_t *node_mem;
+    uint64_t *node_cpu;
     FWCfgState *fw_cfg;
+    bool has_acpi_build;
 };
 
 /* parallel.c */
@@ -173,6 +193,7 @@
                     MemoryRegion *pci_memory,
                     MemoryRegion *ram_memory);
 
+PCIBus *find_i440fx(void);
 /* piix4.c */
 extern PCIDevice *piix4_dev;
 int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
@@ -215,6 +236,7 @@
 
 /* pvpanic.c */
 void pvpanic_init(ISABus *bus);
+uint16_t pvpanic_port(void);
 
 /* e820 types */
 #define E820_RAM        1
@@ -238,6 +260,14 @@
             .driver   = "qemu32-" TYPE_X86_CPU,\
             .property = "model",\
             .value    = stringify(3),\
+        },{\
+            .driver   = "i440FX-pcihost",\
+            .property = "short_root_bus",\
+            .value    = stringify(1),\
+        },{\
+            .driver   = "q35-pcihost",\
+            .property = "short_root_bus",\
+            .value    = stringify(1),\
         }
 
 #define PC_COMPAT_1_5 \
@@ -274,6 +304,14 @@
             .driver = TYPE_X86_CPU,\
             .property = "pmu",\
             .value = "on",\
+        },{\
+            .driver   = "i440FX-pcihost",\
+            .property = "short_root_bus",\
+            .value    = stringify(0),\
+        },{\
+            .driver   = "q35-pcihost",\
+            .property = "short_root_bus",\
+            .value    = stringify(0),\
         }
 
 #define PC_COMPAT_1_4 \
diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h
new file mode 100644
index 0000000..0971e37
--- /dev/null
+++ b/include/hw/intc/arm_gic.h
@@ -0,0 +1,42 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ARM_GIC_H
+#define HW_ARM_GIC_H
+
+#include "arm_gic_common.h"
+
+#define TYPE_ARM_GIC "arm_gic"
+#define ARM_GIC(obj) \
+     OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
+#define ARM_GIC_CLASS(klass) \
+     OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
+#define ARM_GIC_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
+
+typedef struct ARMGICClass {
+    /*< private >*/
+    ARMGICCommonClass parent_class;
+    /*< public >*/
+
+    DeviceRealize parent_realize;
+} ARMGICClass;
+
+#endif
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
new file mode 100644
index 0000000..4f381bd
--- /dev/null
+++ b/include/hw/intc/arm_gic_common.h
@@ -0,0 +1,92 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ARM_GIC_COMMON_H
+#define HW_ARM_GIC_COMMON_H
+
+#include "hw/sysbus.h"
+
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
+/* First 32 are private to each CPU (SGIs and PPIs). */
+#define GIC_INTERNAL 32
+/* Maximum number of possible CPU interfaces, determined by GIC architecture */
+#define GIC_NCPU 8
+
+typedef struct gic_irq_state {
+    /* The enable bits are only banked for per-cpu interrupts.  */
+    uint8_t enabled;
+    uint8_t pending;
+    uint8_t active;
+    uint8_t level;
+    bool model; /* 0 = N:N, 1 = 1:N */
+    bool trigger; /* nonzero = edge triggered.  */
+} gic_irq_state;
+
+typedef struct GICState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    qemu_irq parent_irq[GIC_NCPU];
+    bool enabled;
+    bool cpu_enabled[GIC_NCPU];
+
+    gic_irq_state irq_state[GIC_MAXIRQ];
+    uint8_t irq_target[GIC_MAXIRQ];
+    uint8_t priority1[GIC_INTERNAL][GIC_NCPU];
+    uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
+    uint16_t last_active[GIC_MAXIRQ][GIC_NCPU];
+
+    uint16_t priority_mask[GIC_NCPU];
+    uint16_t running_irq[GIC_NCPU];
+    uint16_t running_priority[GIC_NCPU];
+    uint16_t current_pending[GIC_NCPU];
+
+    uint32_t num_cpu;
+
+    MemoryRegion iomem; /* Distributor */
+    /* This is just so we can have an opaque pointer which identifies
+     * both this GIC and which CPU interface we should be accessing.
+     */
+    struct GICState *backref[GIC_NCPU];
+    MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
+    uint32_t num_irq;
+    uint32_t revision;
+} GICState;
+
+#define TYPE_ARM_GIC_COMMON "arm_gic_common"
+#define ARM_GIC_COMMON(obj) \
+     OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
+#define ARM_GIC_COMMON_CLASS(klass) \
+     OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
+#define ARM_GIC_COMMON_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
+
+typedef struct ARMGICCommonClass {
+    /*< private >*/
+    SysBusDeviceClass parent_class;
+    /*< public >*/
+
+    void (*pre_save)(GICState *s);
+    void (*post_load)(GICState *s);
+} ARMGICCommonClass;
+
+#endif
diff --git a/include/hw/intc/realview_gic.h b/include/hw/intc/realview_gic.h
new file mode 100644
index 0000000..1783ea1
--- /dev/null
+++ b/include/hw/intc/realview_gic.h
@@ -0,0 +1,28 @@
+/*
+ * ARM RealView Emulation Baseboard Interrupt Controller
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_INTC_REALVIEW_GIC_H
+#define HW_INTC_REALVIEW_GIC_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic.h"
+
+#define TYPE_REALVIEW_GIC "realview_gic"
+#define REALVIEW_GIC(obj) \
+    OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC)
+
+typedef struct RealViewGICState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion container;
+
+    GICState gic;
+} RealViewGICState;
+
+#endif
diff --git a/include/hw/irq.h b/include/hw/irq.h
index 610e6b7..d08bc02 100644
--- a/include/hw/irq.h
+++ b/include/hw/irq.h
@@ -30,6 +30,12 @@
  */
 qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
 
+/*
+ * Allocates a single IRQ. The irq is assigned with a handler, an opaque
+ * data and the interrupt number.
+ */
+qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n);
+
 /* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
  * preserved. New IRQs are assigned the argument handler and opaque data.
  */
@@ -37,6 +43,7 @@
                                 void *opaque, int n);
 
 void qemu_free_irqs(qemu_irq *s);
+void qemu_free_irq(qemu_irq irq);
 
 /* Returns a new IRQ with opposite polarity.  */
 qemu_irq qemu_irq_invert(qemu_irq irq);
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 6145736..7a23d6b 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -40,11 +40,13 @@
 
 int rom_add_file(const char *file, const char *fw_dir,
                  hwaddr addr, int32_t bootindex);
-int rom_add_blob(const char *name, const void *blob, size_t len,
-                 hwaddr addr);
+void *rom_add_blob(const char *name, const void *blob, size_t len,
+                   hwaddr addr, const char *fw_file_name,
+                   FWCfgReadCallback fw_callback, void *callback_opaque);
 int rom_add_elf_program(const char *name, void *data, size_t datasize,
                         size_t romsize, hwaddr addr);
 int rom_load_all(void);
+void rom_load_done(void);
 void rom_set_fw(FWCfgState *f);
 int rom_copy(uint8_t *dest, hwaddr addr, size_t size);
 void *rom_ptr(hwaddr addr);
@@ -53,7 +55,7 @@
 #define rom_add_file_fixed(_f, _a, _i)          \
     rom_add_file(_f, NULL, _a, _i)
 #define rom_add_blob_fixed(_f, _b, _l, _a)      \
-    rom_add_blob(_f, _b, _l, _a)
+    rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL)
 
 #define PC_ROM_MIN_VGA     0xc0000
 #define PC_ROM_MIN_OPTION  0xc8000
diff --git a/include/hw/misc/a9scu.h b/include/hw/misc/a9scu.h
new file mode 100644
index 0000000..efb0c30
--- /dev/null
+++ b/include/hw/misc/a9scu.h
@@ -0,0 +1,31 @@
+/*
+ * Cortex-A9MPCore Snoop Control Unit (SCU) emulation.
+ *
+ * Copyright (c) 2009 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited.
+ * Written by Paul Brook, Peter Maydell.
+ *
+ * This code is licensed under the GPL.
+ */
+#ifndef HW_MISC_A9SCU_H
+#define HW_MISC_A9SCU_H
+
+#include "hw/sysbus.h"
+
+/* A9MP private memory region.  */
+
+typedef struct A9SCUState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    MemoryRegion iomem;
+    uint32_t control;
+    uint32_t status;
+    uint32_t num_cpu;
+} A9SCUState;
+
+#define TYPE_A9_SCU "a9-scu"
+#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
+
+#endif
diff --git a/include/hw/misc/arm11scu.h b/include/hw/misc/arm11scu.h
new file mode 100644
index 0000000..5ad0f3d
--- /dev/null
+++ b/include/hw/misc/arm11scu.h
@@ -0,0 +1,29 @@
+/*
+ * ARM11MPCore Snoop Control Unit (SCU) emulation
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2013 SUSE LINUX Products GmbH
+ * Written by Paul Brook and Andreas Färber
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_MISC_ARM11SCU_H
+#define HW_MISC_ARM11SCU_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ARM11_SCU "arm11-scu"
+#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU)
+
+typedef struct ARM11SCUState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    uint32_t control;
+    uint32_t num_cpu;
+    MemoryRegion iomem;
+} ARM11SCUState;
+
+#endif
diff --git a/include/hw/misc/arm_integrator_debug.h b/include/hw/misc/arm_integrator_debug.h
new file mode 100644
index 0000000..37789b6
--- /dev/null
+++ b/include/hw/misc/arm_integrator_debug.h
@@ -0,0 +1,18 @@
+/*
+ * ARM Integrator Board Debug, switch and LED section
+ *
+ * Browse the data sheet:
+ *
+ *    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0159b/Babbfijf.html
+ *
+ * Copyright (c) 2013 Alex Bennée <alex@bennee.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 QEMU_INTEGRATOR_DEBUG_H
+#define QEMU_INTEGRATOR_DEBUG_H
+
+#define TYPE_INTEGRATOR_DEBUG "integrator_debug"
+
+#endif
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index f60dd67..72b1549 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -46,12 +46,14 @@
 
 #define FW_CFG_INVALID          0xffff
 
+#define FW_CFG_MAX_FILE_PATH    56
+
 #ifndef NO_QEMU_PROTOS
 typedef struct FWCfgFile {
     uint32_t  size;        /* file size */
     uint16_t  select;      /* write this to 0x510 to read it */
     uint16_t  reserved;
-    char      name[56];
+    char      name[FW_CFG_MAX_FILE_PATH];
 } FWCfgFile;
 
 typedef struct FWCfgFiles {
@@ -60,6 +62,7 @@
 } FWCfgFiles;
 
 typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
+typedef void (*FWCfgReadCallback)(void *opaque, uint32_t offset);
 
 void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
 void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value);
@@ -70,6 +73,9 @@
                          void *callback_opaque, void *data, size_t len);
 void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
                      size_t len);
+void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
+                              FWCfgReadCallback callback, void *callback_opaque,
+                              void *data, size_t len);
 FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
                         hwaddr crl_addr, hwaddr data_addr);
 
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
index 56de92e..309065f 100644
--- a/include/hw/pci-host/q35.h
+++ b/include/hw/pci-host/q35.h
@@ -61,6 +61,7 @@
     ram_addr_t above_4g_mem_size;
     uint64_t pci_hole64_size;
     PcGuestInfo *guest_info;
+    uint32_t short_root_bus;
 } MCHPCIState;
 
 typedef struct Q35PCIHost {
@@ -156,4 +157,6 @@
 #define MCH_PCIE_DEV                           1
 #define MCH_PCIE_FUNC                          0
 
+uint64_t mch_mcfg_base(void);
+
 #endif /* HW_Q35_H */
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 4b90e5d..b783e68 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -247,9 +247,6 @@
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
 
-    /* IRQ objects for the INTA-INTD pins.  */
-    qemu_irq *irq;
-
     /* Legacy PCI VGA regions */
     MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
     bool has_vga;
@@ -424,25 +421,25 @@
 static inline void
 pci_set_word(uint8_t *config, uint16_t val)
 {
-    cpu_to_le16wu((uint16_t *)config, val);
+    stw_le_p(config, val);
 }
 
 static inline uint16_t
 pci_get_word(const uint8_t *config)
 {
-    return le16_to_cpupu((const uint16_t *)config);
+    return lduw_le_p(config);
 }
 
 static inline void
 pci_set_long(uint8_t *config, uint32_t val)
 {
-    cpu_to_le32wu((uint32_t *)config, val);
+    stl_le_p(config, val);
 }
 
 static inline uint32_t
 pci_get_long(const uint8_t *config)
 {
-    return le32_to_cpupu((const uint32_t *)config);
+    return ldl_le_p(config);
 }
 
 static inline void
@@ -632,6 +629,29 @@
 PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
+qemu_irq pci_allocate_irq(PCIDevice *pci_dev);
+void pci_set_irq(PCIDevice *pci_dev, int level);
+
+static inline void pci_irq_assert(PCIDevice *pci_dev)
+{
+    pci_set_irq(pci_dev, 1);
+}
+
+static inline void pci_irq_deassert(PCIDevice *pci_dev)
+{
+    pci_set_irq(pci_dev, 0);
+}
+
+/*
+ * FIXME: PCI does not work this way.
+ * All the callers to this method should be fixed.
+ */
+static inline void pci_irq_pulse(PCIDevice *pci_dev)
+{
+    pci_irq_assert(pci_dev);
+    pci_irq_deassert(pci_dev);
+}
+
 static inline int pci_is_express(const PCIDevice *d)
 {
     return d->cap_present & QEMU_PCI_CAP_EXPRESS;
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index c010007..1966169 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -64,15 +64,6 @@
     uint8_t exp_cap;
 
     /* SLOT */
-    unsigned int hpev_intx;     /* INTx for hot plug event (0-3:INT[A-D]#)
-                                 * default is 0 = INTA#
-                                 * If the chip wants to use other interrupt
-                                 * line, initialize this member with the
-                                 * desired number.
-                                 * If the chip dynamically changes this member,
-                                 * also initialize it when loaded as
-                                 * appropreately.
-                                 */
     bool hpev_notified; /* Logical AND of conditions for hot plug event.
                          Following 6.7.3.4:
                          Software Notification of Hot-Plug Events, an interrupt
@@ -82,15 +73,6 @@
     /* AER */
     uint16_t aer_cap;
     PCIEAERLog aer_log;
-    unsigned int aer_intx;      /* INTx for error reporting
-                                 * default is 0 = INTA#
-                                 * If the chip wants to use other interrupt
-                                 * line, initialize this member with the
-                                 * desired number.
-                                 * If the chip dynamically changes this member,
-                                 * also initialize it when loaded as
-                                 * appropreately.
-                                 */
 };
 
 /* PCI express capability helper functions */
diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h
index 1228e36..acca45e 100644
--- a/include/hw/pci/pcie_host.h
+++ b/include/hw/pci/pcie_host.h
@@ -28,6 +28,12 @@
 #define PCIE_HOST_BRIDGE(obj) \
     OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
 
+#define PCIE_HOST_MCFG_BASE "MCFG"
+#define PCIE_HOST_MCFG_SIZE "mcfg_size"
+
+/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
+#define PCIE_BASE_ADDR_UNMAPPED  ((hwaddr)-1ULL)
+
 struct PCIExpressHost {
     PCIHostState pci;
 
@@ -51,4 +57,25 @@
                             hwaddr addr,
                             uint32_t size);
 
+/*
+ * PCI express ECAM (Enhanced Configuration Address Mapping) format.
+ * AKA mmcfg address
+ * bit 20 - 28: bus number
+ * bit 15 - 19: device number
+ * bit 12 - 14: function number
+ * bit  0 - 11: offset in configuration space of a given device
+ */
+#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28)
+#define PCIE_MMCFG_SIZE_MIN             (1ULL << 20)
+#define PCIE_MMCFG_BUS_BIT              20
+#define PCIE_MMCFG_BUS_MASK             0x1ff
+#define PCIE_MMCFG_DEVFN_BIT            12
+#define PCIE_MMCFG_DEVFN_MASK           0xff
+#define PCIE_MMCFG_CONFOFFSET_MASK      0xfff
+#define PCIE_MMCFG_BUS(addr)            (((addr) >> PCIE_MMCFG_BUS_BIT) & \
+                                         PCIE_MMCFG_BUS_MASK)
+#define PCIE_MMCFG_DEVFN(addr)          (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
+                                         PCIE_MMCFG_DEVFN_MASK)
+#define PCIE_MMCFG_CONFOFFSET(addr)     ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
+
 #endif /* PCIE_HOST_H */
diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h
index f916693..2695d3c 100644
--- a/include/hw/pcmcia.h
+++ b/include/hw/pcmcia.h
@@ -3,11 +3,11 @@
 
 /* PCMCIA/Cardbus */
 
-#include "qemu-common.h"
+#include "hw/qdev.h"
 
-typedef struct {
+typedef struct PCMCIASocket {
     qemu_irq irq;
-    int attached;
+    bool attached;
     const char *slot_string;
     const char *card_string;
 } PCMCIASocket;
@@ -16,22 +16,42 @@
 void pcmcia_socket_unregister(PCMCIASocket *socket);
 void pcmcia_info(Monitor *mon, const QDict *qdict);
 
+#define TYPE_PCMCIA_CARD "pcmcia-card"
+#define PCMCIA_CARD(obj) \
+    OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD)
+#define PCMCIA_CARD_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD)
+#define PCMCIA_CARD_CLASS(cls) \
+    OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD)
+
 struct PCMCIACardState {
-    void *state;
+    /*< private >*/
+    DeviceState parent_obj;
+    /*< public >*/
+
     PCMCIASocket *slot;
-    int (*attach)(void *state);
-    int (*detach)(void *state);
+};
+
+typedef struct PCMCIACardClass {
+    /*< private >*/
+    DeviceClass parent_class;
+    /*< public >*/
+
+    int (*attach)(PCMCIACardState *state);
+    int (*detach)(PCMCIACardState *state);
+
     const uint8_t *cis;
     int cis_len;
 
     /* Only valid if attached */
-    uint8_t (*attr_read)(void *state, uint32_t address);
-    void (*attr_write)(void *state, uint32_t address, uint8_t value);
-    uint16_t (*common_read)(void *state, uint32_t address);
-    void (*common_write)(void *state, uint32_t address, uint16_t value);
-    uint16_t (*io_read)(void *state, uint32_t address);
-    void (*io_write)(void *state, uint32_t address, uint16_t value);
-};
+    uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address);
+    void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value);
+    uint16_t (*common_read)(PCMCIACardState *card, uint32_t address);
+    void (*common_write)(PCMCIACardState *card,
+                         uint32_t address, uint16_t value);
+    uint16_t (*io_read)(PCMCIACardState *card, uint32_t address);
+    void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
+} PCMCIACardClass;
 
 #define CISTPL_DEVICE		0x01	/* 5V Device Information Tuple */
 #define CISTPL_NO_LINK		0x14	/* No Link Tuple */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index e37b419..fdaab2d 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -29,7 +29,6 @@
     target_ulong entry_point;
     uint32_t next_irq;
     uint64_t rtc_offset;
-    char *cpu_model;
     bool has_graphics;
 
     uint32_t epow_irq;
@@ -283,6 +282,7 @@
 #define H_GET_EM_PARMS          0x2B8
 #define H_SET_MPP               0x2D0
 #define H_GET_MPP               0x2D4
+#define H_XIRR_X                0x2FC
 #define H_SET_MODE              0x31C
 #define MAX_HCALL_OPCODE        H_SET_MODE
 
@@ -332,14 +332,19 @@
     return spapr_allocate_irq(hint, true);
 }
 
+static inline uint64_t ppc64_phys_to_real(uint64_t addr)
+{
+    return addr & ~0xF000000000000000ULL;
+}
+
 static inline uint32_t rtas_ld(target_ulong phys, int n)
 {
-    return ldl_be_phys(phys + 4*n);
+    return ldl_be_phys(ppc64_phys_to_real(phys + 4*n));
 }
 
 static inline void rtas_st(target_ulong phys, int n, uint32_t val)
 {
-    stl_be_phys(phys + 4*n, val);
+    stl_be_phys(ppc64_phys_to_real(phys + 4*n), val);
 }
 
 typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, sPAPREnvironment *spapr,
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 66364c5..0d7673d 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -29,9 +29,24 @@
 
 #include "hw/sysbus.h"
 
+#define TYPE_XICS_COMMON "xics-common"
+#define XICS_COMMON(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_COMMON)
+
 #define TYPE_XICS "xics"
 #define XICS(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS)
 
+#define TYPE_KVM_XICS "xics-kvm"
+#define KVM_XICS(obj) OBJECT_CHECK(KVMXICSState, (obj), TYPE_KVM_XICS)
+
+#define XICS_COMMON_CLASS(klass) \
+     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
+#define XICS_CLASS(klass) \
+     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS)
+#define XICS_COMMON_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON)
+#define XICS_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS)
+
 #define XICS_IPI        0x2
 #define XICS_BUID       0x1
 #define XICS_IRQ_BASE   (XICS_BUID << 12)
@@ -41,11 +56,22 @@
  * (the kernel implementation supports more but we don't exploit
  *  that yet)
  */
+typedef struct XICSStateClass XICSStateClass;
 typedef struct XICSState XICSState;
+typedef struct ICPStateClass ICPStateClass;
 typedef struct ICPState ICPState;
+typedef struct ICSStateClass ICSStateClass;
 typedef struct ICSState ICSState;
 typedef struct ICSIRQState ICSIRQState;
 
+struct XICSStateClass {
+    DeviceClass parent_class;
+
+    void (*cpu_setup)(XICSState *icp, PowerPCCPU *cpu);
+    void (*set_nr_irqs)(XICSState *icp, uint32_t nr_irqs, Error **errp);
+    void (*set_nr_servers)(XICSState *icp, uint32_t nr_servers, Error **errp);
+};
+
 struct XICSState {
     /*< private >*/
     SysBusDevice parent_obj;
@@ -59,10 +85,26 @@
 #define TYPE_ICP "icp"
 #define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP)
 
+#define TYPE_KVM_ICP "icp-kvm"
+#define KVM_ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_KVM_ICP)
+
+#define ICP_CLASS(klass) \
+     OBJECT_CLASS_CHECK(ICPStateClass, (klass), TYPE_ICP)
+#define ICP_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(ICPStateClass, (obj), TYPE_ICP)
+
+struct ICPStateClass {
+    DeviceClass parent_class;
+
+    void (*pre_save)(ICPState *s);
+    int (*post_load)(ICPState *s, int version_id);
+};
+
 struct ICPState {
     /*< private >*/
     DeviceState parent_obj;
     /*< public >*/
+    CPUState *cs;
     uint32_t xirr;
     uint8_t pending_priority;
     uint8_t mfrr;
@@ -72,6 +114,21 @@
 #define TYPE_ICS "ics"
 #define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
 
+#define TYPE_KVM_ICS "icskvm"
+#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
+
+#define ICS_CLASS(klass) \
+     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
+#define ICS_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
+
+struct ICSStateClass {
+    DeviceClass parent_class;
+
+    void (*pre_save)(ICSState *s);
+    int (*post_load)(ICSState *s, int version_id);
+};
+
 struct ICSState {
     /*< private >*/
     DeviceState parent_obj;
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index e191ca0..f2043a6 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -221,7 +221,6 @@
 void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
                                  int required_for_version);
 void qdev_unplug(DeviceState *dev, Error **errp);
-void qdev_free(DeviceState *dev);
 int qdev_simple_unplug_cb(DeviceState *dev);
 void qdev_machine_creation_done(void);
 bool qdev_machine_modified(void);
diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h
index bb50a87..f5aaa05 100644
--- a/include/hw/sysbus.h
+++ b/include/hw/sysbus.h
@@ -68,7 +68,7 @@
 void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
 void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr);
 void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
-                             unsigned priority);
+                             int priority);
 void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
                    MemoryRegion *mem);
 void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem);
diff --git a/include/hw/timer/arm_mptimer.h b/include/hw/timer/arm_mptimer.h
new file mode 100644
index 0000000..b34cba0
--- /dev/null
+++ b/include/hw/timer/arm_mptimer.h
@@ -0,0 +1,54 @@
+/*
+ * Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited
+ * Written by Paul Brook, Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef HW_TIMER_ARM_MPTIMER_H
+#define HW_TIMER_ARM_MPTIMER_H
+
+#include "hw/sysbus.h"
+
+#define ARM_MPTIMER_MAX_CPUS 4
+
+/* State of a single timer or watchdog block */
+typedef struct {
+    uint32_t count;
+    uint32_t load;
+    uint32_t control;
+    uint32_t status;
+    int64_t tick;
+    QEMUTimer *timer;
+    qemu_irq irq;
+    MemoryRegion iomem;
+} TimerBlock;
+
+#define TYPE_ARM_MPTIMER "arm_mptimer"
+#define ARM_MPTIMER(obj) \
+    OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER)
+
+typedef struct {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    uint32_t num_cpu;
+    TimerBlock timerblock[ARM_MPTIMER_MAX_CPUS];
+    MemoryRegion iomem;
+} ARMMPTimerState;
+
+#endif
diff --git a/include/hw/timer/hpet.h b/include/hw/timer/hpet.h
index 757f79f..ab44bd3 100644
--- a/include/hw/timer/hpet.h
+++ b/include/hw/timer/hpet.h
@@ -71,4 +71,6 @@
 } QEMU_PACKED;
 
 extern struct hpet_fw_config hpet_cfg;
+
+bool hpet_find(void);
 #endif
diff --git a/include/net/eth.h b/include/net/eth.h
index 1d48e06..b3273b8 100644
--- a/include/net/eth.h
+++ b/include/net/eth.h
@@ -84,7 +84,7 @@
 } ip_pseudo_header;
 
 /* IPv6 address */
-struct in6_addr {
+struct in6_address {
     union {
         uint8_t __u6_addr8[16];
     } __in6_u;
@@ -105,8 +105,8 @@
             uint8_t  ip6_un3_ecn;  /* 2 bits ECN, top 6 bits payload length */
         } ip6_un3;
     } ip6_ctlun;
-    struct in6_addr ip6_src;     /* source address */
-    struct in6_addr ip6_dst;     /* destination address */
+    struct in6_address ip6_src;    /* source address */
+    struct in6_address ip6_dst;    /* destination address */
 };
 
 struct ip6_ext_hdr {
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 14a5f65..437b8e0 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -410,53 +410,6 @@
     stq_be_p(ptr, u.ll);
 }
 
-/* Legacy unaligned versions.  Note that we never had a complete set.  */
-
-static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
-{
-    stw_le_p(p, v);
-}
-
-static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
-{
-    stl_le_p(p, v);
-}
-
-static inline uint16_t le16_to_cpupu(const uint16_t *p)
-{
-    return lduw_le_p(p);
-}
-
-static inline uint32_t le32_to_cpupu(const uint32_t *p)
-{
-    return ldl_le_p(p);
-}
-
-static inline uint32_t be32_to_cpupu(const uint32_t *p)
-{
-    return ldl_be_p(p);
-}
-
-static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
-{
-    stw_be_p(p, v);
-}
-
-static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
-{
-    stl_be_p(p, v);
-}
-
-static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
-{
-    stq_be_p(p, v);
-}
-
-static inline void cpu_to_32wu(uint32_t *p, uint32_t v)
-{
-    stl_p(p, v);
-}
-
 static inline unsigned long leul_to_cpu(unsigned long v)
 {
     /* In order to break an include loop between here and
diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
index ad4a9e5..508428f 100644
--- a/include/qemu/config-file.h
+++ b/include/qemu/config-file.h
@@ -8,6 +8,7 @@
 QemuOptsList *qemu_find_opts(const char *group);
 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
 void qemu_add_opts(QemuOptsList *list);
+void qemu_add_drive_opts(QemuOptsList *list);
 int qemu_set_option(const char *str);
 int qemu_global_option(const char *str);
 void qemu_add_globals(void);
diff --git a/include/qom/object.h b/include/qom/object.h
index 1a7b71a..a275db2 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -18,9 +18,9 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include "qemu/queue.h"
+#include "qapi/error.h"
 
 struct Visitor;
-struct Error;
 
 struct TypeImpl;
 typedef struct TypeImpl *Type;
@@ -301,7 +301,7 @@
                                       struct Visitor *v,
                                       void *opaque,
                                       const char *name,
-                                      struct Error **errp);
+                                      Error **errp);
 
 /**
  * ObjectPropertyRelease:
@@ -790,9 +790,9 @@
                          ObjectPropertyAccessor *get,
                          ObjectPropertyAccessor *set,
                          ObjectPropertyRelease *release,
-                         void *opaque, struct Error **errp);
+                         void *opaque, Error **errp);
 
-void object_property_del(Object *obj, const char *name, struct Error **errp);
+void object_property_del(Object *obj, const char *name, Error **errp);
 
 /**
  * object_property_find:
@@ -803,7 +803,7 @@
  * Look up a property for an object and return its #ObjectProperty if found.
  */
 ObjectProperty *object_property_find(Object *obj, const char *name,
-                                     struct Error **errp);
+                                     Error **errp);
 
 void object_unparent(Object *obj);
 
@@ -818,7 +818,7 @@
  * Reads a property from a object.
  */
 void object_property_get(Object *obj, struct Visitor *v, const char *name,
-                         struct Error **errp);
+                         Error **errp);
 
 /**
  * object_property_set_str:
@@ -829,7 +829,7 @@
  * Writes a string value to a property.
  */
 void object_property_set_str(Object *obj, const char *value,
-                             const char *name, struct Error **errp);
+                             const char *name, Error **errp);
 
 /**
  * object_property_get_str:
@@ -842,7 +842,7 @@
  * The caller should free the string.
  */
 char *object_property_get_str(Object *obj, const char *name,
-                              struct Error **errp);
+                              Error **errp);
 
 /**
  * object_property_set_link:
@@ -853,7 +853,7 @@
  * Writes an object's canonical path to a property.
  */
 void object_property_set_link(Object *obj, Object *value,
-                              const char *name, struct Error **errp);
+                              const char *name, Error **errp);
 
 /**
  * object_property_get_link:
@@ -866,7 +866,7 @@
  * string or not a valid object path).
  */
 Object *object_property_get_link(Object *obj, const char *name,
-                                 struct Error **errp);
+                                 Error **errp);
 
 /**
  * object_property_set_bool:
@@ -877,7 +877,7 @@
  * Writes a bool value to a property.
  */
 void object_property_set_bool(Object *obj, bool value,
-                              const char *name, struct Error **errp);
+                              const char *name, Error **errp);
 
 /**
  * object_property_get_bool:
@@ -889,7 +889,7 @@
  * an error occurs (including when the property value is not a bool).
  */
 bool object_property_get_bool(Object *obj, const char *name,
-                              struct Error **errp);
+                              Error **errp);
 
 /**
  * object_property_set_int:
@@ -900,7 +900,7 @@
  * Writes an integer value to a property.
  */
 void object_property_set_int(Object *obj, int64_t value,
-                             const char *name, struct Error **errp);
+                             const char *name, Error **errp);
 
 /**
  * object_property_get_int:
@@ -912,7 +912,7 @@
  * an error occurs (including when the property value is not an integer).
  */
 int64_t object_property_get_int(Object *obj, const char *name,
-                                struct Error **errp);
+                                Error **errp);
 
 /**
  * object_property_set:
@@ -926,7 +926,7 @@
  * Writes a property to a object.
  */
 void object_property_set(Object *obj, struct Visitor *v, const char *name,
-                         struct Error **errp);
+                         Error **errp);
 
 /**
  * object_property_parse:
@@ -938,7 +938,7 @@
  * Parses a string and writes the result into a property of an object.
  */
 void object_property_parse(Object *obj, const char *string,
-                           const char *name, struct Error **errp);
+                           const char *name, Error **errp);
 
 /**
  * object_property_print:
@@ -950,7 +950,7 @@
  * caller shall free the string.
  */
 char *object_property_print(Object *obj, const char *name,
-                            struct Error **errp);
+                            Error **errp);
 
 /**
  * object_property_get_type:
@@ -961,7 +961,7 @@
  * Returns:  The type name of the property.
  */
 const char *object_property_get_type(Object *obj, const char *name,
-                                     struct Error **errp);
+                                     Error **errp);
 
 /**
  * object_get_root:
@@ -1054,7 +1054,7 @@
  * The child object itself can be retrieved using object_property_get_link().
  */
 void object_property_add_child(Object *obj, const char *name,
-                               Object *child, struct Error **errp);
+                               Object *child, Error **errp);
 
 /**
  * object_property_add_link:
@@ -1077,7 +1077,7 @@
  */
 void object_property_add_link(Object *obj, const char *name,
                               const char *type, Object **child,
-                              struct Error **errp);
+                              Error **errp);
 
 /**
  * object_property_add_str:
@@ -1092,9 +1092,9 @@
  * property of type 'string'.
  */
 void object_property_add_str(Object *obj, const char *name,
-                             char *(*get)(Object *, struct Error **),
-                             void (*set)(Object *, const char *, struct Error **),
-                             struct Error **errp);
+                             char *(*get)(Object *, Error **),
+                             void (*set)(Object *, const char *, Error **),
+                             Error **errp);
 
 /**
  * object_property_add_bool:
@@ -1108,9 +1108,61 @@
  * property of type 'bool'.
  */
 void object_property_add_bool(Object *obj, const char *name,
-                              bool (*get)(Object *, struct Error **),
-                              void (*set)(Object *, bool, struct Error **),
-                              struct Error **errp);
+                              bool (*get)(Object *, Error **),
+                              void (*set)(Object *, bool, Error **),
+                              Error **errp);
+
+/**
+ * object_property_add_uint8_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add an integer property in memory.  This function will add a
+ * property of type 'uint8'.
+ */
+void object_property_add_uint8_ptr(Object *obj, const char *name,
+                                   const uint8_t *v, Error **errp);
+
+/**
+ * object_property_add_uint16_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add an integer property in memory.  This function will add a
+ * property of type 'uint16'.
+ */
+void object_property_add_uint16_ptr(Object *obj, const char *name,
+                                    const uint16_t *v, Error **errp);
+
+/**
+ * object_property_add_uint32_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add an integer property in memory.  This function will add a
+ * property of type 'uint32'.
+ */
+void object_property_add_uint32_ptr(Object *obj, const char *name,
+                                    const uint32_t *v, Error **errp);
+
+/**
+ * object_property_add_uint64_ptr:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @v: pointer to value
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add an integer property in memory.  This function will add a
+ * property of type 'uint64'.
+ */
+void object_property_add_uint64_ptr(Object *obj, const char *name,
+                                    const uint64_t *v, Error **Errp);
 
 /**
  * object_child_foreach:
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index cd5791e..495dae8 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -193,6 +193,8 @@
 
 bool usb_enabled(bool default_usb);
 
+extern QemuOptsList qemu_legacy_drive_opts;
+extern QemuOptsList qemu_common_drive_opts;
 extern QemuOptsList qemu_drive_opts;
 extern QemuOptsList qemu_chardev_opts;
 extern QemuOptsList qemu_device_opts;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4a14a43..eaaf00d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4870,10 +4870,10 @@
     } else
 #endif
     {
-#if TARGET_ABI_BITS == 64 && !defined(TARGET_ALPHA)
-        struct target_stat *target_st;
-#else
+#if defined(TARGET_HAS_STRUCT_STAT64)
         struct target_stat64 *target_st;
+#else
+        struct target_stat *target_st;
 #endif
 
         if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 5f53a28..fe540f6 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1178,6 +1178,7 @@
 /* This matches struct stat64 in glibc2.1, hence the absolutely
  * insane amounts of padding around dev_t's.
  */
+#define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
 	unsigned short	st_dev;
 	unsigned char	__pad0[10];
@@ -1213,6 +1214,7 @@
 } QEMU_PACKED;
 
 #ifdef TARGET_ARM
+#define TARGET_HAS_STRUCT_STAT64
 struct target_eabi_stat64 {
         unsigned long long st_dev;
         unsigned int    __pad1;
@@ -1262,6 +1264,7 @@
 	abi_ulong	__unused4[2];
 };
 
+#define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
 	unsigned char	__pad0[6];
 	unsigned short	st_dev;
@@ -1317,6 +1320,7 @@
 	abi_ulong	__unused4[2];
 };
 
+#define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
 	unsigned char	__pad0[6];
 	unsigned short	st_dev;
@@ -1384,6 +1388,8 @@
 #endif
 };
 
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
+#define TARGET_HAS_STRUCT_STAT64
 struct QEMU_PACKED target_stat64 {
 	unsigned long long st_dev;
         unsigned long long st_ino;
@@ -1406,6 +1412,7 @@
         unsigned int   __unused4;
         unsigned int   __unused5;
 };
+#endif
 
 #elif defined(TARGET_MICROBLAZE)
 
@@ -1431,6 +1438,7 @@
 };
 
 /* FIXME: Microblaze no-mmu user-space has a difference stat64 layout...  */
+#define TARGET_HAS_STRUCT_STAT64
 struct QEMU_PACKED target_stat64 {
 	uint64_t st_dev;
 #define TARGET_STAT64_HAS_BROKEN_ST_INO 1
@@ -1486,6 +1494,7 @@
 /* This matches struct stat64 in glibc2.1, hence the absolutely
  * insane amounts of padding around dev_t's.
  */
+#define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
 	unsigned long long	st_dev;
 	unsigned char	__pad1[2];
@@ -1594,6 +1603,7 @@
  * struct stat of the 64-bit kernel.
  */
 
+#define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
 	unsigned int	st_dev;
 	unsigned int	st_pad0[3];	/* Reserved for st_dev expansion  */
@@ -1665,6 +1675,7 @@
  * struct stat of the 64-bit kernel.
  */
 
+#define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
 	abi_ulong	st_dev;
 	abi_ulong	st_pad0[3];	/* Reserved for st_dev expansion  */
@@ -1721,6 +1732,7 @@
        unsigned int    st_gen;
 };
 
+#define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
        abi_ulong    st_dev;
        abi_ulong    st_ino;
@@ -1770,6 +1782,7 @@
 /* This matches struct stat64 in glibc2.1, hence the absolutely
  * insane amounts of padding around dev_t's.
  */
+#define TARGET_HAS_STRUCT_STAT64
 struct QEMU_PACKED target_stat64 {
 	unsigned long long	st_dev;
 	unsigned char	__pad0[4];
@@ -1897,6 +1910,7 @@
     unsigned int __unused5;
 };
 
+#define TARGET_HAS_STRUCT_STAT64
 struct target_stat64 {
     uint64_t st_dev;
     uint64_t st_ino;
diff --git a/memory.c b/memory.c
index 7f1f266..28f6449 100644
--- a/memory.c
+++ b/memory.c
@@ -1473,7 +1473,7 @@
 void memory_region_add_subregion_overlap(MemoryRegion *mr,
                                          hwaddr offset,
                                          MemoryRegion *subregion,
-                                         unsigned priority)
+                                         int priority)
 {
     subregion->may_overlap = true;
     subregion->priority = priority;
@@ -1506,7 +1506,7 @@
 void memory_region_set_address(MemoryRegion *mr, hwaddr addr)
 {
     MemoryRegion *parent = mr->parent;
-    unsigned priority = mr->priority;
+    int priority = mr->priority;
     bool may_overlap = mr->may_overlap;
 
     if (addr == mr->addr || !parent) {
diff --git a/monitor.c b/monitor.c
index 74f3f1b..845f608 100644
--- a/monitor.c
+++ b/monitor.c
@@ -511,7 +511,6 @@
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
 
 MonitorEventState monitor_event_state[QEVENT_MAX];
-QemuMutex monitor_event_state_lock;
 
 /*
  * Emits the event to every monitor instance
@@ -543,7 +542,6 @@
     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
     assert(event < QEVENT_MAX);
 
-    qemu_mutex_lock(&monitor_event_state_lock);
     evstate = &(monitor_event_state[event]);
     trace_monitor_protocol_event_queue(event,
                                        data,
@@ -576,7 +574,6 @@
             evstate->last = now;
         }
     }
-    qemu_mutex_unlock(&monitor_event_state_lock);
 }
 
 
@@ -589,7 +586,6 @@
     MonitorEventState *evstate = opaque;
     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
 
-    qemu_mutex_lock(&monitor_event_state_lock);
 
     trace_monitor_protocol_event_handler(evstate->event,
                                          evstate->data,
@@ -601,7 +597,6 @@
         evstate->data = NULL;
     }
     evstate->last = now;
-    qemu_mutex_unlock(&monitor_event_state_lock);
 }
 
 
@@ -638,7 +633,6 @@
  * and initialize state */
 static void monitor_protocol_event_init(void)
 {
-    qemu_mutex_init(&monitor_event_state_lock);
     /* Limit RTC & BALLOON events to 1 per second */
     monitor_protocol_event_throttle(QEVENT_RTC_CHANGE, 1000);
     monitor_protocol_event_throttle(QEVENT_BALLOON_CHANGE, 1000);
@@ -3186,6 +3180,9 @@
 
     { "srr0", offsetof(CPUPPCState, spr[SPR_SRR0]) },
     { "srr1", offsetof(CPUPPCState, spr[SPR_SRR1]) },
+    { "dar", offsetof(CPUPPCState, spr[SPR_DAR]) },
+    { "dsisr", offsetof(CPUPPCState, spr[SPR_DSISR]) },
+    { "cfar", offsetof(CPUPPCState, spr[SPR_CFAR]) },
     { "sprg0", offsetof(CPUPPCState, spr[SPR_SPRG0]) },
     { "sprg1", offsetof(CPUPPCState, spr[SPR_SPRG1]) },
     { "sprg2", offsetof(CPUPPCState, spr[SPR_SPRG2]) },
diff --git a/net/net.c b/net/net.c
index c330c9a..0a88e68 100644
--- a/net/net.c
+++ b/net/net.c
@@ -27,6 +27,7 @@
 #include "clients.h"
 #include "hub.h"
 #include "net/slirp.h"
+#include "net/eth.h"
 #include "util.h"
 
 #include "monitor/monitor.h"
@@ -442,7 +443,6 @@
         if (net_hub_flush(nc->peer)) {
             qemu_notify_event();
         }
-        return;
     }
     if (qemu_net_queue_flush(nc->incoming_queue)) {
         /* We emptied the queue successfully, signal to the IO thread to repoll
@@ -689,6 +689,11 @@
         error_report("invalid syntax for ethernet address");
         return -1;
     }
+    if (nic->has_macaddr &&
+        is_multicast_ether_addr(nd->macaddr.a)) {
+        error_report("NIC cannot have multicast MAC address (odd 1st byte)");
+        return -1;
+    }
     qemu_macaddr_default_if_unset(&nd->macaddr);
 
     if (nic->has_vectors) {
diff --git a/pc-bios/README b/pc-bios/README
index be8dae0..1501cf1 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -17,7 +17,7 @@
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
   https://github.com/aik/SLOF, and the image currently in qemu is
-  built from git tag qemu-slof-20130430.
+  built from git tag qemu-slof-20131015.
 
 - sgabios (the Serial Graphics Adapter option ROM) provides a means for
   legacy x86 software to communicate with an attached serial console as
diff --git a/pc-bios/keymaps/cz b/pc-bios/keymaps/cz
new file mode 100644
index 0000000..6584bfb
--- /dev/null
+++ b/pc-bios/keymaps/cz
@@ -0,0 +1,94 @@
+include common
+
+# Czech qwertz layout
+# comments are czech descriptions of the characters
+
+# -----------
+#  First row
+# -----------
+
+# strednik, kolecko
+semicolon 0x29
+dead_abovering 0x29 shift
+
+# numbers
+plus 0x2
+1 0x2 shift
+ecaron 0x3
+2 0x3 shift
+scaron 0x4
+3 0x4 shift
+ccaron 0x5
+4 0x5 shift
+rcaron 0x6
+5 0x6 shift
+zcaron 0x7
+6 0x7 shift
+yacute 0x8
+7 0x8 shift
+aacute 0x9
+8 0x9 shift
+iacute 0xa
+9 0xa shift
+eacute 0xb
+0 0xb shift
+
+# rovnitko
+equal 0x0c
+percent 0x0c shift
+
+# carka, hacek
+dead_acute 0x0d
+dead_caron 0x0d shift
+
+# ------------
+#  Second row
+# ------------
+
+z 0x15 addupper
+
+# u s carkou, zpetne lomitko
+uacute 0x1a
+slash 0x1a shift
+
+# prava zavorka, leva zavorka
+parenright 0x1b
+parenleft 0x1b shift
+
+# -----------
+#  Third row
+# -----------
+
+# u s krouzkem, uvozovky
+uring 0x27
+quotedbl 0x27 shift
+
+# paragraf, vykricnik
+section 0x28
+exclam 0x28 shift
+
+# vodorovna dvojtecka, apostrof
+dead_diaeresis 0x2b
+apostrophe 0x2b shift
+
+# ------------
+#  Fourth row
+# ------------
+
+# zpetne lomitko, roura
+backslash 0x2b
+bar 0x2b shift
+
+y 0x2c addupper
+
+# carka, otaznik
+comma 0x33
+question 0x33 shift
+
+# tecka, dvojtecka
+period 0x34
+colon 0x34 shift
+
+# minus, podtrzitko
+minus 0x35
+underscore 0x35 shift
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 092e58a..92a9831 100644
--- a/pc-bios/slof.bin
+++ b/pc-bios/slof.bin
Binary files differ
diff --git a/qapi-schema.json b/qapi-schema.json
index 60f3fd1..83fa485 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -225,6 +225,27 @@
   } }
 
 ##
+# @ImageInfoSpecificVmdk:
+#
+# @create-type: The create type of VMDK image
+#
+# @cid: Content id of image
+#
+# @parent-cid: Parent VMDK image's cid
+#
+# @extents: List of extent files
+#
+# Since: 1.7
+##
+{ 'type': 'ImageInfoSpecificVmdk',
+  'data': {
+      'create-type': 'str',
+      'cid': 'int',
+      'parent-cid': 'int',
+      'extents': ['ImageInfo']
+  } }
+
+##
 # @ImageInfoSpecific:
 #
 # A discriminated record of image format specific information structures.
@@ -234,7 +255,8 @@
 
 { 'union': 'ImageInfoSpecific',
   'data': {
-      'qcow2': 'ImageInfoSpecificQCow2'
+      'qcow2': 'ImageInfoSpecificQCow2',
+      'vmdk': 'ImageInfoSpecificVmdk'
   } }
 
 ##
@@ -256,6 +278,8 @@
 #
 # @encrypted: #optional true if the image is encrypted
 #
+# @compressed: #optional true if the image is compressed (Since 1.7)
+#
 # @backing-filename: #optional name of the backing file
 #
 # @full-backing-filename: #optional full path of the backing file
@@ -276,7 +300,7 @@
 { 'type': 'ImageInfo',
   'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
            '*actual-size': 'int', 'virtual-size': 'int',
-           '*cluster-size': 'int', '*encrypted': 'bool',
+           '*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
            '*backing-filename': 'str', '*full-backing-filename': 'str',
            '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
            '*backing-image': 'ImageInfo',
@@ -1712,7 +1736,8 @@
 # @existing: QEMU should look for an existing image file.
 #
 # @absolute-paths: QEMU should create a new image with absolute paths
-# for the backing file.
+# for the backing file. If there is no backing file available, the new
+# image will not be backed either.
 #
 # Since: 1.1
 ##
@@ -1914,7 +1939,7 @@
 #
 # Since: 0.14.0
 #
-# Notes: This command only exists as a stop-gap.  It's use is highly
+# Notes: This command only exists as a stop-gap.  Its use is highly
 #        discouraged.  The semantics of this command are not guaranteed.
 #
 #        Known limitations:
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index 1334de3..dc53545 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -76,6 +76,24 @@
     }
 }
 
+static void qapi_dealloc_start_implicit_struct(Visitor *v,
+                                               void **obj,
+                                               size_t size,
+                                               Error **errp)
+{
+    QapiDeallocVisitor *qov = to_qov(v);
+    qapi_dealloc_push(qov, obj);
+}
+
+static void qapi_dealloc_end_implicit_struct(Visitor *v, Error **errp)
+{
+    QapiDeallocVisitor *qov = to_qov(v);
+    void **obj = qapi_dealloc_pop(qov);
+    if (obj) {
+        g_free(*obj);
+    }
+}
+
 static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
 {
     QapiDeallocVisitor *qov = to_qov(v);
@@ -162,6 +180,8 @@
 
     v->visitor.start_struct = qapi_dealloc_start_struct;
     v->visitor.end_struct = qapi_dealloc_end_struct;
+    v->visitor.start_implicit_struct = qapi_dealloc_start_implicit_struct;
+    v->visitor.end_implicit_struct = qapi_dealloc_end_implicit_struct;
     v->visitor.start_list = qapi_dealloc_start_list;
     v->visitor.next_list = qapi_dealloc_next_list;
     v->visitor.end_list = qapi_dealloc_end_list;
diff --git a/qdev-monitor.c b/qdev-monitor.c
index a02c925..dc37a43 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -453,11 +453,12 @@
 
 DeviceState *qdev_device_add(QemuOpts *opts)
 {
-    ObjectClass *obj;
-    DeviceClass *k;
+    ObjectClass *oc;
+    DeviceClass *dc;
     const char *driver, *path, *id;
-    DeviceState *qdev;
+    DeviceState *dev;
     BusState *bus = NULL;
+    Error *err = NULL;
 
     driver = qemu_opt_get(opts, "driver");
     if (!driver) {
@@ -466,22 +467,28 @@
     }
 
     /* find driver */
-    obj = object_class_by_name(driver);
-    if (!obj) {
+    oc = object_class_by_name(driver);
+    if (!oc) {
         const char *typename = find_typename_by_alias(driver);
 
         if (typename) {
             driver = typename;
-            obj = object_class_by_name(driver);
+            oc = object_class_by_name(driver);
         }
     }
 
-    if (!obj) {
+    if (!oc) {
         qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
         return NULL;
     }
 
-    k = DEVICE_CLASS(obj);
+    if (object_class_is_abstract(oc)) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver",
+                      "non-abstract device type");
+        return NULL;
+    }
+
+    dc = DEVICE_CLASS(oc);
 
     /* find bus */
     path = qemu_opt_get(opts, "bus");
@@ -490,16 +497,16 @@
         if (!bus) {
             return NULL;
         }
-        if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) {
+        if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
             qerror_report(QERR_BAD_BUS_FOR_DEVICE,
                           driver, object_get_typename(OBJECT(bus)));
             return NULL;
         }
-    } else if (k->bus_type != NULL) {
-        bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
+    } else if (dc->bus_type != NULL) {
+        bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
         if (!bus) {
             qerror_report(QERR_NO_BUS_FOR_DEVICE,
-                          k->bus_type, driver);
+                          dc->bus_type, driver);
             return NULL;
         }
     }
@@ -509,36 +516,42 @@
     }
 
     /* create device, set properties */
-    qdev = DEVICE(object_new(driver));
+    dev = DEVICE(object_new(driver));
 
     if (bus) {
-        qdev_set_parent_bus(qdev, bus);
+        qdev_set_parent_bus(dev, bus);
     }
 
     id = qemu_opts_id(opts);
     if (id) {
-        qdev->id = id;
+        dev->id = id;
     }
-    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
-        qdev_free(qdev);
+    if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) {
+        object_unparent(OBJECT(dev));
+        object_unref(OBJECT(dev));
         return NULL;
     }
-    if (qdev->id) {
-        object_property_add_child(qdev_get_peripheral(), qdev->id,
-                                  OBJECT(qdev), NULL);
+    if (dev->id) {
+        object_property_add_child(qdev_get_peripheral(), dev->id,
+                                  OBJECT(dev), NULL);
     } else {
         static int anon_count;
         gchar *name = g_strdup_printf("device[%d]", anon_count++);
         object_property_add_child(qdev_get_peripheral_anon(), name,
-                                  OBJECT(qdev), NULL);
+                                  OBJECT(dev), NULL);
         g_free(name);
-    }        
-    if (qdev_init(qdev) < 0) {
+    }
+    object_property_set_bool(OBJECT(dev), true, "realized", &err);
+    if (err != NULL) {
+        qerror_report_err(err);
+        error_free(err);
+        object_unparent(OBJECT(dev));
+        object_unref(OBJECT(dev));
         qerror_report(QERR_DEVICE_INIT_FAILED, driver);
         return NULL;
     }
-    qdev->opts = opts;
-    return qdev;
+    dev->opts = opts;
+    return dev;
 }
 
 
diff --git a/qemu-coroutine-sleep.c b/qemu-coroutine-sleep.c
index f6db978..ad78fba 100644
--- a/qemu-coroutine-sleep.c
+++ b/qemu-coroutine-sleep.c
@@ -13,6 +13,7 @@
 
 #include "block/coroutine.h"
 #include "qemu/timer.h"
+#include "block/aio.h"
 
 typedef struct CoSleepCB {
     QEMUTimer *ts;
@@ -37,3 +38,16 @@
     timer_del(sleep_cb.ts);
     timer_free(sleep_cb.ts);
 }
+
+void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
+                                  int64_t ns)
+{
+    CoSleepCB sleep_cb = {
+        .co = qemu_coroutine_self(),
+    };
+    sleep_cb.ts = aio_timer_new(ctx, type, SCALE_NS, co_sleep_cb, &sleep_cb);
+    timer_mod(sleep_cb.ts, qemu_clock_get_ns(type) + ns);
+    qemu_coroutine_yield();
+    timer_del(sleep_cb.ts);
+    timer_free(sleep_cb.ts);
+}
diff --git a/qemu-img.c b/qemu-img.c
index 926f0a0..b6b5644 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -607,7 +607,7 @@
         if (output_format == OFORMAT_HUMAN) {
             error_report("This image format does not support checks");
         }
-        ret = 1;
+        ret = 63;
         goto fail;
     }
 
@@ -1020,10 +1020,10 @@
                 }
                 ret = compare_sectors(buf1, buf2, nb_sectors, &pnum);
                 if (ret || pnum != nb_sectors) {
-                    ret = 1;
                     qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
                             sectors_to_bytes(
                                 ret ? sector_num : sector_num + pnum));
+                    ret = 1;
                     goto out;
                 }
             }
@@ -1045,9 +1045,9 @@
             }
             if (ret) {
                 if (ret < 0) {
-                    ret = 4;
                     error_report("Error while reading offset %" PRId64 ": %s",
                                  sectors_to_bytes(sector_num), strerror(-ret));
+                    ret = 4;
                 }
                 goto out;
             }
@@ -1092,10 +1092,10 @@
                                           filename_over, buf1, quiet);
                 if (ret) {
                     if (ret < 0) {
-                        ret = 4;
                         error_report("Error while reading offset %" PRId64
                                      " of %s: %s", sectors_to_bytes(sector_num),
                                      filename_over, strerror(-ret));
+                        ret = 4;
                     }
                     goto out;
                 }
diff --git a/qemu-options.hx b/qemu-options.hx
index 5dc8b75..8b94264 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1605,7 +1605,7 @@
 
 If running QEMU as an unprivileged user, use the network helper
 @var{helper} to configure the TAP interface. The default network
-helper executable is @file{/usr/local/libexec/qemu-bridge-helper}.
+helper executable is @file{/path/to/qemu-bridge-helper}.
 
 @option{fd}=@var{h} can be used to specify the handle of an already
 opened host TAP interface.
@@ -1629,7 +1629,7 @@
 #launch a QEMU instance with the default network helper to
 #connect a TAP device to bridge br0
 qemu-system-i386 linux.img \
-                 -net nic -net tap,"helper=/usr/local/libexec/qemu-bridge-helper"
+                 -net nic -net tap,"helper=/path/to/qemu-bridge-helper"
 @end example
 
 @item -netdev bridge,id=@var{id}[,br=@var{bridge}][,helper=@var{helper}]
@@ -1638,7 +1638,7 @@
 
 Use the network helper @var{helper} to configure the TAP interface and
 attach it to the bridge. The default network helper executable is
-@file{/usr/local/libexec/qemu-bridge-helper} and the default bridge
+@file{/path/to/qemu-bridge-helper} and the default bridge
 device is @file{br0}.
 
 Examples:
diff --git a/qemu.nsi b/qemu.nsi
index 0dc1f52..cc5fafd 100644
--- a/qemu.nsi
+++ b/qemu.nsi
@@ -60,7 +60,11 @@
 
 ; Registry key to check for directory (so if you install again, it will
 ; overwrite the old one automatically)
-InstallDirRegKey HKLM "Software\qemu" "Install_Dir"
+!ifdef W64
+InstallDirRegKey HKLM "Software\qemu64" "Install_Dir"
+!else
+InstallDirRegKey HKLM "Software\qemu32" "Install_Dir"
+!endif
 
 ; Request administrator privileges for Windows Vista.
 RequestExecutionLevel admin
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index f453132..10682f5 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -99,7 +99,7 @@
         reopen_fd_to_null(1);
         reopen_fd_to_null(2);
 
-        execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
+        execle("/sbin/shutdown", "shutdown", "-h", shutdown_flag, "+0",
                "hypervisor initiated shutdown", (char*)NULL, environ);
         _exit(EXIT_FAILURE);
     } else if (pid < 0) {
diff --git a/qga/vss-win32/requester.h b/qga/vss-win32/requester.h
index cffec01..374f9b8 100644
--- a/qga/vss-win32/requester.h
+++ b/qga/vss-win32/requester.h
@@ -13,6 +13,7 @@
 #ifndef VSS_WIN32_REQUESTER_H
 #define VSS_WIN32_REQUESTER_H
 
+#include <basetyps.h>           /* STDAPI */
 #include "qemu/compiler.h"
 
 #ifdef __cplusplus
diff --git a/qom/object.c b/qom/object.c
index e90e382..fc19cf6 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -838,8 +838,9 @@
 void object_property_set_link(Object *obj, Object *value,
                               const char *name, Error **errp)
 {
-    object_property_set_str(obj, object_get_canonical_path(value),
-                            name, errp);
+    gchar *path = object_get_canonical_path(value);
+    object_property_set_str(obj, path, name, errp);
+    g_free(path);
 }
 
 Object *object_property_get_link(Object *obj, const char *name,
@@ -1344,6 +1345,66 @@
     return g_strdup(object_get_typename(obj));
 }
 
+static void property_get_uint8_ptr(Object *obj, Visitor *v,
+                                   void *opaque, const char *name,
+                                   Error **errp)
+{
+    uint8_t value = *(uint8_t *)opaque;
+    visit_type_uint8(v, &value, name, errp);
+}
+
+static void property_get_uint16_ptr(Object *obj, Visitor *v,
+                                   void *opaque, const char *name,
+                                   Error **errp)
+{
+    uint16_t value = *(uint16_t *)opaque;
+    visit_type_uint16(v, &value, name, errp);
+}
+
+static void property_get_uint32_ptr(Object *obj, Visitor *v,
+                                   void *opaque, const char *name,
+                                   Error **errp)
+{
+    uint32_t value = *(uint32_t *)opaque;
+    visit_type_uint32(v, &value, name, errp);
+}
+
+static void property_get_uint64_ptr(Object *obj, Visitor *v,
+                                   void *opaque, const char *name,
+                                   Error **errp)
+{
+    uint64_t value = *(uint64_t *)opaque;
+    visit_type_uint64(v, &value, name, errp);
+}
+
+void object_property_add_uint8_ptr(Object *obj, const char *name,
+                                   const uint8_t *v, Error **errp)
+{
+    object_property_add(obj, name, "uint8", property_get_uint8_ptr,
+                        NULL, NULL, (void *)v, errp);
+}
+
+void object_property_add_uint16_ptr(Object *obj, const char *name,
+                                    const uint16_t *v, Error **errp)
+{
+    object_property_add(obj, name, "uint16", property_get_uint16_ptr,
+                        NULL, NULL, (void *)v, errp);
+}
+
+void object_property_add_uint32_ptr(Object *obj, const char *name,
+                                    const uint32_t *v, Error **errp)
+{
+    object_property_add(obj, name, "uint32", property_get_uint32_ptr,
+                        NULL, NULL, (void *)v, errp);
+}
+
+void object_property_add_uint64_ptr(Object *obj, const char *name,
+                                    const uint64_t *v, Error **errp)
+{
+    object_property_add(obj, name, "uint64", property_get_uint64_ptr,
+                        NULL, NULL, (void *)v, errp);
+}
+
 static void object_instance_init(Object *obj)
 {
     object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
diff --git a/roms/SLOF b/roms/SLOF
index 8cfdfc4..e2e8ac9 160000
--- a/roms/SLOF
+++ b/roms/SLOF
@@ -1 +1 @@
-Subproject commit 8cfdfc43f4c4c8c8dfa4b7cf16f7c19c84eee812
+Subproject commit e2e8ac901e617573ea383f9cffd136146d0675a4
diff --git a/savevm.c b/savevm.c
index 2f631d4..3f912dd 100644
--- a/savevm.c
+++ b/savevm.c
@@ -794,7 +794,7 @@
         if (l > size)
             l = size;
         memcpy(f->buf + f->buf_index, buf, l);
-        f->bytes_xfer += size;
+        f->bytes_xfer += l;
         if (f->ops->writev_buffer) {
             add_to_iovec(f, f->buf + f->buf_index, l);
         }
diff --git a/scripts/acpi_extract.py b/scripts/acpi_extract.py
new file mode 100755
index 0000000..22ea468
--- /dev/null
+++ b/scripts/acpi_extract.py
@@ -0,0 +1,362 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin <mst@redhat.com>
+#
+# 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/>.
+
+# Process mixed ASL/AML listing (.lst file) produced by iasl -l
+# Locate and execute ACPI_EXTRACT directives, output offset info
+#
+# Documentation of ACPI_EXTRACT_* directive tags:
+#
+# These directive tags output offset information from AML for BIOS runtime
+# table generation.
+# Each directive is of the form:
+# ACPI_EXTRACT_<TYPE> <array_name> <Operator> (...)
+# and causes the extractor to create an array
+# named <array_name> with offset, in the generated AML,
+# of an object of a given type in the following <Operator>.
+#
+# A directive must fit on a single code line.
+#
+# Object type in AML is verified, a mismatch causes a build failure.
+#
+# Directives and operators currently supported are:
+# ACPI_EXTRACT_NAME_DWORD_CONST - extract a Dword Const object from Name()
+# ACPI_EXTRACT_NAME_WORD_CONST - extract a Word Const object from Name()
+# ACPI_EXTRACT_NAME_BYTE_CONST - extract a Byte Const object from Name()
+# ACPI_EXTRACT_METHOD_STRING - extract a NameString from Method()
+# ACPI_EXTRACT_NAME_STRING - extract a NameString from Name()
+# ACPI_EXTRACT_PROCESSOR_START - start of Processor() block
+# ACPI_EXTRACT_PROCESSOR_STRING - extract a NameString from Processor()
+# ACPI_EXTRACT_PROCESSOR_END - offset at last byte of Processor() + 1
+# ACPI_EXTRACT_PKG_START - start of Package block
+#
+# ACPI_EXTRACT_ALL_CODE - create an array storing the generated AML bytecode
+#
+# ACPI_EXTRACT is not allowed anywhere else in code, except in comments.
+
+import re;
+import sys;
+import fileinput;
+
+aml = []
+asl = []
+output = {}
+debug = ""
+
+class asl_line:
+    line = None
+    lineno = None
+    aml_offset = None
+
+def die(diag):
+    sys.stderr.write("Error: %s; %s\n" % (diag, debug))
+    sys.exit(1)
+
+#Store an ASL command, matching AML offset, and input line (for debugging)
+def add_asl(lineno, line):
+    l = asl_line()
+    l.line = line
+    l.lineno = lineno
+    l.aml_offset = len(aml)
+    asl.append(l)
+
+#Store an AML byte sequence
+#Verify that offset output by iasl matches # of bytes so far
+def add_aml(offset, line):
+    o = int(offset, 16);
+    # Sanity check: offset must match size of code so far
+    if (o != len(aml)):
+        die("Offset 0x%x != 0x%x" % (o, len(aml)))
+    # Strip any trailing dots and ASCII dump after "
+    line = re.sub(r'\s*\.*\s*".*$',"", line)
+    # Strip traling whitespace
+    line = re.sub(r'\s+$',"", line)
+    # Strip leading whitespace
+    line = re.sub(r'^\s+',"", line)
+    # Split on whitespace
+    code = re.split(r'\s+', line)
+    for c in code:
+        # Require a legal hex number, two digits
+        if (not(re.search(r'^[0-9A-Fa-f][0-9A-Fa-f]$', c))):
+            die("Unexpected octet %s" % c);
+        aml.append(int(c, 16));
+
+# Process aml bytecode array, decoding AML
+def aml_pkglen_bytes(offset):
+    # PkgLength can be multibyte. Bits 8-7 give the # of extra bytes.
+    pkglenbytes = aml[offset] >> 6;
+    return pkglenbytes + 1
+
+def aml_pkglen(offset):
+    pkgstart = offset
+    pkglenbytes = aml_pkglen_bytes(offset)
+    pkglen = aml[offset] & 0x3F
+    # If multibyte, first nibble only uses bits 0-3
+    if ((pkglenbytes > 1) and (pkglen & 0x30)):
+        die("PkgLen bytes 0x%x but first nibble 0x%x expected 0x0X" %
+            (pkglen, pkglen))
+    offset += 1
+    pkglenbytes -= 1
+    for i in range(pkglenbytes):
+        pkglen |= aml[offset + i] << (i * 8 + 4)
+    if (len(aml) < pkgstart + pkglen):
+        die("PckgLen 0x%x at offset 0x%x exceeds AML size 0x%x" %
+            (pkglen, offset, len(aml)))
+    return pkglen
+
+# Given method offset, find its NameString offset
+def aml_method_string(offset):
+    #0x14 MethodOp PkgLength NameString MethodFlags TermList
+    if (aml[offset] != 0x14):
+        die( "Method offset 0x%x: expected 0x14 actual 0x%x" %
+             (offset, aml[offset]));
+    offset += 1;
+    pkglenbytes = aml_pkglen_bytes(offset)
+    offset += pkglenbytes;
+    return offset;
+
+# Given name offset, find its NameString offset
+def aml_name_string(offset):
+    #0x08 NameOp NameString DataRef
+    if (aml[offset] != 0x08):
+        die( "Name offset 0x%x: expected 0x08 actual 0x%x" %
+             (offset, aml[offset]));
+    offset += 1
+    # Block Name Modifier. Skip it.
+    if (aml[offset] == 0x5c or aml[offset] == 0x5e):
+        offset += 1
+    return offset;
+
+# Given data offset, find 8 byte buffer offset
+def aml_data_buffer8(offset):
+    #0x08 NameOp NameString DataRef
+    expect = [0x11, 0x0B, 0x0A, 0x08]
+    if (aml[offset:offset+4] != expect):
+        die( "Name offset 0x%x: expected %s actual %s" %
+             (offset, aml[offset:offset+4], expect))
+    return offset + len(expect)
+
+# Given data offset, find dword const offset
+def aml_data_dword_const(offset):
+    #0x08 NameOp NameString DataRef
+    if (aml[offset] != 0x0C):
+        die( "Name offset 0x%x: expected 0x0C actual 0x%x" %
+             (offset, aml[offset]));
+    return offset + 1;
+
+# Given data offset, find word const offset
+def aml_data_word_const(offset):
+    #0x08 NameOp NameString DataRef
+    if (aml[offset] != 0x0B):
+        die( "Name offset 0x%x: expected 0x0B actual 0x%x" %
+             (offset, aml[offset]));
+    return offset + 1;
+
+# Given data offset, find byte const offset
+def aml_data_byte_const(offset):
+    #0x08 NameOp NameString DataRef
+    if (aml[offset] != 0x0A):
+        die( "Name offset 0x%x: expected 0x0A actual 0x%x" %
+             (offset, aml[offset]));
+    return offset + 1;
+
+# Find name'd buffer8
+def aml_name_buffer8(offset):
+    return aml_data_buffer8(aml_name_string(offset) + 4)
+
+# Given name offset, find dword const offset
+def aml_name_dword_const(offset):
+    return aml_data_dword_const(aml_name_string(offset) + 4)
+
+# Given name offset, find word const offset
+def aml_name_word_const(offset):
+    return aml_data_word_const(aml_name_string(offset) + 4)
+
+# Given name offset, find byte const offset
+def aml_name_byte_const(offset):
+    return aml_data_byte_const(aml_name_string(offset) + 4)
+
+def aml_device_start(offset):
+    #0x5B 0x82 DeviceOp PkgLength NameString
+    if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x82)):
+        die( "Name offset 0x%x: expected 0x5B 0x82 actual 0x%x 0x%x" %
+             (offset, aml[offset], aml[offset + 1]));
+    return offset
+
+def aml_device_string(offset):
+    #0x5B 0x82 DeviceOp PkgLength NameString
+    start = aml_device_start(offset)
+    offset += 2
+    pkglenbytes = aml_pkglen_bytes(offset)
+    offset += pkglenbytes
+    return offset
+
+def aml_device_end(offset):
+    start = aml_device_start(offset)
+    offset += 2
+    pkglenbytes = aml_pkglen_bytes(offset)
+    pkglen = aml_pkglen(offset)
+    return offset + pkglen
+
+def aml_processor_start(offset):
+    #0x5B 0x83 ProcessorOp PkgLength NameString ProcID
+    if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x83)):
+        die( "Name offset 0x%x: expected 0x5B 0x83 actual 0x%x 0x%x" %
+             (offset, aml[offset], aml[offset + 1]));
+    return offset
+
+def aml_processor_string(offset):
+    #0x5B 0x83 ProcessorOp PkgLength NameString ProcID
+    start = aml_processor_start(offset)
+    offset += 2
+    pkglenbytes = aml_pkglen_bytes(offset)
+    offset += pkglenbytes
+    return offset
+
+def aml_processor_end(offset):
+    start = aml_processor_start(offset)
+    offset += 2
+    pkglenbytes = aml_pkglen_bytes(offset)
+    pkglen = aml_pkglen(offset)
+    return offset + pkglen
+
+def aml_package_start(offset):
+    offset = aml_name_string(offset) + 4
+    # 0x12 PkgLength NumElements PackageElementList
+    if (aml[offset] != 0x12):
+        die( "Name offset 0x%x: expected 0x12 actual 0x%x" %
+             (offset, aml[offset]));
+    offset += 1
+    return offset + aml_pkglen_bytes(offset) + 1
+
+lineno = 0
+for line in fileinput.input():
+    # Strip trailing newline
+    line = line.rstrip();
+    # line number and debug string to output in case of errors
+    lineno = lineno + 1
+    debug = "input line %d: %s" % (lineno, line)
+    #ASL listing: space, then line#, then ...., then code
+    pasl = re.compile('^\s+([0-9]+)(:\s\s|\.\.\.\.)\s*')
+    m = pasl.search(line)
+    if (m):
+        add_asl(lineno, pasl.sub("", line));
+    # AML listing: offset in hex, then ...., then code
+    paml = re.compile('^([0-9A-Fa-f]+)(:\s\s|\.\.\.\.)\s*')
+    m = paml.search(line)
+    if (m):
+        add_aml(m.group(1), paml.sub("", line))
+
+# Now go over code
+# Track AML offset of a previous non-empty ASL command
+prev_aml_offset = -1
+for i in range(len(asl)):
+    debug = "input line %d: %s" % (asl[i].lineno, asl[i].line)
+
+    l = asl[i].line
+
+    # skip if not an extract directive
+    a = len(re.findall(r'ACPI_EXTRACT', l))
+    if (not a):
+        # If not empty, store AML offset. Will be used for sanity checks
+        # IASL seems to put {}. at random places in the listing.
+        # Ignore any non-words for the purpose of this test.
+        m = re.search(r'\w+', l)
+        if (m):
+                prev_aml_offset = asl[i].aml_offset
+        continue
+
+    if (a > 1):
+        die("Expected at most one ACPI_EXTRACT per line, actual %d" % a)
+
+    mext = re.search(r'''
+                      ^\s* # leading whitespace
+                      /\*\s* # start C comment
+                      (ACPI_EXTRACT_\w+) # directive: group(1)
+                      \s+ # whitspace separates directive from array name
+                      (\w+) # array name: group(2)
+                      \s*\*/ # end of C comment
+                      \s*$ # trailing whitespace
+                      ''', l, re.VERBOSE)
+    if (not mext):
+        die("Stray ACPI_EXTRACT in input")
+
+    # previous command must have produced some AML,
+    # otherwise we are in a middle of a block
+    if (prev_aml_offset == asl[i].aml_offset):
+        die("ACPI_EXTRACT directive in the middle of a block")
+
+    directive = mext.group(1)
+    array = mext.group(2)
+    offset = asl[i].aml_offset
+
+    if (directive == "ACPI_EXTRACT_ALL_CODE"):
+        if array in output:
+            die("%s directive used more than once" % directive)
+        output[array] = aml
+        continue
+    if (directive == "ACPI_EXTRACT_NAME_BUFFER8"):
+        offset = aml_name_buffer8(offset)
+    elif (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"):
+        offset = aml_name_dword_const(offset)
+    elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"):
+        offset = aml_name_word_const(offset)
+    elif (directive == "ACPI_EXTRACT_NAME_BYTE_CONST"):
+        offset = aml_name_byte_const(offset)
+    elif (directive == "ACPI_EXTRACT_NAME_STRING"):
+        offset = aml_name_string(offset)
+    elif (directive == "ACPI_EXTRACT_METHOD_STRING"):
+        offset = aml_method_string(offset)
+    elif (directive == "ACPI_EXTRACT_DEVICE_START"):
+        offset = aml_device_start(offset)
+    elif (directive == "ACPI_EXTRACT_DEVICE_STRING"):
+        offset = aml_device_string(offset)
+    elif (directive == "ACPI_EXTRACT_DEVICE_END"):
+        offset = aml_device_end(offset)
+    elif (directive == "ACPI_EXTRACT_PROCESSOR_START"):
+        offset = aml_processor_start(offset)
+    elif (directive == "ACPI_EXTRACT_PROCESSOR_STRING"):
+        offset = aml_processor_string(offset)
+    elif (directive == "ACPI_EXTRACT_PROCESSOR_END"):
+        offset = aml_processor_end(offset)
+    elif (directive == "ACPI_EXTRACT_PKG_START"):
+        offset = aml_package_start(offset)
+    else:
+        die("Unsupported directive %s" % directive)
+
+    if array not in output:
+        output[array] = []
+    output[array].append(offset)
+
+debug = "at end of file"
+
+def get_value_type(maxvalue):
+    #Use type large enough to fit the table
+    if (maxvalue >= 0x10000):
+            return "int"
+    elif (maxvalue >= 0x100):
+            return "short"
+    else:
+            return "char"
+
+# Pretty print output
+for array in output.keys():
+    otype = get_value_type(max(output[array]))
+    odata = []
+    for value in output[array]:
+        odata.append("0x%x" % value)
+    sys.stdout.write("static unsigned %s %s[] = {\n" % (otype, array))
+    sys.stdout.write(",\n".join(odata))
+    sys.stdout.write('\n};\n');
diff --git a/scripts/acpi_extract_preprocess.py b/scripts/acpi_extract_preprocess.py
new file mode 100755
index 0000000..69d10d6
--- /dev/null
+++ b/scripts/acpi_extract_preprocess.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin <mst@redhat.com>
+#
+# 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/>.
+
+# Read a preprocessed ASL listing and put each ACPI_EXTRACT
+# directive in a comment, to make iasl skip it.
+# We also put each directive on a new line, the machinery
+# in tools/acpi_extract.py requires this.
+
+import re;
+import sys;
+import fileinput;
+
+def die(diag):
+    sys.stderr.write("Error: %s\n" % (diag))
+    sys.exit(1)
+
+# Note: () around pattern make split return matched string as part of list
+psplit = re.compile(r''' (
+                          \b # At word boundary
+                          ACPI_EXTRACT_\w+ # directive
+                          \s+ # some whitespace
+                          \w+ # array name
+                         )''', re.VERBOSE);
+
+lineno = 0
+for line in fileinput.input():
+    # line number and debug string to output in case of errors
+    lineno = lineno + 1
+    debug = "input line %d: %s" % (lineno, line.rstrip())
+
+    s = psplit.split(line);
+    # The way split works, each odd item is the matching ACPI_EXTRACT directive.
+    # Put each in a comment, and on a line by itself.
+    for i in range(len(s)):
+        if (i % 2):
+            sys.stdout.write("\n/* %s */\n" % s[i])
+        else:
+            sys.stdout.write(s[i])
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index c39e628..65f1a54 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -20,7 +20,10 @@
 def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None):
     substructs = []
     ret = ''
-    full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix)
+    if not fn_prefix:
+        full_name = name
+    else:
+        full_name = "%s_%s" % (name, fn_prefix)
 
     for argname, argentry, optional, structured in parse_args(members):
         if structured:
@@ -97,7 +100,10 @@
 ''')
     push_indent()
 
-    full_name = name if not field_prefix else "%s_%s" % (field_prefix, name)
+    if not field_prefix:
+        full_name = name
+    else:
+        full_name = "%s_%s" % (field_prefix, name)
 
     if len(field_prefix):
         ret += mcgen('''
@@ -283,12 +289,17 @@
             name=name)
 
     pop_indent()
+
+    if not discriminator:
+        desc_type = "type"
+    else:
+        desc_type = discriminator
     ret += mcgen('''
         visit_type_%(name)sKind(m, &(*obj)->kind, "%(type)s", &err);
         if (!err) {
             switch ((*obj)->kind) {
 ''',
-                 name=name, type="type" if not discriminator else discriminator)
+                 name=name, type=desc_type)
 
     for key in members:
         if not discriminator:
diff --git a/scripts/update-acpi.sh b/scripts/update-acpi.sh
new file mode 100644
index 0000000..b5f05ff
--- /dev/null
+++ b/scripts/update-acpi.sh
@@ -0,0 +1,4 @@
+cd x86_64-softmmu
+for file in hw/i386/*.hex; do
+    cp -f $file ../$file.generated
+done
diff --git a/slirp/if.c b/slirp/if.c
index 87ca8a5..fb7acf8 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -142,7 +142,7 @@
 
 /*
  * Send a packet
- * We choose a packet based on it's position in the output queues;
+ * We choose a packet based on its position in the output queues;
  * If there are packets on the fastq, they are sent FIFO, before
  * everything else.  Otherwise we choose the first packet from the
  * batchq and send it.  the next packet chosen will be from the session
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index c24910f..1155e86 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1601,7 +1601,7 @@
         tcg_temp_free(pc);
 
         /* Since the destination is running in PALmode, we don't really
-           need the page permissions check.  We'll see the existance of
+           need the page permissions check.  We'll see the existence of
            the page when we create the TB, and we'll flush all TBs if
            we change the PAL base register.  */
         if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2c56740..9f110f1 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -176,6 +176,7 @@
         uint32_t c9_pmxevtyper; /* perf monitor event type */
         uint32_t c9_pmuserenr; /* perf monitor user enable */
         uint32_t c9_pminten; /* perf monitor interrupt enables */
+        uint32_t c12_vbar; /* vector base address register */
         uint32_t c13_fcse; /* FCSE PID.  */
         uint32_t c13_context; /* Context ID.  */
         uint32_t c13_tls1; /* User RW Thread register.  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index c63bbd7..3445813 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -225,10 +225,16 @@
 
 static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
 {
-    uint32_t aidx = *(uint32_t *)a;
-    uint32_t bidx = *(uint32_t *)b;
+    uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
+    uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
 
-    return aidx - bidx;
+    if (aidx > bidx) {
+        return 1;
+    }
+    if (aidx < bidx) {
+        return -1;
+    }
+    return 0;
 }
 
 static void cpreg_make_keylist(gpointer key, gpointer value, gpointer udata)
@@ -537,6 +543,13 @@
     return 0;
 }
 
+static int vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                      uint64_t value)
+{
+    env->cp15.c12_vbar = value & ~0x1Ful;
+    return 0;
+}
+
 static int ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri,
                        uint64_t *value)
 {
@@ -622,6 +635,10 @@
       .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
       .resetvalue = 0, .writefn = pmintenclr_write, },
+    { .name = "VBAR", .cp = 15, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .writefn = vbar_write,
+      .fieldoffset = offsetof(CPUARMState, cp15.c12_vbar),
+      .resetvalue = 0 },
     { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_scr),
       .resetvalue = 0, },
@@ -2470,7 +2487,17 @@
     }
     /* High vectors.  */
     if (env->cp15.c1_sys & (1 << 13)) {
+        /* when enabled, base address cannot be remapped.  */
         addr += 0xffff0000;
+    } else {
+        /* ARM v7 architectures provide a vector base address register to remap
+         * the interrupt vector table.
+         * This register is only followed in non-monitor mode, and has a secure
+         * and un-secure copy. Since the cpu is always in a un-secure operation
+         * and is never in monitor mode this feature is always active.
+         * Note: only bits 31:5 are valid.
+         */
+        addr += env->cp15.c12_vbar;
     }
     switch_mode (env, new_mode);
     env->spsr = cpsr_read(env);
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index b92e00d..6e5cd36 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -67,7 +67,13 @@
 
 static int compare_u64(const void *a, const void *b)
 {
-    return *(uint64_t *)a - *(uint64_t *)b;
+    if (*(uint64_t *)a > *(uint64_t *)b) {
+        return 1;
+    }
+    if (*(uint64_t *)a < *(uint64_t *)b) {
+        return -1;
+    }
+    return 0;
 }
 
 int kvm_arch_init_vcpu(CPUState *cs)
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 7508cf5..e1415f0 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -246,6 +246,7 @@
     /* lwx/swx reserved address */
 #define RES_ADDR_NONE 0xffffffff /* Use 0xffffffff to indicate no reservation */
     uint32_t res_addr;
+    uint32_t res_val;
 
     /* Internal flags.  */
 #define IMM_FLAG	4
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 1b937b3..9edcb67 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -49,6 +49,8 @@
 static TCGv env_btaken;
 static TCGv env_btarget;
 static TCGv env_iflags;
+static TCGv env_res_addr;
+static TCGv env_res_val;
 
 #include "exec/gen-icount.h"
 
@@ -150,6 +152,10 @@
     tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
 }
 
+/*
+ * write_carry sets the carry bits in MSR based on bit 0 of v.
+ * v[31:1] are ignored.
+ */
 static void write_carry(DisasContext *dc, TCGv v)
 {
     TCGv t0 = tcg_temp_new();
@@ -162,10 +168,10 @@
     tcg_temp_free(t0);
 }
 
-static void write_carryi(DisasContext *dc, int carry)
+static void write_carryi(DisasContext *dc, bool carry)
 {
     TCGv t0 = tcg_temp_new();
-    tcg_gen_movi_tl(t0, carry ? 1 : 0);
+    tcg_gen_movi_tl(t0, carry);
     write_carry(dc, t0);
     tcg_temp_free(t0);
 }
@@ -386,10 +392,7 @@
         return;
 
     if (not) {
-        TCGv t = tcg_temp_new();
-        tcg_gen_not_tl(t, *(dec_alu_op_b(dc)));
-        tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], t);
-        tcg_temp_free(t);
+        tcg_gen_andc_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
     } else
         tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
 }
@@ -749,7 +752,7 @@
 
 static void dec_bit(DisasContext *dc)
 {
-    TCGv t0, t1;
+    TCGv t0;
     unsigned int op;
     int mem_index = cpu_mmu_index(dc->env);
 
@@ -760,32 +763,22 @@
             t0 = tcg_temp_new();
 
             LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
-            tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
+            tcg_gen_andi_tl(t0, cpu_SR[SR_MSR], MSR_CC);
+            write_carry(dc, cpu_R[dc->ra]);
             if (dc->rd) {
-                t1 = tcg_temp_new();
-                read_carry(dc, t1);
-                tcg_gen_shli_tl(t1, t1, 31);
-
                 tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
-                tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1);
-                tcg_temp_free(t1);
+                tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t0);
             }
-
-            /* Update carry.  */
-            write_carry(dc, t0);
             tcg_temp_free(t0);
             break;
 
         case 0x1:
         case 0x41:
             /* srl.  */
-            t0 = tcg_temp_new();
             LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
 
-            /* Update carry.  */
-            tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
-            write_carry(dc, t0);
-            tcg_temp_free(t0);
+            /* Update carry. Note that write carry only looks at the LSB.  */
+            write_carry(dc, cpu_R[dc->ra]);
             if (dc->rd) {
                 if (op == 0x41)
                     tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
@@ -872,7 +865,7 @@
 }
 
 static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
-                            unsigned int size)
+                            unsigned int size, bool exclusive)
 {
     int mem_index = cpu_mmu_index(dc->env);
 
@@ -884,6 +877,11 @@
         tcg_gen_qemu_ld32u(dst, addr, mem_index);
     } else
         cpu_abort(dc->env, "Incorrect load size %d\n", size);
+
+    if (exclusive) {
+        tcg_gen_mov_tl(env_res_addr, addr);
+        tcg_gen_mov_tl(env_res_val, dst);
+    }
 }
 
 static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
@@ -1055,7 +1053,7 @@
          * into v. If the load succeeds, we verify alignment of the
          * address and if that succeeds we write into the destination reg.
          */
-        gen_load(dc, v, *addr, size);
+        gen_load(dc, v, *addr, size, ex);
 
         tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
         gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd),
@@ -1070,20 +1068,19 @@
         tcg_temp_free(v);
     } else {
         if (dc->rd) {
-            gen_load(dc, cpu_R[dc->rd], *addr, size);
+            gen_load(dc, cpu_R[dc->rd], *addr, size, ex);
             if (rev) {
                 dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size);
             }
         } else {
             /* We are loading into r0, no need to reverse.  */
-            gen_load(dc, env_imm, *addr, size);
+            gen_load(dc, env_imm, *addr, size, ex);
         }
     }
 
     if (ex) { /* lwx */
         /* no support for for AXI exclusive so always clear C */
         write_carryi(dc, 0);
-        tcg_gen_st_tl(*addr, cpu_env, offsetof(CPUMBState, res_addr));
     }
 
     if (addr == &t)
@@ -1107,7 +1104,7 @@
 
 static void dec_store(DisasContext *dc)
 {
-    TCGv t, *addr, swx_addr, r_check;
+    TCGv t, *addr, swx_addr;
     int swx_skip = 0;
     unsigned int size, rev = 0, ex = 0;
 
@@ -1131,9 +1128,9 @@
     sync_jmpstate(dc);
     addr = compute_ldst_addr(dc, &t);
 
-    r_check = tcg_temp_new();
     swx_addr = tcg_temp_local_new();
     if (ex) { /* swx */
+        TCGv tval;
 
         /* Force addr into the swx_addr. */
         tcg_gen_mov_tl(swx_addr, *addr);
@@ -1141,11 +1138,20 @@
         /* swx does not throw unaligned access errors, so force alignment */
         tcg_gen_andi_tl(swx_addr, swx_addr, ~3);
 
-        tcg_gen_ld_tl(r_check, cpu_env, offsetof(CPUMBState, res_addr));
         write_carryi(dc, 1);
         swx_skip = gen_new_label();
-        tcg_gen_brcond_tl(TCG_COND_NE, r_check, swx_addr, swx_skip);
+        tcg_gen_brcond_tl(TCG_COND_NE, env_res_addr, swx_addr, swx_skip);
+
+        /* Compare the value loaded at lwx with current contents of
+           the reserved location.
+           FIXME: This only works for system emulation where we can expect
+           this compare and the following write to be atomic. For user
+           emulation we need to add atomicity between threads.  */
+        tval = tcg_temp_new();
+        gen_load(dc, tval, swx_addr, 4, false);
+        tcg_gen_brcond_tl(TCG_COND_NE, env_res_val, tval, swx_skip);
         write_carryi(dc, 0);
+        tcg_temp_free(tval);
     }
 
     if (rev && size != 4) {
@@ -1227,7 +1233,6 @@
     if (ex) {
         gen_set_label(swx_skip);
     }
-    tcg_temp_free(r_check);
     tcg_temp_free(swx_addr);
 
     if (addr == &t)
@@ -2014,6 +2019,12 @@
     env_btaken = tcg_global_mem_new(TCG_AREG0,
                      offsetof(CPUMBState, btaken),
                      "btaken");
+    env_res_addr = tcg_global_mem_new(TCG_AREG0,
+                     offsetof(CPUMBState, res_addr),
+                     "res_addr");
+    env_res_val = tcg_global_mem_new(TCG_AREG0,
+                     offsetof(CPUMBState, res_val),
+                     "res_val");
     for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
         cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
                           offsetof(CPUMBState, regs[i]),
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 8fd0bc0..0f9efdf 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -373,6 +373,7 @@
 /* hw/openrisc_timer.c */
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
 void cpu_openrisc_count_update(OpenRISCCPU *cpu);
+void cpu_openrisc_timer_update(OpenRISCCPU *cpu);
 void cpu_openrisc_count_start(OpenRISCCPU *cpu);
 void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
 
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 16ef4b3..2153e7e 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -30,26 +30,15 @@
     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
     CPUOpenRISCState *env = &cpu->env;
 #ifndef CONFIG_USER_ONLY
-    if (env->flags & D_FLAG) { /* Delay Slot insn */
+
+    env->epcr = env->pc;
+    if (env->flags & D_FLAG) {
         env->flags &= ~D_FLAG;
         env->sr |= SR_DSX;
-        if (env->exception_index == EXCP_TICK    ||
-            env->exception_index == EXCP_INT     ||
-            env->exception_index == EXCP_SYSCALL ||
-            env->exception_index == EXCP_FPE) {
-            env->epcr = env->jmp_pc;
-        } else {
-            env->epcr = env->pc - 4;
-        }
-    } else {
-        if (env->exception_index == EXCP_TICK    ||
-            env->exception_index == EXCP_INT     ||
-            env->exception_index == EXCP_SYSCALL ||
-            env->exception_index == EXCP_FPE) {
-            env->epcr = env->npc;
-        } else {
-            env->epcr = env->pc;
-        }
+        env->epcr -= 4;
+    }
+    if (env->exception_index == EXCP_SYSCALL) {
+        env->epcr += 4;
     }
 
     /* For machine-state changed between user-mode and supervisor mode,
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index 22d7cbe..dd487bd 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -32,7 +32,7 @@
                                 int *prot, target_ulong address, int rw)
 {
     *physical = address;
-    *prot = PAGE_READ | PAGE_WRITE;
+    *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
     return TLBRET_MATCH;
 }
 
@@ -187,7 +187,7 @@
 
     if (ret == TLBRET_MATCH) {
         tlb_set_page(env, address & TARGET_PAGE_MASK,
-                     physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
+                     physical & TARGET_PAGE_MASK, prot,
                      mmu_idx, TARGET_PAGE_SIZE);
         ret = 0;
     } else if (ret < 0) {
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index cccbc0e..be06c45 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -81,7 +81,7 @@
     case TO_SPR(0, 64): /* ESR */
         env->esr = rb;
         break;
-    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+    case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
         idx = spr - TO_SPR(1, 512);
         if (!(rb & 1)) {
             tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
@@ -89,7 +89,7 @@
         env->tlb->dtlb[0][idx].mr = rb;
         break;
 
-    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+    case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
         idx = spr - TO_SPR(1, 640);
         env->tlb->dtlb[0][idx].tr = rb;
         break;
@@ -100,7 +100,7 @@
     case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
     case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
         break;
-    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
+    case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1):   /* ITLBW0MR 0-127 */
         idx = spr - TO_SPR(2, 512);
         if (!(rb & 1)) {
             tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
@@ -108,7 +108,7 @@
         env->tlb->itlb[0][idx].mr = rb;
         break;
 
-    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+    case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
         idx = spr - TO_SPR(2, 640);
         env->tlb->itlb[0][idx].tr = rb;
         break;
@@ -127,33 +127,31 @@
         break;
     case TO_SPR(10, 0): /* TTMR */
         {
+            if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) {
+                switch (rb & TTMR_M) {
+                case TIMER_NONE:
+                    cpu_openrisc_count_stop(cpu);
+                    break;
+                case TIMER_INTR:
+                case TIMER_SHOT:
+                case TIMER_CONT:
+                    cpu_openrisc_count_start(cpu);
+                    break;
+                default:
+                    break;
+                }
+            }
+
             int ip = env->ttmr & TTMR_IP;
 
             if (rb & TTMR_IP) {    /* Keep IP bit.  */
-                env->ttmr = (rb & ~TTMR_IP) + ip;
+                env->ttmr = (rb & ~TTMR_IP) | ip;
             } else {    /* Clear IP bit.  */
                 env->ttmr = rb & ~TTMR_IP;
                 cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
             }
 
-            cpu_openrisc_count_update(cpu);
-
-            switch (env->ttmr & TTMR_M) {
-            case TIMER_NONE:
-                cpu_openrisc_count_stop(cpu);
-                break;
-            case TIMER_INTR:
-                cpu_openrisc_count_start(cpu);
-                break;
-            case TIMER_SHOT:
-                cpu_openrisc_count_start(cpu);
-                break;
-            case TIMER_CONT:
-                cpu_openrisc_count_start(cpu);
-                break;
-            default:
-                break;
-            }
+            cpu_openrisc_timer_update(cpu);
         }
         break;
 
@@ -162,7 +160,7 @@
         if (env->ttmr & TIMER_NONE) {
             return;
         }
-        cpu_openrisc_count_start(cpu);
+        cpu_openrisc_timer_update(cpu);
         break;
     default:
 
@@ -214,11 +212,11 @@
     case TO_SPR(0, 64): /* ESR */
         return env->esr;
 
-    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+    case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
         idx = spr - TO_SPR(1, 512);
         return env->tlb->dtlb[0][idx].mr;
 
-    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+    case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
         idx = spr - TO_SPR(1, 640);
         return env->tlb->dtlb[0][idx].tr;
 
@@ -230,11 +228,11 @@
     case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
         break;
 
-    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
+    case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */
         idx = spr - TO_SPR(2, 512);
         return env->tlb->itlb[0][idx].mr;
 
-    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+    case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
         idx = spr - TO_SPR(2, 640);
         return env->tlb->itlb[0][idx].tr;
 
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 8908a2e..91c60eb 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -209,42 +209,49 @@
 static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
 {
     target_ulong tmp_pc;
-    int lab = gen_new_label();
-    TCGv sr_f = tcg_temp_new();
     /* N26, 26bits imm */
     tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
-    tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
 
-    if (op0 == 0x00) {    /* l.j */
+    switch (op0) {
+    case 0x00:     /* l.j */
         tcg_gen_movi_tl(jmp_pc, tmp_pc);
-    } else if (op0 == 0x01) {    /* l.jal */
+        break;
+    case 0x01:     /* l.jal */
         tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
         tcg_gen_movi_tl(jmp_pc, tmp_pc);
-    } else if (op0 == 0x03) {    /* l.bnf */
-        tcg_gen_movi_tl(jmp_pc, dc->pc+8);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab);
-        tcg_gen_movi_tl(jmp_pc, tmp_pc);
-        gen_set_label(lab);
-    } else if (op0 == 0x04) {    /* l.bf */
-        tcg_gen_movi_tl(jmp_pc, dc->pc+8);
-        tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab);
-        tcg_gen_movi_tl(jmp_pc, tmp_pc);
-        gen_set_label(lab);
-    } else if (op0 == 0x11) {    /* l.jr */
+        break;
+    case 0x03:     /* l.bnf */
+    case 0x04:     /* l.bf  */
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
+                                sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp_pc);
+            gen_set_label(lab);
+            tcg_temp_free(sr_f);
+        }
+        break;
+    case 0x11:     /* l.jr */
         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
-    } else if (op0 == 0x12) {    /* l.jalr */
+        break;
+    case 0x12:     /* l.jalr */
         tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
-    } else {
+        break;
+    default:
         gen_illegal_exception(dc);
+        break;
     }
 
-    tcg_temp_free(sr_f);
     dc->delayed_branch = 2;
     dc->tb_flags |= D_FLAG;
     gen_sync_flags(dc);
 }
 
+
 static void dec_calc(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0, op1, op2;
@@ -904,29 +911,33 @@
     case 0x27:    /* l.addi */
         LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
         {
-            int lab = gen_new_label();
-            TCGv_i64 ta = tcg_temp_new_i64();
-            TCGv_i64 td = tcg_temp_local_new_i64();
-            TCGv_i32 res = tcg_temp_local_new_i32();
-            TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-            tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
-            tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
-            tcg_gen_trunc_i64_i32(res, td);
-            tcg_gen_shri_i64(td, td, 32);
-            tcg_gen_andi_i64(td, td, 0x3);
-            /* Jump to lab when no overflow.  */
-            tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
-            tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
-            tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-            tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
-            tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
-            gen_exception(dc, EXCP_RANGE);
-            gen_set_label(lab);
-            tcg_gen_mov_i32(cpu_R[rd], res);
-            tcg_temp_free_i64(ta);
-            tcg_temp_free_i64(td);
-            tcg_temp_free_i32(res);
-            tcg_temp_free_i32(sr_ove);
+            if (I16 == 0) {
+                tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
+            } else {
+                int lab = gen_new_label();
+                TCGv_i64 ta = tcg_temp_new_i64();
+                TCGv_i64 td = tcg_temp_local_new_i64();
+                TCGv_i32 res = tcg_temp_local_new_i32();
+                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+                tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
+                tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
+                tcg_gen_trunc_i64_i32(res, td);
+                tcg_gen_shri_i64(td, td, 32);
+                tcg_gen_andi_i64(td, td, 0x3);
+                /* Jump to lab when no overflow.  */
+                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
+                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
+                tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+                tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
+                tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
+                gen_exception(dc, EXCP_RANGE);
+                gen_set_label(lab);
+                tcg_gen_mov_i32(cpu_R[rd], res);
+                tcg_temp_free_i64(ta);
+                tcg_temp_free_i64(td);
+                tcg_temp_free_i32(res);
+                tcg_temp_free_i32(sr_ove);
+            }
         }
         break;
 
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 94d6d0c..3cb23e0 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -2,7 +2,7 @@
 obj-y += translate.o
 ifeq ($(CONFIG_SOFTMMU),y)
 obj-y += machine.o mmu_helper.o mmu-hash32.o
-obj-$(TARGET_PPC64) += mmu-hash64.o
+obj-$(TARGET_PPC64) += mmu-hash64.o arch_dump.o
 endif
 obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
 obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
diff --git a/target-ppc/arch_dump.c b/target-ppc/arch_dump.c
new file mode 100644
index 0000000..17fd4c6
--- /dev/null
+++ b/target-ppc/arch_dump.c
@@ -0,0 +1,253 @@
+/*
+ * writing ELF notes for ppc64 arch
+ *
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "elf.h"
+#include "exec/cpu-all.h"
+#include "sysemu/dump.h"
+#include "sysemu/kvm.h"
+
+struct PPC64UserRegStruct {
+    uint64_t gpr[32];
+    uint64_t nip;
+    uint64_t msr;
+    uint64_t orig_gpr3;
+    uint64_t ctr;
+    uint64_t link;
+    uint64_t xer;
+    uint64_t ccr;
+    uint64_t softe;
+    uint64_t trap;
+    uint64_t dar;
+    uint64_t dsisr;
+    uint64_t result;
+} QEMU_PACKED;
+
+struct PPC64ElfPrstatus {
+    char pad1[112];
+    struct PPC64UserRegStruct pr_reg;
+    uint64_t pad2[4];
+} QEMU_PACKED;
+
+
+struct PPC64ElfFpregset {
+    uint64_t fpr[32];
+    uint64_t fpscr;
+}  QEMU_PACKED;
+
+
+struct PPC64ElfVmxregset {
+    ppc_avr_t avr[32];
+    ppc_avr_t vscr;
+    union {
+        ppc_avr_t unused;
+        uint32_t value;
+    } vrsave;
+}  QEMU_PACKED;
+
+struct PPC64ElfVsxregset {
+    uint64_t vsr[32];
+}  QEMU_PACKED;
+
+struct PPC64ElfSperegset {
+    uint32_t evr[32];
+    uint64_t spe_acc;
+    uint32_t spe_fscr;
+}  QEMU_PACKED;
+
+typedef struct noteStruct {
+    Elf64_Nhdr hdr;
+    char name[5];
+    char pad3[3];
+    union {
+        struct PPC64ElfPrstatus  prstatus;
+        struct PPC64ElfFpregset  fpregset;
+        struct PPC64ElfVmxregset vmxregset;
+        struct PPC64ElfVsxregset vsxregset;
+        struct PPC64ElfSperegset speregset;
+    } contents;
+} QEMU_PACKED Note;
+
+
+static void ppc64_write_elf64_prstatus(Note *note, PowerPCCPU *cpu)
+{
+    int i;
+    uint64_t cr;
+    struct PPC64ElfPrstatus *prstatus;
+    struct PPC64UserRegStruct *reg;
+
+    note->hdr.n_type = cpu_to_be32(NT_PRSTATUS);
+
+    prstatus = &note->contents.prstatus;
+    memset(prstatus, 0, sizeof(*prstatus));
+    reg = &prstatus->pr_reg;
+
+    for (i = 0; i < 32; i++) {
+        reg->gpr[i] = cpu_to_be64(cpu->env.gpr[i]);
+    }
+    reg->nip = cpu_to_be64(cpu->env.nip);
+    reg->msr = cpu_to_be64(cpu->env.msr);
+    reg->ctr = cpu_to_be64(cpu->env.ctr);
+    reg->link = cpu_to_be64(cpu->env.lr);
+    reg->xer = cpu_to_be64(cpu_read_xer(&cpu->env));
+
+    cr = 0;
+    for (i = 0; i < 8; i++) {
+        cr |= (cpu->env.crf[i] & 15) << (4 * (7 - i));
+    }
+    reg->ccr = cpu_to_be64(cr);
+}
+
+static void ppc64_write_elf64_fpregset(Note *note, PowerPCCPU *cpu)
+{
+    int i;
+    struct PPC64ElfFpregset  *fpregset;
+
+    note->hdr.n_type = cpu_to_be32(NT_PRFPREG);
+
+    fpregset = &note->contents.fpregset;
+    memset(fpregset, 0, sizeof(*fpregset));
+
+    for (i = 0; i < 32; i++) {
+        fpregset->fpr[i] = cpu_to_be64(cpu->env.fpr[i]);
+    }
+    fpregset->fpscr = cpu_to_be64(cpu->env.fpscr);
+}
+
+static void ppc64_write_elf64_vmxregset(Note *note, PowerPCCPU *cpu)
+{
+    int i;
+    struct PPC64ElfVmxregset *vmxregset;
+
+    note->hdr.n_type = cpu_to_be32(NT_PPC_VMX);
+    vmxregset = &note->contents.vmxregset;
+    memset(vmxregset, 0, sizeof(*vmxregset));
+
+    for (i = 0; i < 32; i++) {
+        vmxregset->avr[i].u64[0] = cpu_to_be64(cpu->env.avr[i].u64[0]);
+        vmxregset->avr[i].u64[1] = cpu_to_be64(cpu->env.avr[i].u64[1]);
+    }
+    vmxregset->vscr.u32[3] = cpu_to_be32(cpu->env.vscr);
+}
+static void ppc64_write_elf64_vsxregset(Note *note, PowerPCCPU *cpu)
+{
+    int i;
+    struct PPC64ElfVsxregset *vsxregset;
+
+    note->hdr.n_type = cpu_to_be32(NT_PPC_VSX);
+    vsxregset = &note->contents.vsxregset;
+    memset(vsxregset, 0, sizeof(*vsxregset));
+
+    for (i = 0; i < 32; i++) {
+        vsxregset->vsr[i] = cpu_to_be64(cpu->env.vsr[i]);
+    }
+}
+static void ppc64_write_elf64_speregset(Note *note, PowerPCCPU *cpu)
+{
+    struct PPC64ElfSperegset *speregset;
+    note->hdr.n_type = cpu_to_be32(NT_PPC_SPE);
+    speregset = &note->contents.speregset;
+    memset(speregset, 0, sizeof(*speregset));
+
+    speregset->spe_acc = cpu_to_be64(cpu->env.spe_acc);
+    speregset->spe_fscr = cpu_to_be32(cpu->env.spe_fscr);
+}
+
+struct NoteFuncDescStruct {
+    int contents_size;
+    void (*note_contents_func)(Note *note, PowerPCCPU *cpu);
+} note_func[] = {
+    {sizeof(((Note *)0)->contents.prstatus),  ppc64_write_elf64_prstatus},
+    {sizeof(((Note *)0)->contents.fpregset),  ppc64_write_elf64_fpregset},
+    {sizeof(((Note *)0)->contents.vmxregset), ppc64_write_elf64_vmxregset},
+    {sizeof(((Note *)0)->contents.vsxregset), ppc64_write_elf64_vsxregset},
+    {sizeof(((Note *)0)->contents.speregset), ppc64_write_elf64_speregset},
+    { 0, NULL}
+};
+
+typedef struct NoteFuncDescStruct NoteFuncDesc;
+
+int cpu_get_dump_info(ArchDumpInfo *info,
+                      const struct GuestPhysBlockList *guest_phys_blocks)
+{
+    /*
+     * Currently only handling PPC64 big endian.
+     */
+    info->d_machine = EM_PPC64;
+    info->d_endian = ELFDATA2MSB;
+    info->d_class = ELFCLASS64;
+
+    return 0;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+    int name_size = 8; /* "CORE" or "QEMU" rounded */
+    size_t elf_note_size = 0;
+    int note_head_size;
+    NoteFuncDesc *nf;
+
+    if (class != ELFCLASS64) {
+        return -1;
+    }
+    assert(machine == EM_PPC64);
+
+    note_head_size = sizeof(Elf64_Nhdr);
+
+    for (nf = note_func; nf->note_contents_func; nf++) {
+        elf_note_size = elf_note_size + note_head_size + name_size +
+                        nf->contents_size;
+    }
+
+    return (elf_note_size) * nr_cpus;
+}
+
+static int ppc64_write_all_elf64_notes(const char *note_name,
+                                       WriteCoreDumpFunction f,
+                                       PowerPCCPU *cpu, int id,
+                                       void *opaque)
+{
+    Note note;
+    int ret = -1;
+    int note_size;
+    NoteFuncDesc *nf;
+
+    for (nf = note_func; nf->note_contents_func; nf++) {
+        note.hdr.n_namesz = cpu_to_be32(sizeof(note.name));
+        note.hdr.n_descsz = cpu_to_be32(nf->contents_size);
+        strncpy(note.name, note_name, sizeof(note.name));
+
+        (*nf->note_contents_func)(&note, cpu);
+
+        note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
+        ret = f(&note, note_size, opaque);
+        if (ret < 0) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+                               int cpuid, void *opaque)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    return ppc64_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque);
+}
+
+int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
+                                   CPUState *cpu, void *opaque)
+{
+    return 0;
+}
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index f3c710a..827e5dd 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -108,7 +108,10 @@
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-
+int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
+                                   CPUState *cpu, void *opaque);
+int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+                               int cpuid, void *opaque);
 #ifndef CONFIG_USER_ONLY
 extern const struct VMStateDescription vmstate_ppc_cpu;
 #endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 422a6bb..26acdba 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -405,6 +405,7 @@
     uint64_t vsid;
 };
 
+#define MAX_SLB_ENTRIES         64
 #define SEGMENT_SHIFT_256M      28
 #define SEGMENT_MASK_256M       (~((1ULL << SEGMENT_SHIFT_256M) - 1))
 
@@ -949,7 +950,7 @@
 #if !defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
     /* PowerPC 64 SLB area */
-    ppc_slb_t slb[64];
+    ppc_slb_t slb[MAX_SLB_ENTRIES];
     int32_t slb_nr;
 #endif
     /* segment registers */
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 8a196c6..b77ce5e 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -818,7 +818,7 @@
 
         /* Sync SLB */
 #ifdef TARGET_PPC64
-        for (i = 0; i < 64; i++) {
+        for (i = 0; i < ARRAY_SIZE(env->slb); i++) {
             sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid;
             sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid;
         }
@@ -1033,9 +1033,22 @@
 
         /* Sync SLB */
 #ifdef TARGET_PPC64
-        for (i = 0; i < 64; i++) {
-            ppc_store_slb(env, sregs.u.s.ppc64.slb[i].slbe,
-                               sregs.u.s.ppc64.slb[i].slbv);
+        /*
+         * The packed SLB array we get from KVM_GET_SREGS only contains
+         * information about valid entries. So we flush our internal
+         * copy to get rid of stale ones, then put all valid SLB entries
+         * back in.
+         */
+        memset(env->slb, 0, sizeof(env->slb));
+        for (i = 0; i < ARRAY_SIZE(env->slb); i++) {
+            target_ulong rb = sregs.u.s.ppc64.slb[i].slbe;
+            target_ulong rs = sregs.u.s.ppc64.slb[i].slbv;
+            /*
+             * Only restore valid entries
+             */
+            if (rb & SLB_ESID_V) {
+                ppc_store_slb(env, rb, rs);
+            }
         }
 #endif
 
@@ -1789,6 +1802,20 @@
     return 0;
 }
 
+int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function)
+{
+    struct kvm_rtas_token_args args = {
+        .token = token,
+    };
+
+    if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_RTAS)) {
+        return -ENOENT;
+    }
+
+    strncpy(args.name, function, sizeof(args.name));
+
+    return kvm_vm_ioctl(kvm_state, KVM_PPC_RTAS_DEFINE_TOKEN, &args);
+}
 
 int kvmppc_get_htab_fd(bool write)
 {
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 4ae7bf2..5f78e4b 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -38,6 +38,7 @@
 #endif /* !CONFIG_USER_ONLY */
 int kvmppc_fixup_cpu(PowerPCCPU *cpu);
 bool kvmppc_has_cap_epr(void);
+int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function);
 int kvmppc_get_htab_fd(bool write);
 int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns);
 int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index,
@@ -164,6 +165,12 @@
     return false;
 }
 
+static inline int kvmppc_define_rtas_kernel_token(uint32_t token,
+                                                  const char *function)
+{
+    return -1;
+}
+
 static inline int kvmppc_get_htab_fd(bool write)
 {
     return -1;
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 12e1512..12c174f 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -312,7 +312,7 @@
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
         VMSTATE_INT32_EQUAL(env.slb_nr, PowerPCCPU),
-        VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, 64),
+        VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES),
         VMSTATE_END_OF_LIST()
     }
 };
diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index d8e63ca..f35ed03 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -212,6 +212,7 @@
         int index = (addr & 0xf) >> sh;                         \
                                                                 \
         if (msr_le) {                                           \
+            index = n_elems - index - 1;                        \
             r->element[LO_IDX ? index : (adjust - index)] =     \
                 swap(access(env, addr));                        \
         } else {                                                \
@@ -236,6 +237,7 @@
         int index = (addr & 0xf) >> sh;                                 \
                                                                         \
         if (msr_le) {                                                   \
+            index = n_elems - index - 1;                                \
             access(env, addr, swap(r->element[LO_IDX ? index :          \
                                               (adjust - index)]));      \
         } else {                                                        \
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 651da6b..47825ac 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -108,6 +108,11 @@
     tcg_temp_free(t0);
     tcg_temp_free(t1);
 }
+
+static void spr_access_nop(void *opaque, int sprn, int gprn)
+{
+}
+
 #endif
 
 /* SPR common to all PowerPC */
@@ -1382,7 +1387,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Not strictly an SPR */
     vscr_init(env, 0x00010000);
@@ -5170,7 +5175,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Time base */
     gen_tbl(env);
@@ -5233,7 +5238,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Time base */
     gen_tbl(env);
@@ -5419,7 +5424,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Time base */
     gen_tbl(env);
@@ -5486,7 +5491,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Time base */
     gen_tbl(env);
@@ -5558,7 +5563,7 @@
     /* XXX : not implemented (XXX: different from 750fx) */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Time base */
     gen_tbl(env);
@@ -5694,7 +5699,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* XXX : not implemented */
     spr_register(env, SPR_L2PMCR, "L2PMCR",
@@ -6650,7 +6655,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Memory management */
     /* XXX: not correct */
@@ -6750,7 +6755,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Memory management */
     /* XXX: not correct */
@@ -6862,7 +6867,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Memory management */
     /* XXX: not correct */
@@ -6962,7 +6967,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Memory management */
     /* XXX: not correct */
@@ -7054,7 +7059,7 @@
     /* XXX : not implemented */
     spr_register(env, SPR_L2CR, "L2CR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, NULL,
+                 &spr_read_generic, spr_access_nop,
                  0x00000000);
     /* Memory management */
     /* XXX: not correct */
@@ -7103,6 +7108,7 @@
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->fw_name = "PowerPC,POWER5";
     dc->desc = "POWER5+";
     pcc->init_proc = init_proc_power5plus;
     pcc->check_pow = check_pow_970FX;
@@ -7213,6 +7219,7 @@
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->fw_name = "PowerPC,POWER7";
     dc->desc = "POWER7";
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
@@ -7247,6 +7254,7 @@
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->fw_name = "PowerPC,POWER8";
     dc->desc = "POWER8";
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
@@ -8567,6 +8575,10 @@
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug;
     cc->vmsd = &vmstate_ppc_cpu;
+#if defined(TARGET_PPC64)
+    cc->write_elf64_note = ppc64_cpu_write_elf64_note;
+    cc->write_elf64_qemunote = ppc64_cpu_write_elf64_qemunote;
+#endif
 #endif
 
     cc->gdb_num_core_regs = 71;
@@ -8575,6 +8587,8 @@
 #else
     cc->gdb_core_xml_file = "power-core.xml";
 #endif
+
+    dc->fw_name = "PowerPC,UNKNOWN";
 }
 
 static const TypeInfo ppc_cpu_type_info = {
diff --git a/target-xtensa/core-dc233c.c b/target-xtensa/core-dc233c.c
index 11acbf3..738d543 100644
--- a/target-xtensa/core-dc233c.c
+++ b/target-xtensa/core-dc233c.c
@@ -49,6 +49,7 @@
     EXCEPTIONS_SECTION,
     INTERRUPTS_SECTION,
     TLB_SECTION,
+    DEBUG_SECTION,
     .clock_freq_khz = 10000,
 };
 
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 0656d39..2d8e00c 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -109,7 +109,6 @@
 };
 
 static const int tcg_target_reg_alloc_order[] = {
-    TCG_REG_R33,
     TCG_REG_R35,
     TCG_REG_R36,
     TCG_REG_R37,
@@ -226,6 +225,7 @@
     OPC_BR_CALL_SPTK_MANY_B5  = 0x02100001000ull,
     OPC_BR_RET_SPTK_MANY_B4   = 0x00108001100ull,
     OPC_BRL_SPTK_MANY_X3      = 0x18000001000ull,
+    OPC_BRL_CALL_SPTK_MANY_X4 = 0x1a000001000ull,
     OPC_CMP_LT_A6             = 0x18000000000ull,
     OPC_CMP_LTU_A6            = 0x1a000000000ull,
     OPC_CMP_EQ_A6             = 0x1c000000000ull,
@@ -263,6 +263,7 @@
     OPC_MOV_I_I26             = 0x00150000000ull,
     OPC_MOVL_X2               = 0x0c000000000ull,
     OPC_OR_A1                 = 0x10070000000ull,
+    OPC_OR_A3                 = 0x10170000000ull,
     OPC_SETF_EXP_M18          = 0x0c748000000ull,
     OPC_SETF_SIG_M18          = 0x0c708000000ull,
     OPC_SHL_I7                = 0x0f240000000ull,
@@ -281,9 +282,13 @@
     OPC_UNPACK4_L_I2          = 0x0f860000000ull,
     OPC_XMA_L_F2              = 0x1d000000000ull,
     OPC_XOR_A1                = 0x10078000000ull,
+    OPC_XOR_A3                = 0x10178000000ull,
     OPC_ZXT1_I29              = 0x00080000000ull,
     OPC_ZXT2_I29              = 0x00088000000ull,
     OPC_ZXT4_I29              = 0x00090000000ull,
+
+    INSN_NOP_M                = OPC_NOP_M48,  /* nop.m 0 */
+    INSN_NOP_I                = OPC_NOP_I18,  /* nop.i 0 */
 };
 
 static inline uint64_t tcg_opc_a1(int qp, uint64_t opc, int r1,
@@ -581,6 +586,8 @@
     return (imm & 0x07fffffffff00000ull) >> 18;
 }
 
+#define tcg_opc_l4  tcg_opc_l3
+
 static inline uint64_t tcg_opc_m1(int qp, uint64_t opc, int r1, int r3)
 {
     return opc
@@ -665,6 +672,15 @@
            | (qp & 0x3f);
 }
 
+static inline uint64_t tcg_opc_x4(int qp, uint64_t opc, int b1, uint64_t imm)
+{
+    return opc
+           | ((imm & 0x0800000000000000ull) >> 23) /* i */
+           | ((imm & 0x00000000000fffffull) << 13) /* imm20b */
+           | ((b1 & 0x7) << 6)
+           | (qp & 0x3f);
+}
+
 
 /*
  * Relocations
@@ -851,20 +867,31 @@
     s->code_ptr += 16;
 }
 
+static inline uint64_t tcg_opc_mov_a(int qp, TCGReg dst, TCGReg src)
+{
+    return tcg_opc_a4(qp, OPC_ADDS_A4, dst, 0, src);
+}
+
 static inline void tcg_out_mov(TCGContext *s, TCGType type,
                                TCGReg ret, TCGReg arg)
 {
     tcg_out_bundle(s, mmI,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, 0, arg));
+                   INSN_NOP_M,
+                   INSN_NOP_M,
+                   tcg_opc_mov_a(TCG_REG_P0, ret, arg));
+}
+
+static inline uint64_t tcg_opc_movi_a(int qp, TCGReg dst, int64_t src)
+{
+    assert(src == sextract64(src, 0, 22));
+    return tcg_opc_a5(qp, OPC_ADDL_A5, dst, src, TCG_REG_R0);
 }
 
 static inline void tcg_out_movi(TCGContext *s, TCGType type,
                                 TCGReg reg, tcg_target_long arg)
 {
     tcg_out_bundle(s, mLX,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_l2 (arg),
                    tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, reg, arg));
 }
@@ -877,8 +904,8 @@
        the existing value and using it again. This ensure that caches and
        memory are kept coherent during retranslation. */
     tcg_out_bundle(s, mmB,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
+                   INSN_NOP_M,
                    tcg_opc_b1 (TCG_REG_P0, OPC_BR_SPTK_MANY_B1,
                                get_reloc_pcrel21b(s->code_ptr + 2)));
 
@@ -890,7 +917,23 @@
     }
 }
 
-static inline void tcg_out_call(TCGContext *s, TCGArg addr)
+static inline void tcg_out_calli(TCGContext *s, uintptr_t addr)
+{
+    /* Look through the function descriptor.  */
+    uintptr_t disp, *desc = (uintptr_t *)addr;
+    tcg_out_bundle(s, mlx,
+                   INSN_NOP_M,
+                   tcg_opc_l2 (desc[1]),
+                   tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, TCG_REG_R1, desc[1]));
+    disp = (desc[0] - (uintptr_t)s->code_ptr) >> 4;
+    tcg_out_bundle(s, mLX,
+                   INSN_NOP_M,
+                   tcg_opc_l4 (disp),
+                   tcg_opc_x4 (TCG_REG_P0, OPC_BRL_CALL_SPTK_MANY_X4,
+                               TCG_REG_B0, disp));
+}
+
+static inline void tcg_out_callr(TCGContext *s, TCGReg addr)
 {
     tcg_out_bundle(s, MmI,
                    tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R2, addr),
@@ -899,7 +942,7 @@
                                TCG_REG_B6, TCG_REG_R2, 0));
     tcg_out_bundle(s, mmB,
                    tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R3),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_b5 (TCG_REG_P0, OPC_BR_CALL_SPTK_MANY_B5,
                                TCG_REG_B0, TCG_REG_B6));
 }
@@ -915,7 +958,7 @@
     imm = (uint64_t)disp >> 4;
 
     tcg_out_bundle(s, mLX,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_l3 (imm),
                    tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, imm));
 }
@@ -932,12 +975,12 @@
         tcg_out_bundle(s, MmI,
                        tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1,
                                    TCG_REG_R2, TCG_REG_R2),
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, TCG_REG_B6,
                                    TCG_REG_R2, 0));
         tcg_out_bundle(s, mmB,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_M,
                        tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4,
                                    TCG_REG_B6));
     }
@@ -947,12 +990,12 @@
 static inline void tcg_out_jmp(TCGContext *s, TCGArg addr)
 {
     tcg_out_bundle(s, mmI,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
+                   INSN_NOP_M,
                    tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, TCG_REG_B6, addr, 0));
     tcg_out_bundle(s, mmB,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
+                   INSN_NOP_M,
                    tcg_opc_b4(TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6));
 }
 
@@ -964,14 +1007,14 @@
                        tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4,
                                   TCG_REG_R2, arg2, arg1),
                        tcg_opc_m1 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     } else {
         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg2);
         tcg_out_bundle(s, MmI,
                        tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1,
                                    TCG_REG_R2, TCG_REG_R2, arg1),
                        tcg_opc_m1 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     }
 }
 
@@ -983,14 +1026,14 @@
                        tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4,
                                   TCG_REG_R2, arg2, arg1),
                        tcg_opc_m4 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     } else {
         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg2);
         tcg_out_bundle(s, MmI,
                        tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1,
                                    TCG_REG_R2, TCG_REG_R2, arg1),
                        tcg_opc_m4 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     }
 }
 
@@ -1014,32 +1057,59 @@
     }
 }
 
-static inline void tcg_out_alu(TCGContext *s, uint64_t opc_a1, TCGArg ret,
-                               TCGArg arg1, int const_arg1,
+static inline void tcg_out_alu(TCGContext *s, uint64_t opc_a1, uint64_t opc_a3,
+                               TCGReg ret, TCGArg arg1, int const_arg1,
                                TCGArg arg2, int const_arg2)
 {
-    uint64_t opc1, opc2;
-
-    if (const_arg1 && arg1 != 0) {
-        opc1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5,
-                          TCG_REG_R2, arg1, TCG_REG_R0);
-        arg1 = TCG_REG_R2;
-    } else {
-        opc1 = tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0);
-    }
+    uint64_t opc1 = 0, opc2 = 0, opc3 = 0;
 
     if (const_arg2 && arg2 != 0) {
-        opc2 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5,
-                          TCG_REG_R3, arg2, TCG_REG_R0);
+        opc2 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R3, arg2);
         arg2 = TCG_REG_R3;
-    } else {
-        opc2 = tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0);
+    }
+    if (const_arg1 && arg1 != 0) {
+        if (opc_a3 && arg1 == (int8_t)arg1) {
+            opc3 = tcg_opc_a3(TCG_REG_P0, opc_a3, ret, arg1, arg2);
+        } else {
+            opc1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, arg1);
+            arg1 = TCG_REG_R2;
+        }
+    }
+    if (opc3 == 0) {
+        opc3 = tcg_opc_a1(TCG_REG_P0, opc_a1, ret, arg1, arg2);
     }
 
-    tcg_out_bundle(s, mII,
-                   opc1,
-                   opc2,
-                   tcg_opc_a1(TCG_REG_P0, opc_a1, ret, arg1, arg2));
+    tcg_out_bundle(s, (opc1 || opc2 ? mII : miI),
+                   opc1 ? opc1 : INSN_NOP_M,
+                   opc2 ? opc2 : INSN_NOP_I,
+                   opc3);
+}
+
+static inline void tcg_out_add(TCGContext *s, TCGReg ret, TCGReg arg1,
+                               TCGArg arg2, int const_arg2)
+{
+    if (const_arg2 && arg2 == sextract64(arg2, 0, 14)) {
+        tcg_out_bundle(s, mmI,
+                       INSN_NOP_M,
+                       INSN_NOP_M,
+                       tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, arg2, arg1));
+    } else {
+        tcg_out_alu(s, OPC_ADD_A1, 0, ret, arg1, 0, arg2, const_arg2);
+    }
+}
+
+static inline void tcg_out_sub(TCGContext *s, TCGReg ret, TCGArg arg1,
+                               int const_arg1, TCGArg arg2, int const_arg2)
+{
+    if (!const_arg1 && const_arg2 && -arg2 == sextract64(-arg2, 0, 14)) {
+        tcg_out_bundle(s, mmI,
+                       INSN_NOP_M,
+                       INSN_NOP_M,
+                       tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, -arg2, arg1));
+    } else {
+        tcg_out_alu(s, OPC_SUB_A1, OPC_SUB_A3, ret,
+                    arg1, const_arg1, arg2, const_arg2);
+    }
 }
 
 static inline void tcg_out_eqv(TCGContext *s, TCGArg ret,
@@ -1047,7 +1117,7 @@
                                TCGArg arg2, int const_arg2)
 {
     tcg_out_bundle(s, mII,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_a1 (TCG_REG_P0, OPC_XOR_A1, ret, arg1, arg2),
                    tcg_opc_a3 (TCG_REG_P0, OPC_ANDCM_A3, ret, -1, ret));
 }
@@ -1057,7 +1127,7 @@
                                 TCGArg arg2, int const_arg2)
 {
     tcg_out_bundle(s, mII,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_a1 (TCG_REG_P0, OPC_AND_A1, ret, arg1, arg2),
                    tcg_opc_a3 (TCG_REG_P0, OPC_ANDCM_A3, ret, -1, ret));
 }
@@ -1067,7 +1137,7 @@
                                TCGArg arg2, int const_arg2)
 {
     tcg_out_bundle(s, mII,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_a1 (TCG_REG_P0, OPC_OR_A1, ret, arg1, arg2),
                    tcg_opc_a3 (TCG_REG_P0, OPC_ANDCM_A3, ret, -1, ret));
 }
@@ -1077,7 +1147,7 @@
                                TCGArg arg2, int const_arg2)
 {
     tcg_out_bundle(s, mII,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_a3 (TCG_REG_P0, OPC_ANDCM_A3, TCG_REG_R2, -1, arg2),
                    tcg_opc_a1 (TCG_REG_P0, OPC_OR_A1, ret, arg1, TCG_REG_R2));
 }
@@ -1088,16 +1158,16 @@
     tcg_out_bundle(s, mmI,
                    tcg_opc_m18(TCG_REG_P0, OPC_SETF_SIG_M18, TCG_REG_F6, arg1),
                    tcg_opc_m18(TCG_REG_P0, OPC_SETF_SIG_M18, TCG_REG_F7, arg2),
-                   tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                   INSN_NOP_I);
     tcg_out_bundle(s, mmF,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
+                   INSN_NOP_M,
                    tcg_opc_f2 (TCG_REG_P0, OPC_XMA_L_F2, TCG_REG_F6, TCG_REG_F6,
                                TCG_REG_F7, TCG_REG_F0));
     tcg_out_bundle(s, miI,
                    tcg_opc_m19(TCG_REG_P0, OPC_GETF_SIG_M19, ret, TCG_REG_F6),
-                   tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                   tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                   INSN_NOP_I,
+                   INSN_NOP_I);
 }
 
 static inline void tcg_out_sar_i32(TCGContext *s, TCGArg ret, TCGArg arg1,
@@ -1105,8 +1175,8 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i11(TCG_REG_P0, OPC_EXTR_I11,
                                    ret, arg1, arg2, 31 - arg2));
     } else {
@@ -1124,14 +1194,14 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i11(TCG_REG_P0, OPC_EXTR_I11,
                                    ret, arg1, arg2, 63 - arg2));
     } else {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i5 (TCG_REG_P0, OPC_SHR_I5, ret, arg1, arg2));
     }
 }
@@ -1141,13 +1211,13 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret,
                                    arg1, 63 - arg2, 31 - arg2));
     } else {
         tcg_out_bundle(s, mII,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_a3 (TCG_REG_P0, OPC_AND_A3, TCG_REG_R2,
                                    0x1f, arg2),
                        tcg_opc_i7 (TCG_REG_P0, OPC_SHL_I7, ret,
@@ -1160,14 +1230,14 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret,
                                    arg1, 63 - arg2, 63 - arg2));
     } else {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i7 (TCG_REG_P0, OPC_SHL_I7, ret,
                                    arg1, arg2));
     }
@@ -1178,8 +1248,8 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, ret,
                                    arg1, arg2, 31 - arg2));
     } else {
@@ -1197,14 +1267,14 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, ret,
                                    arg1, arg2, 63 - arg2));
     } else {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, ret,
                                    arg1, arg2));
     }
@@ -1215,20 +1285,20 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, mII,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i2 (TCG_REG_P0, OPC_UNPACK4_L_I2,
                                    TCG_REG_R2, arg1, arg1),
                        tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, ret,
                                    TCG_REG_R2, 32 - arg2, 31));
     } else {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i2 (TCG_REG_P0, OPC_UNPACK4_L_I2,
                                    TCG_REG_R2, arg1, arg1),
                        tcg_opc_a3 (TCG_REG_P0, OPC_AND_A3, TCG_REG_R3,
                                    0x1f, arg2));
         tcg_out_bundle(s, mII,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_a3 (TCG_REG_P0, OPC_SUB_A3, TCG_REG_R3,
                                    0x20, TCG_REG_R3),
                        tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, ret,
@@ -1241,8 +1311,8 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i10(TCG_REG_P0, OPC_SHRP_I10, ret, arg1,
                                    arg1, 0x40 - arg2));
     } else {
@@ -1254,8 +1324,8 @@
                        tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, TCG_REG_R2,
                                    arg1, TCG_REG_R2));
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_a1 (TCG_REG_P0, OPC_OR_A1, ret,
                                    TCG_REG_R2, TCG_REG_R3));
     }
@@ -1266,7 +1336,7 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, mII,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i2 (TCG_REG_P0, OPC_UNPACK4_L_I2,
                                    TCG_REG_R2, arg1, arg1),
                        tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, ret,
@@ -1287,8 +1357,8 @@
 {
     if (const_arg2) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_i10(TCG_REG_P0, OPC_SHRP_I10, ret, arg1,
                                    arg1, arg2));
     } else {
@@ -1300,44 +1370,63 @@
                        tcg_opc_i7 (TCG_REG_P0, OPC_SHL_I7, TCG_REG_R2,
                                    arg1, TCG_REG_R2));
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_M,
+                       INSN_NOP_I,
                        tcg_opc_a1 (TCG_REG_P0, OPC_OR_A1, ret,
                                    TCG_REG_R2, TCG_REG_R3));
     }
 }
 
+static const uint64_t opc_ext_i29[8] = {
+    OPC_ZXT1_I29, OPC_ZXT2_I29, OPC_ZXT4_I29, 0,
+    OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0
+};
+
+static inline uint64_t tcg_opc_ext_i(int qp, TCGMemOp opc, TCGReg d, TCGReg s)
+{
+    if ((opc & MO_SIZE) == MO_64) {
+        return tcg_opc_mov_a(qp, d, s);
+    } else {
+        return tcg_opc_i29(qp, opc_ext_i29[opc & MO_SSIZE], d, s);
+    }
+}
+
 static inline void tcg_out_ext(TCGContext *s, uint64_t opc_i29,
                                TCGArg ret, TCGArg arg)
 {
     tcg_out_bundle(s, miI,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                   INSN_NOP_M,
+                   INSN_NOP_I,
                    tcg_opc_i29(TCG_REG_P0, opc_i29, ret, arg));
 }
 
+static inline uint64_t tcg_opc_bswap64_i(int qp, TCGReg d, TCGReg s)
+{
+    return tcg_opc_i3(qp, OPC_MUX1_I3, d, s, 0xb);
+}
+
 static inline void tcg_out_bswap16(TCGContext *s, TCGArg ret, TCGArg arg)
 {
     tcg_out_bundle(s, mII,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret, arg, 15, 15),
-                   tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, ret, 0xb));
+                   tcg_opc_bswap64_i(TCG_REG_P0, ret, ret));
 }
 
 static inline void tcg_out_bswap32(TCGContext *s, TCGArg ret, TCGArg arg)
 {
     tcg_out_bundle(s, mII,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret, arg, 31, 31),
-                   tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, ret, 0xb));
+                   tcg_opc_bswap64_i(TCG_REG_P0, ret, ret));
 }
 
 static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg)
 {
     tcg_out_bundle(s, miI,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                   tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, arg, 0xb));
+                   INSN_NOP_M,
+                   INSN_NOP_I,
+                   tcg_opc_bswap64_i(TCG_REG_P0, ret, arg));
 }
 
 static inline void tcg_out_deposit(TCGContext *s, TCGArg ret, TCGArg a1,
@@ -1357,8 +1446,7 @@
         } else {
             /* Otherwise, load any constant into a temporary.  Do this into
                the first I slot to help out with cross-unit delays.  */
-            i1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5,
-                            TCG_REG_R2, a2, TCG_REG_R0);
+            i1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, a2);
             a2 = TCG_REG_R2;
         }
     }
@@ -1366,8 +1454,8 @@
         i2 = tcg_opc_i15(TCG_REG_P0, OPC_DEP_I15, ret, a2, a1, cpos, lm1);
     }
     tcg_out_bundle(s, (i1 ? mII : miI),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   i1 ? i1 : tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                   INSN_NOP_M,
+                   i1 ? i1 : INSN_NOP_I,
                    i2);
 }
 
@@ -1413,38 +1501,16 @@
     }
 }
 
-static inline void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
-                                  int const_arg1, TCGArg arg2, int const_arg2,
-                                  int label_index, int cmp4)
+static inline void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
+                                  TCGReg arg2, int label_index, int cmp4)
 {
     TCGLabel *l = &s->labels[label_index];
-    uint64_t opc1, opc2;
 
-    if (const_arg1 && arg1 != 0) {
-        opc1 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2,
-                          arg1, TCG_REG_R0);
-        arg1 = TCG_REG_R2;
-    } else {
-        opc1 = tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0);
-    }
-
-    if (const_arg2 && arg2 != 0) {
-        opc2 = tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R3,
-                          arg2, TCG_REG_R0);
-        arg2 = TCG_REG_R3;
-    } else {
-        opc2 = tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0);
-    }
-
-    tcg_out_bundle(s, mII,
-                   opc1,
-                   opc2,
-                   tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4));
-    tcg_out_bundle(s, mmB,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_b1 (TCG_REG_P6, OPC_BR_DPTK_FEW_B1,
-                               get_reloc_pcrel21b(s->code_ptr + 2)));
+    tcg_out_bundle(s, miB,
+                   INSN_NOP_M,
+                   tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4),
+                   tcg_opc_b1(TCG_REG_P6, OPC_BR_DPTK_FEW_B1,
+                              get_reloc_pcrel21b(s->code_ptr + 2)));
 
     if (l->has_value) {
         reloc_pcrel21b((s->code_ptr - 16) + 2, l->u.value);
@@ -1459,8 +1525,8 @@
 {
     tcg_out_bundle(s, MmI,
                    tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4),
-                   tcg_opc_a5(TCG_REG_P6, OPC_ADDL_A5, ret, 1, TCG_REG_R0),
-                   tcg_opc_a5(TCG_REG_P7, OPC_ADDL_A5, ret, 0, TCG_REG_R0));
+                   tcg_opc_movi_a(TCG_REG_P6, ret, 1),
+                   tcg_opc_movi_a(TCG_REG_P7, ret, 0));
 }
 
 static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret,
@@ -1471,18 +1537,18 @@
     uint64_t opc1, opc2;
 
     if (const_v1) {
-        opc1 = tcg_opc_a5(TCG_REG_P6, OPC_ADDL_A5, ret, v1, TCG_REG_R0);
+        opc1 = tcg_opc_movi_a(TCG_REG_P6, ret, v1);
     } else if (ret == v1) {
-        opc1 = tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0);
+        opc1 = INSN_NOP_M;
     } else {
-        opc1 = tcg_opc_a4(TCG_REG_P6, OPC_ADDS_A4, ret, 0, v1);
+        opc1 = tcg_opc_mov_a(TCG_REG_P6, ret, v1);
     }
     if (const_v2) {
-        opc2 = tcg_opc_a5(TCG_REG_P7, OPC_ADDL_A5, ret, v2, TCG_REG_R0);
+        opc2 = tcg_opc_movi_a(TCG_REG_P7, ret, v2);
     } else if (ret == v2) {
-        opc2 = tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0);
+        opc2 = INSN_NOP_I;
     } else {
-        opc2 = tcg_opc_a4(TCG_REG_P7, OPC_ADDS_A4, ret, 0, v2);
+        opc2 = tcg_opc_mov_a(TCG_REG_P7, ret, v2);
     }
 
     tcg_out_bundle(s, MmI,
@@ -1496,11 +1562,11 @@
    R2 is loaded with the address of the addend TLB entry.
    R57 is loaded with the address, zero extented on 32-bit targets. */
 static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg,
-                                    int s_bits, uint64_t offset_rw,
+                                    TCGMemOp s_bits, uint64_t offset_rw,
                                     uint64_t offset_addend)
 {
     tcg_out_bundle(s, mII,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R2,
                                addr_reg, TARGET_PAGE_BITS, CPU_TLB_BITS - 1),
                    tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R2,
@@ -1509,12 +1575,9 @@
     tcg_out_bundle(s, mII,
                    tcg_opc_a5 (TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2,
                                offset_rw, TCG_REG_R2),
-#if TARGET_LONG_BITS == 32
-                   tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29, TCG_REG_R57, addr_reg),
-#else
-                   tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R57,
-                              0, addr_reg),
-#endif
+                   tcg_opc_ext_i(TCG_REG_P0,
+                                 TARGET_LONG_BITS == 32 ? MO_UL : MO_Q,
+                                 TCG_REG_R57, addr_reg),
                    tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
                                TCG_REG_R2, TCG_AREG0));
     tcg_out_bundle(s, mII,
@@ -1538,23 +1601,20 @@
     helper_ldq_mmu,
 };
 
-static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
+                                   TCGMemOp opc)
 {
-    int addr_reg, data_reg, mem_index, s_bits, bswap;
-    uint64_t opc_ld_m1[4] = { OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1 };
-    uint64_t opc_ext_i29[8] = { OPC_ZXT1_I29, OPC_ZXT2_I29, OPC_ZXT4_I29, 0,
-                                OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0 };
+    static const uint64_t opc_ld_m1[4] = {
+        OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
+    };
+    int addr_reg, data_reg, mem_index;
+    TCGMemOp s_bits, bswap;
 
     data_reg = *args++;
     addr_reg = *args++;
     mem_index = *args;
-    s_bits = opc & 3;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
+    s_bits = opc & MO_SIZE;
+    bswap = opc & MO_BSWAP;
 
     /* Read the TLB entry */
     tcg_out_qemu_tlb(s, addr_reg, s_bits,
@@ -1563,8 +1623,7 @@
 
     /* P6 is the fast path, and P7 the slow path */
     tcg_out_bundle(s, mLX,
-                   tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4,
-                               TCG_REG_R56, 0, TCG_AREG0),
+                   tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
                    tcg_opc_l2 ((tcg_target_long) qemu_ld_helpers[s_bits]),
                    tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2,
                                (tcg_target_long) qemu_ld_helpers[s_bits]));
@@ -1575,14 +1634,14 @@
                                TCG_REG_R3, TCG_REG_R57),
                    tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6,
                                TCG_REG_R3, 0));
-    if (bswap && s_bits == 1) {
+    if (bswap && s_bits == MO_16) {
         tcg_out_bundle(s, MmI,
                        tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
                                    TCG_REG_R8, TCG_REG_R3),
                        tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
                        tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
                                    TCG_REG_R8, TCG_REG_R8, 15, 15));
-    } else if (bswap && s_bits == 2) {
+    } else if (bswap && s_bits == MO_32) {
         tcg_out_bundle(s, MmI,
                        tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
                                    TCG_REG_R8, TCG_REG_R3),
@@ -1594,38 +1653,26 @@
                        tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
                                    TCG_REG_R8, TCG_REG_R3),
                        tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     }
-    if (!bswap || s_bits == 0) {
+    if (!bswap) {
         tcg_out_bundle(s, miB,
-                       tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58,
-                                   mem_index, TCG_REG_R0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index),
+                       INSN_NOP_I,
                        tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
                                    TCG_REG_B0, TCG_REG_B6));
     } else {
         tcg_out_bundle(s, miB,
-                       tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58,
-                                   mem_index, TCG_REG_R0),
-                       tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3,
-                                   TCG_REG_R8, TCG_REG_R8, 0xb),
+                       tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index),
+                       tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R8, TCG_REG_R8),
                        tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
                                    TCG_REG_B0, TCG_REG_B6));
     }
 
-    if (opc == 3) {
-        tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                       tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
-                                   data_reg, 0, TCG_REG_R8));
-    } else {
-        tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                       tcg_opc_i29(TCG_REG_P0, opc_ext_i29[opc],
-                                   data_reg, TCG_REG_R8));
-    }
+    tcg_out_bundle(s, miI,
+                   INSN_NOP_M,
+                   INSN_NOP_I,
+                   tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8));
 }
 
 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
@@ -1637,32 +1684,30 @@
     helper_stq_mmu,
 };
 
-static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
+                                   TCGMemOp opc)
 {
-    int addr_reg, data_reg, mem_index, bswap;
-    uint64_t opc_st_m4[4] = { OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4 };
+    static const uint64_t opc_st_m4[4] = {
+        OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
+    };
+    int addr_reg, data_reg, mem_index;
+    TCGMemOp s_bits;
 
     data_reg = *args++;
     addr_reg = *args++;
     mem_index = *args;
+    s_bits = opc & MO_SIZE;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
-
-    tcg_out_qemu_tlb(s, addr_reg, opc,
+    tcg_out_qemu_tlb(s, addr_reg, s_bits,
                      offsetof(CPUArchState, tlb_table[mem_index][0].addr_write),
                      offsetof(CPUArchState, tlb_table[mem_index][0].addend));
 
     /* P6 is the fast path, and P7 the slow path */
     tcg_out_bundle(s, mLX,
-                   tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4,
-                               TCG_REG_R56, 0, TCG_AREG0),
-                   tcg_opc_l2 ((tcg_target_long) qemu_st_helpers[opc]),
+                   tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
+                   tcg_opc_l2 ((tcg_target_long) qemu_st_helpers[s_bits]),
                    tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2,
-                               (tcg_target_long) qemu_st_helpers[opc]));
+                               (tcg_target_long) qemu_st_helpers[s_bits]));
     tcg_out_bundle(s, MmI,
                    tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3,
                                TCG_REG_R2, 8),
@@ -1671,150 +1716,145 @@
                    tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6,
                                TCG_REG_R3, 0));
 
-    if (!bswap || opc == 0) {
+    switch (opc) {
+    case MO_8:
+    case MO_16:
+    case MO_32:
+    case MO_64:
         tcg_out_bundle(s, mii,
                        tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
                                    TCG_REG_R1, TCG_REG_R2),
-                       tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58,
-                                   0, data_reg),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
-    } else if (opc == 1) {
+                       tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
+                       INSN_NOP_I);
+        break;
+
+    case MO_16 | MO_BSWAP:
         tcg_out_bundle(s, miI,
                        tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
                                    TCG_REG_R1, TCG_REG_R2),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_I,
                        tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
                                    TCG_REG_R2, data_reg, 15, 15));
         tcg_out_bundle(s, miI,
-                       tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58,
-                                   0, data_reg),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                       tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3,
-                                   TCG_REG_R2, TCG_REG_R2, 0xb));
+                       tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
+                       INSN_NOP_I,
+                       tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2));
         data_reg = TCG_REG_R2;
-    } else if (opc == 2) {
+        break;
+
+    case MO_32 | MO_BSWAP:
         tcg_out_bundle(s, miI,
                        tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
                                    TCG_REG_R1, TCG_REG_R2),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                       INSN_NOP_I,
                        tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
                                    TCG_REG_R2, data_reg, 31, 31));
         tcg_out_bundle(s, miI,
-                       tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58,
-                                   0, data_reg),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                       tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3,
-                                   TCG_REG_R2, TCG_REG_R2, 0xb));
+                       tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
+                       INSN_NOP_I,
+                       tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2));
         data_reg = TCG_REG_R2;
-    } else if (opc == 3) {
+        break;
+
+    case MO_64 | MO_BSWAP:
         tcg_out_bundle(s, miI,
                        tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
                                    TCG_REG_R1, TCG_REG_R2),
-                       tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4, TCG_REG_R58,
-                                   0, data_reg),
-                       tcg_opc_i3 (TCG_REG_P6, OPC_MUX1_I3,
-                                   TCG_REG_R2, data_reg, 0xb));
+                       tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
+                       tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, data_reg));
         data_reg = TCG_REG_R2;
+        break;
+
+    default:
+        tcg_abort();
     }
 
     tcg_out_bundle(s, miB,
-                   tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc],
+                   tcg_opc_m4 (TCG_REG_P6, opc_st_m4[s_bits],
                                data_reg, TCG_REG_R3),
-                   tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R59,
-                               mem_index, TCG_REG_R0),
+                   tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index),
                    tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
                                TCG_REG_B0, TCG_REG_B6));
 }
 
 #else /* !CONFIG_SOFTMMU */
 
-static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
+                                   TCGMemOp opc)
 {
     static uint64_t const opc_ld_m1[4] = {
         OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
     };
-    static uint64_t const opc_sxt_i29[4] = {
-        OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0
-    };
-    int addr_reg, data_reg, s_bits, bswap;
+    int addr_reg, data_reg;
+    TCGMemOp s_bits, bswap;
 
     data_reg = *args++;
     addr_reg = *args++;
-    s_bits = opc & 3;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
+    s_bits = opc & MO_SIZE;
+    bswap = opc & MO_BSWAP;
 
 #if TARGET_LONG_BITS == 32
     if (GUEST_BASE != 0) {
         tcg_out_bundle(s, mII,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
                                    TCG_REG_R3, addr_reg),
                        tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
                                    TCG_GUEST_BASE_REG, TCG_REG_R3));
     } else {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
                                    TCG_REG_R2, addr_reg),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     }
 
-    if (!bswap || s_bits == 0) {
-        if (s_bits == opc) {
+    if (!bswap) {
+        if (!(opc & MO_SIGN)) {
             tcg_out_bundle(s, miI,
                            tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
                                        data_reg, TCG_REG_R2),
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                           INSN_NOP_I,
+                           INSN_NOP_I);
         } else {
             tcg_out_bundle(s, mII,
                            tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
                                        data_reg, TCG_REG_R2),
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                           tcg_opc_i29(TCG_REG_P0, opc_sxt_i29[s_bits],
-                                       data_reg, data_reg));
+                           INSN_NOP_I,
+                           tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, data_reg));
         }
-    } else if (s_bits == 3) {
+    } else if (s_bits == MO_64) {
             tcg_out_bundle(s, mII,
                            tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
                                        data_reg, TCG_REG_R2),
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       data_reg, data_reg, 0xb));
+                           INSN_NOP_I,
+                           tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
     } else {
-        if (s_bits == 1) {
+        if (s_bits == MO_16) {
             tcg_out_bundle(s, mII,
                            tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
                                        data_reg, TCG_REG_R2),
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                           INSN_NOP_I,
                            tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
                                       data_reg, data_reg, 15, 15));
         } else {
             tcg_out_bundle(s, mII,
                            tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
                                        data_reg, TCG_REG_R2),
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
+                           INSN_NOP_I,
                            tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
                                       data_reg, data_reg, 31, 31));
         }
-        if (opc == s_bits) {
+        if (!(opc & MO_SIGN)) {
             tcg_out_bundle(s, miI,
-                           tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       data_reg, data_reg, 0xb));
+                           INSN_NOP_M,
+                           INSN_NOP_I,
+                           tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
         } else {
             tcg_out_bundle(s, mII,
-                           tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       data_reg, data_reg, 0xb),
-                           tcg_opc_i29(TCG_REG_P0, opc_sxt_i29[s_bits],
-                                       data_reg, data_reg));
+                           INSN_NOP_M,
+                           tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg),
+                           tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, data_reg));
         }
     }
 #else
@@ -1824,157 +1864,149 @@
                                    TCG_GUEST_BASE_REG, addr_reg),
                        tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
                                    data_reg, TCG_REG_R2),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     } else {
         tcg_out_bundle(s, mmI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
                                    data_reg, addr_reg),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     }
 
-    if (bswap && s_bits == 1) {
+    if (bswap && s_bits == MO_16) {
         tcg_out_bundle(s, mII,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
                                    data_reg, data_reg, 15, 15),
-                       tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                   data_reg, data_reg, 0xb));
-    } else if (bswap && s_bits == 2) {
+                       tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
+    } else if (bswap && s_bits == MO_32) {
         tcg_out_bundle(s, mII,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
                                    data_reg, data_reg, 31, 31),
-                       tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                   data_reg, data_reg, 0xb));
-    } else if (bswap && s_bits == 3) {
+                       tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
+    } else if (bswap && s_bits == MO_64) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                       tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                   data_reg, data_reg, 0xb));
+                       INSN_NOP_M,
+                       INSN_NOP_I,
+                       tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
     }
-    if (s_bits != opc) {
+    if (opc & MO_SIGN) {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                       tcg_opc_i29(TCG_REG_P0, opc_sxt_i29[s_bits],
-                                   data_reg, data_reg));
+                       INSN_NOP_M,
+                       INSN_NOP_I,
+                       tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, data_reg));
     }
 #endif
 }
 
-static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
+                                   TCGMemOp opc)
 {
     static uint64_t const opc_st_m4[4] = {
         OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
     };
-    int addr_reg, data_reg, bswap;
+    int addr_reg, data_reg;
 #if TARGET_LONG_BITS == 64
     uint64_t add_guest_base;
 #endif
+    TCGMemOp s_bits, bswap;
 
     data_reg = *args++;
     addr_reg = *args++;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
+    s_bits = opc & MO_SIZE;
+    bswap = opc & MO_BSWAP;
 
 #if TARGET_LONG_BITS == 32
     if (GUEST_BASE != 0) {
         tcg_out_bundle(s, mII,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
                                    TCG_REG_R3, addr_reg),
                        tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
                                    TCG_GUEST_BASE_REG, TCG_REG_R3));
     } else {
         tcg_out_bundle(s, miI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
                                    TCG_REG_R2, addr_reg),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     }
 
     if (bswap) {
-        if (opc == 1) {
+        if (s_bits == MO_16) {
             tcg_out_bundle(s, mII,
-                           tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                           INSN_NOP_M,
                            tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
                                        TCG_REG_R3, data_reg, 15, 15),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       TCG_REG_R3, TCG_REG_R3, 0xb));
+                           tcg_opc_bswap64_i(TCG_REG_P0,
+                                             TCG_REG_R3, TCG_REG_R3));
             data_reg = TCG_REG_R3;
-        } else if (opc == 2) {
+        } else if (s_bits == MO_32) {
             tcg_out_bundle(s, mII,
-                           tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                           INSN_NOP_M,
                            tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
                                        TCG_REG_R3, data_reg, 31, 31),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       TCG_REG_R3, TCG_REG_R3, 0xb));
+                           tcg_opc_bswap64_i(TCG_REG_P0,
+                                             TCG_REG_R3, TCG_REG_R3));
             data_reg = TCG_REG_R3;
-        } else if (opc == 3) {
+        } else if (s_bits == MO_64) {
             tcg_out_bundle(s, miI,
-                           tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       TCG_REG_R3, data_reg, 0xb));
+                           INSN_NOP_M,
+                           INSN_NOP_I,
+                           tcg_opc_bswap64_i(TCG_REG_P0, TCG_REG_R3, data_reg));
             data_reg = TCG_REG_R3;
         }
     }
     tcg_out_bundle(s, mmI,
-                   tcg_opc_m4 (TCG_REG_P0, opc_st_m4[opc],
+                   tcg_opc_m4 (TCG_REG_P0, opc_st_m4[s_bits],
                                data_reg, TCG_REG_R2),
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                   tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                   INSN_NOP_M,
+                   INSN_NOP_I);
 #else
     if (GUEST_BASE != 0) {
         add_guest_base = tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
                                      TCG_GUEST_BASE_REG, addr_reg);
         addr_reg = TCG_REG_R2;
     } else {
-        add_guest_base = tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0);
+        add_guest_base = INSN_NOP_M;
     }
 
-    if (!bswap || opc == 0) {
+    if (!bswap) {
         tcg_out_bundle(s, (GUEST_BASE ? MmI : mmI),
                        add_guest_base,
-                       tcg_opc_m4 (TCG_REG_P0, opc_st_m4[opc],
+                       tcg_opc_m4 (TCG_REG_P0, opc_st_m4[s_bits],
                                    data_reg, addr_reg),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I);
     } else {
-        if (opc == 1) {
+        if (s_bits == MO_16) {
             tcg_out_bundle(s, mII,
                            add_guest_base,
                            tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
                                        TCG_REG_R3, data_reg, 15, 15),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       TCG_REG_R3, TCG_REG_R3, 0xb));
+                           tcg_opc_bswap64_i(TCG_REG_P0,
+                                             TCG_REG_R3, TCG_REG_R3));
             data_reg = TCG_REG_R3;
-        } else if (opc == 2) {
+        } else if (s_bits == MO_32) {
             tcg_out_bundle(s, mII,
                            add_guest_base,
                            tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
                                        TCG_REG_R3, data_reg, 31, 31),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       TCG_REG_R3, TCG_REG_R3, 0xb));
+                           tcg_opc_bswap64_i(TCG_REG_P0,
+                                             TCG_REG_R3, TCG_REG_R3));
             data_reg = TCG_REG_R3;
-        } else if (opc == 3) {
+        } else if (s_bits == MO_64) {
             tcg_out_bundle(s, miI,
                            add_guest_base,
-                           tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                           tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
-                                       TCG_REG_R3, data_reg, 0xb));
+                           INSN_NOP_I,
+                           tcg_opc_bswap64_i(TCG_REG_P0, TCG_REG_R3, data_reg));
             data_reg = TCG_REG_R3;
         }
         tcg_out_bundle(s, miI,
-                       tcg_opc_m4 (TCG_REG_P0, opc_st_m4[opc],
+                       tcg_opc_m4 (TCG_REG_P0, opc_st_m4[s_bits],
                                    data_reg, addr_reg),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
-                       tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+                       INSN_NOP_I,
+                       INSN_NOP_I);
     }
 #endif
 }
@@ -1992,7 +2024,11 @@
         tcg_out_br(s, args[0]);
         break;
     case INDEX_op_call:
-        tcg_out_call(s, args[0]);
+        if (likely(const_args[0])) {
+            tcg_out_calli(s, args[0]);
+        } else {
+            tcg_out_callr(s, args[0]);
+        }
         break;
     case INDEX_op_goto_tb:
         tcg_out_goto_tb(s, args[0]);
@@ -2052,24 +2088,23 @@
 
     case INDEX_op_add_i32:
     case INDEX_op_add_i64:
-        tcg_out_alu(s, OPC_ADD_A1, args[0], args[1], const_args[1],
-                    args[2], const_args[2]);
+        tcg_out_add(s, args[0], args[1], args[2], const_args[2]);
         break;
     case INDEX_op_sub_i32:
     case INDEX_op_sub_i64:
-        tcg_out_alu(s, OPC_SUB_A1, args[0], args[1], const_args[1],
-                    args[2], const_args[2]);
+        tcg_out_sub(s, args[0], args[1], const_args[1], args[2], const_args[2]);
         break;
 
     case INDEX_op_and_i32:
     case INDEX_op_and_i64:
-        tcg_out_alu(s, OPC_AND_A1, args[0], args[1], const_args[1],
-                    args[2], const_args[2]);
+        /* TCG expects arg2 constant; A3 expects arg1 constant.  Swap.  */
+        tcg_out_alu(s, OPC_AND_A1, OPC_AND_A3, args[0],
+                    args[2], const_args[2], args[1], const_args[1]);
         break;
     case INDEX_op_andc_i32:
     case INDEX_op_andc_i64:
-        tcg_out_alu(s, OPC_ANDCM_A1, args[0], args[1], const_args[1],
-                    args[2], const_args[2]);
+        tcg_out_alu(s, OPC_ANDCM_A1, OPC_ANDCM_A3, args[0],
+                    args[1], const_args[1], args[2], const_args[2]);
         break;
     case INDEX_op_eqv_i32:
     case INDEX_op_eqv_i64:
@@ -2088,8 +2123,9 @@
         break;
     case INDEX_op_or_i32:
     case INDEX_op_or_i64:
-        tcg_out_alu(s, OPC_OR_A1, args[0], args[1], const_args[1],
-                    args[2], const_args[2]);
+        /* TCG expects arg2 constant; A3 expects arg1 constant.  Swap.  */
+        tcg_out_alu(s, OPC_OR_A1, OPC_OR_A3, args[0],
+                    args[2], const_args[2], args[1], const_args[1]);
         break;
     case INDEX_op_orc_i32:
     case INDEX_op_orc_i64:
@@ -2098,8 +2134,9 @@
         break;
     case INDEX_op_xor_i32:
     case INDEX_op_xor_i64:
-        tcg_out_alu(s, OPC_XOR_A1, args[0], args[1], const_args[1],
-                    args[2], const_args[2]);
+        /* TCG expects arg2 constant; A3 expects arg1 constant.  Swap.  */
+        tcg_out_alu(s, OPC_XOR_A1, OPC_XOR_A3, args[0],
+                    args[2], const_args[2], args[1], const_args[1]);
         break;
 
     case INDEX_op_mul_i32:
@@ -2180,12 +2217,10 @@
         break;
 
     case INDEX_op_brcond_i32:
-        tcg_out_brcond(s, args[2], args[0], const_args[0],
-                       args[1], const_args[1], args[3], 1);
+        tcg_out_brcond(s, args[2], args[0], args[1], args[3], 1);
         break;
     case INDEX_op_brcond_i64:
-        tcg_out_brcond(s, args[2], args[0], const_args[0],
-                       args[1], const_args[1], args[3], 0);
+        tcg_out_brcond(s, args[2], args[0], args[1], args[3], 0);
         break;
     case INDEX_op_setcond_i32:
         tcg_out_setcond(s, args[3], args[0], args[1], args[2], 1);
@@ -2203,39 +2238,39 @@
         break;
 
     case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, 0);
+        tcg_out_qemu_ld(s, args, MO_UB);
         break;
     case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, 0 | 4);
+        tcg_out_qemu_ld(s, args, MO_SB);
         break;
     case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, 1);
+        tcg_out_qemu_ld(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, 1 | 4);
+        tcg_out_qemu_ld(s, args, MO_TESW);
         break;
     case INDEX_op_qemu_ld32:
     case INDEX_op_qemu_ld32u:
-        tcg_out_qemu_ld(s, args, 2);
+        tcg_out_qemu_ld(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_ld32s:
-        tcg_out_qemu_ld(s, args, 2 | 4);
+        tcg_out_qemu_ld(s, args, MO_TESL);
         break;
     case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, 3);
+        tcg_out_qemu_ld(s, args, MO_TEQ);
         break;
 
     case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, 0);
+        tcg_out_qemu_st(s, args, MO_UB);
         break;
     case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, 1);
+        tcg_out_qemu_st(s, args, MO_TEUW);
         break;
     case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, 2);
+        tcg_out_qemu_st(s, args, MO_TEUL);
         break;
     case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, 3);
+        tcg_out_qemu_st(s, args, MO_TEQ);
         break;
 
     default:
@@ -2245,7 +2280,7 @@
 
 static const TCGTargetOpDef ia64_op_defs[] = {
     { INDEX_op_br, { } },
-    { INDEX_op_call, { "r" } },
+    { INDEX_op_call, { "ri" } },
     { INDEX_op_exit_tb, { } },
     { INDEX_op_goto_tb, { } },
 
@@ -2261,7 +2296,7 @@
     { INDEX_op_st16_i32, { "rZ", "r" } },
     { INDEX_op_st_i32, { "rZ", "r" } },
 
-    { INDEX_op_add_i32, { "r", "rI", "rI" } },
+    { INDEX_op_add_i32, { "r", "rZ", "rI" } },
     { INDEX_op_sub_i32, { "r", "rI", "rI" } },
 
     { INDEX_op_and_i32, { "r", "rI", "rI" } },
@@ -2289,7 +2324,7 @@
     { INDEX_op_bswap16_i32, { "r", "rZ" } },
     { INDEX_op_bswap32_i32, { "r", "rZ" } },
 
-    { INDEX_op_brcond_i32, { "rI", "rI" } },
+    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
     { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
     { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rI", "rI" } },
 
@@ -2308,7 +2343,7 @@
     { INDEX_op_st32_i64, { "rZ", "r" } },
     { INDEX_op_st_i64, { "rZ", "r" } },
 
-    { INDEX_op_add_i64, { "r", "rI", "rI" } },
+    { INDEX_op_add_i64, { "r", "rZ", "rI" } },
     { INDEX_op_sub_i64, { "r", "rI", "rI" } },
 
     { INDEX_op_and_i64, { "r", "rI", "rI" } },
@@ -2339,7 +2374,7 @@
     { INDEX_op_bswap32_i64, { "r", "rZ" } },
     { INDEX_op_bswap64_i64, { "r", "rZ" } },
 
-    { INDEX_op_brcond_i64, { "rI", "rI" } },
+    { INDEX_op_brcond_i64, { "rZ", "rZ" } },
     { INDEX_op_setcond_i64, { "r", "rZ", "rZ" } },
     { INDEX_op_movcond_i64, { "r", "rZ", "rZ", "rI", "rI" } },
 
@@ -2384,8 +2419,7 @@
     tcg_out_bundle(s, miI,
                    tcg_opc_m34(TCG_REG_P0, OPC_ALLOC_M34,
                                TCG_REG_R34, 32, 24, 0),
-                   tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
-                               TCG_AREG0, 0, TCG_REG_R32),
+                   INSN_NOP_I,
                    tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21,
                                TCG_REG_B6, TCG_REG_R33, 0));
 
@@ -2393,7 +2427,7 @@
        an ADDL in the M slot of the next bundle.  */
     if (GUEST_BASE != 0) {
         tcg_out_bundle(s, mlx,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                       INSN_NOP_M,
                        tcg_opc_l2 (GUEST_BASE),
                        tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2,
                                    TCG_GUEST_BASE_REG, GUEST_BASE));
@@ -2404,19 +2438,19 @@
                    tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
                                TCG_REG_R12, -frame_size, TCG_REG_R12),
                    tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
-                               TCG_REG_R32, TCG_REG_B0),
+                               TCG_REG_R33, TCG_REG_B0),
                    tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6));
 
     /* epilogue */
     tb_ret_addr = s->code_ptr;
     tcg_out_bundle(s, miI,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21,
-                               TCG_REG_B0, TCG_REG_R32, 0),
+                               TCG_REG_B0, TCG_REG_R33, 0),
                    tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
                                TCG_REG_R12, frame_size, TCG_REG_R12));
     tcg_out_bundle(s, miB,
-                   tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+                   INSN_NOP_M,
                    tcg_opc_i26(TCG_REG_P0, OPC_MOV_I_I26,
                                TCG_REG_PFS, TCG_REG_R34),
                    tcg_opc_b4 (TCG_REG_P0, OPC_BR_RET_SPTK_MANY_B4,
@@ -2469,16 +2503,17 @@
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R3);   /* internal use */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R12);  /* stack pointer */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13);  /* thread pointer */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R32);  /* return address */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R33);  /* return address */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R34);  /* PFS */
 
-    /* The following 3 are not in use, are call-saved, but *not* saved
+    /* The following 4 are not in use, are call-saved, but *not* saved
        by the prologue.  Therefore we cannot use them without modifying
        the prologue.  There doesn't seem to be any good reason to use
        these as opposed to the windowed registers.  */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R4);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R5);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R6);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R7);
 
     tcg_add_target_add_op_defs(ia64_op_defs);
 }
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index c90038a..52a939c 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -92,6 +92,8 @@
     TCG_REG_R61,
     TCG_REG_R62,
     TCG_REG_R63,
+
+    TCG_AREG0 = TCG_REG_R32,
 } TCGReg;
 
 #define TCG_CT_CONST_ZERO 0x100
@@ -162,8 +164,6 @@
 #define TCG_TARGET_HAS_not_i32          0 /* xor r1, -1, r3 */
 #define TCG_TARGET_HAS_not_i64          0 /* xor r1, -1, r3 */
 
-#define TCG_AREG0 TCG_REG_R7
-
 static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
 {
     start = start & ~(32UL - 1UL);
diff --git a/tests/Makefile b/tests/Makefile
index fa4c9f0..379cdd9 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -67,25 +67,52 @@
 check-qtest-i386-y += tests/rtc-test$(EXESUF)
 check-qtest-i386-y += tests/i440fx-test$(EXESUF)
 check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
+check-qtest-i386-y += tests/qom-test$(EXESUF)
+check-qtest-i386-y += tests/blockdev-test$(EXESUF)
+check-qtest-i386-y += tests/qdev-monitor-test$(EXESUF)
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
 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-mips-y += tests/qom-test$(EXESUF)
+check-qtest-mipsel-y += tests/qom-test$(EXESUF)
+check-qtest-mips64-y += tests/qom-test$(EXESUF)
+check-qtest-mips64el-y += tests/qom-test$(EXESUF)
 check-qtest-ppc-y = tests/endianness-test$(EXESUF)
 check-qtest-ppc64-y = tests/endianness-test$(EXESUF)
 check-qtest-sh4-y = tests/endianness-test$(EXESUF)
 check-qtest-sh4eb-y = tests/endianness-test$(EXESUF)
+check-qtest-sh4-y += tests/qom-test$(EXESUF)
+check-qtest-sh4eb-y += tests/qom-test$(EXESUF)
 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/m48t59.c
 gcov-files-sparc64-y += hw/m48t59.c
+check-qtest-sparc-y += tests/qom-test$(EXESUF)
+check-qtest-sparc64-y += tests/qom-test$(EXESUF)
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 gcov-files-arm-y += hw/tmp105.c
+check-qtest-arm-y += tests/qom-test$(EXESUF)
 check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
 check-qtest-ppc64-y += tests/boot-order-test$(EXESUF)
+check-qtest-ppc-y += tests/qom-test$(EXESUF)
+check-qtest-ppc64-y += tests/qom-test$(EXESUF)
+check-qtest-ppcemb-y += tests/qom-test$(EXESUF)
+check-qtest-alpha-y += tests/qom-test$(EXESUF)
+check-qtest-cris-y += tests/qom-test$(EXESUF)
+check-qtest-lm32-y += tests/qom-test$(EXESUF)
+check-qtest-m68k-y += tests/qom-test$(EXESUF)
+check-qtest-microblaze-y += tests/qom-test$(EXESUF)
+check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
+check-qtest-moxie-y += tests/qom-test$(EXESUF)
+check-qtest-or32-y += tests/qom-test$(EXESUF)
+check-qtest-s390x-y += tests/qom-test$(EXESUF)
+check-qtest-unicore32-y += tests/qom-test$(EXESUF)
+check-qtest-xtensa-y += tests/qom-test$(EXESUF)
+check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
 
 check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
         comments.json empty.json funny-char.json indented-expr.json \
@@ -174,6 +201,9 @@
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
+tests/qom-test$(EXESUF): tests/qom-test.o
+tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y)
+tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
 tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
 
 # QTest rules
diff --git a/tests/blockdev-test.c b/tests/blockdev-test.c
new file mode 100644
index 0000000..c940e00
--- /dev/null
+++ b/tests/blockdev-test.c
@@ -0,0 +1,59 @@
+/*
+ * blockdev.c test cases
+ *
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * Authors:
+ *  Stefan Hajnoczi <stefanha@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include "libqtest.h"
+
+static void test_drive_add_empty(void)
+{
+    QDict *response;
+    const char *response_return;
+
+    /* Start with an empty drive */
+    qtest_start("-drive if=none,id=drive0");
+
+    /* Delete the drive */
+    response = qmp("{\"execute\": \"human-monitor-command\","
+                   " \"arguments\": {"
+                   "   \"command-line\": \"drive_del drive0\""
+                   "}}");
+    g_assert(response);
+    response_return = qdict_get_try_str(response, "return");
+    g_assert(response_return);
+    g_assert(strcmp(response_return, "") == 0);
+    QDECREF(response);
+
+    /* Ensure re-adding the drive works - there should be no duplicate ID error
+     * because the old drive must be gone.
+     */
+    response = qmp("{\"execute\": \"human-monitor-command\","
+                   " \"arguments\": {"
+                   "   \"command-line\": \"drive_add 0 if=none,id=drive0\""
+                   "}}");
+    g_assert(response);
+    response_return = qdict_get_try_str(response, "return");
+    g_assert(response_return);
+    g_assert(strcmp(response_return, "OK\r\n") == 0);
+    QDECREF(response);
+
+    qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    qtest_add_func("/qmp/drive_add_empty", test_drive_add_empty);
+
+    return g_test_run();
+}
diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c
index 4b233d0..360a691 100644
--- a/tests/boot-order-test.c
+++ b/tests/boot-order-test.c
@@ -34,19 +34,19 @@
     char *args;
     uint64_t actual;
 
-    args = g_strdup_printf("-nodefaults -display none%s%s %s",
+    args = g_strdup_printf("-nodefaults%s%s %s",
                            machine ? " -M " : "",
                            machine ?: "",
                            test_args);
     qtest_start(args);
     actual = read_boot_order();
     g_assert_cmphex(actual, ==, expected_boot);
-    qmp("{ 'execute': 'system_reset' }");
+    qmp_discard_response("{ 'execute': 'system_reset' }");
     /*
      * system_reset only requests reset.  We get a RESET event after
      * the actual reset completes.  Need to wait for that.
      */
-    qmp("");                    /* HACK: wait for event */
+    qmp_discard_response("");   /* HACK: wait for event */
     actual = read_boot_order();
     g_assert_cmphex(actual, ==, expected_reboot);
     qtest_quit(global_qtest);
diff --git a/tests/endianness-test.c b/tests/endianness-test.c
index feb32a8..646df7d 100644
--- a/tests/endianness-test.c
+++ b/tests/endianness-test.c
@@ -44,7 +44,8 @@
     { "ppc", "prep", 0x80000000, .bswap = true },
     { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" },
     { "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" },
-    { "ppc64", "pseries", 0x10080000000, .bswap = true, .superio = "i82378" },
+    { "ppc64", "pseries", 0x10080000000ULL,
+      .bswap = true, .superio = "i82378" },
     { "sh4", "r2d", 0xfe240000, .superio = "i82378" },
     { "sh4eb", "r2d", 0xfe240000, .bswap = true, .superio = "i82378" },
     { "sparc64", "sun4u", 0x1fe02000000LL, .bswap = true },
@@ -120,7 +121,7 @@
     const TestCase *test = data;
     char *args;
 
-    args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+    args = g_strdup_printf("-M %s%s%s -device pc-testdev",
                            test->machine,
                            test->superio ? " -device " : "",
                            test->superio ?: "");
@@ -195,7 +196,7 @@
     const TestCase *test = data;
     char *args;
 
-    args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+    args = g_strdup_printf("-M %s%s%s -device pc-testdev",
                            test->machine,
                            test->superio ? " -device " : "",
                            test->superio ?: "");
@@ -242,7 +243,7 @@
     const TestCase *test = data;
     char *args;
 
-    args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+    args = g_strdup_printf("-M %s%s%s -device pc-testdev",
                            test->machine,
                            test->superio ? " -device " : "",
                            test->superio ?: "");
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index fd198dc..38b5b17 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -290,10 +290,12 @@
 
     /* Insert media in drive. DSKCHK should not be reset until a step pulse
      * is sent. */
-    qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
-        "'target': '%s' }}", test_image);
-    qmp(""); /* ignore event (FIXME open -> open transition?!) */
-    qmp(""); /* ignore event */
+    qmp_discard_response("{'execute':'change', 'arguments':{"
+                         " 'device':'floppy0', 'target': '%s' }}",
+                         test_image);
+    qmp_discard_response(""); /* ignore event
+                                 (FIXME open -> open transition?!) */
+    qmp_discard_response(""); /* ignore event */
 
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_set(dir, DSKCHG);
@@ -322,8 +324,9 @@
 
     /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
      * reset the bit. */
-    qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}");
-    qmp(""); /* ignore event */
+    qmp_discard_response("{'execute':'eject', 'arguments':{"
+                         " 'device':'floppy0' }}");
+    qmp_discard_response(""); /* ignore event */
 
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_set(dir, DSKCHG);
diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c
index b86e49a..e4f355c 100644
--- a/tests/fw_cfg-test.c
+++ b/tests/fw_cfg-test.c
@@ -126,8 +126,7 @@
     g_test_add_func("/fw_cfg/numa", test_fw_cfg_numa);
     g_test_add_func("/fw_cfg/boot_menu", test_fw_cfg_boot_menu);
 
-    cmdline = g_strdup_printf("-display none "
-                              "-uuid 4600cb32-38ec-4b2f-8acb-81c6ea54f2d8 ");
+    cmdline = g_strdup_printf("-uuid 4600cb32-38ec-4b2f-8acb-81c6ea54f2d8 ");
     s = qtest_start(cmdline);
     g_free(cmdline);
 
diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c
index b72042e..c84d1e7 100644
--- a/tests/hd-geo-test.c
+++ b/tests/hd-geo-test.c
@@ -171,7 +171,7 @@
 {
     memset(cur_ide, 0, sizeof(cur_ide));
     return append_arg(0, argv, argv_sz,
-                      g_strdup("-nodefaults -display none"));
+                      g_strdup("-nodefaults"));
 }
 
 static void setup_mbr(int img_idx, MBRcontents mbr)
diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c
index 08ce820..65c786c 100644
--- a/tests/i440fx-test.c
+++ b/tests/i440fx-test.c
@@ -265,7 +265,7 @@
 
     data.num_cpus = 1;
 
-    cmdline = g_strdup_printf("-display none -smp %d", data.num_cpus);
+    cmdline = g_strdup_printf("-smp %d", data.num_cpus);
     s = qtest_start(cmdline);
     g_free(cmdline);
 
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 7307f1d..d5cec5a 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -81,6 +81,7 @@
     CMD_IDENTIFY    = 0xec,
 
     CMDF_ABORT      = 0x100,
+    CMDF_NO_BM      = 0x200,
 };
 
 enum {
@@ -192,6 +193,11 @@
         g_assert_not_reached();
     }
 
+    if (flags & CMDF_NO_BM) {
+        qpci_config_writew(dev, PCI_COMMAND,
+                           PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+    }
+
     /* Select device 0 */
     outb(IDE_BASE + reg_device, 0 | LBA);
 
@@ -352,6 +358,25 @@
     assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
 }
 
+static void test_bmdma_no_busmaster(void)
+{
+    uint8_t status;
+
+    /* No PRDT_EOT, each entry addr 0/size 64k, and in theory qemu shouldn't be
+     * able to access it anyway because the Bus Master bit in the PCI command
+     * register isn't set. This is complete nonsense, but it used to be pretty
+     * good at confusing and occasionally crashing qemu. */
+    PrdtEntry prdt[4096] = { };
+
+    status = send_dma_request(CMD_READ_DMA | CMDF_NO_BM, 0, 512,
+                              prdt, ARRAY_SIZE(prdt));
+
+    /* Not entirely clear what the expected result is, but this is what we get
+     * in practice. At least we want to be aware of any changes. */
+    g_assert_cmphex(status, ==, BM_STS_ACTIVE | BM_STS_INTR);
+    assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
+}
+
 static void test_bmdma_setup(void)
 {
     ide_test_start(
@@ -435,8 +460,9 @@
         tmp_path);
 
     /* Delay the completion of the flush request until we explicitly do it */
-    qmp("{'execute':'human-monitor-command', 'arguments': { "
-        "'command-line': 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }");
+    qmp_discard_response("{'execute':'human-monitor-command', 'arguments': {"
+                         " 'command-line':"
+                         " 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }");
 
     /* FLUSH CACHE command on device 0*/
     outb(IDE_BASE + reg_device, 0);
@@ -448,8 +474,9 @@
     assert_bit_clear(data, DF | ERR | DRQ);
 
     /* Complete the command */
-    qmp("{'execute':'human-monitor-command', 'arguments': { "
-        "'command-line': 'qemu-io ide0-hd0 \"resume A\"'} }");
+    qmp_discard_response("{'execute':'human-monitor-command', 'arguments': {"
+                         " 'command-line':"
+                         " 'qemu-io ide0-hd0 \"resume A\"'} }");
 
     /* Check registers */
     data = inb(IDE_BASE + reg_device);
@@ -493,6 +520,7 @@
     qtest_add_func("/ide/bmdma/simple_rw", test_bmdma_simple_rw);
     qtest_add_func("/ide/bmdma/short_prdt", test_bmdma_short_prdt);
     qtest_add_func("/ide/bmdma/long_prdt", test_bmdma_long_prdt);
+    qtest_add_func("/ide/bmdma/no_busmaster", test_bmdma_no_busmaster);
     qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown);
 
     qtest_add_func("/ide/flush", test_flush);
diff --git a/tests/libqtest.c b/tests/libqtest.c
index bb82069..359d571 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -30,6 +30,8 @@
 
 #include "qemu/compiler.h"
 #include "qemu/osdep.h"
+#include "qapi/qmp/json-streamer.h"
+#include "qapi/qmp/json-parser.h"
 
 #define MAX_IRQ 256
 
@@ -133,6 +135,7 @@
                                   "-qmp unix:%s,nowait "
                                   "-pidfile %s "
                                   "-machine accel=qtest "
+                                  "-display none "
                                   "%s", qemu_binary, s->socket_path,
                                   s->qmp_socket_path, pid_file,
                                   extra_args ?: "");
@@ -151,8 +154,8 @@
     }
 
     /* Read the QMP greeting and then do the handshake */
-    qtest_qmp(s, "");
-    qtest_qmp(s, "{ 'execute': 'qmp_capabilities' }");
+    qtest_qmp_discard_response(s, "");
+    qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }");
 
     if (getenv("QTEST_STOP")) {
         kill(qtest_qemu_pid(s), SIGSTOP);
@@ -291,16 +294,38 @@
     return words;
 }
 
-void qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
+typedef struct {
+    JSONMessageParser parser;
+    QDict *response;
+} QMPResponseParser;
+
+static void qmp_response(JSONMessageParser *parser, QList *tokens)
 {
-    bool has_reply = false;
-    int nesting = 0;
+    QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser);
+    QObject *obj;
+
+    obj = json_parser_parse(tokens, NULL);
+    if (!obj) {
+        fprintf(stderr, "QMP JSON response parsing failed\n");
+        exit(1);
+    }
+
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+    g_assert(!qmp->response);
+    qmp->response = (QDict *)obj;
+}
+
+QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
+{
+    QMPResponseParser qmp;
 
     /* Send QMP request */
     socket_sendf(s->qmp_fd, fmt, ap);
 
     /* Receive reply */
-    while (!has_reply || nesting > 0) {
+    qmp.response = NULL;
+    json_message_parser_init(&qmp.parser, qmp_response);
+    while (!qmp.response) {
         ssize_t len;
         char c;
 
@@ -314,25 +339,39 @@
             exit(1);
         }
 
-        switch (c) {
-        case '{':
-            nesting++;
-            has_reply = true;
-            break;
-        case '}':
-            nesting--;
-            break;
-        }
+        json_message_parser_feed(&qmp.parser, &c, 1);
     }
+    json_message_parser_destroy(&qmp.parser);
+
+    return qmp.response;
 }
 
-void qtest_qmp(QTestState *s, const char *fmt, ...)
+QDict *qtest_qmp(QTestState *s, const char *fmt, ...)
 {
     va_list ap;
+    QDict *response;
 
     va_start(ap, fmt);
-    qtest_qmpv(s, fmt, ap);
+    response = qtest_qmpv(s, fmt, ap);
     va_end(ap);
+    return response;
+}
+
+void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap)
+{
+    QDict *response = qtest_qmpv(s, fmt, ap);
+    QDECREF(response);
+}
+
+void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...)
+{
+    va_list ap;
+    QDict *response;
+
+    va_start(ap, fmt);
+    response = qtest_qmpv(s, fmt, ap);
+    va_end(ap);
+    QDECREF(response);
 }
 
 const char *qtest_get_arch(void)
diff --git a/tests/libqtest.h b/tests/libqtest.h
index a6e99bd..9deebdc 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -22,6 +22,7 @@
 #include <stdbool.h>
 #include <stdarg.h>
 #include <sys/types.h>
+#include "qapi/qmp/qdict.h"
 
 typedef struct QTestState QTestState;
 
@@ -44,13 +45,32 @@
 void qtest_quit(QTestState *s);
 
 /**
+ * qtest_qmp_discard_response:
+ * @s: #QTestState instance to operate on.
+ * @fmt...: QMP message to send to qemu
+ *
+ * Sends a QMP message to QEMU and consumes the response.
+ */
+void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...);
+
+/**
  * qtest_qmp:
  * @s: #QTestState instance to operate on.
  * @fmt...: QMP message to send to qemu
  *
- * Sends a QMP message to QEMU
+ * Sends a QMP message to QEMU and returns the response.
  */
-void qtest_qmp(QTestState *s, const char *fmt, ...);
+QDict *qtest_qmp(QTestState *s, const char *fmt, ...);
+
+/**
+ * qtest_qmpv_discard_response:
+ * @s: #QTestState instance to operate on.
+ * @fmt: QMP message to send to QEMU
+ * @ap: QMP message arguments
+ *
+ * Sends a QMP message to QEMU and consumes the response.
+ */
+void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap);
 
 /**
  * qtest_qmpv:
@@ -58,9 +78,9 @@
  * @fmt: QMP message to send to QEMU
  * @ap: QMP message arguments
  *
- * Sends a QMP message to QEMU.
+ * Sends a QMP message to QEMU and returns the response.
  */
-void qtest_qmpv(QTestState *s, const char *fmt, va_list ap);
+QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap);
 
 /**
  * qtest_get_irq:
@@ -334,14 +354,31 @@
  * qmp:
  * @fmt...: QMP message to send to qemu
  *
- * Sends a QMP message to QEMU
+ * Sends a QMP message to QEMU and returns the response.
  */
-static inline void qmp(const char *fmt, ...)
+static inline QDict *qmp(const char *fmt, ...)
+{
+    va_list ap;
+    QDict *response;
+
+    va_start(ap, fmt);
+    response = qtest_qmpv(global_qtest, fmt, ap);
+    va_end(ap);
+    return response;
+}
+
+/**
+ * qmp_discard_response:
+ * @fmt...: QMP message to send to qemu
+ *
+ * Sends a QMP message to QEMU and consumes the response.
+ */
+static inline void qmp_discard_response(const char *fmt, ...)
 {
     va_list ap;
 
     va_start(ap, fmt);
-    qtest_qmpv(global_qtest, fmt, ap);
+    qtest_qmpv_discard_response(global_qtest, fmt, ap);
     va_end(ap);
 }
 
diff --git a/tests/m48t59-test.c b/tests/m48t59-test.c
index 4081a5f..6abc4c8 100644
--- a/tests/m48t59-test.c
+++ b/tests/m48t59-test.c
@@ -249,7 +249,7 @@
 
     g_test_init(&argc, &argv, NULL);
 
-    s = qtest_start("-display none -rtc clock=vm");
+    s = qtest_start("-rtc clock=vm");
 
     qtest_add_func("/rtc/bcd/check-time", bcd_check_time);
     qtest_add_func("/rtc/fuzz-registers", fuzz_registers);
diff --git a/tests/multiboot/Makefile b/tests/multiboot/Makefile
new file mode 100644
index 0000000..34cdd81
--- /dev/null
+++ b/tests/multiboot/Makefile
@@ -0,0 +1,18 @@
+CC=gcc
+CCFLAGS=-m32 -Wall -Wextra -Werror -fno-stack-protector -nostdinc -fno-builtin
+ASFLAGS=-m32
+
+LD=ld
+LDFLAGS=-melf_i386 -T link.ld
+LIBS=$(shell $(CC) $(CCFLAGS) -print-libgcc-file-name)
+
+all: mmap.elf
+
+mmap.elf: start.o mmap.o libc.o
+	$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+%.o: %.c
+	$(CC) $(CCFLAGS) -c -o $@ $^
+
+%.o: %.S
+	$(CC) $(ASFLAGS) -c -o $@ $^
diff --git a/tests/multiboot/libc.c b/tests/multiboot/libc.c
new file mode 100644
index 0000000..05abbd9
--- /dev/null
+++ b/tests/multiboot/libc.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "libc.h"
+
+static void print_char(char c)
+{
+    outb(0xe9, c);
+}
+
+static void print_str(char *s)
+{
+    while (*s) {
+        print_char(*s++);
+    }
+}
+
+static void print_num(uint64_t value, int base)
+{
+    char digits[] = "0123456789abcdef";
+    char buf[32] = { 0 };
+    int i = sizeof(buf) - 2;
+
+    do {
+        buf[i--] = digits[value % base];
+        value /= base;
+    } while (value);
+
+    print_str(&buf[i + 1]);
+}
+
+void printf(const char *fmt, ...)
+{
+    va_list ap;
+    uint64_t val;
+    char *str;
+    int base;
+    int has_long;
+    int alt_form;
+
+    va_start(ap, fmt);
+
+    for (; *fmt; fmt++) {
+        if (*fmt != '%') {
+            print_char(*fmt);
+            continue;
+        }
+        fmt++;
+
+        if (*fmt == '#') {
+            fmt++;
+            alt_form = 1;
+        } else {
+            alt_form = 0;
+        }
+
+        if (*fmt == 'l') {
+            fmt++;
+            if (*fmt == 'l') {
+                fmt++;
+                has_long = 2;
+            } else {
+                has_long = 1;
+            }
+        } else {
+            has_long = 0;
+        }
+
+        switch (*fmt) {
+        case 'x':
+        case 'p':
+            base = 16;
+            goto convert_number;
+        case 'd':
+        case 'i':
+        case 'u':
+            base = 10;
+            goto convert_number;
+        case 'o':
+            base = 8;
+            goto convert_number;
+
+        convert_number:
+            switch (has_long) {
+            case 0:
+                val = va_arg(ap, unsigned int);
+                break;
+            case 1:
+                val = va_arg(ap, unsigned long);
+                break;
+            case 2:
+                val = va_arg(ap, unsigned long long);
+                break;
+            }
+
+            if (alt_form && base == 16) {
+                print_str("0x");
+            }
+
+            print_num(val, base);
+            break;
+
+        case 's':
+            str = va_arg(ap, char*);
+            print_str(str);
+            break;
+        case '%':
+            print_char(*fmt);
+            break;
+        default:
+            print_char('%');
+            print_char(*fmt);
+            break;
+        }
+    }
+
+    va_end(ap);
+}
+
+
diff --git a/tests/multiboot/libc.h b/tests/multiboot/libc.h
new file mode 100644
index 0000000..80eec5b
--- /dev/null
+++ b/tests/multiboot/libc.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef LIBC_H
+#define LIBC_H
+
+/* Integer types */
+
+typedef unsigned long long uint64_t;
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+
+typedef signed long long int64_t;
+typedef signed int int32_t;
+typedef signed short int16_t;
+typedef signed char int8_t;
+
+typedef uint32_t uintptr_t;
+
+
+/* stdarg.h */
+
+typedef __builtin_va_list       va_list;
+#define va_start(ap, X)         __builtin_va_start(ap, X)
+#define va_arg(ap, type)        __builtin_va_arg(ap, type)
+#define va_end(ap)              __builtin_va_end(ap)
+
+
+/* Port I/O functions */
+
+static inline void outb(uint16_t port, uint8_t data)
+{
+    asm volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
+}
+
+
+/* Misc functions */
+
+void printf(const char *fmt, ...);
+
+#endif
diff --git a/tests/multiboot/link.ld b/tests/multiboot/link.ld
new file mode 100644
index 0000000..3d49b58
--- /dev/null
+++ b/tests/multiboot/link.ld
@@ -0,0 +1,19 @@
+ENTRY(_start)
+
+SECTIONS
+{
+    . = 0x100000;
+    .text : {
+        *(multiboot)
+        *(.text)
+    }
+    .data ALIGN(4096) : {
+        *(.data)
+    }
+    .rodata ALIGN(4096) : {
+        *(.rodata)
+    }
+    .bss ALIGN(4096) : {
+        *(.bss)
+    }
+}
diff --git a/tests/multiboot/mmap.c b/tests/multiboot/mmap.c
new file mode 100644
index 0000000..766b003
--- /dev/null
+++ b/tests/multiboot/mmap.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "libc.h"
+#include "multiboot.h"
+
+int test_main(uint32_t magic, struct mb_info *mbi)
+{
+    uintptr_t entry_addr;
+    struct mb_mmap_entry *entry;
+
+    (void) magic;
+
+    printf("Lower memory: %dk\n", mbi->mem_lower);
+    printf("Upper memory: %dk\n", mbi->mem_upper);
+
+    printf("\ne820 memory map:\n");
+
+    for (entry_addr = mbi->mmap_addr;
+         entry_addr < mbi->mmap_addr + mbi->mmap_length;
+         entry_addr += entry->size + 4)
+    {
+        entry = (struct mb_mmap_entry*) entry_addr;
+
+        printf("%#llx - %#llx: type %d [entry size: %d]\n",
+               entry->base_addr,
+               entry->base_addr + entry->length,
+               entry->type,
+               entry->size);
+    }
+
+    printf("\nmmap start:       %#x\n", mbi->mmap_addr);
+    printf("mmap end:         %#x\n", mbi->mmap_addr + mbi->mmap_length);
+    printf("real mmap end:    %#x\n", entry_addr);
+
+    return 0;
+}
diff --git a/tests/multiboot/mmap.out b/tests/multiboot/mmap.out
new file mode 100644
index 0000000..e70b6eb
--- /dev/null
+++ b/tests/multiboot/mmap.out
@@ -0,0 +1,93 @@
+
+
+
+=== Running test case: mmap.elf  ===
+
+Lower memory: 639k
+Upper memory: 130040k
+
+e820 memory map:
+0x0 - 0x9fc00: type 1 [entry size: 20]
+0x9fc00 - 0xa0000: type 2 [entry size: 20]
+0xf0000 - 0x100000: type 2 [entry size: 20]
+0x100000 - 0x7ffe000: type 1 [entry size: 20]
+0x7ffe000 - 0x8000000: type 2 [entry size: 20]
+0xfffc0000 - 0x100000000: type 2 [entry size: 20]
+
+mmap start:       0x9000
+mmap end:         0x9090
+real mmap end:    0x9090
+
+
+=== Running test case: mmap.elf -m 1.1M ===
+
+Lower memory: 639k
+Upper memory: 96k
+
+e820 memory map:
+0x0 - 0x9fc00: type 1 [entry size: 20]
+0x9fc00 - 0xa0000: type 2 [entry size: 20]
+0xf0000 - 0x100000: type 2 [entry size: 20]
+0x100000 - 0x118000: type 1 [entry size: 20]
+0x118000 - 0x11a000: type 2 [entry size: 20]
+0xfffc0000 - 0x100000000: type 2 [entry size: 20]
+
+mmap start:       0x9000
+mmap end:         0x9090
+real mmap end:    0x9090
+
+
+=== Running test case: mmap.elf -m 2G ===
+
+Lower memory: 639k
+Upper memory: 2096120k
+
+e820 memory map:
+0x0 - 0x9fc00: type 1 [entry size: 20]
+0x9fc00 - 0xa0000: type 2 [entry size: 20]
+0xf0000 - 0x100000: type 2 [entry size: 20]
+0x100000 - 0x7fffe000: type 1 [entry size: 20]
+0x7fffe000 - 0x80000000: type 2 [entry size: 20]
+0xfffc0000 - 0x100000000: type 2 [entry size: 20]
+
+mmap start:       0x9000
+mmap end:         0x9090
+real mmap end:    0x9090
+
+
+=== Running test case: mmap.elf -m 4G ===
+
+Lower memory: 639k
+Upper memory: 3668984k
+
+e820 memory map:
+0x0 - 0x9fc00: type 1 [entry size: 20]
+0x9fc00 - 0xa0000: type 2 [entry size: 20]
+0xf0000 - 0x100000: type 2 [entry size: 20]
+0x100000 - 0xdfffe000: type 1 [entry size: 20]
+0xdfffe000 - 0xe0000000: type 2 [entry size: 20]
+0xfffc0000 - 0x100000000: type 2 [entry size: 20]
+0x100000000 - 0x120000000: type 1 [entry size: 20]
+
+mmap start:       0x9000
+mmap end:         0x90a8
+real mmap end:    0x90a8
+
+
+=== Running test case: mmap.elf -m 8G ===
+
+Lower memory: 639k
+Upper memory: 3668984k
+
+e820 memory map:
+0x0 - 0x9fc00: type 1 [entry size: 20]
+0x9fc00 - 0xa0000: type 2 [entry size: 20]
+0xf0000 - 0x100000: type 2 [entry size: 20]
+0x100000 - 0xdfffe000: type 1 [entry size: 20]
+0xdfffe000 - 0xe0000000: type 2 [entry size: 20]
+0xfffc0000 - 0x100000000: type 2 [entry size: 20]
+0x100000000 - 0x220000000: type 1 [entry size: 20]
+
+mmap start:       0x9000
+mmap end:         0x90a8
+real mmap end:    0x90a8
diff --git a/tests/multiboot/multiboot.h b/tests/multiboot/multiboot.h
new file mode 100644
index 0000000..4eb1fbe
--- /dev/null
+++ b/tests/multiboot/multiboot.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MULTIBOOT_H
+#define MULTIBOOT_H
+
+#include "libc.h"
+
+struct mb_info {
+    uint32_t    flags;
+    uint32_t    mem_lower;
+    uint32_t    mem_upper;
+    uint32_t    boot_device;
+    uint32_t    cmdline;
+    uint32_t    mods_count;
+    uint32_t    mods_addr;
+    char        syms[16];
+    uint32_t    mmap_length;
+    uint32_t    mmap_addr;
+    uint32_t    drives_length;
+    uint32_t    drives_addr;
+    uint32_t    config_table;
+    uint32_t    boot_loader_name;
+    uint32_t    apm_table;
+    uint32_t    vbe_control_info;
+    uint32_t    vbe_mode_info;
+    uint16_t    vbe_mode;
+    uint16_t    vbe_interface_seg;
+    uint16_t    vbe_interface_off;
+    uint16_t    vbe_interface_len;
+} __attribute__((packed));
+
+struct mb_module {
+    uint32_t    mod_start;
+    uint32_t    mod_end;
+    uint32_t    string;
+    uint32_t    reserved;
+} __attribute__((packed));
+
+struct mb_mmap_entry {
+    uint32_t    size;
+    uint64_t    base_addr;
+    uint64_t    length;
+    uint32_t    type;
+} __attribute__((packed));
+
+#endif
diff --git a/tests/multiboot/run_test.sh b/tests/multiboot/run_test.sh
new file mode 100755
index 0000000..97a9a49
--- /dev/null
+++ b/tests/multiboot/run_test.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+# Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+QEMU=${QEMU:-"../../x86_64-softmmu/qemu-system-x86_64"}
+
+run_qemu() {
+    local kernel=$1
+    shift
+
+    echo -e "\n\n=== Running test case: $kernel $@ ===\n" >> test.log
+
+    $QEMU \
+        -kernel $kernel \
+        -display none \
+        -device isa-debugcon,chardev=stdio \
+        -chardev file,path=test.out,id=stdio \
+        -device isa-debug-exit,iobase=0xf4,iosize=0x4 \
+        "$@"
+    ret=$?
+
+    cat test.out >> test.log
+}
+
+mmap() {
+    run_qemu mmap.elf
+    run_qemu mmap.elf -m 1.1M
+    run_qemu mmap.elf -m 2G
+    run_qemu mmap.elf -m 4G
+    run_qemu mmap.elf -m 8G
+}
+
+
+make all
+
+for t in mmap; do
+
+    echo > test.log
+    $t
+
+    debugexit=$((ret & 0x1))
+    ret=$((ret >> 1))
+    pass=1
+
+    if [ $debugexit != 1 ]; then
+        echo -e "\e[31m ?? \e[0m $t (no debugexit used, exit code $ret)"
+        pass=0
+    elif [ $ret != 0 ]; then
+        echo -e "\e[31mFAIL\e[0m $t (exit code $ret)"
+        pass=0
+    fi
+
+    if ! diff $t.out test.log > /dev/null 2>&1; then
+        echo -e "\e[31mFAIL\e[0m $t (output difference)"
+        diff -u $t.out test.log
+        pass=0
+    fi
+
+    if [ $pass == 1 ]; then
+        echo -e "\e[32mPASS\e[0m $t"
+    fi
+
+done
diff --git a/tests/multiboot/start.S b/tests/multiboot/start.S
new file mode 100644
index 0000000..7d33959
--- /dev/null
+++ b/tests/multiboot/start.S
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+.section multiboot
+
+#define MB_MAGIC 0x1badb002
+#define MB_FLAGS 0x0
+#define MB_CHECKSUM -(MB_MAGIC + MB_FLAGS)
+
+.align  4
+.int    MB_MAGIC
+.int    MB_FLAGS
+.int    MB_CHECKSUM
+
+.section .text
+.global _start
+_start:
+    mov     $stack, %esp
+    push    %ebx
+    push    %eax
+    call    test_main
+
+    /* Test device exit */
+    outl    %eax, $0xf4
+
+    cli
+    hlt
+    jmp .
+
+.section bss
+.space 8192
+stack:
diff --git a/tests/qdev-monitor-test.c b/tests/qdev-monitor-test.c
new file mode 100644
index 0000000..33a8ea4
--- /dev/null
+++ b/tests/qdev-monitor-test.c
@@ -0,0 +1,81 @@
+/*
+ * qdev-monitor.c test cases
+ *
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * Authors:
+ *  Stefan Hajnoczi <stefanha@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include <string.h>
+#include <glib.h>
+#include "libqtest.h"
+#include "qapi/qmp/qjson.h"
+
+static void test_device_add(void)
+{
+    QDict *response;
+    QDict *error;
+
+    qtest_start("-drive if=none,id=drive0");
+
+    /* Make device_add fail.  If this leaks the virtio-blk-pci device then a
+     * reference to drive0 will also be held (via qdev properties).
+     */
+    response = qmp("{\"execute\": \"device_add\","
+                   " \"arguments\": {"
+                   "   \"driver\": \"virtio-blk-pci\","
+                   "   \"drive\": \"drive0\""
+                   "}}");
+    g_assert(response);
+    error = qdict_get_qdict(response, "error");
+    g_assert(!strcmp(qdict_get_try_str(error, "class") ?: "",
+                     "GenericError"));
+    g_assert(!strcmp(qdict_get_try_str(error, "desc") ?: "",
+                     "Device initialization failed."));
+    QDECREF(response);
+
+    /* Delete the drive */
+    response = qmp("{\"execute\": \"human-monitor-command\","
+                   " \"arguments\": {"
+                   "   \"command-line\": \"drive_del drive0\""
+                   "}}");
+    g_assert(response);
+    g_assert(!strcmp(qdict_get_try_str(response, "return") ?: "(null)", ""));
+    QDECREF(response);
+
+    /* Try to re-add the drive.  This fails with duplicate IDs if a leaked
+     * virtio-blk-pci exists that holds a reference to the old drive0.
+     */
+    response = qmp("{\"execute\": \"human-monitor-command\","
+                   " \"arguments\": {"
+                   "   \"command-line\": \"drive_add pci-addr=auto if=none,id=drive0\""
+                   "}}");
+    g_assert(response);
+    g_assert(!strcmp(qdict_get_try_str(response, "return") ?: "",
+                     "OK\r\n"));
+    QDECREF(response);
+
+    qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+    const char *arch = qtest_get_arch();
+
+    /* Check architecture */
+    if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
+        g_test_message("Skipping test for non-x86\n");
+        return 0;
+    }
+
+    /* Run the tests */
+    g_test_init(&argc, &argv, NULL);
+
+    qtest_add_func("/qmp/device_add", test_device_add);
+
+    return g_test_run();
+}
diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
index 45f2c0b..aba3faf 100755
--- a/tests/qemu-iotests/017
+++ b/tests/qemu-iotests/017
@@ -66,7 +66,7 @@
 echo
 
 TEST_IMG=$TEST_IMG_SAVE
-_make_test_img -b $TEST_IMG.base 6G
+_make_test_img -b "$TEST_IMG.base" 6G
 
 echo "Filling test image"
 echo
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
index cd3582c..5bb18d0 100755
--- a/tests/qemu-iotests/019
+++ b/tests/qemu-iotests/019
@@ -90,12 +90,12 @@
 # Test the conversion twice: One test with the old-style -B option and another
 # one with -o backing_file
 
-for backing_option in "-B $TEST_IMG.base" "-o backing_file=$TEST_IMG.base"; do
+for backing_option in "-B " "-o backing_file="; do
 
     echo
-    echo Testing conversion with $backing_option | _filter_testdir | _filter_imgfmt
+    echo Testing conversion with $backing_option$TEST_IMG.base | _filter_testdir | _filter_imgfmt
     echo
-    $QEMU_IMG convert -O $IMGFMT $backing_option "$TEST_IMG.orig" "$TEST_IMG"
+    $QEMU_IMG convert -O $IMGFMT $backing_option"$TEST_IMG.base" "$TEST_IMG.orig" "$TEST_IMG"
 
     echo "Checking if backing clusters are allocated when they shouldn't"
     echo
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index ae56f3b..d0f96ea 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -388,7 +388,9 @@
 
     def setUp(self):
         qemu_img('create', backing_img, str(TestStreamStop.image_len))
+        qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
+        qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
         self.vm = iotests.VM().add_drive(test_img)
         self.vm.launch()
 
@@ -414,7 +416,9 @@
 
     def setUp(self):
         qemu_img('create', backing_img, str(TestSetSpeed.image_len))
+        qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
+        qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
         self.vm = iotests.VM().add_drive(test_img)
         self.vm.launch()
 
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
index f85b4ce..8bade92 100755
--- a/tests/qemu-iotests/039
+++ b/tests/qemu-iotests/039
@@ -54,7 +54,7 @@
 IMGOPTS="compat=1.1,lazy_refcounts=on"
 _make_test_img $size
 
-$QEMU_IO -c "write -P 0x5a 0 512" ""$TEST_IMG"" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
 
 # The dirty bit must not be set
 ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index aad535a..a2e18c5 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -54,22 +54,12 @@
 
         self.assert_no_active_commit()
 
-    def create_image(self, name, size):
-        file = open(name, 'w')
-        i = 0
-        while i < size:
-            sector = struct.pack('>l504xl', i / 512, i / 512)
-            file.write(sector)
-            i = i + 512
-        file.close()
-
-
 class TestSingleDrive(ImageCommitTestCase):
     image_len = 1 * 1024 * 1024
     test_len = 1 * 1024 * 256
 
     def setUp(self):
-        self.create_image(backing_img, TestSingleDrive.image_len)
+        iotests.create_image(backing_img, TestSingleDrive.image_len)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
         qemu_io('-c', 'write -P 0xab 0 524288', backing_img)
@@ -167,7 +157,7 @@
         except OSError as exception:
             if exception.errno != errno.EEXIST:
                 raise
-        self.create_image(self.backing_img_abs, TestRelativePaths.image_len)
+        iotests.create_image(self.backing_img_abs, TestRelativePaths.image_len)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.backing_img_abs, self.mid_img_abs)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.mid_img_abs, self.test_img)
         qemu_img('rebase', '-u', '-b', self.backing_img, self.mid_img_abs)
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 6661c03..5d40265 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -677,5 +677,30 @@
 
         self.wait_ready_and_cancel()
 
+class TestUnbackedSource(ImageMirroringTestCase):
+    image_len = 2 * 1024 * 1024 # MB
+
+    def setUp(self):
+        qemu_img('create', '-f', iotests.imgfmt, test_img,
+                 str(TestUnbackedSource.image_len))
+        self.vm = iotests.VM().add_drive(test_img)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        os.remove(test_img)
+        os.remove(target_img)
+
+    def test_absolute_paths(self):
+        self.assert_no_active_block_jobs()
+
+        for sync_mode in ['full', 'top', 'none']:
+            result = self.vm.qmp('drive-mirror', device='drive0',
+                                 sync=sync_mode, target=target_img,
+                                 mode='absolute-paths')
+            self.assert_qmp(result, 'return', {})
+            self.complete_and_wait()
+            self.assert_no_active_block_jobs()
+
 if __name__ == '__main__':
     iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
index 42314e9..4fd1c2d 100644
--- a/tests/qemu-iotests/041.out
+++ b/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-........................
+.........................
 ----------------------------------------------------------------------
-Ran 24 tests
+Ran 25 tests
 
 OK
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
index 9b9d118..9def7fc 100755
--- a/tests/qemu-iotests/048
+++ b/tests/qemu-iotests/048
@@ -74,5 +74,39 @@
 io_pattern write 0 $CLUSTER_SIZE 0 1 123
 _compare
 
+# Test unaligned case of mismatch offsets in allocated clusters
+_make_test_img $size
+io_pattern write 0 512 0 1 100
+cp "$TEST_IMG" "$TEST_IMG2"
+io_pattern write 512 512 0 1 101
+_compare
+
+# Test cluster allocated in one, with IO error
+cat > "$TEST_DIR/blkdebug.conf"<<EOF
+[inject-error]
+event = "read_aio"
+errno = "5"
+once ="off"
+EOF
+_make_test_img $size
+cp "$TEST_IMG" "$TEST_IMG2"
+io_pattern write 512 512 0 1 102
+TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" _compare 2>&1 |\
+    _filter_testdir | _filter_imgfmt
+
+# Test cluster allocated in one, with different sizes and IO error in the part
+# that exists only in one image
+cat > "$TEST_DIR/blkdebug.conf"<<EOF
+[inject-error]
+event = "read_aio"
+errno = "5"
+once ="off"
+EOF
+_make_test_img $size
+TEST_IMG="$TEST_IMG2" _make_test_img 0
+io_pattern write 512 512 0 1 102
+TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" _compare 2>&1 |\
+    _filter_testdir | _filter_imgfmt
+
 # Cleanup
 status=0
diff --git a/tests/qemu-iotests/048.out b/tests/qemu-iotests/048.out
index 68f65d5..d141e05 100644
--- a/tests/qemu-iotests/048.out
+++ b/tests/qemu-iotests/048.out
@@ -1,5 +1,5 @@
 QA output created by 048
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 === IO: pattern 45
 qemu-io> wrote 4096/4096 bytes at offset 524288
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -28,4 +28,29 @@
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> Content mismatch at offset 0!
 1
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+=== IO: pattern 100
+qemu-io> wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> === IO: pattern 101
+qemu-io> wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> Content mismatch at offset 512!
+1
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+=== IO: pattern 102
+qemu-io> wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Error while reading offset 0: Input/output error
+4
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0 
+=== IO: pattern 102
+qemu-io> wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+Warning: Image size mismatch!
+4
 Cleanup
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 356c375..3a75bda 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -64,9 +64,9 @@
 size=128M
 
 _make_test_img $size
-cp $TEST_IMG $TEST_IMG.orig
-mv $TEST_IMG $TEST_IMG.base
-_make_test_img -b $TEST_IMG.base $size
+cp "$TEST_IMG" "$TEST_IMG.orig"
+mv "$TEST_IMG" "$TEST_IMG.base"
+_make_test_img -b "$TEST_IMG.base" $size
 
 echo
 echo === Unknown option ===
@@ -78,10 +78,17 @@
 run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=foo
 
 echo
+echo === Invalid format ===
+echo
+
+run_qemu -drive file="$TEST_IMG",format=foo
+run_qemu -drive file="$TEST_IMG",driver=foo
+
+echo
 echo === Overriding backing file ===
 echo
 
-echo "info block" | run_qemu -drive file=$TEST_IMG,driver=qcow2,backing.file.filename=$TEST_IMG.orig -nodefaults
+echo "info block" | run_qemu -drive file="$TEST_IMG",driver=qcow2,backing.file.filename="$TEST_IMG.orig" -nodefaults
 
 echo
 echo === Enable and disable lazy refcounting on the command line, plus some invalid values ===
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 2839e32..8769c8e 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -17,6 +17,15 @@
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
 
 
+=== Invalid format ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=foo: 'foo' invalid format
+
+Testing: -drive file=TEST_DIR/t.qcow2,driver=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TEST_DIR/t.qcow2: Invalid driver: 'foo'
+
+
 === Overriding backing file ===
 
 Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults
@@ -24,7 +33,7 @@
 (qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
 ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
     Backing file:     TEST_DIR/t.qcow2.orig (chain depth: 1)
- [not inserted](qemu) qququiquit
+(qemu) qququiquit
 
 
 === Enable and disable lazy refcounting on the command line, plus some invalid values ===
@@ -226,6 +235,6 @@
 QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: Unknown protocol
 
 Testing: -drive file.filename=foo:bar
-QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open file: No such file or directory
+QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open 'foo:bar': No such file or directory
 
 *** done
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index b81c575..6a27ac9 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -69,7 +69,7 @@
 echo
 echo "=== Testing monolithicFlat creation and opening ==="
 IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
-$QEMU_IMG info $TEST_IMG | _filter_testdir
+_img_info
 
 echo
 echo "=== Testing monolithicFlat with zeroed_grain ==="
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 9b12efb..2ded8a9 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -18,10 +18,9 @@
 
 === Testing monolithicFlat creation and opening ===
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
-image: TEST_DIR/t.vmdk
-file format: vmdk
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
 virtual size: 2.0G (2147483648 bytes)
-disk size: 4.0K
 
 === Testing monolithicFlat with zeroed_grain ===
 qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
index fa9319d..e42f9bd 100755
--- a/tests/qemu-iotests/061
+++ b/tests/qemu-iotests/061
@@ -163,7 +163,7 @@
 echo
 IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
 $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
-IMGOPTS="compat=1.1,backing_file=$TEST_IMG.base" _make_test_img 64M
+IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
 $QEMU_IO -c "read -P 0x2a 0 128k" -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io
 $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
 _check_test_img
@@ -174,7 +174,7 @@
 echo
 IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
 $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
-IMGOPTS="compat=1.1,backing_file=$TEST_IMG.base" _make_test_img 64M
+IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
 $QEMU_IO -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io
 $QEMU_IMG snapshot -c foo "$TEST_IMG"
 $QEMU_IO -c "write -P 0x42 0 128k" "$TEST_IMG" | _filter_qemu_io
@@ -190,7 +190,7 @@
 echo
 IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
 $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
-IMGOPTS="compat=1.1,backing_file=$TEST_IMG.base" _make_test_img 64M
+IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
 $QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
 $QEMU_IMG snapshot -c foo "$TEST_IMG"
 $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
diff --git a/tests/qemu-iotests/064 b/tests/qemu-iotests/064
index 6789aa6..1c74c31 100755
--- a/tests/qemu-iotests/064
+++ b/tests/qemu-iotests/064
@@ -56,6 +56,17 @@
 echo "=== Verify pattern 0x00, 66M - 1024M ==="
 $QEMU_IO -r -c "read -pP 0x00 66M 958M" "$TEST_IMG" | _filter_qemu_io
 
+echo
+echo "=== Verify pattern write, 0xc3 99M-157M ==="
+$QEMU_IO -c "write -pP 0xc3 99M 58M" "$TEST_IMG" | _filter_qemu_io
+# first verify we didn't write where we should not have
+$QEMU_IO -c "read -pP 0xa5 0 33M" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -pP 0x96 33M 33M" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -pP 0x00 66M 33M" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -pP 0x00 157MM 867MM" "$TEST_IMG" | _filter_qemu_io
+# now verify what we should have actually written
+$QEMU_IO -c "read -pP 0xc3 99M 58M" "$TEST_IMG" | _filter_qemu_io
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/064.out b/tests/qemu-iotests/064.out
index b9e8e4a..5346a4e 100644
--- a/tests/qemu-iotests/064.out
+++ b/tests/qemu-iotests/064.out
@@ -11,4 +11,18 @@
 === Verify pattern 0x00, 66M - 1024M ===
 read 1004535808/1004535808 bytes at offset 69206016
 958 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Verify pattern write, 0xc3 99M-157M ===
+wrote 60817408/60817408 bytes at offset 103809024
+58 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 34603008/34603008 bytes at offset 0
+33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 34603008/34603008 bytes at offset 34603008
+33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 34603008/34603008 bytes at offset 69206016
+33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 909115392/909115392 bytes at offset 164626432
+867 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 60817408/60817408 bytes at offset 103809024
+58 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 *** done
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
index 79dc38b..d025192 100755
--- a/tests/qemu-iotests/067
+++ b/tests/qemu-iotests/067
@@ -45,7 +45,7 @@
 
 function run_qemu()
 {
-    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp
+    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g'
 }
 
 size=128M
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
index 4bb9ff9..8d271cc 100644
--- a/tests/qemu-iotests/067.out
+++ b/tests/qemu-iotests/067.out
@@ -6,7 +6,7 @@
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0
 QMP_VERSION
 {"return": {}}
-{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "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}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
@@ -24,7 +24,7 @@
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
 QMP_VERSION
 {"return": {}}
-{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
+{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "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}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"return": {}}
 {"return": {}}
@@ -44,7 +44,7 @@
 QMP_VERSION
 {"return": {}}
 {"return": "OK\r\n"}
-{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "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}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"return": {}}
 {"return": {}}
@@ -64,14 +64,14 @@
 QMP_VERSION
 {"return": {}}
 {"return": {}}
-{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "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}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"return": {}}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "RESET"}
-{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": 139264, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "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}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
new file mode 100755
index 0000000..b72e555
--- /dev/null
+++ b/tests/qemu-iotests/068
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# Test case for loading a saved VM state from a qcow2 image
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# This tests qocw2-specific low-level functionality
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+IMGOPTS="compat=1.1"
+IMG_SIZE=128K
+
+echo
+echo "=== Saving and reloading a VM state to/from a qcow2 image ==="
+echo
+_make_test_img $IMG_SIZE
+# Give qemu some time to boot before saving the VM state
+bash -c 'sleep 1; echo -e "savevm 0\nquit"' |\
+    $QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" |\
+    _filter_qemu
+# Now try to continue from that VM state (this should just work)
+echo quit |\
+    $QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" -loadvm 0 |\
+    _filter_qemu
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/068.out b/tests/qemu-iotests/068.out
new file mode 100644
index 0000000..abe35a9
--- /dev/null
+++ b/tests/qemu-iotests/068.out
@@ -0,0 +1,11 @@
+QA output created by 068
+
+=== Saving and reloading a VM state to/from a qcow2 image ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) ssasavsavesavevsavevmsavevm savevm 0
+(qemu) qququiquit
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+*** done
diff --git a/tests/qemu-iotests/069 b/tests/qemu-iotests/069
new file mode 100755
index 0000000..3042803
--- /dev/null
+++ b/tests/qemu-iotests/069
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# Test case for deleting a backing file
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt cow qed qcow qcow2 vmdk
+_supported_proto generic
+_supported_os Linux
+
+IMG_SIZE=128K
+
+echo
+echo "=== Creating an image with a backing file and deleting that file ==="
+echo
+TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE
+_make_test_img -b "$TEST_IMG.base" $IMG_SIZE
+rm -f "$TEST_IMG.base"
+# Just open the image and close it right again (this should print an error message)
+$QEMU_IO -c quit "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/069.out b/tests/qemu-iotests/069.out
new file mode 100644
index 0000000..b48306d
--- /dev/null
+++ b/tests/qemu-iotests/069.out
@@ -0,0 +1,8 @@
+QA output created by 069
+
+=== Creating an image with a backing file and deleting that file ===
+
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072 
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file='TEST_DIR/t.IMGFMT.base' 
+qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open backing file: Could not open 'TEST_DIR/t.IMGFMT.base': No such file or directory
+*** done
diff --git a/tests/qemu-iotests/070 b/tests/qemu-iotests/070
new file mode 100755
index 0000000..41bf100
--- /dev/null
+++ b/tests/qemu-iotests/070
@@ -0,0 +1,67 @@
+#!/bin/bash
+#
+# Test VHDX log replay from an image with a journal that needs to be
+# replayed
+#
+# Copyright (C) 2013 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=jcody@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+    _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt vhdx
+_supported_proto generic
+_supported_os Linux
+
+# With the log replayed, the pattern 0xa5 extends to 0xc025000
+# If the log was not replayed, it would only extend to 0xc000000
+#
+# This image is a 10G dynamic image, with 4M block size, and 1 unplayed
+# data sector in the log
+#
+# This image was created with qemu-img, however it was verified using
+# Hyper-V to properly replay the logs and give the same post-replay
+# image as qemu.
+_use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2
+
+echo
+echo "=== Verify open image read-only fails, due to dirty log ==="
+$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | grep -o "Permission denied"
+
+echo "=== Verify open image replays log  ==="
+$QEMU_IO  -c "read -pP 0xa5 0 18M" "$TEST_IMG" | _filter_qemu_io
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/070.out b/tests/qemu-iotests/070.out
new file mode 100644
index 0000000..9db8ff2
--- /dev/null
+++ b/tests/qemu-iotests/070.out
@@ -0,0 +1,8 @@
+QA output created by 070
+
+=== Verify open image read-only fails, due to dirty log ===
+Permission denied
+=== Verify open image replays log  ===
+read 18874368/18874368 bytes at offset 0
+18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
new file mode 100755
index 0000000..392db54
--- /dev/null
+++ b/tests/qemu-iotests/073
@@ -0,0 +1,166 @@
+#!/bin/bash
+#
+# Test count_contiguous_clusters in qcow2
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+    _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+CLUSTER_SIZE=64k
+size=128M
+
+echo
+echo "== creating backing file =="
+
+TEST_IMG="$TEST_IMG.base" _make_test_img $size
+
+_make_test_img -b "$TEST_IMG.base"
+$QEMU_IO -c "write -P 0xa5 0 $size" "$TEST_IMG.base" | _filter_qemu_io
+
+echo
+echo "== normal -> unallocated =="
+
+$QEMU_IO -c "write -P 0x11 0 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x11 0x10000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x11 0 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== normal -> compressed =="
+
+$QEMU_IO -c "write -P 0x22 0x20000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -c -P 0x22 0x30000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x22 0x20000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== normal -> zero =="
+
+$QEMU_IO -c "write -P 0x33 0x40000 0x20000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x33 0x40000 0x20000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 0x40000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x50000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x40000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo
+echo "== unallocated -> normal =="
+
+$QEMU_IO -c "write -P 0x44 0x60000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x44 0x70000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x44 0x60000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== unallocated -> compressed =="
+
+$QEMU_IO -c "write -P 0x55 0x80000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -c -P 0x55 0x90000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x55 0x80000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== unallocated -> zero =="
+
+$QEMU_IO -c "write -P 0x66 0xa0000 0x20000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 0xa0000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 0xb0000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0xa0000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo
+echo "== compressed -> normal =="
+
+$QEMU_IO -c "write -c -P 0x77 0xc0000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x77 0xd0000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x77 0xc0000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== compressed -> unallocated =="
+
+$QEMU_IO -c "write -c -P 0x88 0xe0000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x88 0xf0000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x88 0xe0000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== compressed -> zero =="
+
+$QEMU_IO -c "write -c -P 0 0x100000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -c -P 0x99 0x110000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x110000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x100000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo
+echo "== zero -> normal =="
+
+$QEMU_IO -c "write -P 0xaa 0x120000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 0x130000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x120000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x120000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== zero -> unallocated =="
+
+$QEMU_IO -c "write -z 0x140000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 0x150000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x140000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== zero -> compressed =="
+
+$QEMU_IO -c "write -c -P 0 0x170000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x160000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x160000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+
+_check_test_img
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/073.out b/tests/qemu-iotests/073.out
new file mode 100644
index 0000000..c9b0076
--- /dev/null
+++ b/tests/qemu-iotests/073.out
@@ -0,0 +1,118 @@
+QA output created by 073
+
+== creating backing file ==
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' 
+wrote 134217728/134217728 bytes at offset 0
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== normal -> unallocated ==
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 0
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== normal -> compressed ==
+wrote 65536/65536 bytes at offset 131072
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 196608
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 131072
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== normal -> zero ==
+wrote 131072/131072 bytes at offset 262144
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 262144
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 262144
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 327680
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 262144
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+
+== unallocated -> normal ==
+wrote 65536/65536 bytes at offset 393216
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 458752
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 393216
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== unallocated -> compressed ==
+wrote 65536/65536 bytes at offset 524288
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 589824
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 524288
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== unallocated -> zero ==
+wrote 131072/131072 bytes at offset 655360
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 655360
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 720896
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 655360
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+
+== compressed -> normal ==
+wrote 65536/65536 bytes at offset 786432
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 851968
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 786432
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== compressed -> unallocated ==
+wrote 65536/65536 bytes at offset 917504
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 983040
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 917504
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== compressed -> zero ==
+wrote 65536/65536 bytes at offset 1048576
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1114112
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1114112
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1048576
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+
+== zero -> normal ==
+wrote 65536/65536 bytes at offset 1179648
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1245184
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1179648
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1179648
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== zero -> unallocated ==
+wrote 65536/65536 bytes at offset 1310720
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1376256
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1310720
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== zero -> compressed ==
+wrote 65536/65536 bytes at offset 1507328
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1441792
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1441792
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
+*** done
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index 2932e14..8cde7f1 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -200,7 +200,6 @@
         -vhdx)
             IMGFMT=vhdx
             xpand=false
-            IMGFMT_GENERIC=false
             ;;
 
         -rbd)
diff --git a/tests/qemu-iotests/common.pattern b/tests/qemu-iotests/common.pattern
index 00e0f60..ddfbca1 100644
--- a/tests/qemu-iotests/common.pattern
+++ b/tests/qemu-iotests/common.pattern
@@ -28,7 +28,7 @@
 }
 
 function is_allocated() {
-    do_is_allocated "$@" | $QEMU_IO $TEST_IMG | _filter_qemu_io
+    do_is_allocated "$@" | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 }
 
 function do_io() {
@@ -46,18 +46,18 @@
 }
 
 function io_pattern() {
-    do_io "$@" | $QEMU_IO $TEST_IMG | _filter_qemu_io
+    do_io "$@" | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 }
 
 function io() {
     local start=$2
     local pattern=$(( (start >> 9) % 256 ))
 
-    do_io "$@" $pattern | $QEMU_IO $TEST_IMG | _filter_qemu_io
+    do_io "$@" $pattern | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 }
 
 function io_zero() {
-    do_io "$@" 0 | $QEMU_IO $TEST_IMG | _filter_qemu_io
+    do_io "$@" 0 | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
 }
 
 function io_test() {
@@ -117,8 +117,8 @@
     echo === Clusters to be compressed [3]
     io_pattern writev $((offset + 8 * $cluster_size)) $cluster_size $((9 * $cluster_size)) $num 165
 
-    mv $TEST_IMG $TEST_IMG.orig
-    $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -c $TEST_IMG.orig $TEST_IMG
+    mv "$TEST_IMG" "$TEST_IMG.orig"
+    $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -c "$TEST_IMG.orig" "$TEST_IMG"
 
     # Write the used clusters
     echo === Used clusters [1]
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 4e82604..7f62457 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -111,6 +111,8 @@
     local image_size=$*
     local optstr=""
     local img_name=""
+    local use_backing=0
+    local backing_file=""
 
     if [ -n "$TEST_IMG_FILE" ]; then
         img_name=$TEST_IMG_FILE
@@ -123,7 +125,8 @@
     fi
 
     if [ "$1" = "-b" ]; then
-        extra_img_options="$1 $2"
+        use_backing=1
+        backing_file=$2
         image_size=$3
     fi
     if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then
@@ -135,7 +138,13 @@
     fi
 
     # XXX(hch): have global image options?
-    $QEMU_IMG create -f $IMGFMT $extra_img_options $img_name $image_size 2>&1 | \
+    (
+     if [ $use_backing = 1 ]; then
+        $QEMU_IMG create -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1
+     else
+        $QEMU_IMG create -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
+     fi
+    ) | \
         sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
             -e "s#$TEST_DIR#TEST_DIR#g" \
             -e "s#$IMGFMT#IMGFMT#g" \
@@ -148,7 +157,10 @@
             -e "s# zeroed_grain=\\(on\\|off\\)##g" \
             -e "s# subformat='[^']*'##g" \
             -e "s# adapter_type='[^']*'##g" \
-            -e "s# lazy_refcounts=\\(on\\|off\\)##g"
+            -e "s# lazy_refcounts=\\(on\\|off\\)##g" \
+            -e "s# block_size=[0-9]\\+##g" \
+            -e "s# block_state_zero=\\(on\\|off\\)##g" \
+            -e "s# log_size=[0-9]\\+##g"
 
     # Start an NBD server on the image file, which is what we'll be talking to
     if [ $IMGPROTO = "nbd" ]; then
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 13c5500..b63b18c 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -73,3 +73,7 @@
 065 rw auto
 066 rw auto
 067 rw auto
+068 rw auto
+069 rw auto
+070 rw auto
+073 rw auto
diff --git a/tests/qemu-iotests/sample_images/iotest-dirtylog-10G-4M.vhdx.bz2 b/tests/qemu-iotests/sample_images/iotest-dirtylog-10G-4M.vhdx.bz2
new file mode 100644
index 0000000..4b91cfc
--- /dev/null
+++ b/tests/qemu-iotests/sample_images/iotest-dirtylog-10G-4M.vhdx.bz2
Binary files differ
diff --git a/tests/qom-test.c b/tests/qom-test.c
new file mode 100644
index 0000000..499be40
--- /dev/null
+++ b/tests/qom-test.c
@@ -0,0 +1,253 @@
+/*
+ * QTest testcase for QOM
+ *
+ * Copyright (c) 2013 SUSE LINUX Products GmbH
+ *
+ * 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 "libqtest.h"
+
+#include <glib.h>
+#include <string.h>
+#include "qemu/osdep.h"
+
+static void test_nop(gconstpointer data)
+{
+    QTestState *s;
+    const char *machine = data;
+    char *args;
+
+    args = g_strdup_printf("-machine %s", machine);
+    s = qtest_start(args);
+    if (s) {
+        qtest_quit(s);
+    }
+    g_free(args);
+}
+
+static const char *x86_machines[] = {
+    "pc",
+    "isapc",
+    "q35",
+};
+
+static const char *alpha_machines[] = {
+    "clipper",
+};
+
+static const char *arm_machines[] = {
+    "integratorcp",
+    "versatilepb",
+    "versatileab",
+    "lm3s811evb",
+    "lm3s6965evb",
+    "collie",
+    "akita",
+    "spitz",
+    "borzoi",
+    "terrier",
+    "tosa",
+    "cheetah",
+    "sx1-v1",
+    "sx1",
+    "realview-eb",
+    "realview-eb-mpcore",
+    "realview-pb-a8",
+    "realview-pbx-a9",
+    "musicpal",
+    "mainstone",
+    "connex",
+    "verdex",
+    "z2",
+    "n800",
+    "n810",
+    "kzm",
+    "vexpress-a9",
+    "vexpress-a15",
+    "smdkc210",
+    "nuri",
+    "xilinx-zynq-a9",
+    "highbank",
+    "midway",
+};
+
+static const char *cris_machines[] = {
+    "axis-dev88",
+};
+
+static const char *lm32_machines[] = {
+    "lm32-evr",
+    "lm32-uclinux",
+    "milkymist",
+};
+
+static const char *m68k_machines[] = {
+    "mcf5208evb",
+    "an5206",
+    "dummy",
+};
+
+static const char *microblaze_machines[] = {
+    "petalogix-ml605",
+    "petalogix-s3adsp1800",
+};
+
+static const char *mips_machines[] = {
+    "malta",
+    "magnum",
+    "mips",
+    "mipssim",
+    "pica61",
+};
+
+static const char *moxie_machines[] = {
+    "moxiesim",
+};
+
+static const char *openrisc_machines[] = {
+    "or32-sim",
+};
+
+static const char *ppc_machines[] = {
+    "g3beige",
+    "mac99",
+    "prep",
+    "mpc8544ds",
+    "ppce500",
+};
+
+static const char *ppc64_machines[] = {
+    "pseries",
+};
+
+static const char *ppc405_machines[] = {
+    "ref405ep",
+    "taihu",
+};
+
+static const char *ppc440_machines[] = {
+    "bamboo",
+    "virtex-ml507",
+};
+
+static const char *s390_machines[] = {
+    "s390-virtio",
+    "s390-ccw-virtio",
+};
+
+static const char *superh_machines[] = {
+    "r2d",
+    "shix",
+};
+
+static const char *sparc_machines[] = {
+    "SS-4",
+    "SS-5",
+    "SS-10",
+    "SS-20",
+    "SS-600MP",
+    "LX",
+    "SPARCClassic",
+    "SPARCbook",
+    "leon3_generic",
+};
+
+static const char *sparc64_machines[] = {
+    "sun4u",
+    "sun4v",
+    "Niagara",
+};
+
+static const char *unicore32_machines[] = {
+    "puv3",
+};
+
+static const char *xtensa_machines[] = {
+    "sim",
+    "lx60",
+    "lx200",
+};
+
+static void add_test_cases(const char *arch, const char *machine)
+{
+    char *path;
+    path = g_strdup_printf("/%s/qom/%s", arch, machine);
+    g_test_add_data_func(path, machine, test_nop);
+}
+
+#define ADD_MACHINE_TESTS(arch, array) do { \
+    int i; \
+    for (i = 0; i < ARRAY_SIZE(array); i++) { \
+        add_test_cases((arch), (array)[i]); \
+    } \
+} while (false)
+
+int main(int argc, char **argv)
+{
+    const char *arch = qtest_get_arch();
+
+    g_test_init(&argc, &argv, NULL);
+
+    add_test_cases(arch, "none");
+
+    if (strcmp(arch, "i386") == 0 ||
+        strcmp(arch, "x86_64") == 0) {
+        ADD_MACHINE_TESTS(arch, x86_machines);
+    } else if (strcmp(arch, "alpha") == 0) {
+        ADD_MACHINE_TESTS(arch, alpha_machines);
+    } else if (strcmp(arch, "arm") == 0) {
+        ADD_MACHINE_TESTS(arch, arm_machines);
+    } else if (strcmp(arch, "cris") == 0) {
+        ADD_MACHINE_TESTS(arch, cris_machines);
+    } else if (strcmp(arch, "lm32") == 0) {
+        ADD_MACHINE_TESTS(arch, lm32_machines);
+    } else if (strcmp(arch, "m68k") == 0) {
+        ADD_MACHINE_TESTS(arch, m68k_machines);
+    } else if (strcmp(arch, "microblaze") == 0 ||
+               strcmp(arch, "microblazeel") == 0) {
+        ADD_MACHINE_TESTS(arch, microblaze_machines);
+    } else if (strcmp(arch, "mips") == 0 ||
+               strcmp(arch, "mipsel") == 0 ||
+               strcmp(arch, "mips64") == 0) {
+        ADD_MACHINE_TESTS(arch, mips_machines);
+    } else if (strcmp(arch, "mips64el") == 0) {
+        ADD_MACHINE_TESTS(arch, mips_machines);
+        add_test_cases(arch, "fulong2e");
+    } else if (strcmp(arch, "moxie") == 0) {
+        ADD_MACHINE_TESTS(arch, moxie_machines);
+    } else if (strcmp(arch, "or32") == 0) {
+        ADD_MACHINE_TESTS(arch, openrisc_machines);
+    } else if (strcmp(arch, "ppcemb") == 0) {
+#if 0
+        /* XXX Available in ppcemb but don't work */
+        ADD_MACHINE_TESTS(arch, ppc405_machines);
+#endif
+        ADD_MACHINE_TESTS(arch, ppc440_machines);
+    } else if (strcmp(arch, "ppc") == 0) {
+        ADD_MACHINE_TESTS(arch, ppc405_machines);
+        ADD_MACHINE_TESTS(arch, ppc440_machines);
+        ADD_MACHINE_TESTS(arch, ppc_machines);
+    } else if (strcmp(arch, "ppc64") == 0) {
+        ADD_MACHINE_TESTS(arch, ppc405_machines);
+        ADD_MACHINE_TESTS(arch, ppc440_machines);
+        ADD_MACHINE_TESTS(arch, ppc_machines);
+        ADD_MACHINE_TESTS(arch, ppc64_machines);
+    } else if (strcmp(arch, "s390x") == 0) {
+        ADD_MACHINE_TESTS(arch, s390_machines);
+    } else if (strcmp(arch, "sh4") == 0 ||
+               strcmp(arch, "sh4eb") == 0) {
+        ADD_MACHINE_TESTS(arch, superh_machines);
+    } else if (strcmp(arch, "sparc") == 0) {
+        ADD_MACHINE_TESTS(arch, sparc_machines);
+    } else if (strcmp(arch, "sparc64") == 0) {
+        ADD_MACHINE_TESTS(arch, sparc64_machines);
+    } else if (strcmp(arch, "unicore32") == 0) {
+        ADD_MACHINE_TESTS(arch, unicore32_machines);
+    } else if (strcmp(arch, "xtensa") == 0 ||
+               strcmp(arch, "xtensaeb") == 0) {
+        ADD_MACHINE_TESTS(arch, xtensa_machines);
+    }
+
+    return g_test_run();
+}
diff --git a/tests/rtc-test.c b/tests/rtc-test.c
index 3395d7f..f1b123f 100644
--- a/tests/rtc-test.c
+++ b/tests/rtc-test.c
@@ -552,7 +552,7 @@
 
     g_test_init(&argc, &argv, NULL);
 
-    s = qtest_start("-display none -rtc clock=vm");
+    s = qtest_start("-rtc clock=vm");
     qtest_irq_intercept_in(s, "ioapic");
 
     qtest_add_func("/rtc/check-time/bcd", bcd_check_time);
diff --git a/tests/tcg/openrisc/test_addc.c b/tests/tcg/openrisc/test_addc.c
index 05d18f8..a8f756a 100644
--- a/tests/tcg/openrisc/test_addc.c
+++ b/tests/tcg/openrisc/test_addc.c
@@ -7,9 +7,10 @@
 
     b = 0x01;
     c = 0xffffffff;
-    result = 1;
+    result = 0;
     __asm
-    ("l.addc   %0, %1, %2\n\t"
+    ("l.add r1, r1, r0\n\t" /* clear carry */
+     "l.addc   %0, %1, %2\n\t"
      : "=r"(a)
      : "r"(b), "r"(c)
     );
@@ -22,7 +23,8 @@
     c = 0xffffffff;
     result = 0x80000001;
     __asm
-    ("l.addc   %0, %1, %2\n\t"
+    ("l.add r1, r1, r0\n\t" /* clear carry */
+     "l.addc   %0, %1, %2\n\t"
      "l.movhi  %2, 0x7fff\n\t"
      "l.ori    %2, %2, 0xffff\n\t"
      "l.addc   %0, %1, %2\n\t"
diff --git a/tests/tcg/openrisc/test_addic.c b/tests/tcg/openrisc/test_addic.c
index 4ba7432..857aaa1 100644
--- a/tests/tcg/openrisc/test_addic.c
+++ b/tests/tcg/openrisc/test_addic.c
@@ -6,9 +6,10 @@
     int result;
 
     a = 1;
-    result = 0x1;
+    result = 0x0;
     __asm
-    ("l.addic %0, %0, 0xffff\n\t"
+    ("l.add r1, r1, r0\n\t" /* clear carry */
+     "l.addic %0, %0, 0xffff\n\t"
      : "+r"(a)
     );
     if (a != result) {
@@ -16,10 +17,11 @@
         return -1;
    }
 
-    a = 0x1;
+    a = -1;
     result = 0x201;
     __asm
-    ("l.addic %0, %0, 0xffff\n\t"
+    ("l.add r1, r1, r0\n\t"  /* clear carry */
+     "l.addic %0, %0, 0x1\n\t"
      "l.ori   %0, r0, 0x100\n\t"
      "l.addic %0, %0, 0x100\n\t"
      : "+r"(a)
diff --git a/tests/test-bitops.c b/tests/test-bitops.c
index 4e713e4..8238eb5 100644
--- a/tests/test-bitops.c
+++ b/tests/test-bitops.c
@@ -31,8 +31,8 @@
 };
 
 static const S64Test test_s64_data[] = {
-    { 0x8459826734967223, 60, 4, -8 },
-    { 0x8459826734967223, 0, 64, 0x8459826734967223 },
+    { 0x8459826734967223ULL, 60, 4, -8 },
+    { 0x8459826734967223ULL, 0, 64, 0x8459826734967223LL },
 };
 
 static void test_sextract32(void)
diff --git a/tests/test-opts-visitor.c b/tests/test-opts-visitor.c
index 9f902b5..ebeee5d 100644
--- a/tests/test-opts-visitor.c
+++ b/tests/test-opts-visitor.c
@@ -125,7 +125,7 @@
         g_assert((magic & bitval) == 0);
         magic |= bitval;
     }
-    g_assert(magic == 0xBADC0FFEE0DDF00D);
+    g_assert(magic == 0xBADC0FFEE0DDF00DULL);
 
     magic = 0;
     for (u16 = f->userdef->u16; u16 != NULL; u16 = u16->next) {
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 0beb8fb..1e1c6fa 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -604,6 +604,7 @@
     g_assert(error_is_set(&errp));
     g_assert(p->string == NULL);
 
+    error_free(errp);
     g_free(p->string);
     g_free(p);
 }
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
index 7608126..1d4ffd3 100644
--- a/tests/test-throttle.c
+++ b/tests/test-throttle.c
@@ -18,7 +18,7 @@
 ThrottleConfig cfg;
 ThrottleState  ts;
 
-/* usefull function */
+/* useful function */
 static bool double_cmp(double x, double y)
 {
     return fabsl(x - y) < 1e-6;
@@ -320,7 +320,7 @@
     /* zero the structure */
     memset(&ts, 0, sizeof(ts));
 
-    /* no timer set shoudl return false */
+    /* no timer set should return false */
     g_assert(!throttle_have_timer(&ts));
 
     /* init the structure */
diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c
index fecd6dc..5ac48e2 100644
--- a/tests/tmp105-test.c
+++ b/tests/tmp105-test.c
@@ -59,7 +59,7 @@
 
     g_test_init(&argc, &argv, NULL);
 
-    s = qtest_start("-display none -machine n800");
+    s = qtest_start("-machine n800");
     i2c = omap_i2c_create(OMAP2_I2C_1_BASE);
     addr = N8X0_ADDR;
 
diff --git a/ui/console.c b/ui/console.c
index aad4fc9..199ba69 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -409,39 +409,6 @@
     }
 };
 
-#ifdef DEBUG_CONSOLE
-static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
-{
-    if (t_attrib->bold) {
-        printf("b");
-    } else {
-        printf(" ");
-    }
-    if (t_attrib->uline) {
-        printf("u");
-    } else {
-        printf(" ");
-    }
-    if (t_attrib->blink) {
-        printf("l");
-    } else {
-        printf(" ");
-    }
-    if (t_attrib->invers) {
-        printf("i");
-    } else {
-        printf(" ");
-    }
-    if (t_attrib->unvisible) {
-        printf("n");
-    } else {
-        printf(" ");
-    }
-
-    printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
-}
-#endif
-
 static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
                           TextAttributes *t_attrib)
 {
diff --git a/ui/keymaps.c b/ui/keymaps.c
index f373cc5..80d658d 100644
--- a/ui/keymaps.c
+++ b/ui/keymaps.c
@@ -33,6 +33,12 @@
         if (!strcmp(p->name, name))
             return p->keysym;
     }
+    if (name[0] == 'U' && strlen(name) == 5) { /* try unicode Uxxxx */
+        char *end;
+        int ret = (int)strtoul(name + 1, &end, 16);
+        if (*end == '\0' && ret > 0)
+          return ret;
+    }
     return 0;
 }
 
diff --git a/ui/sdl.c b/ui/sdl.c
index 39a42d6..9d8583c 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -86,6 +86,7 @@
 static void do_sdl_resize(int width, int height, int bpp)
 {
     int flags;
+    SDL_Surface *tmp_screen;
 
     //    printf("resizing to %d %d\n", w, h);
 
@@ -98,12 +99,26 @@
     if (gui_noframe)
         flags |= SDL_NOFRAME;
 
-    real_screen = SDL_SetVideoMode(width, height, bpp, flags);
+    tmp_screen = SDL_SetVideoMode(width, height, bpp, flags);
     if (!real_screen) {
-	fprintf(stderr, "Could not open SDL display (%dx%dx%d): %s\n", width, 
-		height, bpp, SDL_GetError());
-        exit(1);
+        if (!tmp_screen) {
+            fprintf(stderr, "Could not open SDL display (%dx%dx%d): %s\n",
+                    width, height, bpp, SDL_GetError());
+            exit(1);
+        }
+    } else {
+        /*
+         * Revert to the previous video mode if the change of resizing or
+         * resolution failed.
+         */
+        if (!tmp_screen) {
+            fprintf(stderr, "Failed to set SDL display (%dx%dx%d): %s\n",
+                    width, height, bpp, SDL_GetError());
+            return;
+        }
     }
+
+    real_screen = tmp_screen;
 }
 
 static void sdl_switch(DisplayChangeListener *dcl,
diff --git a/ui/vnc-enc-zywrle.h b/ui/vnc-enc-zywrle.h
index 1ff40b1..d436d58 100644
--- a/ui/vnc-enc-zywrle.h
+++ b/ui/vnc-enc-zywrle.h
@@ -305,7 +305,7 @@
    |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
 
  In this method, H/L and X0/X1 is always same position.
- This lead us to more speed and less memory.
+ This leads us to more speed and less memory.
  Of cause, the result of both method is quite same
  because it's only difference that coefficient position.
 */
diff --git a/ui/vnc_keysym.h b/ui/vnc_keysym.h
index 6250bec..1dc039f 100644
--- a/ui/vnc_keysym.h
+++ b/ui/vnc_keysym.h
@@ -224,6 +224,14 @@
 { "odoubleacute",         0x1f5},
 { "udoubleacute",         0x1fb},
 
+/* Czech national characters */
+{ "ecaron",               0x1ec},
+{ "scaron",               0x1b9},
+{ "ccaron",               0x1e8},
+{ "rcaron",               0x1f8},
+{ "zcaron",               0x1be},
+{ "uring",                0x1f9},
+
     /* modifiers */
 {"ISO_Level3_Shift", 0xfe03}, /* XK_ISO_Level3_Shift */
 {"Control_L", 0xffe3}, /* XK_Control_L */
@@ -342,5 +350,370 @@
 {"Katakana_Real", 0xff25},
 {"Eisu_toggle", 0xff30},
 
+{"abovedot",                      0x01ff},  /* U+02D9 DOT ABOVE */
+{"amacron",                       0x03e0},  /* U+0101 LATIN SMALL LETTER A WITH MACRON */
+{"Amacron",                       0x03c0},  /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */
+{"Arabic_ain",                    0x05d9},  /* U+0639 ARABIC LETTER AIN */
+{"Arabic_alef",                   0x05c7},  /* U+0627 ARABIC LETTER ALEF */
+{"Arabic_alefmaksura",            0x05e9},  /* U+0649 ARABIC LETTER ALEF MAKSURA */
+{"Arabic_beh",                    0x05c8},  /* U+0628 ARABIC LETTER BEH */
+{"Arabic_comma",                  0x05ac},  /* U+060C ARABIC COMMA */
+{"Arabic_dad",                    0x05d6},  /* U+0636 ARABIC LETTER DAD */
+{"Arabic_dal",                    0x05cf},  /* U+062F ARABIC LETTER DAL */
+{"Arabic_damma",                  0x05ef},  /* U+064F ARABIC DAMMA */
+{"Arabic_dammatan",               0x05ec},  /* U+064C ARABIC DAMMATAN */
+{"Arabic_fatha",                  0x05ee},  /* U+064E ARABIC FATHA */
+{"Arabic_fathatan",               0x05eb},  /* U+064B ARABIC FATHATAN */
+{"Arabic_feh",                    0x05e1},  /* U+0641 ARABIC LETTER FEH */
+{"Arabic_ghain",                  0x05da},  /* U+063A ARABIC LETTER GHAIN */
+{"Arabic_ha",                     0x05e7},  /* U+0647 ARABIC LETTER HEH */
+{"Arabic_hah",                    0x05cd},  /* U+062D ARABIC LETTER HAH */
+{"Arabic_hamza",                  0x05c1},  /* U+0621 ARABIC LETTER HAMZA */
+{"Arabic_hamzaonalef",            0x05c3},  /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
+{"Arabic_hamzaonwaw",             0x05c4},  /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
+{"Arabic_hamzaonyeh",             0x05c6},  /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
+{"Arabic_hamzaunderalef",         0x05c5},  /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
+{"Arabic_jeem",                   0x05cc},  /* U+062C ARABIC LETTER JEEM */
+{"Arabic_kaf",                    0x05e3},  /* U+0643 ARABIC LETTER KAF */
+{"Arabic_kasra",                  0x05f0},  /* U+0650 ARABIC KASRA */
+{"Arabic_kasratan",               0x05ed},  /* U+064D ARABIC KASRATAN */
+{"Arabic_khah",                   0x05ce},  /* U+062E ARABIC LETTER KHAH */
+{"Arabic_lam",                    0x05e4},  /* U+0644 ARABIC LETTER LAM */
+{"Arabic_maddaonalef",            0x05c2},  /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
+{"Arabic_meem",                   0x05e5},  /* U+0645 ARABIC LETTER MEEM */
+{"Arabic_noon",                   0x05e6},  /* U+0646 ARABIC LETTER NOON */
+{"Arabic_qaf",                    0x05e2},  /* U+0642 ARABIC LETTER QAF */
+{"Arabic_question_mark",          0x05bf},  /* U+061F ARABIC QUESTION MARK */
+{"Arabic_ra",                     0x05d1},  /* U+0631 ARABIC LETTER REH */
+{"Arabic_sad",                    0x05d5},  /* U+0635 ARABIC LETTER SAD */
+{"Arabic_seen",                   0x05d3},  /* U+0633 ARABIC LETTER SEEN */
+{"Arabic_semicolon",              0x05bb},  /* U+061B ARABIC SEMICOLON */
+{"Arabic_shadda",                 0x05f1},  /* U+0651 ARABIC SHADDA */
+{"Arabic_sheen",                  0x05d4},  /* U+0634 ARABIC LETTER SHEEN */
+{"Arabic_sukun",                  0x05f2},  /* U+0652 ARABIC SUKUN */
+{"Arabic_tah",                    0x05d7},  /* U+0637 ARABIC LETTER TAH */
+{"Arabic_tatweel",                0x05e0},  /* U+0640 ARABIC TATWEEL */
+{"Arabic_teh",                    0x05ca},  /* U+062A ARABIC LETTER TEH */
+{"Arabic_tehmarbuta",             0x05c9},  /* U+0629 ARABIC LETTER TEH MARBUTA */
+{"Arabic_thal",                   0x05d0},  /* U+0630 ARABIC LETTER THAL */
+{"Arabic_theh",                   0x05cb},  /* U+062B ARABIC LETTER THEH */
+{"Arabic_waw",                    0x05e8},  /* U+0648 ARABIC LETTER WAW */
+{"Arabic_yeh",                    0x05ea},  /* U+064A ARABIC LETTER YEH */
+{"Arabic_zah",                    0x05d8},  /* U+0638 ARABIC LETTER ZAH */
+{"Arabic_zain",                   0x05d2},  /* U+0632 ARABIC LETTER ZAIN */
+{"breve",                         0x01a2},  /* U+02D8 BREVE */
+{"caron",                         0x01b7},  /* U+02C7 CARON */
+{"Ccaron",                        0x01c8},  /* U+010C LATIN CAPITAL LETTER C WITH CARON */
+{"Cyrillic_a",                    0x06c1},  /* U+0430 CYRILLIC SMALL LETTER A */
+{"Cyrillic_A",                    0x06e1},  /* U+0410 CYRILLIC CAPITAL LETTER A */
+{"Cyrillic_be",                   0x06c2},  /* U+0431 CYRILLIC SMALL LETTER BE */
+{"Cyrillic_BE",                   0x06e2},  /* U+0411 CYRILLIC CAPITAL LETTER BE */
+{"Cyrillic_che",                  0x06de},  /* U+0447 CYRILLIC SMALL LETTER CHE */
+{"Cyrillic_CHE",                  0x06fe},  /* U+0427 CYRILLIC CAPITAL LETTER CHE */
+{"Cyrillic_de",                   0x06c4},  /* U+0434 CYRILLIC SMALL LETTER DE */
+{"Cyrillic_DE",                   0x06e4},  /* U+0414 CYRILLIC CAPITAL LETTER DE */
+{"Cyrillic_dzhe",                 0x06af},  /* U+045F CYRILLIC SMALL LETTER DZHE */
+{"Cyrillic_DZHE",                 0x06bf},  /* U+040F CYRILLIC CAPITAL LETTER DZHE */
+{"Cyrillic_e",                    0x06dc},  /* U+044D CYRILLIC SMALL LETTER E */
+{"Cyrillic_E",                    0x06fc},  /* U+042D CYRILLIC CAPITAL LETTER E */
+{"Cyrillic_ef",                   0x06c6},  /* U+0444 CYRILLIC SMALL LETTER EF */
+{"Cyrillic_EF",                   0x06e6},  /* U+0424 CYRILLIC CAPITAL LETTER EF */
+{"Cyrillic_el",                   0x06cc},  /* U+043B CYRILLIC SMALL LETTER EL */
+{"Cyrillic_EL",                   0x06ec},  /* U+041B CYRILLIC CAPITAL LETTER EL */
+{"Cyrillic_em",                   0x06cd},  /* U+043C CYRILLIC SMALL LETTER EM */
+{"Cyrillic_EM",                   0x06ed},  /* U+041C CYRILLIC CAPITAL LETTER EM */
+{"Cyrillic_en",                   0x06ce},  /* U+043D CYRILLIC SMALL LETTER EN */
+{"Cyrillic_EN",                   0x06ee},  /* U+041D CYRILLIC CAPITAL LETTER EN */
+{"Cyrillic_er",                   0x06d2},  /* U+0440 CYRILLIC SMALL LETTER ER */
+{"Cyrillic_ER",                   0x06f2},  /* U+0420 CYRILLIC CAPITAL LETTER ER */
+{"Cyrillic_es",                   0x06d3},  /* U+0441 CYRILLIC SMALL LETTER ES */
+{"Cyrillic_ES",                   0x06f3},  /* U+0421 CYRILLIC CAPITAL LETTER ES */
+{"Cyrillic_ghe",                  0x06c7},  /* U+0433 CYRILLIC SMALL LETTER GHE */
+{"Cyrillic_GHE",                  0x06e7},  /* U+0413 CYRILLIC CAPITAL LETTER GHE */
+{"Cyrillic_ha",                   0x06c8},  /* U+0445 CYRILLIC SMALL LETTER HA */
+{"Cyrillic_HA",                   0x06e8},  /* U+0425 CYRILLIC CAPITAL LETTER HA */
+{"Cyrillic_hardsign",             0x06df},  /* U+044A CYRILLIC SMALL LETTER HARD SIGN */
+{"Cyrillic_HARDSIGN",             0x06ff},  /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */
+{"Cyrillic_i",                    0x06c9},  /* U+0438 CYRILLIC SMALL LETTER I */
+{"Cyrillic_I",                    0x06e9},  /* U+0418 CYRILLIC CAPITAL LETTER I */
+{"Cyrillic_ie",                   0x06c5},  /* U+0435 CYRILLIC SMALL LETTER IE */
+{"Cyrillic_IE",                   0x06e5},  /* U+0415 CYRILLIC CAPITAL LETTER IE */
+{"Cyrillic_io",                   0x06a3},  /* U+0451 CYRILLIC SMALL LETTER IO */
+{"Cyrillic_IO",                   0x06b3},  /* U+0401 CYRILLIC CAPITAL LETTER IO */
+{"Cyrillic_je",                   0x06a8},  /* U+0458 CYRILLIC SMALL LETTER JE */
+{"Cyrillic_JE",                   0x06b8},  /* U+0408 CYRILLIC CAPITAL LETTER JE */
+{"Cyrillic_ka",                   0x06cb},  /* U+043A CYRILLIC SMALL LETTER KA */
+{"Cyrillic_KA",                   0x06eb},  /* U+041A CYRILLIC CAPITAL LETTER KA */
+{"Cyrillic_lje",                  0x06a9},  /* U+0459 CYRILLIC SMALL LETTER LJE */
+{"Cyrillic_LJE",                  0x06b9},  /* U+0409 CYRILLIC CAPITAL LETTER LJE */
+{"Cyrillic_nje",                  0x06aa},  /* U+045A CYRILLIC SMALL LETTER NJE */
+{"Cyrillic_NJE",                  0x06ba},  /* U+040A CYRILLIC CAPITAL LETTER NJE */
+{"Cyrillic_o",                    0x06cf},  /* U+043E CYRILLIC SMALL LETTER O */
+{"Cyrillic_O",                    0x06ef},  /* U+041E CYRILLIC CAPITAL LETTER O */
+{"Cyrillic_pe",                   0x06d0},  /* U+043F CYRILLIC SMALL LETTER PE */
+{"Cyrillic_PE",                   0x06f0},  /* U+041F CYRILLIC CAPITAL LETTER PE */
+{"Cyrillic_sha",                  0x06db},  /* U+0448 CYRILLIC SMALL LETTER SHA */
+{"Cyrillic_SHA",                  0x06fb},  /* U+0428 CYRILLIC CAPITAL LETTER SHA */
+{"Cyrillic_shcha",                0x06dd},  /* U+0449 CYRILLIC SMALL LETTER SHCHA */
+{"Cyrillic_SHCHA",                0x06fd},  /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */
+{"Cyrillic_shorti",               0x06ca},  /* U+0439 CYRILLIC SMALL LETTER SHORT I */
+{"Cyrillic_SHORTI",               0x06ea},  /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */
+{"Cyrillic_softsign",             0x06d8},  /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */
+{"Cyrillic_SOFTSIGN",             0x06f8},  /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */
+{"Cyrillic_te",                   0x06d4},  /* U+0442 CYRILLIC SMALL LETTER TE */
+{"Cyrillic_TE",                   0x06f4},  /* U+0422 CYRILLIC CAPITAL LETTER TE */
+{"Cyrillic_tse",                  0x06c3},  /* U+0446 CYRILLIC SMALL LETTER TSE */
+{"Cyrillic_TSE",                  0x06e3},  /* U+0426 CYRILLIC CAPITAL LETTER TSE */
+{"Cyrillic_u",                    0x06d5},  /* U+0443 CYRILLIC SMALL LETTER U */
+{"Cyrillic_U",                    0x06f5},  /* U+0423 CYRILLIC CAPITAL LETTER U */
+{"Cyrillic_ve",                   0x06d7},  /* U+0432 CYRILLIC SMALL LETTER VE */
+{"Cyrillic_VE",                   0x06f7},  /* U+0412 CYRILLIC CAPITAL LETTER VE */
+{"Cyrillic_ya",                   0x06d1},  /* U+044F CYRILLIC SMALL LETTER YA */
+{"Cyrillic_YA",                   0x06f1},  /* U+042F CYRILLIC CAPITAL LETTER YA */
+{"Cyrillic_yeru",                 0x06d9},  /* U+044B CYRILLIC SMALL LETTER YERU */
+{"Cyrillic_YERU",                 0x06f9},  /* U+042B CYRILLIC CAPITAL LETTER YERU */
+{"Cyrillic_yu",                   0x06c0},  /* U+044E CYRILLIC SMALL LETTER YU */
+{"Cyrillic_YU",                   0x06e0},  /* U+042E CYRILLIC CAPITAL LETTER YU */
+{"Cyrillic_ze",                   0x06da},  /* U+0437 CYRILLIC SMALL LETTER ZE */
+{"Cyrillic_ZE",                   0x06fa},  /* U+0417 CYRILLIC CAPITAL LETTER ZE */
+{"Cyrillic_zhe",                  0x06d6},  /* U+0436 CYRILLIC SMALL LETTER ZHE */
+{"Cyrillic_ZHE",                  0x06f6},  /* U+0416 CYRILLIC CAPITAL LETTER ZHE */
+{"doubleacute",                   0x01bd},  /* U+02DD DOUBLE ACUTE ACCENT */
+{"doublelowquotemark",            0x0afe},  /* U+201E DOUBLE LOW-9 QUOTATION MARK */
+{"downarrow",                     0x08fe},  /* U+2193 DOWNWARDS ARROW */
+{"dstroke",                       0x01f0},  /* U+0111 LATIN SMALL LETTER D WITH STROKE */
+{"Dstroke",                       0x01d0},  /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */
+{"eabovedot",                     0x03ec},  /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */
+{"Eabovedot",                     0x03cc},  /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */
+{"emacron",                       0x03ba},  /* U+0113 LATIN SMALL LETTER E WITH MACRON */
+{"Emacron",                       0x03aa},  /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */
+{"endash",                        0x0aaa},  /* U+2013 EN DASH */
+{"eng",                           0x03bf},  /* U+014B LATIN SMALL LETTER ENG */
+{"ENG",                           0x03bd},  /* U+014A LATIN CAPITAL LETTER ENG */
+{"Execute",                       0xff62},  /* Execute, run, do */
+{"F16",                           0xffcd},
+{"F17",                           0xffce},
+{"F18",                           0xffcf},
+{"F19",                           0xffd0},
+{"F20",                           0xffd1},
+{"F21",                           0xffd2},
+{"F22",                           0xffd3},
+{"F23",                           0xffd4},
+{"F24",                           0xffd5},
+{"F25",                           0xffd6},
+{"F26",                           0xffd7},
+{"F27",                           0xffd8},
+{"F28",                           0xffd9},
+{"F29",                           0xffda},
+{"F30",                           0xffdb},
+{"F31",                           0xffdc},
+{"F32",                           0xffdd},
+{"F33",                           0xffde},
+{"F34",                           0xffdf},
+{"F35",                           0xffe0},
+{"fiveeighths",                   0x0ac5},  /* U+215D VULGAR FRACTION FIVE EIGHTHS */
+{"gbreve",                        0x02bb},  /* U+011F LATIN SMALL LETTER G WITH BREVE */
+{"Gbreve",                        0x02ab},  /* U+011E LATIN CAPITAL LETTER G WITH BREVE */
+{"gcedilla",                      0x03bb},  /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */
+{"Gcedilla",                      0x03ab},  /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */
+{"Greek_OMEGA",                   0x07d9},  /* U+03A9 GREEK CAPITAL LETTER OMEGA */
+{"Henkan_Mode",                   0xff23},  /* Start/Stop Conversion */
+{"horizconnector",                0x08a3},  /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/
+{"hstroke",                       0x02b1},  /* U+0127 LATIN SMALL LETTER H WITH STROKE */
+{"Hstroke",                       0x02a1},  /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */
+{"Iabovedot",                     0x02a9},  /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */
+{"idotless",                      0x02b9},  /* U+0131 LATIN SMALL LETTER DOTLESS I */
+{"imacron",                       0x03ef},  /* U+012B LATIN SMALL LETTER I WITH MACRON */
+{"Imacron",                       0x03cf},  /* U+012A LATIN CAPITAL LETTER I WITH MACRON */
+{"iogonek",                       0x03e7},  /* U+012F LATIN SMALL LETTER I WITH OGONEK */
+{"Iogonek",                       0x03c7},  /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */
+{"ISO_First_Group",               0xfe0c},
+{"ISO_Last_Group",                0xfe0e},
+{"ISO_Next_Group",                0xfe08},
+{"kana_a",                        0x04a7},  /* U+30A1 KATAKANA LETTER SMALL A */
+{"kana_A",                        0x04b1},  /* U+30A2 KATAKANA LETTER A */
+{"kana_CHI",                      0x04c1},  /* U+30C1 KATAKANA LETTER TI */
+{"kana_closingbracket",           0x04a3},  /* U+300D RIGHT CORNER BRACKET */
+{"kana_comma",                    0x04a4},  /* U+3001 IDEOGRAPHIC COMMA */
+{"kana_conjunctive",              0x04a5},  /* U+30FB KATAKANA MIDDLE DOT */
+{"kana_e",                        0x04aa},  /* U+30A7 KATAKANA LETTER SMALL E */
+{"kana_E",                        0x04b4},  /* U+30A8 KATAKANA LETTER E */
+{"kana_FU",                       0x04cc},  /* U+30D5 KATAKANA LETTER HU */
+{"kana_fullstop",                 0x04a1},  /* U+3002 IDEOGRAPHIC FULL STOP */
+{"kana_HA",                       0x04ca},  /* U+30CF KATAKANA LETTER HA */
+{"kana_HE",                       0x04cd},  /* U+30D8 KATAKANA LETTER HE */
+{"kana_HI",                       0x04cb},  /* U+30D2 KATAKANA LETTER HI */
+{"kana_HO",                       0x04ce},  /* U+30DB KATAKANA LETTER HO */
+{"kana_i",                        0x04a8},  /* U+30A3 KATAKANA LETTER SMALL I */
+{"kana_I",                        0x04b2},  /* U+30A4 KATAKANA LETTER I */
+{"kana_KA",                       0x04b6},  /* U+30AB KATAKANA LETTER KA */
+{"kana_KE",                       0x04b9},  /* U+30B1 KATAKANA LETTER KE */
+{"kana_KI",                       0x04b7},  /* U+30AD KATAKANA LETTER KI */
+{"kana_KO",                       0x04ba},  /* U+30B3 KATAKANA LETTER KO */
+{"kana_KU",                       0x04b8},  /* U+30AF KATAKANA LETTER KU */
+{"kana_MA",                       0x04cf},  /* U+30DE KATAKANA LETTER MA */
+{"kana_ME",                       0x04d2},  /* U+30E1 KATAKANA LETTER ME */
+{"kana_MI",                       0x04d0},  /* U+30DF KATAKANA LETTER MI */
+{"kana_MO",                       0x04d3},  /* U+30E2 KATAKANA LETTER MO */
+{"kana_MU",                       0x04d1},  /* U+30E0 KATAKANA LETTER MU */
+{"kana_N",                        0x04dd},  /* U+30F3 KATAKANA LETTER N */
+{"kana_NA",                       0x04c5},  /* U+30CA KATAKANA LETTER NA */
+{"kana_NE",                       0x04c8},  /* U+30CD KATAKANA LETTER NE */
+{"kana_NI",                       0x04c6},  /* U+30CB KATAKANA LETTER NI */
+{"kana_NO",                       0x04c9},  /* U+30CE KATAKANA LETTER NO */
+{"kana_NU",                       0x04c7},  /* U+30CC KATAKANA LETTER NU */
+{"kana_o",                        0x04ab},  /* U+30A9 KATAKANA LETTER SMALL O */
+{"kana_O",                        0x04b5},  /* U+30AA KATAKANA LETTER O */
+{"kana_openingbracket",           0x04a2},  /* U+300C LEFT CORNER BRACKET */
+{"kana_RA",                       0x04d7},  /* U+30E9 KATAKANA LETTER RA */
+{"kana_RE",                       0x04da},  /* U+30EC KATAKANA LETTER RE */
+{"kana_RI",                       0x04d8},  /* U+30EA KATAKANA LETTER RI */
+{"kana_RU",                       0x04d9},  /* U+30EB KATAKANA LETTER RU */
+{"kana_SA",                       0x04bb},  /* U+30B5 KATAKANA LETTER SA */
+{"kana_SE",                       0x04be},  /* U+30BB KATAKANA LETTER SE */
+{"kana_SHI",                      0x04bc},  /* U+30B7 KATAKANA LETTER SI */
+{"kana_SO",                       0x04bf},  /* U+30BD KATAKANA LETTER SO */
+{"kana_SU",                       0x04bd},  /* U+30B9 KATAKANA LETTER SU */
+{"kana_TA",                       0x04c0},  /* U+30BF KATAKANA LETTER TA */
+{"kana_TE",                       0x04c3},  /* U+30C6 KATAKANA LETTER TE */
+{"kana_TO",                       0x04c4},  /* U+30C8 KATAKANA LETTER TO */
+{"kana_tsu",                      0x04af},  /* U+30C3 KATAKANA LETTER SMALL TU */
+{"kana_TSU",                      0x04c2},  /* U+30C4 KATAKANA LETTER TU */
+{"kana_u",                        0x04a9},  /* U+30A5 KATAKANA LETTER SMALL U */
+{"kana_U",                        0x04b3},  /* U+30A6 KATAKANA LETTER U */
+{"kana_WA",                       0x04dc},  /* U+30EF KATAKANA LETTER WA */
+{"kana_WO",                       0x04a6},  /* U+30F2 KATAKANA LETTER WO */
+{"kana_ya",                       0x04ac},  /* U+30E3 KATAKANA LETTER SMALL YA */
+{"kana_YA",                       0x04d4},  /* U+30E4 KATAKANA LETTER YA */
+{"kana_yo",                       0x04ae},  /* U+30E7 KATAKANA LETTER SMALL YO */
+{"kana_YO",                       0x04d6},  /* U+30E8 KATAKANA LETTER YO */
+{"kana_yu",                       0x04ad},  /* U+30E5 KATAKANA LETTER SMALL YU */
+{"kana_YU",                       0x04d5},  /* U+30E6 KATAKANA LETTER YU */
+{"Kanji",                         0xff21},  /* Kanji, Kanji convert */
+{"kcedilla",                      0x03f3},  /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */
+{"Kcedilla",                      0x03d3},  /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */
+{"kra",                           0x03a2},  /* U+0138 LATIN SMALL LETTER KRA */
+{"lcedilla",                      0x03b6},  /* U+013C LATIN SMALL LETTER L WITH CEDILLA */
+{"Lcedilla",                      0x03a6},  /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */
+{"leftarrow",                     0x08fb},  /* U+2190 LEFTWARDS ARROW */
+{"leftdoublequotemark",           0x0ad2},  /* U+201C LEFT DOUBLE QUOTATION MARK */
+{"Macedonia_dse",                 0x06a5},  /* U+0455 CYRILLIC SMALL LETTER DZE */
+{"Macedonia_DSE",                 0x06b5},  /* U+0405 CYRILLIC CAPITAL LETTER DZE */
+{"Macedonia_gje",                 0x06a2},  /* U+0453 CYRILLIC SMALL LETTER GJE */
+{"Macedonia_GJE",                 0x06b2},  /* U+0403 CYRILLIC CAPITAL LETTER GJE */
+{"Macedonia_kje",                 0x06ac},  /* U+045C CYRILLIC SMALL LETTER KJE */
+{"Macedonia_KJE",                 0x06bc},  /* U+040C CYRILLIC CAPITAL LETTER KJE */
+{"ncedilla",                      0x03f1},  /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */
+{"Ncedilla",                      0x03d1},  /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */
+{"oe",                            0x13bd},  /* U+0153 LATIN SMALL LIGATURE OE */
+{"OE",                            0x13bc},  /* U+0152 LATIN CAPITAL LIGATURE OE */
+{"ogonek",                        0x01b2},  /* U+02DB OGONEK */
+{"omacron",                       0x03f2},  /* U+014D LATIN SMALL LETTER O WITH MACRON */
+{"Omacron",                       0x03d2},  /* U+014C LATIN CAPITAL LETTER O WITH MACRON */
+{"oneeighth",                     0x0ac3},  /* U+215B VULGAR FRACTION ONE EIGHTH */
+{"rcedilla",                      0x03b3},  /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */
+{"Rcedilla",                      0x03a3},  /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */
+{"rightarrow",                    0x08fd},  /* U+2192 RIGHTWARDS ARROW */
+{"rightdoublequotemark",          0x0ad3},  /* U+201D RIGHT DOUBLE QUOTATION MARK */
+{"Scaron",                        0x01a9},  /* U+0160 LATIN CAPITAL LETTER S WITH CARON */
+{"scedilla",                      0x01ba},  /* U+015F LATIN SMALL LETTER S WITH CEDILLA */
+{"Scedilla",                      0x01aa},  /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */
+{"semivoicedsound",               0x04df},  /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+{"seveneighths",                  0x0ac6},  /* U+215E VULGAR FRACTION SEVEN EIGHTHS */
+{"Thai_baht",                     0x0ddf},  /* U+0E3F THAI CURRENCY SYMBOL BAHT */
+{"Thai_bobaimai",                 0x0dba},  /* U+0E1A THAI CHARACTER BO BAIMAI */
+{"Thai_chochan",                  0x0da8},  /* U+0E08 THAI CHARACTER CHO CHAN */
+{"Thai_chochang",                 0x0daa},  /* U+0E0A THAI CHARACTER CHO CHANG */
+{"Thai_choching",                 0x0da9},  /* U+0E09 THAI CHARACTER CHO CHING */
+{"Thai_chochoe",                  0x0dac},  /* U+0E0C THAI CHARACTER CHO CHOE */
+{"Thai_dochada",                  0x0dae},  /* U+0E0E THAI CHARACTER DO CHADA */
+{"Thai_dodek",                    0x0db4},  /* U+0E14 THAI CHARACTER DO DEK */
+{"Thai_fofa",                     0x0dbd},  /* U+0E1D THAI CHARACTER FO FA */
+{"Thai_fofan",                    0x0dbf},  /* U+0E1F THAI CHARACTER FO FAN */
+{"Thai_hohip",                    0x0dcb},  /* U+0E2B THAI CHARACTER HO HIP */
+{"Thai_honokhuk",                 0x0dce},  /* U+0E2E THAI CHARACTER HO NOKHUK */
+{"Thai_khokhai",                  0x0da2},  /* U+0E02 THAI CHARACTER KHO KHAI */
+{"Thai_khokhon",                  0x0da5},  /* U+0E05 THAI CHARACTER KHO KHON */
+{"Thai_khokhuat",                 0x0da3},  /* U+0E03 THAI CHARACTER KHO KHUAT */
+{"Thai_khokhwai",                 0x0da4},  /* U+0E04 THAI CHARACTER KHO KHWAI */
+{"Thai_khorakhang",               0x0da6},  /* U+0E06 THAI CHARACTER KHO RAKHANG */
+{"Thai_kokai",                    0x0da1},  /* U+0E01 THAI CHARACTER KO KAI */
+{"Thai_lakkhangyao",              0x0de5},  /* U+0E45 THAI CHARACTER LAKKHANGYAO */
+{"Thai_lekchet",                  0x0df7},  /* U+0E57 THAI DIGIT SEVEN */
+{"Thai_lekha",                    0x0df5},  /* U+0E55 THAI DIGIT FIVE */
+{"Thai_lekhok",                   0x0df6},  /* U+0E56 THAI DIGIT SIX */
+{"Thai_lekkao",                   0x0df9},  /* U+0E59 THAI DIGIT NINE */
+{"Thai_leknung",                  0x0df1},  /* U+0E51 THAI DIGIT ONE */
+{"Thai_lekpaet",                  0x0df8},  /* U+0E58 THAI DIGIT EIGHT */
+{"Thai_leksam",                   0x0df3},  /* U+0E53 THAI DIGIT THREE */
+{"Thai_leksi",                    0x0df4},  /* U+0E54 THAI DIGIT FOUR */
+{"Thai_leksong",                  0x0df2},  /* U+0E52 THAI DIGIT TWO */
+{"Thai_leksun",                   0x0df0},  /* U+0E50 THAI DIGIT ZERO */
+{"Thai_lochula",                  0x0dcc},  /* U+0E2C THAI CHARACTER LO CHULA */
+{"Thai_loling",                   0x0dc5},  /* U+0E25 THAI CHARACTER LO LING */
+{"Thai_lu",                       0x0dc6},  /* U+0E26 THAI CHARACTER LU */
+{"Thai_maichattawa",              0x0deb},  /* U+0E4B THAI CHARACTER MAI CHATTAWA */
+{"Thai_maiek",                    0x0de8},  /* U+0E48 THAI CHARACTER MAI EK */
+{"Thai_maihanakat",               0x0dd1},  /* U+0E31 THAI CHARACTER MAI HAN-AKAT */
+{"Thai_maitaikhu",                0x0de7},  /* U+0E47 THAI CHARACTER MAITAIKHU */
+{"Thai_maitho",                   0x0de9},  /* U+0E49 THAI CHARACTER MAI THO */
+{"Thai_maitri",                   0x0dea},  /* U+0E4A THAI CHARACTER MAI TRI */
+{"Thai_maiyamok",                 0x0de6},  /* U+0E46 THAI CHARACTER MAIYAMOK */
+{"Thai_moma",                     0x0dc1},  /* U+0E21 THAI CHARACTER MO MA */
+{"Thai_ngongu",                   0x0da7},  /* U+0E07 THAI CHARACTER NGO NGU */
+{"Thai_nikhahit",                 0x0ded},  /* U+0E4D THAI CHARACTER NIKHAHIT */
+{"Thai_nonen",                    0x0db3},  /* U+0E13 THAI CHARACTER NO NEN */
+{"Thai_nonu",                     0x0db9},  /* U+0E19 THAI CHARACTER NO NU */
+{"Thai_oang",                     0x0dcd},  /* U+0E2D THAI CHARACTER O ANG */
+{"Thai_paiyannoi",                0x0dcf},  /* U+0E2F THAI CHARACTER PAIYANNOI */
+{"Thai_phinthu",                  0x0dda},  /* U+0E3A THAI CHARACTER PHINTHU */
+{"Thai_phophan",                  0x0dbe},  /* U+0E1E THAI CHARACTER PHO PHAN */
+{"Thai_phophung",                 0x0dbc},  /* U+0E1C THAI CHARACTER PHO PHUNG */
+{"Thai_phosamphao",               0x0dc0},  /* U+0E20 THAI CHARACTER PHO SAMPHAO */
+{"Thai_popla",                    0x0dbb},  /* U+0E1B THAI CHARACTER PO PLA */
+{"Thai_rorua",                    0x0dc3},  /* U+0E23 THAI CHARACTER RO RUA */
+{"Thai_ru",                       0x0dc4},  /* U+0E24 THAI CHARACTER RU */
+{"Thai_saraa",                    0x0dd0},  /* U+0E30 THAI CHARACTER SARA A */
+{"Thai_saraaa",                   0x0dd2},  /* U+0E32 THAI CHARACTER SARA AA */
+{"Thai_saraae",                   0x0de1},  /* U+0E41 THAI CHARACTER SARA AE */
+{"Thai_saraaimaimalai",           0x0de4},  /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */
+{"Thai_saraaimaimuan",            0x0de3},  /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */
+{"Thai_saraam",                   0x0dd3},  /* U+0E33 THAI CHARACTER SARA AM */
+{"Thai_sarae",                    0x0de0},  /* U+0E40 THAI CHARACTER SARA E */
+{"Thai_sarai",                    0x0dd4},  /* U+0E34 THAI CHARACTER SARA I */
+{"Thai_saraii",                   0x0dd5},  /* U+0E35 THAI CHARACTER SARA II */
+{"Thai_sarao",                    0x0de2},  /* U+0E42 THAI CHARACTER SARA O */
+{"Thai_sarau",                    0x0dd8},  /* U+0E38 THAI CHARACTER SARA U */
+{"Thai_saraue",                   0x0dd6},  /* U+0E36 THAI CHARACTER SARA UE */
+{"Thai_sarauee",                  0x0dd7},  /* U+0E37 THAI CHARACTER SARA UEE */
+{"Thai_sarauu",                   0x0dd9},  /* U+0E39 THAI CHARACTER SARA UU */
+{"Thai_sorusi",                   0x0dc9},  /* U+0E29 THAI CHARACTER SO RUSI */
+{"Thai_sosala",                   0x0dc8},  /* U+0E28 THAI CHARACTER SO SALA */
+{"Thai_soso",                     0x0dab},  /* U+0E0B THAI CHARACTER SO SO */
+{"Thai_sosua",                    0x0dca},  /* U+0E2A THAI CHARACTER SO SUA */
+{"Thai_thanthakhat",              0x0dec},  /* U+0E4C THAI CHARACTER THANTHAKHAT */
+{"Thai_thonangmontho",            0x0db1},  /* U+0E11 THAI CHARACTER THO NANGMONTHO */
+{"Thai_thophuthao",               0x0db2},  /* U+0E12 THAI CHARACTER THO PHUTHAO */
+{"Thai_thothahan",                0x0db7},  /* U+0E17 THAI CHARACTER THO THAHAN */
+{"Thai_thothan",                  0x0db0},  /* U+0E10 THAI CHARACTER THO THAN */
+{"Thai_thothong",                 0x0db8},  /* U+0E18 THAI CHARACTER THO THONG */
+{"Thai_thothung",                 0x0db6},  /* U+0E16 THAI CHARACTER THO THUNG */
+{"Thai_topatak",                  0x0daf},  /* U+0E0F THAI CHARACTER TO PATAK */
+{"Thai_totao",                    0x0db5},  /* U+0E15 THAI CHARACTER TO TAO */
+{"Thai_wowaen",                   0x0dc7},  /* U+0E27 THAI CHARACTER WO WAEN */
+{"Thai_yoyak",                    0x0dc2},  /* U+0E22 THAI CHARACTER YO YAK */
+{"Thai_yoying",                   0x0dad},  /* U+0E0D THAI CHARACTER YO YING */
+{"threeeighths",                  0x0ac4},  /* U+215C VULGAR FRACTION THREE EIGHTHS */
+{"trademark",                     0x0ac9},  /* U+2122 TRADE MARK SIGN */
+{"tslash",                        0x03bc},  /* U+0167 LATIN SMALL LETTER T WITH STROKE */
+{"Tslash",                        0x03ac},  /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */
+{"umacron",                       0x03fe},  /* U+016B LATIN SMALL LETTER U WITH MACRON */
+{"Umacron",                       0x03de},  /* U+016A LATIN CAPITAL LETTER U WITH MACRON */
+{"uogonek",                       0x03f9},  /* U+0173 LATIN SMALL LETTER U WITH OGONEK */
+{"Uogonek",                       0x03d9},  /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */
+{"uparrow",                       0x08fc},  /* U+2191 UPWARDS ARROW */
+{"voicedsound",                   0x04de},  /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */
+{"Zcaron",                        0x01ae},  /* U+017D LATIN CAPITAL LETTER Z WITH CARON */
+
 {NULL,0},
 };
diff --git a/util/qemu-config.c b/util/qemu-config.c
index a59568d..04da942 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -8,6 +8,7 @@
 #include "qmp-commands.h"
 
 static QemuOptsList *vm_config_groups[32];
+static QemuOptsList *drive_config_groups[4];
 
 static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
                                Error **errp)
@@ -77,6 +78,59 @@
     return param_list;
 }
 
+/* remove repeated entry from the info list */
+static void cleanup_infolist(CommandLineParameterInfoList *head)
+{
+    CommandLineParameterInfoList *pre_entry, *cur, *del_entry;
+
+    cur = head;
+    while (cur->next) {
+        pre_entry = head;
+        while (pre_entry != cur->next) {
+            if (!strcmp(pre_entry->value->name, cur->next->value->name)) {
+                del_entry = cur->next;
+                cur->next = cur->next->next;
+                g_free(del_entry);
+                break;
+            }
+            pre_entry = pre_entry->next;
+        }
+        cur = cur->next;
+    }
+}
+
+/* merge the description items of two parameter infolists */
+static void connect_infolist(CommandLineParameterInfoList *head,
+                             CommandLineParameterInfoList *new)
+{
+    CommandLineParameterInfoList *cur;
+
+    cur = head;
+    while (cur->next) {
+        cur = cur->next;
+    }
+    cur->next = new;
+}
+
+/* access all the local QemuOptsLists for drive option */
+static CommandLineParameterInfoList *get_drive_infolist(void)
+{
+    CommandLineParameterInfoList *head = NULL, *cur;
+    int i;
+
+    for (i = 0; drive_config_groups[i] != NULL; i++) {
+        if (!head) {
+            head = query_option_descs(drive_config_groups[i]->desc);
+        } else {
+            cur = query_option_descs(drive_config_groups[i]->desc);
+            connect_infolist(head, cur);
+        }
+    }
+    cleanup_infolist(head);
+
+    return head;
+}
+
 CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option,
                                                           const char *option,
                                                           Error **errp)
@@ -89,7 +143,12 @@
         if (!has_option || !strcmp(option, vm_config_groups[i]->name)) {
             info = g_malloc0(sizeof(*info));
             info->option = g_strdup(vm_config_groups[i]->name);
-            info->parameters = query_option_descs(vm_config_groups[i]->desc);
+            if (!strcmp("drive", vm_config_groups[i]->name)) {
+                info->parameters = get_drive_infolist();
+            } else {
+                info->parameters =
+                    query_option_descs(vm_config_groups[i]->desc);
+            }
             entry = g_malloc0(sizeof(*entry));
             entry->value = info;
             entry->next = conf_list;
@@ -109,6 +168,22 @@
     return find_list(vm_config_groups, group, errp);
 }
 
+void qemu_add_drive_opts(QemuOptsList *list)
+{
+    int entries, i;
+
+    entries = ARRAY_SIZE(drive_config_groups);
+    entries--; /* keep list NULL terminated */
+    for (i = 0; i < entries; i++) {
+        if (drive_config_groups[i] == NULL) {
+            drive_config_groups[i] = list;
+            return;
+        }
+    }
+    fprintf(stderr, "ran out of space in drive_config_groups");
+    abort();
+}
+
 void qemu_add_opts(QemuOptsList *list)
 {
     int entries, i;
diff --git a/vl.c b/vl.c
index b42ac67..8d5d874 100644
--- a/vl.c
+++ b/vl.c
@@ -638,9 +638,8 @@
     { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
     { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
 
-    { RUN_STATE_GUEST_PANICKED, RUN_STATE_PAUSED },
+    { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
     { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_GUEST_PANICKED, RUN_STATE_DEBUG },
 
     { RUN_STATE_MAX, RUN_STATE_MAX },
 };
@@ -686,8 +685,7 @@
 bool runstate_needs_reset(void)
 {
     return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-        runstate_check(RUN_STATE_SHUTDOWN) ||
-        runstate_check(RUN_STATE_GUEST_PANICKED);
+        runstate_check(RUN_STATE_SHUTDOWN);
 }
 
 StatusInfo *qmp_query_status(Error **errp)
@@ -2869,6 +2867,9 @@
     module_call_init(MODULE_INIT_QOM);
 
     qemu_add_opts(&qemu_drive_opts);
+    qemu_add_drive_opts(&qemu_legacy_drive_opts);
+    qemu_add_drive_opts(&qemu_common_drive_opts);
+    qemu_add_drive_opts(&qemu_drive_opts);
     qemu_add_opts(&qemu_chardev_opts);
     qemu_add_opts(&qemu_device_opts);
     qemu_add_opts(&qemu_netdev_opts);
@@ -4269,6 +4270,7 @@
     /* init local displays */
     switch (display_type) {
     case DT_NOGRAPHIC:
+        (void)ds;	/* avoid warning if no display is configured */
         break;
 #if defined(CONFIG_CURSES)
     case DT_CURSES:
@@ -4336,6 +4338,9 @@
     qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
     qemu_run_machine_init_done_notifiers();
 
+    /* Done notifiers can load ROMs */
+    rom_load_done();
+
     qemu_system_reset(VMRESET_SILENT);
     if (loadvm) {
         if (load_vmstate(loadvm) < 0) {